GrAAHairLinePathRenderer.cpp revision d42aca31b9ddc1cb9a81522b4c73a9fe550450bc
1f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com 2f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com/* 3f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com * Copyright 2011 Google Inc. 4f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com * 5f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com * Use of this source code is governed by a BSD-style license that can be 6f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com * found in the LICENSE file. 7f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com */ 8f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com 9aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#include "GrAAHairLinePathRenderer.h" 10aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 11aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#include "GrContext.h" 129381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com#include "GrDrawState.h" 13c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrDrawTargetCaps.h" 1490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org#include "GrEffect.h" 15aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#include "GrGpu.h" 16aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#include "GrIndexBuffer.h" 17dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com#include "GrPathUtils.h" 1890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org#include "GrTBackendEffectFactory.h" 19aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#include "SkGeometry.h" 2012b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com#include "SkStroke.h" 21aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#include "SkTemplates.h" 22aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 2390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org#include "gl/GrGLEffect.h" 2490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org#include "gl/GrGLSL.h" 254647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com 26aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comnamespace { 27aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com// quadratics are rendered as 5-sided polys in order to bound the 28aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com// AA stroke around the center-curve. See comments in push_quad_index_buffer and 29aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com// bloat_quad. 30aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comstatic const int kVertsPerQuad = 5; 31aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comstatic const int kIdxsPerQuad = 9; 32aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 33aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comstatic const int kVertsPerLineSeg = 4; 34aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comstatic const int kIdxsPerLineSeg = 6; 35aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 36aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comstatic const int kNumQuadsInIdxBuffer = 256; 37aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comstatic const size_t kQuadIdxSBufize = kIdxsPerQuad * 38aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com sizeof(uint16_t) * 39aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com kNumQuadsInIdxBuffer; 40aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 41aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.combool push_quad_index_data(GrIndexBuffer* qIdxBuffer) { 42aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com uint16_t* data = (uint16_t*) qIdxBuffer->lock(); 43aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bool tempData = NULL == data; 44aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (tempData) { 45c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com data = SkNEW_ARRAY(uint16_t, kNumQuadsInIdxBuffer * kIdxsPerQuad); 46aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 47aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com for (int i = 0; i < kNumQuadsInIdxBuffer; ++i) { 48aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 49aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // Each quadratic is rendered as a five sided polygon. This poly bounds 50aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // the quadratic's bounding triangle but has been expanded so that the 51aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // 1-pixel wide area around the curve is inside the poly. 52aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // If a,b,c are the original control points then the poly a0,b0,c0,c1,a1 53aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // that is rendered would look like this: 54aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // b0 55aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // b 56aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // 57aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // a0 c0 58aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // a c 59aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // a1 c1 600e5104c1570de4709e04720e62d80a0ca8970260bsalomon@google.com // Each is drawn as three triangles specified by these 9 indices: 61aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int baseIdx = i * kIdxsPerQuad; 62aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com uint16_t baseVert = (uint16_t)(i * kVertsPerQuad); 63aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[0 + baseIdx] = baseVert + 0; // a0 64aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[1 + baseIdx] = baseVert + 1; // a1 65aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[2 + baseIdx] = baseVert + 2; // b0 66aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[3 + baseIdx] = baseVert + 2; // b0 67aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[4 + baseIdx] = baseVert + 4; // c1 68aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[5 + baseIdx] = baseVert + 3; // c0 69aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[6 + baseIdx] = baseVert + 1; // a1 70aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[7 + baseIdx] = baseVert + 4; // c1 71aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[8 + baseIdx] = baseVert + 2; // b0 72aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 73aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (tempData) { 74aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bool ret = qIdxBuffer->updateData(data, kQuadIdxSBufize); 75aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com delete[] data; 76aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return ret; 77aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 78aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com qIdxBuffer->unlock(); 79aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return true; 80aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 81aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 82aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 83aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 84aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comGrPathRenderer* GrAAHairLinePathRenderer::Create(GrContext* context) { 85a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com const GrIndexBuffer* lIdxBuffer = context->getQuadIndexBuffer(); 86a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com if (NULL == lIdxBuffer) { 87aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return NULL; 88aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 89a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com GrGpu* gpu = context->getGpu(); 90a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com GrIndexBuffer* qIdxBuf = gpu->createIndexBuffer(kQuadIdxSBufize, false); 91a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com SkAutoTUnref<GrIndexBuffer> qIdxBuffer(qIdxBuf); 92a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com if (NULL == qIdxBuf || 93a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com !push_quad_index_data(qIdxBuf)) { 94a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com return NULL; 95a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com } 96c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com return SkNEW_ARGS(GrAAHairLinePathRenderer, 97c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com (context, lIdxBuffer, qIdxBuf)); 98aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 99aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 100aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comGrAAHairLinePathRenderer::GrAAHairLinePathRenderer( 101aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const GrContext* context, 102aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const GrIndexBuffer* linesIndexBuffer, 103aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const GrIndexBuffer* quadsIndexBuffer) { 104aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com fLinesIndexBuffer = linesIndexBuffer; 105aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com linesIndexBuffer->ref(); 106aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com fQuadsIndexBuffer = quadsIndexBuffer; 107aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com quadsIndexBuffer->ref(); 108aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 109aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 110aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comGrAAHairLinePathRenderer::~GrAAHairLinePathRenderer() { 111aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com fLinesIndexBuffer->unref(); 112aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com fQuadsIndexBuffer->unref(); 113aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 114aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 115aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comnamespace { 116aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 11749313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.comtypedef SkTArray<SkPoint, true> PtArray; 11892669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com#define PREALLOC_PTARRAY(N) SkSTArray<(N),SkPoint, true> 11949313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.comtypedef SkTArray<int, true> IntArray; 120aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 121aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com// Takes 178th time of logf on Z600 / VC2010 122aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comint get_float_exp(float x) { 123aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GR_STATIC_ASSERT(sizeof(int) == sizeof(float)); 124aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#if GR_DEBUG 125aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com static bool tested; 126aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (!tested) { 127aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com tested = true; 128aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(0.25f) == -2); 129aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(0.3f) == -2); 130aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(0.5f) == -1); 131aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(1.f) == 0); 132aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(2.f) == 1); 133aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(2.5f) == 1); 134aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(8.f) == 3); 135aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(100.f) == 6); 136aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(1000.f) == 9); 137aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(1024.f) == 10); 138aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(3000000.f) == 21); 139aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 140aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#endif 1412ec7280a178ad3dcfd2e645bc330eeb04a84bfcfbsalomon@google.com const int* iptr = (const int*)&x; 1422ec7280a178ad3dcfd2e645bc330eeb04a84bfcfbsalomon@google.com return (((*iptr) & 0x7f800000) >> 23) - 127; 143aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 144aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 145aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com// we subdivide the quads to avoid huge overfill 146aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com// if it returns -1 then should be drawn as lines 147aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comint num_quad_subdivs(const SkPoint p[3]) { 148aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com static const SkScalar gDegenerateToLineTol = SK_Scalar1; 149fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com static const SkScalar gDegenerateToLineTolSqd = 15046a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com SkScalarMul(gDegenerateToLineTol, gDegenerateToLineTol); 15146a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com 15246a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com if (p[0].distanceToSqd(p[1]) < gDegenerateToLineTolSqd || 15346a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com p[1].distanceToSqd(p[2]) < gDegenerateToLineTolSqd) { 15446a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com return -1; 15546a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com } 156aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 15781712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar dsqd = p[1].distanceToLineBetweenSqd(p[0], p[2]); 15846a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com if (dsqd < gDegenerateToLineTolSqd) { 159aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return -1; 160aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 16146a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com 16246a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com if (p[2].distanceToLineBetweenSqd(p[1], p[0]) < gDegenerateToLineTolSqd) { 163aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return -1; 164aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 165aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 166aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // tolerance of triangle height in pixels 167aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // tuned on windows Quadro FX 380 / Z600 168aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // trade off of fill vs cpu time on verts 169aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // maybe different when do this using gpu (geo or tess shaders) 170aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com static const SkScalar gSubdivTol = 175 * SK_Scalar1; 171aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 1727460b378d68217167013ca889a4cdcae742908e7robertphillips@google.com if (dsqd <= SkScalarMul(gSubdivTol, gSubdivTol)) { 173aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return 0; 174aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 17587379e17c5e95c6fe0d88b3b9ae134355cfafc66robertphillips@google.com static const int kMaxSub = 4; 176aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // subdividing the quad reduces d by 4. so we want x = log4(d/tol) 177aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // = log4(d*d/tol*tol)/2 178aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // = log2(d*d/tol*tol) 179aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 180aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#ifdef SK_SCALAR_IS_FLOAT 181aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // +1 since we're ignoring the mantissa contribution. 182aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int log = get_float_exp(dsqd/(gSubdivTol*gSubdivTol)) + 1; 183aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com log = GrMin(GrMax(0, log), kMaxSub); 184aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return log; 185aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#else 1867460b378d68217167013ca889a4cdcae742908e7robertphillips@google.com SkScalar log = SkScalarLog( 187fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com SkScalarDiv(dsqd, 1887460b378d68217167013ca889a4cdcae742908e7robertphillips@google.com SkScalarMul(gSubdivTol, gSubdivTol))); 189aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com static const SkScalar conv = SkScalarInvert(SkScalarLog(2)); 190aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com log = SkScalarMul(log, conv); 191aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return GrMin(GrMax(0, SkScalarCeilToInt(log)),kMaxSub); 192aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#endif 193aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 194aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 195aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 196dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com/** 197dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * Generates the lines and quads to be rendered. Lines are always recorded in 198dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * device space. We will do a device space bloat to account for the 1pixel 199dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * thickness. 200dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * Quads are recorded in device space unless m contains 201dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * perspective, then in they are in src space. We do this because we will 202dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * subdivide large quads to reduce over-fill. This subdivision has to be 203dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * performed before applying the perspective matrix. 204dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com */ 205dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.comint generate_lines_and_quads(const SkPath& path, 206dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com const SkMatrix& m, 2077b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com const GrIRect& devClipBounds, 208dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com PtArray* lines, 209dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com PtArray* quads, 210dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com IntArray* quadSubdivCnts) { 211aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkPath::Iter iter(path, false); 212aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 213aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int totalQuadCount = 0; 214aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrRect bounds; 215aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrIRect ibounds; 216dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com 217dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bool persp = m.hasPerspective(); 218dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com 219aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com for (;;) { 220aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrPoint pts[4]; 221dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com GrPoint devPts[4]; 222aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrPathCmd cmd = (GrPathCmd)iter.next(pts); 223aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com switch (cmd) { 224aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com case kMove_PathCmd: 225aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com break; 226aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com case kLine_PathCmd: 227dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com m.mapPoints(devPts, pts, 2); 228dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bounds.setBounds(devPts, 2); 229aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.outset(SK_Scalar1, SK_Scalar1); 230aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.roundOut(&ibounds); 2317b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com if (SkIRect::Intersects(devClipBounds, ibounds)) { 232a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com SkPoint* pts = lines->push_back_n(2); 233a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[0] = devPts[0]; 234a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[1] = devPts[1]; 235aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 236aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com break; 237dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com case kQuadratic_PathCmd: 238dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com m.mapPoints(devPts, pts, 3); 239dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bounds.setBounds(devPts, 3); 240aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.outset(SK_Scalar1, SK_Scalar1); 241aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.roundOut(&ibounds); 2427b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com if (SkIRect::Intersects(devClipBounds, ibounds)) { 243dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com int subdiv = num_quad_subdivs(devPts); 244aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(subdiv >= -1); 245aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (-1 == subdiv) { 246a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com SkPoint* pts = lines->push_back_n(4); 247a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[0] = devPts[0]; 248a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[1] = devPts[1]; 249a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[2] = devPts[1]; 250a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[3] = devPts[2]; 251aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 252dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // when in perspective keep quads in src space 253dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com SkPoint* qPts = persp ? pts : devPts; 254a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com SkPoint* pts = quads->push_back_n(3); 255a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[0] = qPts[0]; 256a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[1] = qPts[1]; 257a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[2] = qPts[2]; 258aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com quadSubdivCnts->push_back() = subdiv; 259aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com totalQuadCount += 1 << subdiv; 260aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 261aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 262a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com break; 263dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com case kCubic_PathCmd: 264dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com m.mapPoints(devPts, pts, 4); 265dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bounds.setBounds(devPts, 4); 266aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.outset(SK_Scalar1, SK_Scalar1); 267aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.roundOut(&ibounds); 2687b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com if (SkIRect::Intersects(devClipBounds, ibounds)) { 26992669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com PREALLOC_PTARRAY(32) q; 270a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com // we don't need a direction if we aren't constraining the subdivision 271a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com static const SkPath::Direction kDummyDir = SkPath::kCCW_Direction; 27269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com // We convert cubics to quadratics (for now). 27369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com // In perspective have to do conversion in src space. 274dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (persp) { 275fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com SkScalar tolScale = 276dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com GrPathUtils::scaleToleranceToSrc(SK_Scalar1, m, 277dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com path.getBounds()); 278a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com GrPathUtils::convertCubicToQuads(pts, tolScale, false, kDummyDir, &q); 279dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } else { 280a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com GrPathUtils::convertCubicToQuads(devPts, SK_Scalar1, false, kDummyDir, &q); 281dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 282aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com for (int i = 0; i < q.count(); i += 3) { 283dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com SkPoint* qInDevSpace; 284dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // bounds has to be calculated in device space, but q is 285dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // in src space when there is perspective. 286dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (persp) { 287dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com m.mapPoints(devPts, &q[i], 3); 288dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bounds.setBounds(devPts, 3); 289dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com qInDevSpace = devPts; 290dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } else { 291dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bounds.setBounds(&q[i], 3); 292dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com qInDevSpace = &q[i]; 293dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 294aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.outset(SK_Scalar1, SK_Scalar1); 295aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.roundOut(&ibounds); 2967b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com if (SkIRect::Intersects(devClipBounds, ibounds)) { 297dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com int subdiv = num_quad_subdivs(qInDevSpace); 298aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(subdiv >= -1); 299aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (-1 == subdiv) { 300a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com SkPoint* pts = lines->push_back_n(4); 301dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // lines should always be in device coords 302a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[0] = qInDevSpace[0]; 303a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[1] = qInDevSpace[1]; 304a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[2] = qInDevSpace[1]; 305a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[3] = qInDevSpace[2]; 306aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 307a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com SkPoint* pts = quads->push_back_n(3); 308dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // q is already in src space when there is no 309dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // perspective and dev coords otherwise. 310a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[0] = q[0 + i]; 311a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[1] = q[1 + i]; 312a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[2] = q[2 + i]; 313aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com quadSubdivCnts->push_back() = subdiv; 314aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com totalQuadCount += 1 << subdiv; 315aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 316aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 317aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 318aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 319a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com break; 320aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com case kClose_PathCmd: 321aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com break; 322aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com case kEnd_PathCmd: 323aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return totalQuadCount; 324aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 325aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 326aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 327aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 328aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comstruct Vertex { 329aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrPoint fPos; 330aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com union { 331aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com struct { 33281712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar fA; 33381712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar fB; 33481712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar fC; 335aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } fLine; 336aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrVec fQuadCoord; 337aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com struct { 33881712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar fBogus[4]; 339aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com }; 340aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com }; 341aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com}; 342aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comGR_STATIC_ASSERT(sizeof(Vertex) == 3 * sizeof(GrPoint)); 343aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 344aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comvoid intersect_lines(const SkPoint& ptA, const SkVector& normA, 345aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const SkPoint& ptB, const SkVector& normB, 346aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkPoint* result) { 347aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 348aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkScalar lineAW = -normA.dot(ptA); 349aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkScalar lineBW = -normB.dot(ptB); 350aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 351aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkScalar wInv = SkScalarMul(normA.fX, normB.fY) - 352aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkScalarMul(normA.fY, normB.fX); 353aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com wInv = SkScalarInvert(wInv); 354aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 355aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com result->fX = SkScalarMul(normA.fY, lineBW) - SkScalarMul(lineAW, normB.fY); 356aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com result->fX = SkScalarMul(result->fX, wInv); 357fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 358aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com result->fY = SkScalarMul(lineAW, normB.fX) - SkScalarMul(normA.fX, lineBW); 359aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com result->fY = SkScalarMul(result->fY, wInv); 360aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 361aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 362b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.comvoid bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice, 363b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com const SkMatrix* toSrc, Vertex verts[kVertsPerQuad]) { 364dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com GrAssert(!toDevice == !toSrc); 365aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // original quad is specified by tri a,b,c 366dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com SkPoint a = qpts[0]; 367dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com SkPoint b = qpts[1]; 368dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com SkPoint c = qpts[2]; 369aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 370dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // this should be in the src space, not dev coords, when we have perspective 3711971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com GrPathUtils::QuadUVMatrix DevToUV(qpts); 372aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 373dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (toDevice) { 374dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toDevice->mapPoints(&a, 1); 375dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toDevice->mapPoints(&b, 1); 376dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toDevice->mapPoints(&c, 1); 377dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 378dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // make a new poly where we replace a and c by a 1-pixel wide edges orthog 379dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // to edges ab and bc: 380dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // 381dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // before | after 382dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // | b0 383dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // b | 384dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // | 385dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // | a0 c0 386dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // a c | a1 c1 387dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // 388dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // edges a0->b0 and b0->c0 are parallel to original edges a->b and b->c, 389dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // respectively. 390dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com Vertex& a0 = verts[0]; 391dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com Vertex& a1 = verts[1]; 392dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com Vertex& b0 = verts[2]; 393dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com Vertex& c0 = verts[3]; 394dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com Vertex& c1 = verts[4]; 395dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com 396aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector ab = b; 397aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com ab -= a; 398aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector ac = c; 399aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com ac -= a; 400aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector cb = b; 401aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com cb -= c; 402aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 403aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // We should have already handled degenerates 404aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(ab.length() > 0 && cb.length() > 0); 405aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 406aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com ab.normalize(); 407aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector abN; 408aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com abN.setOrthog(ab, SkVector::kLeft_Side); 409aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (abN.dot(ac) > 0) { 410aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com abN.negate(); 411aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 412aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 413aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com cb.normalize(); 414aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector cbN; 415aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com cbN.setOrthog(cb, SkVector::kLeft_Side); 416aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (cbN.dot(ac) < 0) { 417aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com cbN.negate(); 418aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 419aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 420aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com a0.fPos = a; 421aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com a0.fPos += abN; 422aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com a1.fPos = a; 423aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com a1.fPos -= abN; 424aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 425aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com c0.fPos = c; 426aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com c0.fPos += cbN; 427aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com c1.fPos = c; 428aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com c1.fPos -= cbN; 429aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 430aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com intersect_lines(a0.fPos, abN, c0.fPos, cbN, &b0.fPos); 431aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 432dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (toSrc) { 433dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toSrc->mapPointsWithStride(&verts[0].fPos, sizeof(Vertex), kVertsPerQuad); 434dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 4351971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com DevToUV.apply<kVertsPerQuad, sizeof(Vertex), sizeof(GrPoint)>(verts); 436aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 437aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 438aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comvoid add_quads(const SkPoint p[3], 439aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int subdiv, 440b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com const SkMatrix* toDevice, 441b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com const SkMatrix* toSrc, 442aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com Vertex** vert) { 443aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(subdiv >= 0); 444aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (subdiv) { 445aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkPoint newP[5]; 446aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkChopQuadAtHalf(p, newP); 447dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com add_quads(newP + 0, subdiv-1, toDevice, toSrc, vert); 448dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com add_quads(newP + 2, subdiv-1, toDevice, toSrc, vert); 449aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 450dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bloat_quad(p, toDevice, toSrc, *vert); 451aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com *vert += kVertsPerQuad; 452aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 453aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 454aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 455aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comvoid add_line(const SkPoint p[2], 456aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int rtHeight, 457dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com const SkMatrix* toSrc, 458aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com Vertex** vert) { 459aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const SkPoint& a = p[0]; 460aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const SkPoint& b = p[1]; 461aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 462aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector orthVec = b; 463aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com orthVec -= a; 464aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 465aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (orthVec.setLength(SK_Scalar1)) { 466aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com orthVec.setOrthog(orthVec); 467aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 468706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com SkScalar lineC = -(a.dot(orthVec)); 469aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com for (int i = 0; i < kVertsPerLineSeg; ++i) { 470aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[i].fPos = (i < 2) ? a : b; 471aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (0 == i || 3 == i) { 472aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[i].fPos -= orthVec; 473aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 474aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[i].fPos += orthVec; 475aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 476706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com (*vert)[i].fLine.fA = orthVec.fX; 477706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com (*vert)[i].fLine.fB = orthVec.fY; 478aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[i].fLine.fC = lineC; 479aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 480dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (NULL != toSrc) { 481dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toSrc->mapPointsWithStride(&(*vert)->fPos, 482dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com sizeof(Vertex), 483dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com kVertsPerLineSeg); 484dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 485aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 486aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // just make it degenerate and likely offscreen 487aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[0].fPos.set(SK_ScalarMax, SK_ScalarMax); 488aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[1].fPos.set(SK_ScalarMax, SK_ScalarMax); 489aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[2].fPos.set(SK_ScalarMax, SK_ScalarMax); 490aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[3].fPos.set(SK_ScalarMax, SK_ScalarMax); 491aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 492aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 493aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com *vert += kVertsPerLineSeg; 494aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 495aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 496aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 497aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 49890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 49990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 50090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/** 50190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * The output of this effect is a hairline edge for quadratics. 50290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * Quadratic specified by 0=u^2-v canonical coords. u and v are the first 50390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * two components of the vertex attribute. Uses unsigned distance. 504041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com * Coverage is min(0, 1-distance). 3rd & 4th component unused. 505041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com * Requires shader derivative instruction support. 50690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org */ 50790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgclass HairQuadEdgeEffect : public GrEffect { 50890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgpublic: 50990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 51090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org static GrEffectRef* Create() { 511d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com GR_CREATE_STATIC_EFFECT(gHairQuadEdgeEffect, HairQuadEdgeEffect, ()); 512d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com gHairQuadEdgeEffect->ref(); 513d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com return gHairQuadEdgeEffect; 51490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 51590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 51690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual ~HairQuadEdgeEffect() {} 51790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 51890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org static const char* Name() { return "HairQuadEdge"; } 51990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 520041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com virtual void getConstantColorComponents(GrColor* color, 52190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org uint32_t* validFlags) const SK_OVERRIDE { 52290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org *validFlags = 0; 52390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 52490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 52590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { 52690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org return GrTBackendEffectFactory<HairQuadEdgeEffect>::getInstance(); 52790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 52890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 52990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org class GLEffect : public GrGLEffect { 53090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org public: 53190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) 53290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org : INHERITED (factory) {} 53390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 53490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual void emitCode(GrGLShaderBuilder* builder, 53590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const GrDrawEffect& drawEffect, 53690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org EffectKey key, 53790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const char* outputColor, 53890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const char* inputColor, 53990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const TextureSamplerArray& samplers) SK_OVERRIDE { 54090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const char *vsName, *fsName; 54190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const SkString* attrName = 54290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); 54390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n"); 54490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 54590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org SkAssertResult(builder->enableFeature( 54690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GrGLShaderBuilder::kStandardDerivatives_GLSLFeature)); 54790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->addVarying(kVec4f_GrSLType, "HairQuadEdge", &vsName, &fsName); 54890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 54990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName); 55090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName); 55190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n" 55290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org "\t\t 2.0*%s.x*duvdy.x - duvdy.y);\n", 55390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org fsName, fsName); 55490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, 55590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org fsName); 55690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppend("\t\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / dot(gF, gF));\n"); 55790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); 55890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 55990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org SkString modulate; 560018f179efb2413431bdb1a9e6701eb44ef36b792bsalomon@google.com GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha"); 56190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str()); 56290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 56390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); 56490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 56590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 56690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { 56790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org return 0x0; 56890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 56990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 57090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {} 57190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 57290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org private: 57390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org typedef GrGLEffect INHERITED; 57490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org }; 57590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 57690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgprivate: 577041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com HairQuadEdgeEffect() { 578041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com this->addVertexAttrib(kVec4f_GrSLType); 57990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 58090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 58190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { 58290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org return true; 58390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 58490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 58590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GR_DECLARE_EFFECT_TEST; 58690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 58790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org typedef GrEffect INHERITED; 58890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org}; 58990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 59090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgGR_DEFINE_EFFECT_TEST(HairQuadEdgeEffect); 59190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 59290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgGrEffectRef* HairQuadEdgeEffect::TestCreate(SkMWCRandom* random, 59390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GrContext*, 59490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const GrDrawTargetCaps& caps, 59590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GrTexture*[]) { 59690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org // Doesn't work without derivative instructions. 59790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org return caps.shaderDerivativeSupport() ? HairQuadEdgeEffect::Create() : NULL;} 59890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 59990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 60090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 60190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/** 602041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com * The output of this effect is a 1-pixel wide line. 603041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com * Input is 2D implicit device coord line eq (a*x + b*y +c = 0). 4th component unused. 60490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org */ 60590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgclass HairLineEdgeEffect : public GrEffect { 60690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgpublic: 60790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 60890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org static GrEffectRef* Create() { 609d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com GR_CREATE_STATIC_EFFECT(gHairLineEdge, HairLineEdgeEffect, ()); 610d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com gHairLineEdge->ref(); 611d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com return gHairLineEdge; 61290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 61390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 61490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual ~HairLineEdgeEffect() {} 61590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 61690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org static const char* Name() { return "HairLineEdge"; } 61790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 618041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com virtual void getConstantColorComponents(GrColor* color, 61990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org uint32_t* validFlags) const SK_OVERRIDE { 62090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org *validFlags = 0; 62190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 62290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 62390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { 62490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org return GrTBackendEffectFactory<HairLineEdgeEffect>::getInstance(); 62590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 62690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 62790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org class GLEffect : public GrGLEffect { 62890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org public: 62990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) 63090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org : INHERITED (factory) {} 63190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 63290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual void emitCode(GrGLShaderBuilder* builder, 63390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const GrDrawEffect& drawEffect, 63490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org EffectKey key, 63590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const char* outputColor, 63690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const char* inputColor, 63790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const TextureSamplerArray& samplers) SK_OVERRIDE { 63890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const char *vsName, *fsName; 63990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const SkString* attrName = 64090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); 64190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n"); 64290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 64390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->addVarying(kVec4f_GrSLType, "HairLineEdge", &vsName, &fsName); 64490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 64590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\tedgeAlpha = abs(dot(vec3(%s.xy,1), %s.xyz));\n", 64690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fragmentPosition(), fsName); 64790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); 64890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 64990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org SkString modulate; 650018f179efb2413431bdb1a9e6701eb44ef36b792bsalomon@google.com GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha"); 65190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str()); 65290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 65390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); 65490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 65590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 65690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { 65790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org return 0x0; 65890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 65990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 66090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {} 66190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 66290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org private: 66390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org typedef GrGLEffect INHERITED; 66490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org }; 66590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 66690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgprivate: 667041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com HairLineEdgeEffect() { 668041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com this->addVertexAttrib(kVec4f_GrSLType); 66990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 67090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 67190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { 67290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org return true; 67390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 67490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 67590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GR_DECLARE_EFFECT_TEST; 67690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 67790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org typedef GrEffect INHERITED; 67890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org}; 67990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 68090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgGR_DEFINE_EFFECT_TEST(HairLineEdgeEffect); 68190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 68290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgGrEffectRef* HairLineEdgeEffect::TestCreate(SkMWCRandom* random, 68390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GrContext*, 68490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const GrDrawTargetCaps& caps, 68590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GrTexture*[]) { 68690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org return HairLineEdgeEffect::Create(); 68790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org} 68890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 68990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 69090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 691429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.comnamespace { 692429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com 693429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com// position + edge 694429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.comextern const GrVertexAttrib gHairlineAttribs[] = { 695429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, 696429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding} 697429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com}; 698429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com 699429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com}; 700429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com 701b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.combool GrAAHairLinePathRenderer::createGeom( 702b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com const SkPath& path, 703b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com GrDrawTarget* target, 704b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com int* lineCnt, 705b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com int* quadCnt, 706b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com GrDrawTarget::AutoReleaseGeometry* arg) { 7079b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com GrDrawState* drawState = target->drawState(); 7089b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com int rtHeight = drawState->getRenderTarget()->height(); 709aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 7107b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com GrIRect devClipBounds; 7119b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com target->getClip()->getConservativeBounds(drawState->getRenderTarget(), 7127b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com &devClipBounds); 713aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 7149b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com SkMatrix viewM = drawState->getViewMatrix(); 715aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 71692669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com PREALLOC_PTARRAY(128) lines; 71792669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com PREALLOC_PTARRAY(128) quads; 718aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com IntArray qSubdivs; 7190f11e1ab5b6e53f6176dde2dbb25a8e3ae34858fbsalomon@google.com *quadCnt = generate_lines_and_quads(path, viewM, devClipBounds, 720dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com &lines, &quads, &qSubdivs); 721aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 722c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com *lineCnt = lines.count() / 2; 723c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com int vertCnt = kVertsPerLineSeg * *lineCnt + kVertsPerQuad * *quadCnt; 724aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 725429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com target->drawState()->setVertexAttribs<gHairlineAttribs>(SK_ARRAY_COUNT(gHairlineAttribs)); 726b75b0a0b8492e14c7728e0a0881f87dc64ce60f9jvanverth@google.com GrAssert(sizeof(Vertex) == target->getDrawState().getVertexSize()); 727aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 728b75b0a0b8492e14c7728e0a0881f87dc64ce60f9jvanverth@google.com if (!arg->set(target, vertCnt, 0)) { 729aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return false; 730aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 731dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com 732b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com Vertex* verts = reinterpret_cast<Vertex*>(arg->vertices()); 733b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com 734b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com const SkMatrix* toDevice = NULL; 735b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com const SkMatrix* toSrc = NULL; 736b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com SkMatrix ivm; 737dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com 738dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (viewM.hasPerspective()) { 739dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (viewM.invert(&ivm)) { 740dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toDevice = &viewM; 741dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toSrc = &ivm; 742dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 743dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 744aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 745c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com for (int i = 0; i < *lineCnt; ++i) { 746dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com add_line(&lines[2*i], rtHeight, toSrc, &verts); 747aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 748dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com 749aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int unsubdivQuadCnt = quads.count() / 3; 750aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com for (int i = 0; i < unsubdivQuadCnt; ++i) { 751aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(qSubdivs[i] >= 0); 752dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts); 753aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 754aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 755aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return true; 756aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 757aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 7588a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.combool GrAAHairLinePathRenderer::canDrawPath(const SkPath& path, 7595f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com const SkStrokeRec& stroke, 7608a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com const GrDrawTarget* target, 7618a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com bool antiAlias) const { 7625f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com if (!stroke.isHairlineStyle() || !antiAlias) { 763c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return false; 764c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com } 765c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 766c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com static const uint32_t gReqDerivMask = SkPath::kCubic_SegmentMask | 767c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com SkPath::kQuad_SegmentMask; 768bcce8926524827775539874346dd424a9510dbc9bsalomon@google.com if (!target->caps()->shaderDerivativeSupport() && 769c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com (gReqDerivMask & path.getSegmentMasks())) { 770c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return false; 771c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com } 772c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return true; 773c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com} 774aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 775c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.combool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path, 7765f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com const SkStrokeRec&, 777c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com GrDrawTarget* target, 778c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com bool antiAlias) { 779c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 780c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com int lineCnt; 781c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com int quadCnt; 782b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com GrDrawTarget::AutoReleaseGeometry arg; 783c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com if (!this->createGeom(path, 784c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com target, 785c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com &lineCnt, 786b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com &quadCnt, 787b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com &arg)) { 788c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return false; 789aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 790aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 7914647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kPreserve_ASRInit); 792873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com GrDrawState* drawState = target->drawState(); 7934647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com 7944647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com GrDrawState::AutoDeviceCoordDraw adcd; 795a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com // createGeom transforms the geometry to device space when the matrix does not have 796a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com // perspective. 7978f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com if (!drawState->getViewMatrix().hasPerspective()) { 798a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com adcd.set(drawState); 799a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com if (!adcd.succeeded()) { 800e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com return false; 801dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 802aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 803fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 804aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // TODO: See whether rendering lines as degenerate quads improves perf 805aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // when we have a mix 806a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com 8074647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com enum { 8084647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com // the edge effects share this stage with glyph rendering 8094647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com // (kGlyphMaskStage in GrTextContext) && SW path rendering 8104647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com // (kPathMaskStage in GrSWMaskHelper) 8114647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com kEdgeEffectStage = GrPaint::kTotalStages, 8124647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com }; 8134647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com static const int kEdgeAttrIndex = 1; 814a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com 81590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GrEffectRef* hairLineEffect = HairLineEdgeEffect::Create(); 81690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GrEffectRef* hairQuadEffect = HairQuadEdgeEffect::Create(); 81737cbc7fd014e3b35833523dbdbe3bc3ac52ecacdskia.committer@gmail.com 818c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com target->setIndexSourceToBuffer(fLinesIndexBuffer); 819aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int lines = 0; 820aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int nBufLines = fLinesIndexBuffer->maxQuads(); 8214647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com drawState->setEffect(kEdgeEffectStage, hairLineEffect, kEdgeAttrIndex)->unref(); 822c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com while (lines < lineCnt) { 823c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com int n = GrMin(lineCnt - lines, nBufLines); 82447059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com target->drawIndexed(kTriangles_GrPrimitiveType, 825c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com kVertsPerLineSeg*lines, // startV 826c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 0, // startI 827c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com kVertsPerLineSeg*n, // vCount 828c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com kIdxsPerLineSeg*n); // iCount 829aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com lines += n; 830aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 831aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 832c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com target->setIndexSourceToBuffer(fQuadsIndexBuffer); 833aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int quads = 0; 8344647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com drawState->setEffect(kEdgeEffectStage, hairQuadEffect, kEdgeAttrIndex)->unref(); 835c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com while (quads < quadCnt) { 836c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com int n = GrMin(quadCnt - quads, kNumQuadsInIdxBuffer); 83747059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com target->drawIndexed(kTriangles_GrPrimitiveType, 838c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 4 * lineCnt + kVertsPerQuad*quads, // startV 839c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 0, // startI 840c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com kVertsPerQuad*n, // vCount 841c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com kIdxsPerQuad*n); // iCount 842aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com quads += n; 843aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 8440406b9e1faee06c6ecb2732a1bcf3b0e53104e07bsalomon@google.com target->resetIndexSource(); 8454647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com 846c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return true; 847aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 848