GrAAHairLinePathRenderer.cpp revision 1dd9baa6c8faeb4ce837c39d179ce9c9a09719ef
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]; 22294b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com SkPath::Verb verb = iter.next(pts); 22394b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com switch (verb) { 22494b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kMove_Verb: 225aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com break; 22694b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kLine_Verb: 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; 23794b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kQuad_Verb: 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; 26394b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kCubic_Verb: 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; 32094b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kClose_Verb: 321aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com break; 32294b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kDone_Verb: 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, 3631dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com const SkMatrix* toSrc, Vertex verts[kVertsPerQuad], 3641dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com SkRect* devBounds) { 365dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com GrAssert(!toDevice == !toSrc); 366aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // original quad is specified by tri a,b,c 367dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com SkPoint a = qpts[0]; 368dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com SkPoint b = qpts[1]; 369dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com SkPoint c = qpts[2]; 370aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 371dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // this should be in the src space, not dev coords, when we have perspective 3721971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com GrPathUtils::QuadUVMatrix DevToUV(qpts); 373aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 374dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (toDevice) { 375dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toDevice->mapPoints(&a, 1); 376dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toDevice->mapPoints(&b, 1); 377dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toDevice->mapPoints(&c, 1); 378dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 379dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // make a new poly where we replace a and c by a 1-pixel wide edges orthog 380dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // to edges ab and bc: 381dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // 382dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // before | after 383dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // | b0 384dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // b | 385dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // | 386dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // | a0 c0 387dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // a c | a1 c1 388dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // 389dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // edges a0->b0 and b0->c0 are parallel to original edges a->b and b->c, 390dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // respectively. 391dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com Vertex& a0 = verts[0]; 392dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com Vertex& a1 = verts[1]; 393dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com Vertex& b0 = verts[2]; 394dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com Vertex& c0 = verts[3]; 395dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com Vertex& c1 = verts[4]; 396dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com 397aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector ab = b; 398aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com ab -= a; 399aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector ac = c; 400aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com ac -= a; 401aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector cb = b; 402aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com cb -= c; 403aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 404aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // We should have already handled degenerates 405aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(ab.length() > 0 && cb.length() > 0); 406aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 407aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com ab.normalize(); 408aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector abN; 409aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com abN.setOrthog(ab, SkVector::kLeft_Side); 410aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (abN.dot(ac) > 0) { 411aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com abN.negate(); 412aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 413aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 414aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com cb.normalize(); 415aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector cbN; 416aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com cbN.setOrthog(cb, SkVector::kLeft_Side); 417aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (cbN.dot(ac) < 0) { 418aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com cbN.negate(); 419aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 420aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 421aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com a0.fPos = a; 422aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com a0.fPos += abN; 423aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com a1.fPos = a; 424aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com a1.fPos -= abN; 425aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 426aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com c0.fPos = c; 427aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com c0.fPos += cbN; 428aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com c1.fPos = c; 429aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com c1.fPos -= cbN; 430aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 4311dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com // This point may not be within 1 pixel of a control point. We update the bounding box to 4321dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com // include it. 433aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com intersect_lines(a0.fPos, abN, c0.fPos, cbN, &b0.fPos); 4341dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com devBounds->growToInclude(b0.fPos.fX, b0.fPos.fY); 435aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 436dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (toSrc) { 437dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toSrc->mapPointsWithStride(&verts[0].fPos, sizeof(Vertex), kVertsPerQuad); 438dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 4391971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com DevToUV.apply<kVertsPerQuad, sizeof(Vertex), sizeof(GrPoint)>(verts); 440aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 441aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 442aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comvoid add_quads(const SkPoint p[3], 443aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int subdiv, 444b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com const SkMatrix* toDevice, 445b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com const SkMatrix* toSrc, 4461dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com Vertex** vert, 4471dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com SkRect* devBounds) { 448aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(subdiv >= 0); 449aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (subdiv) { 450aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkPoint newP[5]; 451aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkChopQuadAtHalf(p, newP); 4521dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com add_quads(newP + 0, subdiv-1, toDevice, toSrc, vert, devBounds); 4531dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com add_quads(newP + 2, subdiv-1, toDevice, toSrc, vert, devBounds); 454aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 4551dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com bloat_quad(p, toDevice, toSrc, *vert, devBounds); 456aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com *vert += kVertsPerQuad; 457aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 458aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 459aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 460aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comvoid add_line(const SkPoint p[2], 461aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int rtHeight, 462dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com const SkMatrix* toSrc, 463aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com Vertex** vert) { 464aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const SkPoint& a = p[0]; 465aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const SkPoint& b = p[1]; 466aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 467aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector orthVec = b; 468aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com orthVec -= a; 469aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 470aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (orthVec.setLength(SK_Scalar1)) { 471aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com orthVec.setOrthog(orthVec); 472aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 473706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com SkScalar lineC = -(a.dot(orthVec)); 474aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com for (int i = 0; i < kVertsPerLineSeg; ++i) { 475aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[i].fPos = (i < 2) ? a : b; 476aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (0 == i || 3 == i) { 477aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[i].fPos -= orthVec; 478aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 479aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[i].fPos += orthVec; 480aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 481706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com (*vert)[i].fLine.fA = orthVec.fX; 482706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com (*vert)[i].fLine.fB = orthVec.fY; 483aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[i].fLine.fC = lineC; 484aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 485dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (NULL != toSrc) { 486dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toSrc->mapPointsWithStride(&(*vert)->fPos, 487dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com sizeof(Vertex), 488dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com kVertsPerLineSeg); 489dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 490aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 491aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // just make it degenerate and likely offscreen 492aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[0].fPos.set(SK_ScalarMax, SK_ScalarMax); 493aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[1].fPos.set(SK_ScalarMax, SK_ScalarMax); 494aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[2].fPos.set(SK_ScalarMax, SK_ScalarMax); 495aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[3].fPos.set(SK_ScalarMax, SK_ScalarMax); 496aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 497aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 498aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com *vert += kVertsPerLineSeg; 499aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 500aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 501aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 502aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 50390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 50490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 50590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/** 50690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * The output of this effect is a hairline edge for quadratics. 50790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * Quadratic specified by 0=u^2-v canonical coords. u and v are the first 50890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * two components of the vertex attribute. Uses unsigned distance. 509041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com * Coverage is min(0, 1-distance). 3rd & 4th component unused. 510041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com * Requires shader derivative instruction support. 51190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org */ 51290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgclass HairQuadEdgeEffect : public GrEffect { 51390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgpublic: 51490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 51590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org static GrEffectRef* Create() { 516d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com GR_CREATE_STATIC_EFFECT(gHairQuadEdgeEffect, HairQuadEdgeEffect, ()); 517d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com gHairQuadEdgeEffect->ref(); 518d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com return gHairQuadEdgeEffect; 51990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 52090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 52190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual ~HairQuadEdgeEffect() {} 52290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 52390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org static const char* Name() { return "HairQuadEdge"; } 52490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 525041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com virtual void getConstantColorComponents(GrColor* color, 52690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org uint32_t* validFlags) const SK_OVERRIDE { 52790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org *validFlags = 0; 52890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 52990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 53090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { 53190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org return GrTBackendEffectFactory<HairQuadEdgeEffect>::getInstance(); 53290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 53390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 53490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org class GLEffect : public GrGLEffect { 53590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org public: 53690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) 53790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org : INHERITED (factory) {} 53890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 53990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual void emitCode(GrGLShaderBuilder* builder, 54090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const GrDrawEffect& drawEffect, 54190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org EffectKey key, 54290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const char* outputColor, 54390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const char* inputColor, 54490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const TextureSamplerArray& samplers) SK_OVERRIDE { 54590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const char *vsName, *fsName; 54690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const SkString* attrName = 54790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); 54890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n"); 54990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 55090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org SkAssertResult(builder->enableFeature( 55190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GrGLShaderBuilder::kStandardDerivatives_GLSLFeature)); 55290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->addVarying(kVec4f_GrSLType, "HairQuadEdge", &vsName, &fsName); 55390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 55490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName); 55590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName); 55690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n" 55790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org "\t\t 2.0*%s.x*duvdy.x - duvdy.y);\n", 55890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org fsName, fsName); 55990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, 56090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org fsName); 56190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppend("\t\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / dot(gF, gF));\n"); 56290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); 56390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 56490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org SkString modulate; 565018f179efb2413431bdb1a9e6701eb44ef36b792bsalomon@google.com GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha"); 56690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str()); 56790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 56890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); 56990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 57090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 57190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { 57290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org return 0x0; 57390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 57490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 57590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {} 57690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 57790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org private: 57890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org typedef GrGLEffect INHERITED; 57990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org }; 58090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 58190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgprivate: 582041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com HairQuadEdgeEffect() { 583041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com this->addVertexAttrib(kVec4f_GrSLType); 58490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 58590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 58690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { 58790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org return true; 58890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 58990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 59090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GR_DECLARE_EFFECT_TEST; 59190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 59290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org typedef GrEffect INHERITED; 59390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org}; 59490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 59590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgGR_DEFINE_EFFECT_TEST(HairQuadEdgeEffect); 59690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 59790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgGrEffectRef* HairQuadEdgeEffect::TestCreate(SkMWCRandom* random, 59890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GrContext*, 59990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const GrDrawTargetCaps& caps, 60090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GrTexture*[]) { 60190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org // Doesn't work without derivative instructions. 60290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org return caps.shaderDerivativeSupport() ? HairQuadEdgeEffect::Create() : NULL;} 60390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 60490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 60590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 60690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/** 607041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com * The output of this effect is a 1-pixel wide line. 608041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com * Input is 2D implicit device coord line eq (a*x + b*y +c = 0). 4th component unused. 60990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org */ 61090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgclass HairLineEdgeEffect : public GrEffect { 61190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgpublic: 61290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 61390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org static GrEffectRef* Create() { 614d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com GR_CREATE_STATIC_EFFECT(gHairLineEdge, HairLineEdgeEffect, ()); 615d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com gHairLineEdge->ref(); 616d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com return gHairLineEdge; 61790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 61890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 61990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual ~HairLineEdgeEffect() {} 62090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 62190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org static const char* Name() { return "HairLineEdge"; } 62290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 623041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com virtual void getConstantColorComponents(GrColor* color, 62490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org uint32_t* validFlags) const SK_OVERRIDE { 62590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org *validFlags = 0; 62690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 62790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 62890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { 62990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org return GrTBackendEffectFactory<HairLineEdgeEffect>::getInstance(); 63090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 63190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 63290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org class GLEffect : public GrGLEffect { 63390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org public: 63490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) 63590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org : INHERITED (factory) {} 63690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 63790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual void emitCode(GrGLShaderBuilder* builder, 63890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const GrDrawEffect& drawEffect, 63990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org EffectKey key, 64090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const char* outputColor, 64190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const char* inputColor, 64290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const TextureSamplerArray& samplers) SK_OVERRIDE { 64390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const char *vsName, *fsName; 64490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const SkString* attrName = 64590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); 64690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n"); 64790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 64890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->addVarying(kVec4f_GrSLType, "HairLineEdge", &vsName, &fsName); 64990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 65090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\tedgeAlpha = abs(dot(vec3(%s.xy,1), %s.xyz));\n", 65190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fragmentPosition(), fsName); 65290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); 65390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 65490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org SkString modulate; 655018f179efb2413431bdb1a9e6701eb44ef36b792bsalomon@google.com GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha"); 65690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str()); 65790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 65890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); 65990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 66090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 66190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { 66290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org return 0x0; 66390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 66490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 66590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {} 66690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 66790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org private: 66890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org typedef GrGLEffect INHERITED; 66990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org }; 67090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 67190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgprivate: 672041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com HairLineEdgeEffect() { 673041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com this->addVertexAttrib(kVec4f_GrSLType); 6748d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org this->setWillReadFragmentPosition(); 67590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 67690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 67790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { 67890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org return true; 67990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 68090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 68190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GR_DECLARE_EFFECT_TEST; 68290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 68390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org typedef GrEffect INHERITED; 68490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org}; 68590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 68690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgGR_DEFINE_EFFECT_TEST(HairLineEdgeEffect); 68790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 68890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgGrEffectRef* HairLineEdgeEffect::TestCreate(SkMWCRandom* random, 68990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GrContext*, 69090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const GrDrawTargetCaps& caps, 69190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GrTexture*[]) { 69290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org return HairLineEdgeEffect::Create(); 69390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org} 69490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 69590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 69690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 697429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.comnamespace { 698429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com 699429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com// position + edge 700429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.comextern const GrVertexAttrib gHairlineAttribs[] = { 701429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, 702429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding} 703429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com}; 704429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com 705429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com}; 706429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com 707b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.combool GrAAHairLinePathRenderer::createGeom( 708b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com const SkPath& path, 709b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com GrDrawTarget* target, 710b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com int* lineCnt, 711b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com int* quadCnt, 7121dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com GrDrawTarget::AutoReleaseGeometry* arg, 7131dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com SkRect* devBounds) { 7149b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com GrDrawState* drawState = target->drawState(); 7159b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com int rtHeight = drawState->getRenderTarget()->height(); 716aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 7177b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com GrIRect devClipBounds; 7189b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com target->getClip()->getConservativeBounds(drawState->getRenderTarget(), 7197b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com &devClipBounds); 720aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 7219b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com SkMatrix viewM = drawState->getViewMatrix(); 722aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 7231dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com // All the vertices that we compute are within 1 of path control points with the exception of 7241dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com // one of the bounding vertices for each quad. The add_quads() function will update the bounds 7251dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com // for each quad added. 7261dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com *devBounds = path.getBounds(); 7271dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com viewM.mapRect(devBounds); 7281dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com devBounds->outset(SK_Scalar1, SK_Scalar1); 7291dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com 73092669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com PREALLOC_PTARRAY(128) lines; 73192669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com PREALLOC_PTARRAY(128) quads; 732aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com IntArray qSubdivs; 7330f11e1ab5b6e53f6176dde2dbb25a8e3ae34858fbsalomon@google.com *quadCnt = generate_lines_and_quads(path, viewM, devClipBounds, 734dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com &lines, &quads, &qSubdivs); 735aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 736c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com *lineCnt = lines.count() / 2; 737c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com int vertCnt = kVertsPerLineSeg * *lineCnt + kVertsPerQuad * *quadCnt; 738aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 739429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com target->drawState()->setVertexAttribs<gHairlineAttribs>(SK_ARRAY_COUNT(gHairlineAttribs)); 740b75b0a0b8492e14c7728e0a0881f87dc64ce60f9jvanverth@google.com GrAssert(sizeof(Vertex) == target->getDrawState().getVertexSize()); 741aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 742b75b0a0b8492e14c7728e0a0881f87dc64ce60f9jvanverth@google.com if (!arg->set(target, vertCnt, 0)) { 743aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return false; 744aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 745dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com 746b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com Vertex* verts = reinterpret_cast<Vertex*>(arg->vertices()); 747b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com 748b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com const SkMatrix* toDevice = NULL; 749b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com const SkMatrix* toSrc = NULL; 750b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com SkMatrix ivm; 751dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com 752dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (viewM.hasPerspective()) { 753dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (viewM.invert(&ivm)) { 754dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toDevice = &viewM; 755dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toSrc = &ivm; 756dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 757dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 758aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 759c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com for (int i = 0; i < *lineCnt; ++i) { 760dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com add_line(&lines[2*i], rtHeight, toSrc, &verts); 761aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 762dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com 763aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int unsubdivQuadCnt = quads.count() / 3; 764aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com for (int i = 0; i < unsubdivQuadCnt; ++i) { 765aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(qSubdivs[i] >= 0); 7661dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts, devBounds); 767aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 768aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 769aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return true; 770aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 771aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 7728a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.combool GrAAHairLinePathRenderer::canDrawPath(const SkPath& path, 7735f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com const SkStrokeRec& stroke, 7748a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com const GrDrawTarget* target, 7758a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com bool antiAlias) const { 7765f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com if (!stroke.isHairlineStyle() || !antiAlias) { 777c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return false; 778c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com } 779c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 780c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com static const uint32_t gReqDerivMask = SkPath::kCubic_SegmentMask | 781c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com SkPath::kQuad_SegmentMask; 782bcce8926524827775539874346dd424a9510dbc9bsalomon@google.com if (!target->caps()->shaderDerivativeSupport() && 783c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com (gReqDerivMask & path.getSegmentMasks())) { 784c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return false; 785c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com } 786c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return true; 787c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com} 788aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 789c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.combool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path, 7905f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com const SkStrokeRec&, 791c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com GrDrawTarget* target, 792c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com bool antiAlias) { 793c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 794c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com int lineCnt; 795c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com int quadCnt; 796b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com GrDrawTarget::AutoReleaseGeometry arg; 7971dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com SkRect devBounds; 7981dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com 799c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com if (!this->createGeom(path, 800c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com target, 801c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com &lineCnt, 802b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com &quadCnt, 8031dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com &arg, 8041dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com &devBounds)) { 805c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return false; 806aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 807aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 8084647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kPreserve_ASRInit); 809873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com GrDrawState* drawState = target->drawState(); 8104647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com 8114647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com GrDrawState::AutoDeviceCoordDraw adcd; 812a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com // createGeom transforms the geometry to device space when the matrix does not have 813a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com // perspective. 8148f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com if (!drawState->getViewMatrix().hasPerspective()) { 815a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com adcd.set(drawState); 816a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com if (!adcd.succeeded()) { 817e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com return false; 818dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 819aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 820fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 821aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // TODO: See whether rendering lines as degenerate quads improves perf 822aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // when we have a mix 823a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com 8244647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com enum { 8254647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com // the edge effects share this stage with glyph rendering 8264647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com // (kGlyphMaskStage in GrTextContext) && SW path rendering 8274647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com // (kPathMaskStage in GrSWMaskHelper) 8284647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com kEdgeEffectStage = GrPaint::kTotalStages, 8294647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com }; 8304647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com static const int kEdgeAttrIndex = 1; 831a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com 83290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GrEffectRef* hairLineEffect = HairLineEdgeEffect::Create(); 83390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org GrEffectRef* hairQuadEffect = HairQuadEdgeEffect::Create(); 83437cbc7fd014e3b35833523dbdbe3bc3ac52ecacdskia.committer@gmail.com 8351dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com // Check devBounds 8361dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com#if GR_DEBUG 8371dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com SkRect tolDevBounds = devBounds; 8381dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com tolDevBounds.outset(SK_Scalar1 / 10000, SK_Scalar1 / 10000); 8391dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com SkRect actualBounds; 8401dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com Vertex* verts = reinterpret_cast<Vertex*>(arg.vertices()); 8411dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com int vCount = kVertsPerLineSeg * lineCnt + kVertsPerQuad * quadCnt; 8421dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com bool first = true; 8431dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com for (int i = 0; i < vCount; ++i) { 8441dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com SkPoint pos = verts[i].fPos; 8451dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com // This is a hack to workaround the fact that we move some degenerate segments offscreen. 8461dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com if (SK_ScalarMax == pos.fX) { 8471dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com continue; 8481dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com } 8491dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com drawState->getViewMatrix().mapPoints(&pos, 1); 8501dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com if (first) { 8511dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com actualBounds.set(pos.fX, pos.fY, pos.fX, pos.fY); 8521dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com first = false; 8531dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com } else { 8541dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com actualBounds.growToInclude(pos.fX, pos.fY); 8551dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com } 8561dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com } 8571dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com if (!first) { 8581dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com GrAssert(tolDevBounds.contains(actualBounds)); 8591dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com } 8601dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com#endif 8611dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com 862c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com target->setIndexSourceToBuffer(fLinesIndexBuffer); 863aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int lines = 0; 864aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int nBufLines = fLinesIndexBuffer->maxQuads(); 8654647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com drawState->setEffect(kEdgeEffectStage, hairLineEffect, kEdgeAttrIndex)->unref(); 866c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com while (lines < lineCnt) { 867c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com int n = GrMin(lineCnt - lines, nBufLines); 86847059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com target->drawIndexed(kTriangles_GrPrimitiveType, 869c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com kVertsPerLineSeg*lines, // startV 870c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 0, // startI 871c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com kVertsPerLineSeg*n, // vCount 8721dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com kIdxsPerLineSeg*n, 8731dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com &devBounds); // iCount 874aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com lines += n; 875aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 876aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 877c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com target->setIndexSourceToBuffer(fQuadsIndexBuffer); 878aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int quads = 0; 8794647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com drawState->setEffect(kEdgeEffectStage, hairQuadEffect, kEdgeAttrIndex)->unref(); 880c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com while (quads < quadCnt) { 881c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com int n = GrMin(quadCnt - quads, kNumQuadsInIdxBuffer); 88247059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com target->drawIndexed(kTriangles_GrPrimitiveType, 883c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 4 * lineCnt + kVertsPerQuad*quads, // startV 884c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 0, // startI 885c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com kVertsPerQuad*n, // vCount 8861dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com kIdxsPerQuad*n, // iCount 8871dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com &devBounds); 888aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com quads += n; 889aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 8900406b9e1faee06c6ecb2732a1bcf3b0e53104e07bsalomon@google.com target->resetIndexSource(); 8914647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com 892c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return true; 893aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 894