GrContext.cpp revision a292112154f803feb9f5cc002bbfab559f7cb633
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 12b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com#include "effects/GrConvolutionEffect.h" 13aa72eab5d82d4c2aa9f6f41755a001282443b042tomhudson@google.com#include "effects/GrSingleTextureEffect.h" 14a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com#include "effects/GrConfigConversionEffect.h" 15b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com 16278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com#include "GrBufferAllocPool.h" 1705ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.com#include "GrGpu.h" 1827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#include "GrIndexBuffer.h" 1927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#include "GrInOrderDrawBuffer.h" 2027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#include "GrPathRenderer.h" 21d22b6e4351e552a8379d7781096d9e79feeae263tomhudson@google.com#include "GrPathUtils.h" 2250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com#include "GrResourceCache.h" 2372176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com#include "GrSoftwarePathRenderer.h" 24558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com#include "GrStencilBuffer.h" 25278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com#include "GrTextStrike.h" 268c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com#include "SkTLazy.h" 27c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com#include "SkTLS.h" 280c8d93a94099dee2dff8da6000ded9ad59676488tomhudson@google.com#include "SkTrace.h" 2927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 30fa35e3ddcc9d130ce87c927218bdf27879c38711reed@google.comSK_DEFINE_INST_COUNT(GrContext) 31fa35e3ddcc9d130ce87c927218bdf27879c38711reed@google.comSK_DEFINE_INST_COUNT(GrDrawState) 32fa35e3ddcc9d130ce87c927218bdf27879c38711reed@google.com 331d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com// It can be useful to set this to kNo_BufferedDraw to test whether a bug is caused by using the 341d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com// InOrderDrawBuffer, to compare performance of using/not using InOrderDrawBuffer, or to make 351d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com// debugging easier. 361d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com#define DEFAULT_BUFFERING (GR_DISABLE_DRAW_BUFFERING ? kNo_BufferedDraw : kYes_BufferedDraw) 3727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 383b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org#define MAX_BLUR_SIGMA 4.0f 393b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org 40d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com// When we're using coverage AA but the blend is incompatible (given gpu 41d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com// limitations) should we disable AA or draw wrong? 42950d7a8d8def14efc98d12d6947347fde351b737bsalomon@google.com#define DISABLE_COVERAGE_AA_FOR_BLEND 1 43d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com 444b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com#if GR_DEBUG 454b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com // change this to a 1 to see notifications when partial coverage fails 464b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com #define GR_DEBUG_PARTIAL_COVERAGE_CHECK 0 474b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com#else 484b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com #define GR_DEBUG_PARTIAL_COVERAGE_CHECK 0 494b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com#endif 504b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com 5107fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.comstatic const size_t MAX_TEXTURE_CACHE_COUNT = 256; 5207fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.comstatic const size_t MAX_TEXTURE_CACHE_BYTES = 16 * 1024 * 1024; 5327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 5460361493548d5259d0a8afae84274c2a3c31dcacbsalomon@google.comstatic const size_t DRAW_BUFFER_VBPOOL_BUFFER_SIZE = 1 << 15; 5527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic const int DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS = 4; 5627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 571d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.comstatic const size_t DRAW_BUFFER_IBPOOL_BUFFER_SIZE = 1 << 11; 581d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.comstatic const int DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS = 4; 5927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 60bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com#define ASSERT_OWNED_RESOURCE(R) GrAssert(!(R) || (R)->getContext() == this) 61bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com 6205ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.comGrContext* GrContext::Create(GrEngine engine, 6305ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.com GrPlatform3DContext context3D) { 6427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com GrContext* ctx = NULL; 6527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com GrGpu* fGpu = GrGpu::Create(engine, context3D); 6627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com if (NULL != fGpu) { 67c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com ctx = SkNEW_ARGS(GrContext, (fGpu)); 6827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com fGpu->unref(); 6927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 7027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com return ctx; 7127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 7227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 73c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.comnamespace { 74c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.comvoid* CreateThreadInstanceCount() { 75c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com return SkNEW_ARGS(int, (0)); 76c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com} 77c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.comvoid DeleteThreadInstanceCount(void* v) { 78c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com delete reinterpret_cast<int*>(v); 79c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com} 80c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com#define THREAD_INSTANCE_COUNT \ 81c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com (*reinterpret_cast<int*>(SkTLS::Get(CreateThreadInstanceCount, \ 82c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com DeleteThreadInstanceCount))) 83c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com 84c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com} 85c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com 86c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.comint GrContext::GetThreadInstanceCount() { 87c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com return THREAD_INSTANCE_COUNT; 88c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com} 89c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com 9027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comGrContext::~GrContext() { 918fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com this->flush(); 925acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com 935acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com // Since the gpu can hold scratch textures, give it a chance to let go 945acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com // of them before freeing the texture cache 955acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com fGpu->purgeResources(); 965acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com 9727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com delete fTextureCache; 9827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com delete fFontCache; 9927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com delete fDrawBuffer; 10027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com delete fDrawBufferVBAllocPool; 101de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com delete fDrawBufferIBAllocPool; 1023008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com 103f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com fAARectRenderer->unref(); 104f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com 105205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com fGpu->unref(); 1063008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com GrSafeUnref(fPathRendererChain); 10772176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com GrSafeUnref(fSoftwarePathRenderer); 10810e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com fDrawState->unref(); 109c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com 110c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com --THREAD_INSTANCE_COUNT; 11127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 11227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 1138fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::contextLost() { 11453a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com contextDestroyed(); 11553a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com this->setupDrawBuffer(); 11653a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com} 11753a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com 11853a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.comvoid GrContext::contextDestroyed() { 119205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com // abandon first to so destructors 120205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com // don't try to free the resources in the API. 121205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com fGpu->abandonResources(); 122205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com 1233008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com // a path renderer may be holding onto resources that 1243008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com // are now unusable 1253008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com GrSafeSetNull(fPathRendererChain); 12672176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com GrSafeSetNull(fSoftwarePathRenderer); 1273008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com 1288fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com delete fDrawBuffer; 1298fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com fDrawBuffer = NULL; 130205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com 1318fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com delete fDrawBufferVBAllocPool; 1328fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com fDrawBufferVBAllocPool = NULL; 133205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com 1348fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com delete fDrawBufferIBAllocPool; 1358fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com fDrawBufferIBAllocPool = NULL; 1368fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com 137f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com fAARectRenderer->reset(); 138205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com 139a292112154f803feb9f5cc002bbfab559f7cb633bsalomon@google.com fTextureCache->purgeAllUnlocked(); 1408fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com fFontCache->freeAll(); 1418fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com fGpu->markContextDirty(); 1428fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com} 1438fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com 1448fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::resetContext() { 1458fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com fGpu->markContextDirty(); 1468fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com} 1478fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com 1488fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::freeGpuResources() { 1498fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com this->flush(); 150fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 151ff17584e1c15f68ccc296be517e8a6776a9ddabdrobertphillips@google.com fGpu->purgeResources(); 152ff17584e1c15f68ccc296be517e8a6776a9ddabdrobertphillips@google.com 153f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com fAARectRenderer->reset(); 154f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com 155a292112154f803feb9f5cc002bbfab559f7cb633bsalomon@google.com fTextureCache->purgeAllUnlocked(); 1568fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com fFontCache->freeAll(); 1573008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com // a path renderer may be holding onto resources 1583008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com GrSafeSetNull(fPathRendererChain); 15972176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com GrSafeSetNull(fSoftwarePathRenderer); 16027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 16127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 16205e70247c31ae927074ef27ea9893634a8dda543twiz@google.comsize_t GrContext::getGpuTextureCacheBytes() const { 16305e70247c31ae927074ef27ea9893634a8dda543twiz@google.com return fTextureCache->getCachedResourceBytes(); 16405e70247c31ae927074ef27ea9893634a8dda543twiz@google.com} 16505e70247c31ae927074ef27ea9893634a8dda543twiz@google.com 166fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 167fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com 16850398bf7f1953e640e5529616e710cf540799731bsalomon@google.comnamespace { 169558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com 1703b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.orgvoid scale_rect(SkRect* rect, float xScale, float yScale) { 1715af56069010b33562d337a4f76543d898ca8d485robertphillips@google.com rect->fLeft = SkScalarMul(rect->fLeft, SkFloatToScalar(xScale)); 1725af56069010b33562d337a4f76543d898ca8d485robertphillips@google.com rect->fTop = SkScalarMul(rect->fTop, SkFloatToScalar(yScale)); 1735af56069010b33562d337a4f76543d898ca8d485robertphillips@google.com rect->fRight = SkScalarMul(rect->fRight, SkFloatToScalar(xScale)); 1745af56069010b33562d337a4f76543d898ca8d485robertphillips@google.com rect->fBottom = SkScalarMul(rect->fBottom, SkFloatToScalar(yScale)); 1753b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org} 1763b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org 177b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.comfloat adjust_sigma(float sigma, int *scaleFactor, int *radius) { 1783b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org *scaleFactor = 1; 1793b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org while (sigma > MAX_BLUR_SIGMA) { 1803b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org *scaleFactor *= 2; 1813b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org sigma *= 0.5f; 1823b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org } 183b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com *radius = static_cast<int>(ceilf(sigma * 3.0f)); 184b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com GrAssert(*radius <= GrConvolutionEffect::kMaxKernelRadius); 1853b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org return sigma; 1863b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org} 1873b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org 18807ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.comvoid convolve_gaussian(GrDrawTarget* target, 189b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com GrTexture* texture, 190b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com const SkRect& rect, 191b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com float sigma, 192b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com int radius, 193b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com Gr1DKernelEffect::Direction direction) { 19407ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com GrRenderTarget* rt = target->drawState()->getRenderTarget(); 19507ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kReset_ASRInit); 19607ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com GrDrawState* drawState = target->drawState(); 19707ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com drawState->setRenderTarget(rt); 1983b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org GrMatrix sampleM; 1993b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org sampleM.setIDiv(texture->width(), texture->height()); 200b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com drawState->sampler(0)->reset(sampleM); 201c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com SkAutoTUnref<GrConvolutionEffect> conv(SkNEW_ARGS(GrConvolutionEffect, 202fde2c0af2fd5aae19ab6c8b5228debd5b6209856tomhudson@google.com (texture, direction, radius, 203fde2c0af2fd5aae19ab6c8b5228debd5b6209856tomhudson@google.com sigma))); 204b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com drawState->sampler(0)->setCustomStage(conv); 20507ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com target->drawSimpleRect(rect, NULL); 2063b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org} 2073b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org 208fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com} 209fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com 2101f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.comGrTexture* GrContext::findAndLockTexture(const GrTextureDesc& desc, 2111f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com const GrCacheData& cacheData, 2121f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com const GrTextureParams* params) { 2139c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, params, desc, cacheData, false); 2141f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com GrResource* resource = fTextureCache->findAndLock(resourceKey, 2151f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com GrResourceCache::kNested_LockType); 2161f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com return static_cast<GrTexture*>(resource); 217558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com} 218558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com 21975b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.combool GrContext::isTextureInCache(const GrTextureDesc& desc, 2209c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com const GrCacheData& cacheData, 221b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com const GrTextureParams* params) const { 2229c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, params, desc, cacheData, false); 223fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com return fTextureCache->hasKey(resourceKey); 224fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com} 225fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com 2261f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.comvoid GrContext::addAndLockStencilBuffer(GrStencilBuffer* sb) { 227bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com ASSERT_OWNED_RESOURCE(sb); 22846a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com 22946a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com GrResourceKey resourceKey = GrStencilBuffer::ComputeKey(sb->width(), 23046a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com sb->height(), 23146a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com sb->numSamples()); 2321f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com fTextureCache->createAndLock(resourceKey, sb); 233558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com} 234558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com 235558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.comGrStencilBuffer* GrContext::findStencilBuffer(int width, int height, 236558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com int sampleCnt) { 23746a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com GrResourceKey resourceKey = GrStencilBuffer::ComputeKey(width, 23846a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com height, 23946a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com sampleCnt); 2401f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com GrResource* resource = fTextureCache->findAndLock(resourceKey, 241558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com GrResourceCache::kSingle_LockType); 2421f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com return static_cast<GrStencilBuffer*>(resource); 243558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com} 244558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com 2451f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.comvoid GrContext::unlockStencilBuffer(GrStencilBuffer* sb) { 2461f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com ASSERT_OWNED_RESOURCE(sb); 2471f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com GrAssert(NULL != sb->getCacheEntry()); 2481f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com 2491f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com fTextureCache->unlock(sb->getCacheEntry()); 25027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 25127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 25227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic void stretchImage(void* dst, 25327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com int dstW, 25427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com int dstH, 25527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com void* src, 25627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com int srcW, 25727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com int srcH, 25827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com int bpp) { 25927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com GrFixed dx = (srcW << 16) / dstW; 26027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com GrFixed dy = (srcH << 16) / dstH; 26127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 26227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com GrFixed y = dy >> 1; 26327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 26427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com int dstXLimit = dstW*bpp; 26527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com for (int j = 0; j < dstH; ++j) { 26627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com GrFixed x = dx >> 1; 26727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com void* srcRow = (uint8_t*)src + (y>>16)*srcW*bpp; 26827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com void* dstRow = (uint8_t*)dst + j*dstW*bpp; 26927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com for (int i = 0; i < dstXLimit; i += bpp) { 27027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com memcpy((uint8_t*) dstRow + i, 27127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com (uint8_t*) srcRow + (x>>16)*bpp, 27227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com bpp); 27327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com x += dx; 27427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 27527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com y += dy; 27627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 27727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 27827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 279fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com// The desired texture is NPOT and tiled but that isn't supported by 2803319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com// the current hardware. Resize the texture to be a POT 2813319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.comGrTexture* GrContext::createResizedTexture(const GrTextureDesc& desc, 2823319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com const GrCacheData& cacheData, 2833319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com void* srcData, 2843319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com size_t rowBytes, 2853319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com bool needsFiltering) { 2861f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com GrTexture* clampedTexture = this->findAndLockTexture(desc, cacheData, NULL); 2873319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com 2881f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com if (NULL == clampedTexture) { 2891f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com clampedTexture = this->createAndLockTexture(NULL, desc, cacheData, srcData, rowBytes); 2901f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com GrAssert(NULL != clampedTexture); 2911f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com if (NULL == clampedTexture) { 2923319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com return NULL; 2933319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com } 2943319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com } 2953319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com GrTextureDesc rtDesc = desc; 2963319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com rtDesc.fFlags = rtDesc.fFlags | 2973319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com kRenderTarget_GrTextureFlagBit | 2983319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com kNoStencil_GrTextureFlagBit; 2993319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com rtDesc.fWidth = GrNextPow2(GrMax(desc.fWidth, 64)); 3003319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com rtDesc.fHeight = GrNextPow2(GrMax(desc.fHeight, 64)); 3013319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com 3023319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com GrTexture* texture = fGpu->createTexture(rtDesc, NULL, 0); 3033319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com 3043319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com if (NULL != texture) { 3053319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit); 3063319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com GrDrawState* drawState = fGpu->drawState(); 3073319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com drawState->setRenderTarget(texture->asRenderTarget()); 3083319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com 3093319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com // if filtering is not desired then we want to ensure all 3103319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com // texels in the resampled image are copies of texels from 3113319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com // the original. 3123319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com drawState->sampler(0)->reset(SkShader::kClamp_TileMode, 3133319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com needsFiltering); 3141f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com drawState->createTextureEffect(0, clampedTexture); 3153319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com 3163319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com static const GrVertexLayout layout = 3173319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com GrDrawTarget::StageTexCoordVertexLayoutBit(0,0); 3183319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com GrDrawTarget::AutoReleaseGeometry arg(fGpu, layout, 4, 0); 3193319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com 3203319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com if (arg.succeeded()) { 3213319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com GrPoint* verts = (GrPoint*) arg.vertices(); 3223319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com verts[0].setIRectFan(0, 0, 3233319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com texture->width(), 3243319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com texture->height(), 3253319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com 2*sizeof(GrPoint)); 3263319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com verts[1].setIRectFan(0, 0, 1, 1, 2*sizeof(GrPoint)); 3273319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com fGpu->drawNonIndexed(kTriangleFan_GrPrimitiveType, 3283319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com 0, 4); 3293319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com } 3303319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com texture->releaseRenderTarget(); 3313319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com } else { 3323319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com // TODO: Our CPU stretch doesn't filter. But we create separate 3333319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com // stretched textures when the sampler state is either filtered or 3343319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com // not. Either implement filtered stretch blit on CPU or just create 3353319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com // one when FBO case fails. 3363319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com 3373319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com rtDesc.fFlags = kNone_GrTextureFlags; 3383319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com // no longer need to clamp at min RT size. 3393319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com rtDesc.fWidth = GrNextPow2(desc.fWidth); 3403319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com rtDesc.fHeight = GrNextPow2(desc.fHeight); 3413319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com int bpp = GrBytesPerPixel(desc.fConfig); 3423319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com SkAutoSMalloc<128*128*4> stretchedPixels(bpp * 3433319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com rtDesc.fWidth * 3443319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com rtDesc.fHeight); 3453319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com stretchImage(stretchedPixels.get(), rtDesc.fWidth, rtDesc.fHeight, 3463319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com srcData, desc.fWidth, desc.fHeight, bpp); 3473319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com 3483319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com size_t stretchedRowBytes = rtDesc.fWidth * bpp; 3493319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com 3503319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com GrTexture* texture = fGpu->createTexture(rtDesc, 3513319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com stretchedPixels.get(), 3523319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com stretchedRowBytes); 3533319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com GrAssert(NULL != texture); 3543319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com } 3551f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com this->unlockTexture(clampedTexture); 3563319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com 3573319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com return texture; 3583319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com} 3593319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com 3601f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.comGrTexture* GrContext::createAndLockTexture( 361b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com const GrTextureParams* params, 3621fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com const GrTextureDesc& desc, 3639c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com const GrCacheData& cacheData, 3641fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com void* srcData, 3651fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com size_t rowBytes) { 366278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com SK_TRACE_EVENT0("GrContext::createAndLockTexture"); 36727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 36827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if GR_DUMP_TEXTURE_UPLOAD 36927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com GrPrintf("GrContext::createAndLockTexture [%d %d]\n", desc.fWidth, desc.fHeight); 37027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif 37127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 3729c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, params, desc, cacheData, false); 373a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com 3743319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com GrTexture* texture = NULL; 375a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com if (GrTexture::NeedsResizing(resourceKey)) { 3763319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com texture = this->createResizedTexture(desc, cacheData, 377fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com srcData, rowBytes, 3783319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com GrTexture::NeedsFiltering(resourceKey)); 37927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } else { 3803319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com texture = fGpu->createTexture(desc, srcData, rowBytes); 3813319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com } 3823319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com 3833319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com if (NULL != texture) { 3841f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com fTextureCache->createAndLock(resourceKey, texture); 38527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 3863319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com 3871f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com return texture; 38827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 38927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 3901f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.comGrTexture* GrContext::lockScratchTexture(const GrTextureDesc& inDesc, 3911f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com ScratchTexMatch match) { 392b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com GrTextureDesc desc = inDesc; 3939c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com GrCacheData cacheData(GrCacheData::kScratch_CacheID); 39475b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com 3952afb8ec738fc50ea6e4500545c3cacbf346ed187rileya@google.com GrAssert((desc.fFlags & kRenderTarget_GrTextureFlagBit) || 3962afb8ec738fc50ea6e4500545c3cacbf346ed187rileya@google.com !(desc.fFlags & kNoStencil_GrTextureFlagBit)); 3972afb8ec738fc50ea6e4500545c3cacbf346ed187rileya@google.com 39850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com if (kExact_ScratchTexMatch != match) { 39950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com // bin by pow2 with a reasonable min 40050398bf7f1953e640e5529616e710cf540799731bsalomon@google.com static const int MIN_SIZE = 256; 40150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com desc.fWidth = GrMax(MIN_SIZE, GrNextPow2(desc.fWidth)); 40250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com desc.fHeight = GrMax(MIN_SIZE, GrNextPow2(desc.fHeight)); 40350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com } 404b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com 4051f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com GrResource* resource = NULL; 406b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com int origWidth = desc.fWidth; 407b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com int origHeight = desc.fHeight; 408b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com bool doubledW = false; 409b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com bool doubledH = false; 410b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com 411b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com do { 4129c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com GrResourceKey key = GrTexture::ComputeKey(fGpu, NULL, desc, cacheData, true); 4131f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com resource = fTextureCache->findAndLock(key, 4141f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com GrResourceCache::kNested_LockType); 415b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com // if we miss, relax the fit of the flags... 416b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com // then try doubling width... then height. 4171f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com if (NULL != resource || kExact_ScratchTexMatch == match) { 418b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com break; 419b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com } 420fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com // We no longer try to reuse textures that were previously used as render targets in 4212afb8ec738fc50ea6e4500545c3cacbf346ed187rileya@google.com // situations where no RT is needed; doing otherwise can confuse the video driver and 4222afb8ec738fc50ea6e4500545c3cacbf346ed187rileya@google.com // cause significant performance problems in some cases. 4232afb8ec738fc50ea6e4500545c3cacbf346ed187rileya@google.com if (desc.fFlags & kNoStencil_GrTextureFlagBit) { 424b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com desc.fFlags = desc.fFlags & ~kNoStencil_GrTextureFlagBit; 425fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } else if (!doubledW) { 426b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com desc.fFlags = inDesc.fFlags; 427b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com desc.fWidth *= 2; 428b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com doubledW = true; 429b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com } else if (!doubledH) { 430b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com desc.fFlags = inDesc.fFlags; 431b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com desc.fWidth = origWidth; 432b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com desc.fHeight *= 2; 433b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com doubledH = true; 434b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com } else { 435b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com break; 436b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com } 437fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 438b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com } while (true); 439b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com 4401f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com if (NULL == resource) { 441b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com desc.fFlags = inDesc.fFlags; 442b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com desc.fWidth = origWidth; 443b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com desc.fHeight = origHeight; 444b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com GrTexture* texture = fGpu->createTexture(desc, NULL, 0); 445b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com if (NULL != texture) { 44675b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com GrResourceKey key = GrTexture::ComputeKey(fGpu, NULL, 447a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com texture->desc(), 4489c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com cacheData, 449a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com true); 4501f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com fTextureCache->createAndLock(key, texture); 4511f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com resource = texture; 452b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com } 453b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com } 454b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com 455b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com // If the caller gives us the same desc/sampler twice we don't want 456b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com // to return the same texture the second time (unless it was previously 457521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com // released). So make it exclusive to hide it from future searches. 4581f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com if (NULL != resource) { 459521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com fTextureCache->makeExclusive(resource->getCacheEntry()); 460b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com } 461521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com 4621f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com return static_cast<GrTexture*>(resource); 463b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com} 464b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com 46515c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.comvoid GrContext::addExistingTextureToCache(GrTexture* texture) { 46615c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com 46715c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com if (NULL == texture) { 46815c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com return; 46915c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com } 47015c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com 471521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com // This texture should already have a cache entry since it was once 472521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com // attached 473521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com GrAssert(NULL != texture->getCacheEntry()); 474521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com 475521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com // Conceptually, the cache entry is going to assume responsibility 476521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com // for the creation ref. 477521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com GrAssert(1 == texture->getRefCnt()); 478521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com 479521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com // Since this texture came from an AutoScratchTexture it should 480521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com // still be in the exclusive pile 481521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com fTextureCache->makeNonExclusive(texture->getCacheEntry()); 4829c2ea846351a29208cb4a36301ee611e7fb384earobertphillips@google.com 483521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com // and it should still be locked 484521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com fTextureCache->unlock(texture->getCacheEntry()); 48515c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com} 48615c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com 4871f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.comvoid GrContext::unlockTexture(GrTexture* texture) { 4881f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com ASSERT_OWNED_RESOURCE(texture); 4891f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com GrAssert(NULL != texture->getCacheEntry()); 4901f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com 49150398bf7f1953e640e5529616e710cf540799731bsalomon@google.com // If this is a scratch texture we detached it from the cache 49250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com // while it was locked (to avoid two callers simultaneously getting 49350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com // the same texture). 4941f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com if (GrTexture::IsScratchTexture(texture->getCacheEntry()->key())) { 495521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com fTextureCache->makeNonExclusive(texture->getCacheEntry()); 496fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com } 49715c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com 498521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com fTextureCache->unlock(texture->getCacheEntry()); 49915c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com} 50015c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com 50175b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.comGrTexture* GrContext::createUncachedTexture(const GrTextureDesc& descIn, 50227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com void* srcData, 50327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com size_t rowBytes) { 50475b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com GrTextureDesc descCopy = descIn; 50575b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com return fGpu->createTexture(descCopy, srcData, rowBytes); 50627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 50727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 50807fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.comvoid GrContext::getTextureCacheLimits(int* maxTextures, 50907fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.com size_t* maxTextureBytes) const { 51007fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.com fTextureCache->getLimits(maxTextures, maxTextureBytes); 51127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 51227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 51307fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.comvoid GrContext::setTextureCacheLimits(int maxTextures, size_t maxTextureBytes) { 51407fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.com fTextureCache->setLimits(maxTextures, maxTextureBytes); 51527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 51627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 517919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.comint GrContext::getMaxTextureSize() const { 51818c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com return fGpu->getCaps().fMaxTextureSize; 519919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com} 520919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com 521919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.comint GrContext::getMaxRenderTargetSize() const { 52218c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com return fGpu->getCaps().fMaxRenderTargetSize; 52327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 52427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 52527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com/////////////////////////////////////////////////////////////////////////////// 52627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 527e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.comGrTexture* GrContext::createPlatformTexture(const GrPlatformTextureDesc& desc) { 528e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com return fGpu->createPlatformTexture(desc); 529e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com} 530e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com 531e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.comGrRenderTarget* GrContext::createPlatformRenderTarget(const GrPlatformRenderTargetDesc& desc) { 532e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com return fGpu->createPlatformRenderTarget(desc); 533e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com} 534e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com 5355877ffd5ea71a3ea70096d5c11c843798defa690bsalomon@google.com/////////////////////////////////////////////////////////////////////////////// 5365877ffd5ea71a3ea70096d5c11c843798defa690bsalomon@google.com 537b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.combool GrContext::supportsIndex8PixelConfig(const GrTextureParams* params, 5381f221a70214fa1ab87b8a32dd66facf485f318eebsalomon@google.com int width, int height) const { 53918c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com const GrDrawTarget::Caps& caps = fGpu->getCaps(); 54018c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com if (!caps.f8BitPaletteSupport) { 54127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com return false; 54227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 54327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 54427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com bool isPow2 = GrIsPow2(width) && GrIsPow2(height); 54527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 54627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com if (!isPow2) { 547b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com bool tiled = NULL != params && params->isTiled(); 54818c9c198f571997463d9a7134dbd88298e592ec2bsalomon@google.com if (tiled && !caps.fNPOTTextureTileSupport) { 54927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com return false; 55027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 55127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 55227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com return true; 55327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 55427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 55527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 55627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 557beb1af78d016d2700c350487a383c6bcfa7e2e20robertphillips@google.comconst GrClipData* GrContext::getClip() const { 558fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com return fGpu->getClip(); 559beb1af78d016d2700c350487a383c6bcfa7e2e20robertphillips@google.com} 56005ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.com 561beb1af78d016d2700c350487a383c6bcfa7e2e20robertphillips@google.comvoid GrContext::setClip(const GrClipData* clipData) { 562beb1af78d016d2700c350487a383c6bcfa7e2e20robertphillips@google.com fGpu->setClip(clipData); 56310e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com fDrawState->enableState(GrDrawState::kClip_StateBit); 56427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 56527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 56627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 56727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 56807ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.comvoid GrContext::clear(const GrIRect* rect, 56907ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com const GrColor color, 570c82a8b7aa4ec19fba508c394920a9e88d3e5bd12robertphillips@google.com GrRenderTarget* target) { 57107ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com this->prepareToDraw(NULL, DEFAULT_BUFFERING)->clear(rect, color, target); 57227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 57327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 57427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawPaint(const GrPaint& paint) { 57527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com // set rect to be big enough to fill the space, but not super-huge, so we 57627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com // don't overflow fixed-point implementations 577d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com GrRect r; 578d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com r.setLTRB(0, 0, 579d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com GrIntToScalar(getRenderTarget()->width()), 580d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com GrIntToScalar(getRenderTarget()->height())); 58127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com GrMatrix inverse; 5828c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com SkTLazy<GrPaint> tmpPaint; 5838c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com const GrPaint* p = &paint; 584fea85ac3e31842f80493e2df8a93a28f21cd815frobertphillips@google.com AutoMatrix am; 5858f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com 5864f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com // We attempt to map r by the inverse matrix and draw that. mapRect will 5874f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com // map the four corners and bound them with a new rect. This will not 5884f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com // produce a correct result for some perspective matrices. 5898c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com if (!this->getMatrix().hasPerspective()) { 59010e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com if (!fDrawState->getViewInverse(&inverse)) { 591e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com GrPrintf("Could not invert matrix\n"); 5928c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com return; 5938c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com } 59427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com inverse.mapRect(&r); 59527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } else { 596e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com if (paint.hasTextureOrMask()) { 5978c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com tmpPaint.set(paint); 5988c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com p = tmpPaint.get(); 599e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com if (!tmpPaint.get()->preConcatSamplerMatricesWithInverse(fDrawState->getViewMatrix())) { 600e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com GrPrintf("Could not invert matrix\n"); 601e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com } 6028c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com } 6034f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com am.set(this, GrMatrix::I()); 60427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 6054f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com // by definition this fills the entire clip, no need for AA 6064f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com if (paint.fAntiAlias) { 6078c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com if (!tmpPaint.isValid()) { 6088c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com tmpPaint.set(paint); 6098c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com p = tmpPaint.get(); 6108c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com } 6118c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com GrAssert(p == tmpPaint.get()); 6128c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com tmpPaint.get()->fAntiAlias = false; 6134f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com } 6144f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com this->drawRect(*p, r); 61527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 61627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 617205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 618205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com 619d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.comnamespace { 620d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.cominline bool disable_coverage_aa_for_blend(GrDrawTarget* target) { 621d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com return DISABLE_COVERAGE_AA_FOR_BLEND && !target->canApplyCoverage(); 622d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com} 623d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com} 624d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com 62506afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 62606afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com 62727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com/* create a triangle strip that strokes the specified triangle. There are 8 62827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com unique vertices, but we repreat the last 2 to close up. Alternatively we 62927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com could use an indices array, and then only send 8 verts, but not sure that 63027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com would be faster. 63127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com */ 632205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comstatic void setStrokeRectStrip(GrPoint verts[10], GrRect rect, 63327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com GrScalar width) { 63427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com const GrScalar rad = GrScalarHalf(width); 635205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com rect.sort(); 63627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 63727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com verts[0].set(rect.fLeft + rad, rect.fTop + rad); 63827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com verts[1].set(rect.fLeft - rad, rect.fTop - rad); 63927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com verts[2].set(rect.fRight - rad, rect.fTop + rad); 64027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com verts[3].set(rect.fRight + rad, rect.fTop - rad); 64127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com verts[4].set(rect.fRight - rad, rect.fBottom - rad); 64227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com verts[5].set(rect.fRight + rad, rect.fBottom + rad); 64327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com verts[6].set(rect.fLeft + rad, rect.fBottom - rad); 64427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com verts[7].set(rect.fLeft - rad, rect.fBottom + rad); 64527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com verts[8] = verts[0]; 64627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com verts[9] = verts[1]; 64727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 64827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 64920efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com/** 65020efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com * Returns true if the rects edges are integer-aligned. 65120efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com */ 65220efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.comstatic bool isIRect(const GrRect& r) { 653fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com return GrScalarIsInt(r.fLeft) && GrScalarIsInt(r.fTop) && 65420efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com GrScalarIsInt(r.fRight) && GrScalarIsInt(r.fBottom); 65520efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com} 65620efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com 657205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comstatic bool apply_aa_to_rect(GrDrawTarget* target, 658205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com const GrRect& rect, 659fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com GrScalar width, 660205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com const GrMatrix* matrix, 661205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com GrMatrix* combinedMatrix, 662a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com GrRect* devRect, 663a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com bool* useVertexCoverage) { 6642eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com // we use a simple coverage ramp to do aa on axis-aligned rects 665fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com // we check if the rect will be axis-aligned, and the rect won't land on 6662eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com // integer coords. 667d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com 668a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com // we are keeping around the "tweak the alpha" trick because 669a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com // it is our only hope for the fixed-pipe implementation. 670a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com // In a shader implementation we can give a separate coverage input 671289533ada623f2238a83771eec977f204f75994fbsalomon@google.com // TODO: remove this ugliness when we drop the fixed-pipe impl 672a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com *useVertexCoverage = false; 673d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com if (!target->canTweakAlphaForCoverage()) { 6742eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com if (disable_coverage_aa_for_blend(target)) { 6751983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#if GR_DEBUG 6762eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com //GrPrintf("Turning off AA to correctly apply blend.\n"); 6771983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#endif 678a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com return false; 6792eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com } else { 6802eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com *useVertexCoverage = true; 681a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com } 682205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com } 6838f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com const GrDrawState& drawState = target->getDrawState(); 6848f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com if (drawState.getRenderTarget()->isMultisampled()) { 685205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com return false; 686205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com } 687205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com 688471d471dcd7422e5dd9c822c1092b2ba4721dcfebsalomon@google.com if (0 == width && target->willUseHWAALines()) { 689205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com return false; 690205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com } 691205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com 6928f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com if (!drawState.getViewMatrix().preservesAxisAlignment()) { 693205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com return false; 694205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com } 695205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com 696fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com if (NULL != matrix && 697205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com !matrix->preservesAxisAlignment()) { 698205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com return false; 699205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com } 700205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com 7018f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com *combinedMatrix = drawState.getViewMatrix(); 702205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com if (NULL != matrix) { 703205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com combinedMatrix->preConcat(*matrix); 704205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com GrAssert(combinedMatrix->preservesAxisAlignment()); 705205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com } 706fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 707205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com combinedMatrix->mapRect(devRect, rect); 708205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com devRect->sort(); 709205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com 710205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com if (width < 0) { 71120efde71b4fd28691b10c8f1cfe15cb2aafddaeareed@google.com return !isIRect(*devRect); 712205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com } else { 713205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com return true; 714205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com } 715205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com} 716205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com 71727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawRect(const GrPaint& paint, 71827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com const GrRect& rect, 71927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com GrScalar width, 72027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com const GrMatrix* matrix) { 721278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com SK_TRACE_EVENT0("GrContext::drawRect"); 72227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 72307ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com GrDrawTarget* target = this->prepareToDraw(&paint, DEFAULT_BUFFERING); 7247d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com GrDrawState::AutoStageDisable atr(fDrawState); 72527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 726205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com GrRect devRect = rect; 727205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com GrMatrix combinedMatrix; 728a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com bool useVertexCoverage; 729289533ada623f2238a83771eec977f204f75994fbsalomon@google.com bool needAA = paint.fAntiAlias && 730289533ada623f2238a83771eec977f204f75994fbsalomon@google.com !this->getRenderTarget()->isMultisampled(); 731289533ada623f2238a83771eec977f204f75994fbsalomon@google.com bool doAA = needAA && apply_aa_to_rect(target, rect, width, matrix, 732289533ada623f2238a83771eec977f204f75994fbsalomon@google.com &combinedMatrix, &devRect, 733289533ada623f2238a83771eec977f204f75994fbsalomon@google.com &useVertexCoverage); 734205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com 735205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com if (doAA) { 736e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com GrDrawTarget::AutoDeviceCoordDraw adcd(target); 737e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com if (!adcd.succeeded()) { 738e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com return; 739e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com } 740205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com if (width >= 0) { 741205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com GrVec strokeSize;; 742205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com if (width > 0) { 743205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com strokeSize.set(width, width); 744cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com combinedMatrix.mapVectors(&strokeSize, 1); 745205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com strokeSize.setAbs(strokeSize); 746205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com } else { 747205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com strokeSize.set(GR_Scalar1, GR_Scalar1); 748205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com } 749fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com fAARectRenderer->strokeAARect(this->getGpu(), target, devRect, 750f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com strokeSize, useVertexCoverage); 751205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com } else { 752fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com fAARectRenderer->fillAARect(this->getGpu(), target, 753f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com devRect, useVertexCoverage); 754205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com } 755205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com return; 756205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com } 757205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com 75827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com if (width >= 0) { 75927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com // TODO: consider making static vertex buffers for these cases. 76027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com // Hairline could be done by just adding closing vertex to 76127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com // unitSquareVertexBuffer() 76226c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com 76327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com static const int worstCaseVertCount = 10; 764e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com GrDrawTarget::AutoReleaseGeometry geo(target, 0, worstCaseVertCount, 0); 76527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 76627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com if (!geo.succeeded()) { 7676513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com GrPrintf("Failed to get space for vertices!\n"); 76827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com return; 76927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 77027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 77127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com GrPrimitiveType primType; 77227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com int vertCount; 77327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com GrPoint* vertex = geo.positions(); 77427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 77527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com if (width > 0) { 77627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com vertCount = 10; 77747059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com primType = kTriangleStrip_GrPrimitiveType; 77827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com setStrokeRectStrip(vertex, rect, width); 77927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } else { 78027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com // hairline 78127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com vertCount = 5; 78247059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com primType = kLineStrip_GrPrimitiveType; 78327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com vertex[0].set(rect.fLeft, rect.fTop); 78427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com vertex[1].set(rect.fRight, rect.fTop); 78527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com vertex[2].set(rect.fRight, rect.fBottom); 78627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com vertex[3].set(rect.fLeft, rect.fBottom); 78727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com vertex[4].set(rect.fLeft, rect.fTop); 78827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 78927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 7908f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com GrDrawState::AutoViewMatrixRestore avmr; 79127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com if (NULL != matrix) { 7928f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com GrDrawState* drawState = target->drawState(); 7938f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com avmr.set(drawState); 7948f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com drawState->preConcatViewMatrix(*matrix); 795e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com drawState->preConcatSamplerMatrices(*matrix); 79627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 79727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 79827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com target->drawNonIndexed(primType, 0, vertCount); 79927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } else { 8008f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com#if GR_STATIC_RECT_VB 8016513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer(); 8026513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com if (NULL == sqVB) { 8036513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com GrPrintf("Failed to create static rect vb.\n"); 8046513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com return; 8056513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com } 806e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com target->setVertexSourceToBuffer(0, sqVB); 8078f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com GrDrawState* drawState = target->drawState(); 8088f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com GrDrawState::AutoViewMatrixRestore avmr(drawState); 80927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com GrMatrix m; 8108295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com m.setAll(rect.width(), 0, rect.fLeft, 811205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com 0, rect.height(), rect.fTop, 812205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com 0, 0, GrMatrix::I()[8]); 81327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 81427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com if (NULL != matrix) { 81527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com m.postConcat(*matrix); 81627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 8178f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com drawState->preConcatViewMatrix(m); 818e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com drawState->preConcatSamplerMatrices(m); 819fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 82047059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com target->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4); 8218f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com#else 822e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com target->drawSimpleRect(rect, matrix); 8238f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com#endif 82427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 82527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 82627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 82727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawRectToRect(const GrPaint& paint, 82827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com const GrRect& dstRect, 82927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com const GrRect& srcRect, 83027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com const GrMatrix* dstMatrix, 83127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com const GrMatrix* srcMatrix) { 832278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com SK_TRACE_EVENT0("GrContext::drawRectToRect"); 83327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 83426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com // srcRect refers to paint's first texture 835f13f58804659175925042a291304d483a4fd9278tomhudson@google.com if (!paint.isTextureStageEnabled(0)) { 83627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com drawRect(paint, dstRect, -1, dstMatrix); 83727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com return; 83827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 839de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com 84007ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com GrDrawTarget* target = this->prepareToDraw(&paint, DEFAULT_BUFFERING); 84127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 84227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#if GR_STATIC_RECT_VB 8437d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com GrDrawState::AutoStageDisable atr(fDrawState); 8448f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com GrDrawState* drawState = target->drawState(); 8458f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com GrDrawState::AutoViewMatrixRestore avmr(drawState); 84627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 84727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com GrMatrix m; 84827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 84927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com m.setAll(dstRect.width(), 0, dstRect.fLeft, 85027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 0, dstRect.height(), dstRect.fTop, 85127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 0, 0, GrMatrix::I()[8]); 85227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com if (NULL != dstMatrix) { 85327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com m.postConcat(*dstMatrix); 85427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 8558f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com drawState->preConcatViewMatrix(m); 85627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 857e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com // we explicitly setup the correct coords for the first stage. The others 858e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com // must know about the view matrix change. 859e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com for (int s = 1; s < GrPaint::kTotalStages; ++s) { 860e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com if (drawState->isStageEnabled(s)) { 861e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com drawState->sampler(s)->preConcatMatrix(m); 862e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com } 86326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com } 86426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com 86527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com m.setAll(srcRect.width(), 0, srcRect.fLeft, 86627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 0, srcRect.height(), srcRect.fTop, 86727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 0, 0, GrMatrix::I()[8]); 86827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com if (NULL != srcMatrix) { 86927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com m.postConcat(*srcMatrix); 87027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 8718f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com drawState->sampler(GrPaint::kFirstTextureStage)->preConcatMatrix(m); 87227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 8736513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer(); 8746513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com if (NULL == sqVB) { 8756513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com GrPrintf("Failed to create static rect vb.\n"); 8766513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com return; 8776513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com } 878e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com target->setVertexSourceToBuffer(0, sqVB); 87947059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com target->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4); 88027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#else 8817d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com GrDrawState::AutoStageDisable atr(fDrawState); 88227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 8839381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com const GrRect* srcRects[GrDrawState::kNumStages] = {NULL}; 8849381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com const GrMatrix* srcMatrices[GrDrawState::kNumStages] = {NULL}; 88527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com srcRects[0] = &srcRect; 88627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com srcMatrices[0] = srcMatrix; 88727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 888e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com target->drawRect(dstRect, dstMatrix, srcRects, srcMatrices); 88927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#endif 89027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 89127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 89227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawVertices(const GrPaint& paint, 89327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com GrPrimitiveType primitiveType, 89427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com int vertexCount, 89527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com const GrPoint positions[], 89627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com const GrPoint texCoords[], 89727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com const GrColor colors[], 89827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com const uint16_t indices[], 89927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com int indexCount) { 900278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com SK_TRACE_EVENT0("GrContext::drawVertices"); 90127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 90227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com GrDrawTarget::AutoReleaseGeometry geo; 90327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 90407ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com GrDrawTarget* target = this->prepareToDraw(&paint, DEFAULT_BUFFERING); 9057d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com GrDrawState::AutoStageDisable atr(fDrawState); 90627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 907e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com GrVertexLayout layout = 0; 908e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com if (NULL != texCoords) { 909e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com layout |= GrDrawTarget::StageTexCoordVertexLayoutBit(0, 0); 910e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com } 91127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com if (NULL != colors) { 91227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com layout |= GrDrawTarget::kColor_VertexLayoutBit; 91327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 91426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com int vertexSize = GrDrawTarget::VertexSize(layout); 91527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 91627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com if (sizeof(GrPoint) != vertexSize) { 91727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com if (!geo.set(target, layout, vertexCount, 0)) { 9186513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com GrPrintf("Failed to get space for vertices!\n"); 91927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com return; 92027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 9219381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com int texOffsets[GrDrawState::kMaxTexCoords]; 92227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com int colorOffset; 92326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com GrDrawTarget::VertexSizeAndOffsetsByIdx(layout, 92426c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com texOffsets, 925aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com &colorOffset, 926a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com NULL, 927a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com NULL); 92827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com void* curVertex = geo.vertices(); 92927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 93027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com for (int i = 0; i < vertexCount; ++i) { 93127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com *((GrPoint*)curVertex) = positions[i]; 93227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 93327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com if (texOffsets[0] > 0) { 93427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com *(GrPoint*)((intptr_t)curVertex + texOffsets[0]) = texCoords[i]; 93527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 93627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com if (colorOffset > 0) { 93727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com *(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i]; 93827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 93926c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com curVertex = (void*)((intptr_t)curVertex + vertexSize); 94027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 94127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } else { 94227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com target->setVertexSourceToArray(layout, positions, vertexCount); 94327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 94427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 945fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com // we don't currently apply offscreen AA to this path. Need improved 946919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com // management of GrDrawTarget's geometry to avoid copying points per-tile. 947a47a48dca5045d71cbc5de343404045209a13e15bsalomon@google.com 9488295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com if (NULL != indices) { 949919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com target->setIndexSourceToArray(indices, indexCount); 9508295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount); 95127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } else { 9528295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com target->drawNonIndexed(primitiveType, 0, vertexCount); 9538295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com } 95427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 95527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 95606afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com/////////////////////////////////////////////////////////////////////////////// 957150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.comnamespace { 958150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com 95993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.comstruct CircleVertex { 96093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com GrPoint fPos; 96193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com GrPoint fCenter; 96293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com GrScalar fOuterRadius; 96393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com GrScalar fInnerRadius; 96493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com}; 96593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com 96693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com/* Returns true if will map a circle to another circle. This can be true 96793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com * if the matrix only includes square-scale, rotation, translation. 96893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com */ 96993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.cominline bool isSimilarityTransformation(const SkMatrix& matrix, 97093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com SkScalar tol = SK_ScalarNearlyZero) { 97193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com if (matrix.isIdentity() || matrix.getType() == SkMatrix::kTranslate_Mask) { 97293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com return true; 97393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com } 97493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com if (matrix.hasPerspective()) { 97593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com return false; 97693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com } 97793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com 97893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com SkScalar mx = matrix.get(SkMatrix::kMScaleX); 97993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com SkScalar sx = matrix.get(SkMatrix::kMSkewX); 98093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com SkScalar my = matrix.get(SkMatrix::kMScaleY); 98193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com SkScalar sy = matrix.get(SkMatrix::kMSkewY); 98293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com 98393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com if (mx == 0 && sx == 0 && my == 0 && sy == 0) { 98493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com return false; 98593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com } 98693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com 98793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com // it has scales or skews, but it could also be rotation, check it out. 98893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com SkVector vec[2]; 98993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com vec[0].set(mx, sx); 99093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com vec[1].set(sy, my); 99193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com 99293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com return SkScalarNearlyZero(vec[0].dot(vec[1]), SkScalarSquare(tol)) && 99393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com SkScalarNearlyEqual(vec[0].lengthSqd(), vec[1].lengthSqd(), 99493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com SkScalarSquare(tol)); 99593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com} 99693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com 99793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com} 99893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com 99993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com// TODO: strokeWidth can't be larger than zero right now. 100093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com// It will be fixed when drawPath() can handle strokes. 100193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.comvoid GrContext::drawOval(const GrPaint& paint, 100293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com const GrRect& rect, 100393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com SkScalar strokeWidth) { 10040982d35187da7e1ed6c0eba5951bbdadca8b33e7bsalomon@google.com GrAssert(strokeWidth <= 0); 10050982d35187da7e1ed6c0eba5951bbdadca8b33e7bsalomon@google.com if (!isSimilarityTransformation(this->getMatrix()) || 100693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com !paint.fAntiAlias || 100793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com rect.height() != rect.width()) { 100893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com SkPath path; 100993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com path.addOval(rect); 101093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com GrPathFill fill = (strokeWidth == 0) ? 10110982d35187da7e1ed6c0eba5951bbdadca8b33e7bsalomon@google.com kHairLine_GrPathFill : kWinding_GrPathFill; 101293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com this->internalDrawPath(paint, path, fill, NULL); 101393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com return; 101493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com } 101593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com 101607ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com GrDrawTarget* target = this->prepareToDraw(&paint, DEFAULT_BUFFERING); 101707ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com 10180982d35187da7e1ed6c0eba5951bbdadca8b33e7bsalomon@google.com GrDrawState* drawState = target->drawState(); 10190982d35187da7e1ed6c0eba5951bbdadca8b33e7bsalomon@google.com GrDrawState::AutoStageDisable atr(fDrawState); 10200982d35187da7e1ed6c0eba5951bbdadca8b33e7bsalomon@google.com const GrMatrix vm = drawState->getViewMatrix(); 10210982d35187da7e1ed6c0eba5951bbdadca8b33e7bsalomon@google.com 102293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com const GrRenderTarget* rt = drawState->getRenderTarget(); 102393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com if (NULL == rt) { 102493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com return; 102593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com } 102693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com 1027e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com GrDrawTarget::AutoDeviceCoordDraw adcd(target); 1028e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com if (!adcd.succeeded()) { 1029e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com return; 1030e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com } 103193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com 1032e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com GrVertexLayout layout = GrDrawTarget::kEdge_VertexLayoutBit; 103393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com GrAssert(sizeof(CircleVertex) == GrDrawTarget::VertexSize(layout)); 103493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com 103593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com GrPoint center = GrPoint::Make(rect.centerX(), rect.centerY()); 103693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com GrScalar radius = SkScalarHalf(rect.width()); 103793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com 103893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com vm.mapPoints(¢er, 1); 103993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com radius = vm.mapRadius(radius); 104093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com 104193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com GrScalar outerRadius = radius; 104293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com GrScalar innerRadius = 0; 104393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com SkScalar halfWidth = 0; 104493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com if (strokeWidth == 0) { 104593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com halfWidth = SkScalarHalf(SK_Scalar1); 104693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com 104793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com outerRadius += halfWidth; 104893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com innerRadius = SkMaxScalar(0, radius - halfWidth); 104993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com } 105093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com 105193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com GrDrawTarget::AutoReleaseGeometry geo(target, layout, 4, 0); 105293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com if (!geo.succeeded()) { 105393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com GrPrintf("Failed to get space for vertices!\n"); 105493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com return; 105593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com } 105693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com 105793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices()); 105893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com 1059a0a66c118392fdc6f84f18ac634473468e31becbrobertphillips@google.com // The fragment shader will extend the radius out half a pixel 1060a0a66c118392fdc6f84f18ac634473468e31becbrobertphillips@google.com // to antialias. Expand the drawn rect here so all the pixels 1061a0a66c118392fdc6f84f18ac634473468e31becbrobertphillips@google.com // will be captured. 1062a0a66c118392fdc6f84f18ac634473468e31becbrobertphillips@google.com SkScalar L = center.fX - outerRadius - SkFloatToScalar(0.5f); 1063a0a66c118392fdc6f84f18ac634473468e31becbrobertphillips@google.com SkScalar R = center.fX + outerRadius + SkFloatToScalar(0.5f); 1064a0a66c118392fdc6f84f18ac634473468e31becbrobertphillips@google.com SkScalar T = center.fY - outerRadius - SkFloatToScalar(0.5f); 1065a0a66c118392fdc6f84f18ac634473468e31becbrobertphillips@google.com SkScalar B = center.fY + outerRadius + SkFloatToScalar(0.5f); 106693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com 106793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com verts[0].fPos = SkPoint::Make(L, T); 106893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com verts[1].fPos = SkPoint::Make(R, T); 106993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com verts[2].fPos = SkPoint::Make(L, B); 107093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com verts[3].fPos = SkPoint::Make(R, B); 107193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com 107293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com for (int i = 0; i < 4; ++i) { 107393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com // this goes to fragment shader, it should be in y-points-up space. 107493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com verts[i].fCenter = SkPoint::Make(center.fX, rt->height() - center.fY); 107593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com 107693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com verts[i].fOuterRadius = outerRadius; 107793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com verts[i].fInnerRadius = innerRadius; 107893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com } 107993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com 108093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com drawState->setVertexEdgeType(GrDrawState::kCircle_EdgeType); 108147059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4); 1082150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com} 108327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 10848d033a1b125886c62906d975b5cc28a382064526bsalomon@google.comvoid GrContext::drawPath(const GrPaint& paint, const SkPath& path, 108507f3ee10d34f09342abb93d758b5e151ff78f7a5reed@google.com GrPathFill fill, const GrPoint* translate) { 108627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 1087fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com if (path.isEmpty()) { 1088fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com if (GrIsFillInverted(fill)) { 1089fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com this->drawPaint(paint); 1090fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com } 1091fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com return; 1092fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com } 1093fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com 109493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com SkRect ovalRect; 109593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com if (!GrIsFillInverted(fill) && path.isOval(&ovalRect)) { 109693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com if (translate) { 109793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com ovalRect.offset(*translate); 109893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com } 109947059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com SkScalar width = (fill == kHairLine_GrPathFill) ? 0 : -SK_Scalar1; 110093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com this->drawOval(paint, ovalRect, width); 110193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com return; 110293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com } 110393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com 110493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com internalDrawPath(paint, path, fill, translate); 110593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com} 110693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com 11078d033a1b125886c62906d975b5cc28a382064526bsalomon@google.comvoid GrContext::internalDrawPath(const GrPaint& paint, const SkPath& path, 110893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com GrPathFill fill, const GrPoint* translate) { 110993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com 1110fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com // Note that below we may sw-rasterize the path into a scratch texture. 1111fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com // Scratch textures can be recycled after they are returned to the texture 1112fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com // cache. This presents a potential hazard for buffered drawing. However, 1113fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com // the writePixels that uploads to the scratch will perform a flush so we're 1114fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com // OK. 111507ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com GrDrawTarget* target = this->prepareToDraw(&paint, DEFAULT_BUFFERING); 11167d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com GrDrawState::AutoStageDisable atr(fDrawState); 1117d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com 1118289533ada623f2238a83771eec977f204f75994fbsalomon@google.com bool prAA = paint.fAntiAlias && !this->getRenderTarget()->isMultisampled(); 1119289533ada623f2238a83771eec977f204f75994fbsalomon@google.com 1120d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com // An Assumption here is that path renderer would use some form of tweaking 1121d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com // the src color (either the input alpha or in the frag shader) to implement 1122d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com // aa. If we have some future driver-mojo path AA that can do the right 1123d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com // thing WRT to the blend then we'll need some query on the PR. 1124d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com if (disable_coverage_aa_for_blend(target)) { 11251983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#if GR_DEBUG 1126979432ba2621b617f5e85a9ff48c6b6cd1504a0dbsalomon@google.com //GrPrintf("Turning off AA to correctly apply blend.\n"); 11271983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#endif 1128289533ada623f2238a83771eec977f204f75994fbsalomon@google.com prAA = false; 1129d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com } 1130289533ada623f2238a83771eec977f204f75994fbsalomon@google.com 113172176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com GrPathRenderer* pr = this->getPathRenderer(path, fill, target, prAA, true); 11323008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com if (NULL == pr) { 11331983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#if GR_DEBUG 11343008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com GrPrintf("Unable to find path renderer compatible with path.\n"); 11351983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#endif 11363008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com return; 11373008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com } 11383008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com 1139e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com pr->drawPath(path, fill, translate, target, prAA); 114027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 11418295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com 114227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 114327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 1144a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.comvoid GrContext::flush(int flagsBitfield) { 1145a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com if (kDiscard_FlushBit & flagsBitfield) { 1146a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com fDrawBuffer->reset(); 1147a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com } else { 1148c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com this->flushDrawBuffer(); 1149a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com } 1150a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com if (kForceCurrentRenderTarget_FlushBit & flagsBitfield) { 115127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com fGpu->forceRenderTargetFlush(); 115227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 115327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 115427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 115527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::flushDrawBuffer() { 115653a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com if (fDrawBuffer) { 115758b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com // With addition of the AA clip path, flushing the draw buffer can 115858b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com // result in the generation of an AA clip mask. During this 115958b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com // process the SW path renderer may be invoked which recusively 116058b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com // calls this method (via internalWriteTexturePixels) creating 116158b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com // infinite recursion 116258b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com GrInOrderDrawBuffer* temp = fDrawBuffer; 116358b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com fDrawBuffer = NULL; 116458b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com 116558b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com temp->flushTo(fGpu); 116658b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com 116758b381841cb8d234d09c85af43720cbff00e6212robertphillips@google.com fDrawBuffer = temp; 116853a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com } 116927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 117027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 11710342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.comvoid GrContext::writeTexturePixels(GrTexture* texture, 11720342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com int left, int top, int width, int height, 11730342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com GrPixelConfig config, const void* buffer, size_t rowBytes, 11740342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com uint32_t flags) { 11756f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com SK_TRACE_EVENT0("GrContext::writeTexturePixels"); 1176bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com ASSERT_OWNED_RESOURCE(texture); 1177bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com 11786f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com // TODO: use scratch texture to perform conversion 11790342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com if (kUnpremul_PixelOpsFlag & flags) { 11806f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com return; 11816f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com } 11820342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com if (!(kDontFlush_PixelOpsFlag & flags)) { 11830342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com this->flush(); 11840342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com } 11856f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com 1186fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com fGpu->writeTexturePixels(texture, left, top, width, height, 11876f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com config, buffer, rowBytes); 11886f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com} 11896f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com 11900342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.combool GrContext::readTexturePixels(GrTexture* texture, 11910342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com int left, int top, int width, int height, 11920342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com GrPixelConfig config, void* buffer, size_t rowBytes, 11930342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com uint32_t flags) { 1194278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com SK_TRACE_EVENT0("GrContext::readTexturePixels"); 1195bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com ASSERT_OWNED_RESOURCE(texture); 1196669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com 1197a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com // TODO: code read pixels for textures that aren't also rendertargets 1198669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com GrRenderTarget* target = texture->asRenderTarget(); 1199669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com if (NULL != target) { 12000342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com return this->readRenderTargetPixels(target, 12010342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com left, top, width, height, 12020342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com config, buffer, rowBytes, 12030342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com flags); 1204669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com } else { 1205669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com return false; 1206669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com } 1207669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com} 1208669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com 1209a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com#include "SkConfig8888.h" 1210a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com 1211a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.comnamespace { 1212a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com/** 1213a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com * Converts a GrPixelConfig to a SkCanvas::Config8888. Only byte-per-channel 1214a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com * formats are representable as Config8888 and so the function returns false 1215a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com * if the GrPixelConfig has no equivalent Config8888. 1216a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com */ 1217a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.combool grconfig_to_config8888(GrPixelConfig config, 12180342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com bool unpremul, 1219a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com SkCanvas::Config8888* config8888) { 1220a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com switch (config) { 12210342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com case kRGBA_8888_GrPixelConfig: 12220342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com if (unpremul) { 12230342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com *config8888 = SkCanvas::kRGBA_Unpremul_Config8888; 12240342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com } else { 12250342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com *config8888 = SkCanvas::kRGBA_Premul_Config8888; 12260342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com } 1227a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com return true; 12280342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com case kBGRA_8888_GrPixelConfig: 12290342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com if (unpremul) { 12300342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com *config8888 = SkCanvas::kBGRA_Unpremul_Config8888; 12310342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com } else { 12320342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com *config8888 = SkCanvas::kBGRA_Premul_Config8888; 12330342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com } 1234a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com return true; 1235a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com default: 1236a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com return false; 1237a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com } 1238a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com} 1239a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com 1240a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com// It returns a configuration with where the byte position of the R & B components are swapped in 1241a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com// relation to the input config. This should only be called with the result of 1242a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com// grconfig_to_config8888 as it will fail for other configs. 1243a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.comSkCanvas::Config8888 swap_config8888_red_and_blue(SkCanvas::Config8888 config8888) { 1244a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com switch (config8888) { 1245a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com case SkCanvas::kBGRA_Premul_Config8888: 1246a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com return SkCanvas::kRGBA_Premul_Config8888; 1247a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com case SkCanvas::kBGRA_Unpremul_Config8888: 1248a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com return SkCanvas::kRGBA_Unpremul_Config8888; 1249a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com case SkCanvas::kRGBA_Premul_Config8888: 1250a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com return SkCanvas::kBGRA_Premul_Config8888; 1251a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com case SkCanvas::kRGBA_Unpremul_Config8888: 1252a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com return SkCanvas::kBGRA_Unpremul_Config8888; 1253a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com default: 1254a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com GrCrash("Unexpected input"); 1255a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com return SkCanvas::kBGRA_Unpremul_Config8888;; 1256a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com } 1257a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com} 1258a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com} 1259a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com 12600342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.combool GrContext::readRenderTargetPixels(GrRenderTarget* target, 12610342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com int left, int top, int width, int height, 12620342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com GrPixelConfig config, void* buffer, size_t rowBytes, 12630342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com uint32_t flags) { 1264278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com SK_TRACE_EVENT0("GrContext::readRenderTargetPixels"); 1265bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com ASSERT_OWNED_RESOURCE(target); 1266bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com 1267fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com if (NULL == target) { 126810e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com target = fDrawState->getRenderTarget(); 1269c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com if (NULL == target) { 1270c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com return false; 1271c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com } 1272c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com } 1273669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com 12746f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com if (!(kDontFlush_PixelOpsFlag & flags)) { 12756f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com this->flush(); 12766f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com } 1277c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com 1278a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // Determine which conversions have to be applied: flipY, swapRAnd, and/or unpremul. 1279c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com 1280a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // If fGpu->readPixels would incur a y-flip cost then we will read the pixels upside down. We'll 1281a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // either do the flipY by drawing into a scratch with a matrix or on the cpu after the read. 1282a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com bool flipY = fGpu->readPixelsWillPayForYFlip(target, left, top, 1283c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com width, height, config, 1284c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com rowBytes); 1285a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com bool swapRAndB = fGpu->preferredReadPixelsConfig(config) == GrPixelConfigSwapRAndB(config); 1286a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com 12870342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags); 1288c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com 1289a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // flipY will get set to false when it is handled below using a scratch. However, in that case 1290a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // we still want to do the read upside down. 1291a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com bool readUpsideDown = flipY; 1292a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com 1293a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com if (unpremul && kRGBA_8888_GrPixelConfig != config && kBGRA_8888_GrPixelConfig != config) { 1294a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // The unpremul flag is only allowed for these two configs. 12950a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com return false; 12960a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com } 1297a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com 1298a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com GrPixelConfig readConfig; 1299a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com if (swapRAndB) { 1300a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com readConfig = GrPixelConfigSwapRAndB(config); 1301a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com GrAssert(kUnknown_GrPixelConfig != config); 1302a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com } else { 1303a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com readConfig = config; 1304a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com } 1305a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com 1306a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // If the src is a texture and we would have to do conversions after read pixels, we instead 1307a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // do the conversions by drawing the src to a scratch texture. If we handle any of the 1308a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // conversions in the draw we set the corresponding bool to false so that we don't reapply it 1309a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // on the read back pixels. 1310a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com GrTexture* src = target->asTexture(); 1311c4ff22a2965616629765b8ffe0e58f6d05f92fa3bsalomon@google.com GrAutoScratchTexture ast; 1312a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com if (NULL != src && (swapRAndB || unpremul || flipY)) { 1313a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // Make the scratch a render target because we don't have a robust readTexturePixels as of 1314a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // yet. It calls this function. 131575b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com GrTextureDesc desc; 131675b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com desc.fFlags = kRenderTarget_GrTextureFlagBit; 131775b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com desc.fWidth = width; 131875b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com desc.fHeight = height; 1319a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com desc.fConfig = readConfig; 1320c4ff22a2965616629765b8ffe0e58f6d05f92fa3bsalomon@google.com 1321a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // When a full readback is faster than a partial we could always make the scratch exactly 1322a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // match the passed rect. However, if we see many different size rectangles we will trash 1323a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // our texture cache and pay the cost of creating and destroying many textures. So, we only 1324a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // request an exact match when the caller is reading an entire RT. 132556d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com ScratchTexMatch match = kApprox_ScratchTexMatch; 132656d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com if (0 == left && 132756d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com 0 == top && 132856d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com target->width() == width && 132956d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com target->height() == height && 133056d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com fGpu->fullReadPixelsIsFasterThanPartial()) { 133156d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com match = kExact_ScratchTexMatch; 133256d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com } 133356d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com ast.set(this, desc, match); 1334c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com GrTexture* texture = ast.texture(); 1335a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com if (texture) { 1336a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com SkAutoTUnref<GrCustomStage> stage; 1337a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com if (unpremul) { 1338a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com stage.reset(this->createPMToUPMEffect(src, swapRAndB)); 1339a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com } 1340a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // If we failed to create a PM->UPM effect and have no other conversions to perform then 1341a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // there is no longer any point to using the scratch. 1342a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com if (NULL != stage || flipY || swapRAndB) { 1343a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com if (NULL == stage) { 1344a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com stage.reset(GrConfigConversionEffect::Create(src, swapRAndB)); 1345a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com GrAssert(NULL != stage); 1346a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com } else { 1347a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com unpremul = false; // we will handle the UPM conversion in the draw 1348a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com } 1349a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com swapRAndB = false; // we will handle the swap in the draw. 1350a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com 1351a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit); 1352a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com GrDrawState* drawState = fGpu->drawState(); 1353a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com drawState->setRenderTarget(texture->asRenderTarget()); 1354a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com GrMatrix matrix; 1355a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com if (flipY) { 1356a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com matrix.setTranslate(SK_Scalar1 * left, 1357a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com SK_Scalar1 * (top + height)); 1358a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com matrix.set(GrMatrix::kMScaleY, -GR_Scalar1); 1359a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com flipY = false; // the y flip will be handled in the draw 1360a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com } else { 1361a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com matrix.setTranslate(SK_Scalar1 *left, SK_Scalar1 *top); 1362a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com } 1363a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com matrix.postIDiv(src->width(), src->height()); 1364a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com drawState->sampler(0)->reset(matrix); 1365a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com drawState->sampler(0)->setCustomStage(stage); 1366a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com GrRect rect = GrRect::MakeWH(GrIntToScalar(width), GrIntToScalar(height)); 1367a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com fGpu->drawSimpleRect(rect, NULL); 1368a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // we want to read back from the scratch's origin 1369a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com left = 0; 1370a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com top = 0; 1371a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com target = texture->asRenderTarget(); 1372a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com } 1373c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com } 1374a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com } 1375a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com if (!fGpu->readPixels(target, 1376a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com left, top, width, height, 1377a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com readConfig, buffer, rowBytes, readUpsideDown)) { 1378a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com return false; 1379a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com } 1380a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // Perform any conversions we weren't able to perfom using a scratch texture. 1381a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com if (unpremul || swapRAndB || flipY) { 1382a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com SkCanvas::Config8888 srcC8888; 1383a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com SkCanvas::Config8888 dstC8888; 1384a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com bool c8888IsValid = grconfig_to_config8888(config, false, &srcC8888); 1385a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com grconfig_to_config8888(config, unpremul, &dstC8888); 1386a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com if (swapRAndB) { 1387a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com GrAssert(c8888IsValid); // we should only do r/b swap on 8888 configs 1388a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com srcC8888 = swap_config8888_red_and_blue(srcC8888); 13890342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com } 1390c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com if (flipY) { 1391a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com size_t tightRB = width * GrBytesPerPixel(config); 1392a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com if (0 == rowBytes) { 1393a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com rowBytes = tightRB; 1394a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com } 1395a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com SkAutoSTMalloc<256, uint8_t> tempRow(tightRB); 1396a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com intptr_t top = reinterpret_cast<intptr_t>(buffer); 1397a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com intptr_t bot = top + (height - 1) * rowBytes; 1398a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com while (top < bot) { 1399a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com uint32_t* t = reinterpret_cast<uint32_t*>(top); 1400a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com uint32_t* b = reinterpret_cast<uint32_t*>(bot); 1401a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com uint32_t* temp = reinterpret_cast<uint32_t*>(tempRow.get()); 1402a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com memcpy(temp, t, tightRB); 1403a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com if (c8888IsValid) { 1404a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com SkConvertConfig8888Pixels(t, tightRB, dstC8888, 1405a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com b, tightRB, srcC8888, 1406a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com width, 1); 1407a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com SkConvertConfig8888Pixels(b, tightRB, dstC8888, 1408a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com temp, tightRB, srcC8888, 1409a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com width, 1); 1410a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com } else { 1411a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com memcpy(t, b, tightRB); 1412a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com memcpy(b, temp, tightRB); 1413a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com } 1414a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com top += rowBytes; 1415a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com bot -= rowBytes; 1416a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com } 1417a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // The above loop does nothing on the middle row when height is odd. 1418a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com if (top == bot && c8888IsValid && dstC8888 != srcC8888) { 1419a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com uint32_t* mid = reinterpret_cast<uint32_t*>(top); 1420a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com SkConvertConfig8888Pixels(mid, tightRB, dstC8888, mid, tightRB, srcC8888, width, 1); 1421a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com } 1422c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com } else { 1423a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // if we aren't flipping Y then we have no reason to be here other than doing 1424a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // conversions for 8888 (r/b swap or upm). 1425a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com GrAssert(c8888IsValid); 1426a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com uint32_t* b32 = reinterpret_cast<uint32_t*>(buffer); 1427a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com SkConvertConfig8888Pixels(b32, rowBytes, dstC8888, 1428a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com b32, rowBytes, srcC8888, 1429a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com width, height); 1430c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com } 1431c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com } 1432a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com return true; 143327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 143427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 143575f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.comvoid GrContext::resolveRenderTarget(GrRenderTarget* target) { 143675f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com GrAssert(target); 143775f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com ASSERT_OWNED_RESOURCE(target); 143875f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com // In the future we may track whether there are any pending draws to this 143975f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com // target. We don't today so we always perform a flush. We don't promise 144075f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com // this to our clients, though. 144175f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com this->flush(); 144275f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com fGpu->resolveRenderTarget(target); 144375f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com} 144475f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com 1445ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.orgvoid GrContext::copyTexture(GrTexture* src, GrRenderTarget* dst) { 1446ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org if (NULL == src || NULL == dst) { 1447ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org return; 1448ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org } 1449ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org ASSERT_OWNED_RESOURCE(src); 1450ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org 14511ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com // Writes pending to the source texture are not tracked, so a flush 14521ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com // is required to ensure that the copy captures the most recent contents 14531ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com // of the source texture. See similar behaviour in 14541ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com // GrContext::resolveRenderTarget. 14551ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com this->flush(); 14561ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com 1457873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit); 14588f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com GrDrawState* drawState = fGpu->drawState(); 14598f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com drawState->setRenderTarget(dst); 1460ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org GrMatrix sampleM; 1461ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org sampleM.setIDiv(src->width(), src->height()); 14621e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com drawState->sampler(0)->reset(sampleM); 14631e8f016305805d4d8cad74aba3a21b78486f9d6ftomhudson@google.com drawState->createTextureEffect(0, src); 14645db3b6cce4e9e02415a0a31d95666c044c953ac2bsalomon@google.com SkRect rect = SkRect::MakeXYWH(0, 0, 14655db3b6cce4e9e02415a0a31d95666c044c953ac2bsalomon@google.com SK_Scalar1 * src->width(), 14665db3b6cce4e9e02415a0a31d95666c044c953ac2bsalomon@google.com SK_Scalar1 * src->height()); 1467e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com fGpu->drawSimpleRect(rect, NULL); 1468ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org} 1469ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org 1470fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.comvoid GrContext::writeRenderTargetPixels(GrRenderTarget* target, 14710342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com int left, int top, int width, int height, 14720342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com GrPixelConfig config, 14730342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com const void* buffer, 14740342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com size_t rowBytes, 14750342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com uint32_t flags) { 14766f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com SK_TRACE_EVENT0("GrContext::writeRenderTargetPixels"); 1477bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com ASSERT_OWNED_RESOURCE(target); 14786f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com 1479fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com if (NULL == target) { 1480873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com target = fDrawState->getRenderTarget(); 14816f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com if (NULL == target) { 14826f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com return; 14836f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com } 14846f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com } 148527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 1486a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // TODO: when underlying api has a direct way to do this we should use it (e.g. glDrawPixels on 1487a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // desktop GL). 1488a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com 1489a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // We will always call some form of writeTexturePixels and we will pass our flags on to it. 1490a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // Thus, we don't perform a flush here since that call will do it (if the kNoFlush flag isn't 1491a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // set.) 149227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 14930342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com // If the RT is also a texture and we don't have to premultiply then take the texture path. 14940342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com // We expect to be at least as fast or faster since it doesn't use an intermediate texture as 14950342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com // we do below. 1496fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1497a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com#if !GR_MAC_BUILD 1498a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // At least some drivers on the Mac get confused when glTexImage2D is called on a texture 1499a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // attached to an FBO. The FBO still sees the old image. TODO: determine what OS versions and/or 1500a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // HW is affected. 15010342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com if (NULL != target->asTexture() && !(kUnpremul_PixelOpsFlag & flags)) { 15020342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com this->writeTexturePixels(target->asTexture(), 15030342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com left, top, width, height, 15040342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com config, buffer, rowBytes, flags); 1505a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com return; 1506a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com } 1507a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com#endif 1508a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com SkAutoTUnref<GrCustomStage> stage; 1509a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com bool swapRAndB = (fGpu->preferredReadPixelsConfig(config) == GrPixelConfigSwapRAndB(config)); 1510a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com 1511a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com GrPixelConfig textureConfig; 1512a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com if (swapRAndB) { 1513a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com textureConfig = GrPixelConfigSwapRAndB(config); 1514a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com } else { 1515a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com textureConfig = config; 1516a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com } 1517a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com 151875b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com GrTextureDesc desc; 151975b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com desc.fWidth = width; 152075b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com desc.fHeight = height; 1521a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com desc.fConfig = textureConfig; 152250398bf7f1953e640e5529616e710cf540799731bsalomon@google.com GrAutoScratchTexture ast(this, desc); 152350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com GrTexture* texture = ast.texture(); 152427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com if (NULL == texture) { 152527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com return; 152627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 1527a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com // allocate a tmp buffer and sw convert the pixels to premul 1528a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0); 1529a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com 1530a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com if (kUnpremul_PixelOpsFlag & flags) { 1531a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com if (kRGBA_8888_GrPixelConfig != config && kBGRA_8888_GrPixelConfig != config) { 1532a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com return; 1533a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com } 1534a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com stage.reset(this->createUPMToPMEffect(texture, swapRAndB)); 1535a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com if (NULL == stage) { 1536a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com SkCanvas::Config8888 srcConfig8888, dstConfig8888; 1537a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com GR_DEBUGCODE(bool success = ) 1538a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com grconfig_to_config8888(config, true, &srcConfig8888); 1539a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com GrAssert(success); 1540a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com GR_DEBUGCODE(success = ) 1541a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com grconfig_to_config8888(config, false, &dstConfig8888); 1542a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com GrAssert(success); 1543a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com const uint32_t* src = reinterpret_cast<const uint32_t*>(buffer); 1544a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com tmpPixels.reset(width * height); 1545a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com SkConvertConfig8888Pixels(tmpPixels.get(), 4 * width, dstConfig8888, 1546a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com src, rowBytes, srcConfig8888, 1547a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com width, height); 1548a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com buffer = tmpPixels.get(); 1549a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com rowBytes = 4 * width; 1550a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com } 1551a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com } 1552a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com if (NULL == stage) { 1553a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com stage.reset(GrConfigConversionEffect::Create(texture, swapRAndB)); 1554a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com GrAssert(NULL != stage); 1555a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com } 1556a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com 1557a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com this->writeTexturePixels(texture, 1558a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com 0, 0, width, height, 1559a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com textureConfig, buffer, rowBytes, 1560a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com flags & ~kUnpremul_PixelOpsFlag); 156127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 1562873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit); 15638f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com GrDrawState* drawState = fGpu->drawState(); 156427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 156527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com GrMatrix matrix; 156627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com matrix.setTranslate(GrIntToScalar(left), GrIntToScalar(top)); 15678f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com drawState->setViewMatrix(matrix); 15688f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com drawState->setRenderTarget(target); 156927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 15705c63865b529eb5714e41419dfa23c70d26ff6e4ebsalomon@google.com matrix.setIDiv(texture->width(), texture->height()); 1571b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com drawState->sampler(0)->reset(matrix); 1572a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com drawState->sampler(0)->setCustomStage(stage); 1573a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com 1574a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com fGpu->drawSimpleRect(GrRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)), NULL); 157527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 157627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 157727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 157810e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.comvoid GrContext::setPaint(const GrPaint& paint) { 1579cb325ceda16fab97fd3281785e6ae10fcb8dcf83tomhudson@google.com GrAssert(fDrawState->stagesDisabled()); 158026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com 158126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com for (int i = 0; i < GrPaint::kMaxTextures; ++i) { 158226c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com int s = i + GrPaint::kFirstTextureStage; 1583f13f58804659175925042a291304d483a4fd9278tomhudson@google.com if (paint.isTextureStageEnabled(i)) { 158410e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com *fDrawState->sampler(s) = paint.getTextureSampler(i); 1585f864ec467dfd518e32f6e4d709fafe57f1b3dbc6bsalomon@google.com } 158626c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com } 158726c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com 158810e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com fDrawState->setFirstCoverageStage(GrPaint::kFirstMaskStage); 158926c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com 159026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com for (int i = 0; i < GrPaint::kMaxMasks; ++i) { 159126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com int s = i + GrPaint::kFirstMaskStage; 1592f13f58804659175925042a291304d483a4fd9278tomhudson@google.com if (paint.isMaskStageEnabled(i)) { 159310e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com *fDrawState->sampler(s) = paint.getMaskSampler(i); 1594f864ec467dfd518e32f6e4d709fafe57f1b3dbc6bsalomon@google.com } 159526c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com } 1596fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 159726936d071f9e426e11db9a8cf67f5ce86e83feb1bsalomon@google.com // disable all stages not accessible via the paint 159826936d071f9e426e11db9a8cf67f5ce86e83feb1bsalomon@google.com for (int s = GrPaint::kTotalStages; s < GrDrawState::kNumStages; ++s) { 1599676e66096c60615bac52f365111596de5c4ca8a6tomhudson@google.com fDrawState->disableStage(s); 160026936d071f9e426e11db9a8cf67f5ce86e83feb1bsalomon@google.com } 160126c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com 160210e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com fDrawState->setColor(paint.fColor); 160327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 160427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com if (paint.fDither) { 160510e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com fDrawState->enableState(GrDrawState::kDither_StateBit); 160627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } else { 160710e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com fDrawState->disableState(GrDrawState::kDither_StateBit); 160827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 160927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com if (paint.fAntiAlias) { 161010e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com fDrawState->enableState(GrDrawState::kHWAntialias_StateBit); 161127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } else { 161210e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com fDrawState->disableState(GrDrawState::kHWAntialias_StateBit); 161327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 161450bdad85db2fe6be4d0bf0c5b6473f712b1bdd32senorblanco@chromium.org if (paint.fColorMatrixEnabled) { 161510e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com fDrawState->enableState(GrDrawState::kColorMatrix_StateBit); 161610e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com fDrawState->setColorMatrix(paint.fColorMatrix); 161750bdad85db2fe6be4d0bf0c5b6473f712b1bdd32senorblanco@chromium.org } else { 161810e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com fDrawState->disableState(GrDrawState::kColorMatrix_StateBit); 161950bdad85db2fe6be4d0bf0c5b6473f712b1bdd32senorblanco@chromium.org } 162010e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com fDrawState->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff); 162110e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com fDrawState->setColorFilter(paint.fColorFilterColor, paint.fColorFilterXfermode); 162210e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com fDrawState->setCoverage(paint.fCoverage); 16234b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com#if GR_DEBUG_PARTIAL_COVERAGE_CHECK 1624e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com if ((paint.hasMask() || 0xff != paint.fCoverage) && 162510e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com !fGpu->canApplyCoverage()) { 1626d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com GrPrintf("Partial pixel coverage will be incorrectly blended.\n"); 1627d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com } 162895cd7bdf2b4dee54739f0a375fe99a02f86178b0bsalomon@google.com#endif 162927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 163027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 163107ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.comGrDrawTarget* GrContext::prepareToDraw(const GrPaint* paint, BufferedDraw buffered) { 16321d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com if (kNo_BufferedDraw == buffered && kYes_BufferedDraw == fLastDrawWasBuffered) { 1633fb4ce6fe9f3f09bf9828aa50b36287f7d22bb78bbsalomon@google.com this->flushDrawBuffer(); 16341d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com fLastDrawWasBuffered = kNo_BufferedDraw; 163527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 163607ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com if (NULL != paint) { 163707ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com this->setPaint(*paint); 163807ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com } 16391d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com if (kYes_BufferedDraw == buffered) { 16401d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com fDrawBuffer->setClip(fGpu->getClip()); 16411d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com fLastDrawWasBuffered = kYes_BufferedDraw; 16421d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com return fDrawBuffer; 16431d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com } else { 16441d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com GrAssert(kNo_BufferedDraw == buffered); 16451d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com return fGpu; 164627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 164727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 164827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 164972176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com/* 165072176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com * This method finds a path renderer that can draw the specified path on 165172176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com * the provided target. 1652fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * Due to its expense, the software path renderer has split out so it can 165372176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com * can be individually allowed/disallowed via the "allowSW" boolean. 165472176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com */ 16558d033a1b125886c62906d975b5cc28a382064526bsalomon@google.comGrPathRenderer* GrContext::getPathRenderer(const SkPath& path, 1656289533ada623f2238a83771eec977f204f75994fbsalomon@google.com GrPathFill fill, 1657c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com const GrDrawTarget* target, 165872176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com bool antiAlias, 165972176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com bool allowSW) { 16603008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com if (NULL == fPathRendererChain) { 1661fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com fPathRendererChain = 1662c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com SkNEW_ARGS(GrPathRendererChain, 1663c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com (this, GrPathRendererChain::kNone_UsageFlag)); 16643008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com } 166572176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com 166672176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com GrPathRenderer* pr = fPathRendererChain->getPathRenderer(path, fill, 166772176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com target, 166872176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com antiAlias); 166972176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com 167072176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com if (NULL == pr && allowSW) { 167172176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com if (NULL == fSoftwarePathRenderer) { 1672c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com fSoftwarePathRenderer = SkNEW_ARGS(GrSoftwarePathRenderer, (this)); 167372176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com } 167472176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com 167572176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com pr = fSoftwarePathRenderer; 167672176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com } 167772176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com 167872176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com return pr; 16793008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com} 16803008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com 168127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 168227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 168327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::setRenderTarget(GrRenderTarget* target) { 1684bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com ASSERT_OWNED_RESOURCE(target); 168507ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com fDrawState->setRenderTarget(target); 168627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 168727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 168827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comGrRenderTarget* GrContext::getRenderTarget() { 168910e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com return fDrawState->getRenderTarget(); 169027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 169127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 169227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comconst GrRenderTarget* GrContext::getRenderTarget() const { 169310e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com return fDrawState->getRenderTarget(); 169427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 169527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 169699a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.combool GrContext::isConfigRenderable(GrPixelConfig config) const { 169799a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com return fGpu->isConfigRenderable(config); 169899a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com} 169999a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com 170027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comconst GrMatrix& GrContext::getMatrix() const { 170110e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com return fDrawState->getViewMatrix(); 170227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 170327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 170427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::setMatrix(const GrMatrix& m) { 170510e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com fDrawState->setViewMatrix(m); 170627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 170727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 170827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::concatMatrix(const GrMatrix& m) const { 170910e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com fDrawState->preConcatViewMatrix(m); 171027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 171127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 171227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic inline intptr_t setOrClear(intptr_t bits, int shift, intptr_t pred) { 171327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com intptr_t mask = 1 << shift; 171427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com if (pred) { 171527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com bits |= mask; 171627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } else { 171727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com bits &= ~mask; 171827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com } 171927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com return bits; 172027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 172127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 1722583a1e38503ebd57ba9bd39a3fabe89bead8e76cbsalomon@google.comGrContext::GrContext(GrGpu* gpu) { 1723c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com ++THREAD_INSTANCE_COUNT; 1724c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com 172527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com fGpu = gpu; 172627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com fGpu->ref(); 1727669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com fGpu->setContext(this); 17288fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com 1729c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com fDrawState = SkNEW(GrDrawState); 173010e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com fGpu->setDrawState(fDrawState); 173110e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com 17323008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com fPathRendererChain = NULL; 173372176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com fSoftwarePathRenderer = NULL; 1734dfe75bcf98b0c04535efbf7fe36492a7fb53c90dbsalomon@google.com 1735c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com fTextureCache = SkNEW_ARGS(GrResourceCache, 1736c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com (MAX_TEXTURE_CACHE_COUNT, 1737c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com MAX_TEXTURE_CACHE_BYTES)); 1738c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com fFontCache = SkNEW_ARGS(GrFontCache, (fGpu)); 173927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 17401d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com fLastDrawWasBuffered = kNo_BufferedDraw; 174127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 17428fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com fDrawBuffer = NULL; 17438fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com fDrawBufferVBAllocPool = NULL; 17448fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com fDrawBufferIBAllocPool = NULL; 17458fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com 1746c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com fAARectRenderer = SkNEW(GrAARectRenderer); 174710e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com 1748a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com fDidTestPMConversions = false; 1749a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com 17508fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com this->setupDrawBuffer(); 17518fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com} 17528fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com 17538fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::setupDrawBuffer() { 17548fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com 17558fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com GrAssert(NULL == fDrawBuffer); 17568fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com GrAssert(NULL == fDrawBufferVBAllocPool); 17578fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com GrAssert(NULL == fDrawBufferIBAllocPool); 17588fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com 1759de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com fDrawBufferVBAllocPool = 1760c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com SkNEW_ARGS(GrVertexBufferAllocPool, (fGpu, false, 176127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com DRAW_BUFFER_VBPOOL_BUFFER_SIZE, 1762c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS)); 1763de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com fDrawBufferIBAllocPool = 1764c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com SkNEW_ARGS(GrIndexBufferAllocPool, (fGpu, false, 1765de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com DRAW_BUFFER_IBPOOL_BUFFER_SIZE, 1766c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS)); 176727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 1768c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com fDrawBuffer = SkNEW_ARGS(GrInOrderDrawBuffer, (fGpu, 1769471d471dcd7422e5dd9c822c1092b2ba4721dcfebsalomon@google.com fDrawBufferVBAllocPool, 1770c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com fDrawBufferIBAllocPool)); 17713c4d032aeb2831a64fd6eff570667d590e3ed209bsalomon@google.com 177227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com fDrawBuffer->setQuadIndexBuffer(this->getQuadIndexBuffer()); 17731015e034676a90d88544c396ff4dce3849186aa9bsalomon@google.com if (fDrawBuffer) { 17741015e034676a90d88544c396ff4dce3849186aa9bsalomon@google.com fDrawBuffer->setAutoFlushTarget(fGpu); 17751015e034676a90d88544c396ff4dce3849186aa9bsalomon@google.com fDrawBuffer->setDrawState(fDrawState); 17761015e034676a90d88544c396ff4dce3849186aa9bsalomon@google.com } 177727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 177827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 177927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comGrDrawTarget* GrContext::getTextTarget(const GrPaint& paint) { 178007ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com return prepareToDraw(&paint, DEFAULT_BUFFERING); 178127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 178227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com 178327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comconst GrIndexBuffer* GrContext::getQuadIndexBuffer() const { 178427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com return fGpu->getQuadIndexBuffer(); 178527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com} 1786dfe75bcf98b0c04535efbf7fe36492a7fb53c90dbsalomon@google.com 1787a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.comnamespace { 1788a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.comvoid test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) { 1789a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com GrConfigConversionEffect::PMConversion pmToUPM; 1790a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com GrConfigConversionEffect::PMConversion upmToPM; 1791a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com GrConfigConversionEffect::TestForPreservingPMConversions(ctx, &pmToUPM, &upmToPM); 1792a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com *pmToUPMValue = pmToUPM; 1793a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com *upmToPMValue = upmToPM; 1794a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com} 1795a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com} 1796a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com 1797a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.comGrCustomStage* GrContext::createPMToUPMEffect(GrTexture* texture, bool swapRAndB) { 1798a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com if (!fDidTestPMConversions) { 1799a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion); 1800a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com } 1801a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com GrConfigConversionEffect::PMConversion pmToUPM = 1802a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion); 1803a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) { 1804a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com return GrConfigConversionEffect::Create(texture, swapRAndB, pmToUPM); 1805a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com } else { 1806a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com return NULL; 1807a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com } 1808a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com} 1809a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com 1810a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.comGrCustomStage* GrContext::createUPMToPMEffect(GrTexture* texture, bool swapRAndB) { 1811a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com if (!fDidTestPMConversions) { 1812a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion); 1813a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com } 1814a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com GrConfigConversionEffect::PMConversion upmToPM = 1815a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion); 1816a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) { 1817a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com return GrConfigConversionEffect::Create(texture, swapRAndB, upmToPM); 1818a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com } else { 1819a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com return NULL; 1820a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com } 1821a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com} 1822a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com 18233b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.orgGrTexture* GrContext::gaussianBlur(GrTexture* srcTexture, 18241e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org bool canClobberSrc, 18253b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org const SkRect& rect, 18263b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org float sigmaX, float sigmaY) { 1827ceb441476e1712861e87a9bb428f119349ef6bb5senorblanco@chromium.org ASSERT_OWNED_RESOURCE(srcTexture); 18283b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org GrRenderTarget* oldRenderTarget = this->getRenderTarget(); 1829fea85ac3e31842f80493e2df8a93a28f21cd815frobertphillips@google.com AutoMatrix avm(this, GrMatrix::I()); 18303b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org SkIRect clearRect; 1831b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com int scaleFactorX, radiusX; 1832b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com int scaleFactorY, radiusY; 1833b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com sigmaX = adjust_sigma(sigmaX, &scaleFactorX, &radiusX); 1834b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com sigmaY = adjust_sigma(sigmaY, &scaleFactorY, &radiusY); 18353b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org 18363b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org SkRect srcRect(rect); 18373b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY); 18383b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org srcRect.roundOut(); 1839fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com scale_rect(&srcRect, static_cast<float>(scaleFactorX), 18408637a365518a82901d313d61eecd83a0c5102fe9robertphillips@google.com static_cast<float>(scaleFactorY)); 18413e11c0bd92fbd12f59080c3f9450201d6105db83robertphillips@google.com 184256c79b10377e358b8092d9c6ab3e1aacf2cd60e5robertphillips@google.com AutoClip acs(this, srcRect); 1843bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com 18440342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com GrAssert(kBGRA_8888_GrPixelConfig == srcTexture->config() || 18450342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com kRGBA_8888_GrPixelConfig == srcTexture->config() || 184699a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com kAlpha_8_GrPixelConfig == srcTexture->config()); 184799a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com 184875b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com GrTextureDesc desc; 184975b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; 185075b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com desc.fWidth = SkScalarFloorToInt(srcRect.width()); 185175b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com desc.fHeight = SkScalarFloorToInt(srcRect.height()); 185275b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com desc.fConfig = srcTexture->config(); 18531e266f8ff2fb2f05f44e77e046a24410ff7b4c77bsalomon@google.com 18541e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org GrAutoScratchTexture temp1, temp2; 18551e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org GrTexture* dstTexture = temp1.set(this, desc); 18561e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org GrTexture* tempTexture = canClobberSrc ? srcTexture : temp2.set(this, desc); 18573b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org 18583b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org GrPaint paint; 18593b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org paint.reset(); 1860b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com paint.textureSampler(0)->textureParams()->setBilerp(true); 18613b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org 18623b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) { 18633b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org paint.textureSampler(0)->matrix()->setIDiv(srcTexture->width(), 18643b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org srcTexture->height()); 18653b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org this->setRenderTarget(dstTexture->asRenderTarget()); 18663b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org SkRect dstRect(srcRect); 18673b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f, 18683b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org i < scaleFactorY ? 0.5f : 1.0f); 1869aa72eab5d82d4c2aa9f6f41755a001282443b042tomhudson@google.com paint.textureSampler(0)->setCustomStage(SkNEW_ARGS(GrSingleTextureEffect, 1870aa72eab5d82d4c2aa9f6f41755a001282443b042tomhudson@google.com (srcTexture)))->unref(); 18713b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org this->drawRectToRect(paint, dstRect, srcRect); 18723b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org srcRect = dstRect; 18731e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org srcTexture = dstTexture; 18741e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org SkTSwap(dstTexture, tempTexture); 18753b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org } 18763b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org 18777a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com SkIRect srcIRect; 18787a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com srcRect.roundOut(&srcIRect); 18797a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com 18803b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org if (sigmaX > 0.0f) { 18813b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org if (scaleFactorX > 1) { 1882b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com // Clear out a radius to the right of the srcRect to prevent the 18833b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org // X convolution from reading garbage. 1884fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop, 1885b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com radiusX, srcIRect.height()); 18863b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org this->clear(&clearRect, 0x0); 18873b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org } 188805054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org 18893b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org this->setRenderTarget(dstTexture->asRenderTarget()); 189007ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com GrDrawTarget* target = this->prepareToDraw(NULL, DEFAULT_BUFFERING); 189107ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com convolve_gaussian(target, srcTexture, srcRect, sigmaX, radiusX, 1892b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com Gr1DKernelEffect::kX_Direction); 18931e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org srcTexture = dstTexture; 18941e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org SkTSwap(dstTexture, tempTexture); 18953b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org } 18963b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org 18973b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org if (sigmaY > 0.0f) { 18983b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org if (scaleFactorY > 1 || sigmaX > 0.0f) { 1899b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com // Clear out a radius below the srcRect to prevent the Y 19003b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org // convolution from reading garbage. 1901fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom, 1902b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com srcIRect.width(), radiusY); 19033b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org this->clear(&clearRect, 0x0); 19043b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org } 19053b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org 19063b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org this->setRenderTarget(dstTexture->asRenderTarget()); 190707ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com GrDrawTarget* target = this->prepareToDraw(NULL, DEFAULT_BUFFERING); 190807ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com convolve_gaussian(target, srcTexture, srcRect, sigmaY, radiusY, 1909b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com Gr1DKernelEffect::kY_Direction); 19101e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org srcTexture = dstTexture; 19111e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org SkTSwap(dstTexture, tempTexture); 19123b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org } 19133b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org 19143b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org if (scaleFactorX > 1 || scaleFactorY > 1) { 19153b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org // Clear one pixel to the right and below, to accommodate bilinear 19163b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org // upsampling. 1917fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom, 19187a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com srcIRect.width() + 1, 1); 19193b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org this->clear(&clearRect, 0x0); 1920fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop, 19217a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com 1, srcIRect.height()); 19223b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org this->clear(&clearRect, 0x0); 19233b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org // FIXME: This should be mitchell, not bilinear. 1924b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com paint.textureSampler(0)->textureParams()->setBilerp(true); 19253b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org paint.textureSampler(0)->matrix()->setIDiv(srcTexture->width(), 19263b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org srcTexture->height()); 19273b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org this->setRenderTarget(dstTexture->asRenderTarget()); 1928aa72eab5d82d4c2aa9f6f41755a001282443b042tomhudson@google.com paint.textureSampler(0)->setCustomStage(SkNEW_ARGS(GrSingleTextureEffect, 1929aa72eab5d82d4c2aa9f6f41755a001282443b042tomhudson@google.com (srcTexture)))->unref(); 19303b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org SkRect dstRect(srcRect); 19317a39633318f8ae41488f03d3258deade4b36b996robertphillips@google.com scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY); 19323b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org this->drawRectToRect(paint, dstRect, srcRect); 19333b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org srcRect = dstRect; 19341e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org srcTexture = dstTexture; 19351e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org SkTSwap(dstTexture, tempTexture); 19363b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org } 19373b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org this->setRenderTarget(oldRenderTarget); 19381e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org if (srcTexture == temp1.texture()) { 19391e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org return temp1.detach(); 19401e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org } else if (srcTexture == temp2.texture()) { 19411e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org return temp2.detach(); 19421e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org } else { 19431e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org srcTexture->ref(); 19441e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org return srcTexture; 19451e95d715d06c5125ef6e5439e953fd0353be92b2senorblanco@chromium.org } 19463b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org} 19473b4dd90282932c9cd695d13f3876f98c9c6d6d5esenorblanco@chromium.org 1948c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com/////////////////////////////////////////////////////////////////////////////// 19495f9f2f574fe9b195f5f3e40edeb2e28b673511fdrobertphillips@google.com#if GR_DEBUG 19505f9f2f574fe9b195f5f3e40edeb2e28b673511fdrobertphillips@google.comvoid GrContext::printCacheStats() const { 19515f9f2f574fe9b195f5f3e40edeb2e28b673511fdrobertphillips@google.com fTextureCache->printStats(); 19525f9f2f574fe9b195f5f3e40edeb2e28b673511fdrobertphillips@google.com} 19535f9f2f574fe9b195f5f3e40edeb2e28b673511fdrobertphillips@google.com#endif 1954