GrAAHairLinePathRenderer.cpp revision 3b0d631cdfe2dcf59e7b7ea60d92566eade7bfc0
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" 13aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#include "GrGpu.h" 14aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#include "GrIndexBuffer.h" 15dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com#include "GrPathUtils.h" 16aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#include "SkGeometry.h" 1712b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com#include "SkStroke.h" 18aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#include "SkTemplates.h" 19aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 20aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comnamespace { 21aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com// quadratics are rendered as 5-sided polys in order to bound the 22aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com// AA stroke around the center-curve. See comments in push_quad_index_buffer and 23aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com// bloat_quad. 24aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comstatic const int kVertsPerQuad = 5; 25aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comstatic const int kIdxsPerQuad = 9; 26aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 27aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comstatic const int kVertsPerLineSeg = 4; 28aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comstatic const int kIdxsPerLineSeg = 6; 29aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 30aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comstatic const int kNumQuadsInIdxBuffer = 256; 31aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comstatic const size_t kQuadIdxSBufize = kIdxsPerQuad * 32aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com sizeof(uint16_t) * 33aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com kNumQuadsInIdxBuffer; 34aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 35aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.combool push_quad_index_data(GrIndexBuffer* qIdxBuffer) { 36aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com uint16_t* data = (uint16_t*) qIdxBuffer->lock(); 37aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bool tempData = NULL == data; 38aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (tempData) { 39c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com data = SkNEW_ARRAY(uint16_t, kNumQuadsInIdxBuffer * kIdxsPerQuad); 40aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 41aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com for (int i = 0; i < kNumQuadsInIdxBuffer; ++i) { 42aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 43aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // Each quadratic is rendered as a five sided polygon. This poly bounds 44aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // the quadratic's bounding triangle but has been expanded so that the 45aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // 1-pixel wide area around the curve is inside the poly. 46aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // If a,b,c are the original control points then the poly a0,b0,c0,c1,a1 47aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // that is rendered would look like this: 48aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // b0 49aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // b 50aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // 51aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // a0 c0 52aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // a c 53aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // a1 c1 540e5104c1570de4709e04720e62d80a0ca8970260bsalomon@google.com // Each is drawn as three triangles specified by these 9 indices: 55aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int baseIdx = i * kIdxsPerQuad; 56aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com uint16_t baseVert = (uint16_t)(i * kVertsPerQuad); 57aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[0 + baseIdx] = baseVert + 0; // a0 58aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[1 + baseIdx] = baseVert + 1; // a1 59aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[2 + baseIdx] = baseVert + 2; // b0 60aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[3 + baseIdx] = baseVert + 2; // b0 61aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[4 + baseIdx] = baseVert + 4; // c1 62aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[5 + baseIdx] = baseVert + 3; // c0 63aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[6 + baseIdx] = baseVert + 1; // a1 64aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[7 + baseIdx] = baseVert + 4; // c1 65aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com data[8 + baseIdx] = baseVert + 2; // b0 66aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 67aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (tempData) { 68aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bool ret = qIdxBuffer->updateData(data, kQuadIdxSBufize); 69aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com delete[] data; 70aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return ret; 71aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 72aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com qIdxBuffer->unlock(); 73aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return true; 74aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 75aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 76aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 77aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 78aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comGrPathRenderer* GrAAHairLinePathRenderer::Create(GrContext* context) { 79a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com const GrIndexBuffer* lIdxBuffer = context->getQuadIndexBuffer(); 80a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com if (NULL == lIdxBuffer) { 81aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return NULL; 82aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 83a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com GrGpu* gpu = context->getGpu(); 84a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com GrIndexBuffer* qIdxBuf = gpu->createIndexBuffer(kQuadIdxSBufize, false); 85a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com SkAutoTUnref<GrIndexBuffer> qIdxBuffer(qIdxBuf); 86a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com if (NULL == qIdxBuf || 87a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com !push_quad_index_data(qIdxBuf)) { 88a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com return NULL; 89a8a6a32f428e77ee865780ad93bd5f8e1ce3c687bsalomon@google.com } 90c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com return SkNEW_ARGS(GrAAHairLinePathRenderer, 91c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com (context, lIdxBuffer, qIdxBuf)); 92aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 93aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 94aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comGrAAHairLinePathRenderer::GrAAHairLinePathRenderer( 95aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const GrContext* context, 96aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const GrIndexBuffer* linesIndexBuffer, 97aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const GrIndexBuffer* quadsIndexBuffer) { 98aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com fLinesIndexBuffer = linesIndexBuffer; 99aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com linesIndexBuffer->ref(); 100aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com fQuadsIndexBuffer = quadsIndexBuffer; 101aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com quadsIndexBuffer->ref(); 102aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 103aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 104aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comGrAAHairLinePathRenderer::~GrAAHairLinePathRenderer() { 105aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com fLinesIndexBuffer->unref(); 106aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com fQuadsIndexBuffer->unref(); 107aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 108aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 109aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comnamespace { 110aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 11149313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.comtypedef SkTArray<SkPoint, true> PtArray; 11292669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com#define PREALLOC_PTARRAY(N) SkSTArray<(N),SkPoint, true> 11349313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.comtypedef SkTArray<int, true> IntArray; 114aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 115aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com// Takes 178th time of logf on Z600 / VC2010 116aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comint get_float_exp(float x) { 117aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GR_STATIC_ASSERT(sizeof(int) == sizeof(float)); 118aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#if GR_DEBUG 119aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com static bool tested; 120aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (!tested) { 121aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com tested = true; 122aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(0.25f) == -2); 123aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(0.3f) == -2); 124aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(0.5f) == -1); 125aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(1.f) == 0); 126aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(2.f) == 1); 127aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(2.5f) == 1); 128aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(8.f) == 3); 129aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(100.f) == 6); 130aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(1000.f) == 9); 131aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(1024.f) == 10); 132aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(get_float_exp(3000000.f) == 21); 133aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 134aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#endif 1352ec7280a178ad3dcfd2e645bc330eeb04a84bfcfbsalomon@google.com const int* iptr = (const int*)&x; 1362ec7280a178ad3dcfd2e645bc330eeb04a84bfcfbsalomon@google.com return (((*iptr) & 0x7f800000) >> 23) - 127; 137aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 138aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 139aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com// we subdivide the quads to avoid huge overfill 140aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com// if it returns -1 then should be drawn as lines 141aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comint num_quad_subdivs(const SkPoint p[3]) { 142aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com static const SkScalar gDegenerateToLineTol = SK_Scalar1; 143fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com static const SkScalar gDegenerateToLineTolSqd = 14446a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com SkScalarMul(gDegenerateToLineTol, gDegenerateToLineTol); 14546a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com 14646a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com if (p[0].distanceToSqd(p[1]) < gDegenerateToLineTolSqd || 14746a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com p[1].distanceToSqd(p[2]) < gDegenerateToLineTolSqd) { 14846a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com return -1; 14946a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com } 150aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 15181712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar dsqd = p[1].distanceToLineBetweenSqd(p[0], p[2]); 15246a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com if (dsqd < gDegenerateToLineTolSqd) { 153aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return -1; 154aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 15546a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com 15646a2a1ee46b591b43a76f80d0c9d7e78b5a0a96cbsalomon@google.com if (p[2].distanceToLineBetweenSqd(p[1], p[0]) < gDegenerateToLineTolSqd) { 157aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return -1; 158aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 159aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 160aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com static const int kMaxSub = 4; 161aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // tolerance of triangle height in pixels 162aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // tuned on windows Quadro FX 380 / Z600 163aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // trade off of fill vs cpu time on verts 164aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // maybe different when do this using gpu (geo or tess shaders) 165aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com static const SkScalar gSubdivTol = 175 * SK_Scalar1; 166aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 1677460b378d68217167013ca889a4cdcae742908e7robertphillips@google.com if (dsqd <= SkScalarMul(gSubdivTol, gSubdivTol)) { 168aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return 0; 169aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 170aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // subdividing the quad reduces d by 4. so we want x = log4(d/tol) 171aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // = log4(d*d/tol*tol)/2 172aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // = log2(d*d/tol*tol) 173aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 174aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#ifdef SK_SCALAR_IS_FLOAT 175aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // +1 since we're ignoring the mantissa contribution. 176aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int log = get_float_exp(dsqd/(gSubdivTol*gSubdivTol)) + 1; 177aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com log = GrMin(GrMax(0, log), kMaxSub); 178aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return log; 179aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#else 1807460b378d68217167013ca889a4cdcae742908e7robertphillips@google.com SkScalar log = SkScalarLog( 181fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com SkScalarDiv(dsqd, 1827460b378d68217167013ca889a4cdcae742908e7robertphillips@google.com SkScalarMul(gSubdivTol, gSubdivTol))); 183aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com static const SkScalar conv = SkScalarInvert(SkScalarLog(2)); 184aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com log = SkScalarMul(log, conv); 185aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return GrMin(GrMax(0, SkScalarCeilToInt(log)),kMaxSub); 186aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com#endif 187aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 188aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 189aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 190dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com/** 191dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * Generates the lines and quads to be rendered. Lines are always recorded in 192dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * device space. We will do a device space bloat to account for the 1pixel 193dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * thickness. 194dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * Quads are recorded in device space unless m contains 195dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * perspective, then in they are in src space. We do this because we will 196dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * subdivide large quads to reduce over-fill. This subdivision has to be 197dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com * performed before applying the perspective matrix. 198dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com */ 199dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.comint generate_lines_and_quads(const SkPath& path, 200dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com const SkMatrix& m, 2017b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com const GrIRect& devClipBounds, 202dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com PtArray* lines, 203dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com PtArray* quads, 204dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com IntArray* quadSubdivCnts) { 205aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkPath::Iter iter(path, false); 206aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 207aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int totalQuadCount = 0; 208aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrRect bounds; 209aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrIRect ibounds; 210dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com 211dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bool persp = m.hasPerspective(); 212dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com 213aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com for (;;) { 214aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrPoint pts[4]; 215dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com GrPoint devPts[4]; 216aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrPathCmd cmd = (GrPathCmd)iter.next(pts); 217aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com switch (cmd) { 218aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com case kMove_PathCmd: 219aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com break; 220aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com case kLine_PathCmd: 221dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com m.mapPoints(devPts, pts, 2); 222dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bounds.setBounds(devPts, 2); 223aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.outset(SK_Scalar1, SK_Scalar1); 224aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.roundOut(&ibounds); 2257b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com if (SkIRect::Intersects(devClipBounds, ibounds)) { 226a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com SkPoint* pts = lines->push_back_n(2); 227a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[0] = devPts[0]; 228a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[1] = devPts[1]; 229aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 230aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com break; 231dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com case kQuadratic_PathCmd: 232dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com m.mapPoints(devPts, pts, 3); 233dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bounds.setBounds(devPts, 3); 234aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.outset(SK_Scalar1, SK_Scalar1); 235aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.roundOut(&ibounds); 2367b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com if (SkIRect::Intersects(devClipBounds, ibounds)) { 237dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com int subdiv = num_quad_subdivs(devPts); 238aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(subdiv >= -1); 239aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (-1 == subdiv) { 240a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com SkPoint* pts = lines->push_back_n(4); 241a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[0] = devPts[0]; 242a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[1] = devPts[1]; 243a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[2] = devPts[1]; 244a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[3] = devPts[2]; 245aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 246dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // when in perspective keep quads in src space 247dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com SkPoint* qPts = persp ? pts : devPts; 248a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com SkPoint* pts = quads->push_back_n(3); 249a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[0] = qPts[0]; 250a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[1] = qPts[1]; 251a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[2] = qPts[2]; 252aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com quadSubdivCnts->push_back() = subdiv; 253aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com totalQuadCount += 1 << subdiv; 254aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 255aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 256a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com break; 257dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com case kCubic_PathCmd: 258dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com m.mapPoints(devPts, pts, 4); 259dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bounds.setBounds(devPts, 4); 260aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.outset(SK_Scalar1, SK_Scalar1); 261aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.roundOut(&ibounds); 2627b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com if (SkIRect::Intersects(devClipBounds, ibounds)) { 26392669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com PREALLOC_PTARRAY(32) q; 264a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com // we don't need a direction if we aren't constraining the subdivision 265a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com static const SkPath::Direction kDummyDir = SkPath::kCCW_Direction; 26669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com // We convert cubics to quadratics (for now). 26769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com // In perspective have to do conversion in src space. 268dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (persp) { 269fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com SkScalar tolScale = 270dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com GrPathUtils::scaleToleranceToSrc(SK_Scalar1, m, 271dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com path.getBounds()); 272a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com GrPathUtils::convertCubicToQuads(pts, tolScale, false, kDummyDir, &q); 273dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } else { 274a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com GrPathUtils::convertCubicToQuads(devPts, SK_Scalar1, false, kDummyDir, &q); 275dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 276aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com for (int i = 0; i < q.count(); i += 3) { 277dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com SkPoint* qInDevSpace; 278dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // bounds has to be calculated in device space, but q is 279dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // in src space when there is perspective. 280dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (persp) { 281dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com m.mapPoints(devPts, &q[i], 3); 282dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bounds.setBounds(devPts, 3); 283dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com qInDevSpace = devPts; 284dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } else { 285dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bounds.setBounds(&q[i], 3); 286dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com qInDevSpace = &q[i]; 287dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 288aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.outset(SK_Scalar1, SK_Scalar1); 289aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com bounds.roundOut(&ibounds); 2907b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com if (SkIRect::Intersects(devClipBounds, ibounds)) { 291dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com int subdiv = num_quad_subdivs(qInDevSpace); 292aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(subdiv >= -1); 293aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (-1 == subdiv) { 294a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com SkPoint* pts = lines->push_back_n(4); 295dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // lines should always be in device coords 296a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[0] = qInDevSpace[0]; 297a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[1] = qInDevSpace[1]; 298a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[2] = qInDevSpace[1]; 299a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[3] = qInDevSpace[2]; 300aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 301a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com SkPoint* pts = quads->push_back_n(3); 302dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // q is already in src space when there is no 303dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // perspective and dev coords otherwise. 304a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[0] = q[0 + i]; 305a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[1] = q[1 + i]; 306a996fec40444e8b914cd84c17037f0c84301f717bsalomon@google.com pts[2] = q[2 + i]; 307aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com quadSubdivCnts->push_back() = subdiv; 308aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com totalQuadCount += 1 << subdiv; 309aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 310aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 311aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 312aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 313a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com break; 314aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com case kClose_PathCmd: 315aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com break; 316aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com case kEnd_PathCmd: 317aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return totalQuadCount; 318aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 319aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 320aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 321aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 322aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comstruct Vertex { 323aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrPoint fPos; 324aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com union { 325aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com struct { 32681712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar fA; 32781712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar fB; 32881712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar fC; 329aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } fLine; 330aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrVec fQuadCoord; 331aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com struct { 33281712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar fBogus[4]; 333aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com }; 334aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com }; 335aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com}; 336aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comGR_STATIC_ASSERT(sizeof(Vertex) == 3 * sizeof(GrPoint)); 337aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 338aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comvoid intersect_lines(const SkPoint& ptA, const SkVector& normA, 339aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const SkPoint& ptB, const SkVector& normB, 340aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkPoint* result) { 341aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 342aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkScalar lineAW = -normA.dot(ptA); 343aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkScalar lineBW = -normB.dot(ptB); 344aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 345aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkScalar wInv = SkScalarMul(normA.fX, normB.fY) - 346aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkScalarMul(normA.fY, normB.fX); 347aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com wInv = SkScalarInvert(wInv); 348aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 349aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com result->fX = SkScalarMul(normA.fY, lineBW) - SkScalarMul(lineAW, normB.fY); 350aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com result->fX = SkScalarMul(result->fX, wInv); 351fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 352aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com result->fY = SkScalarMul(lineAW, normB.fX) - SkScalarMul(normA.fX, lineBW); 353aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com result->fY = SkScalarMul(result->fY, wInv); 354aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 355aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 356b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.comvoid bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice, 357b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com const SkMatrix* toSrc, Vertex verts[kVertsPerQuad]) { 358dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com GrAssert(!toDevice == !toSrc); 359aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // original quad is specified by tri a,b,c 360dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com SkPoint a = qpts[0]; 361dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com SkPoint b = qpts[1]; 362dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com SkPoint c = qpts[2]; 363aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 364dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // this should be in the src space, not dev coords, when we have perspective 3651971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com GrPathUtils::QuadUVMatrix DevToUV(qpts); 366aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 367dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (toDevice) { 368dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toDevice->mapPoints(&a, 1); 369dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toDevice->mapPoints(&b, 1); 370dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toDevice->mapPoints(&c, 1); 371dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 372dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // make a new poly where we replace a and c by a 1-pixel wide edges orthog 373dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // to edges ab and bc: 374dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // 375dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // before | after 376dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // | b0 377dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // b | 378dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // | 379dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // | a0 c0 380dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // a c | a1 c1 381dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // 382dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // edges a0->b0 and b0->c0 are parallel to original edges a->b and b->c, 383dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com // respectively. 384dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com Vertex& a0 = verts[0]; 385dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com Vertex& a1 = verts[1]; 386dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com Vertex& b0 = verts[2]; 387dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com Vertex& c0 = verts[3]; 388dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com Vertex& c1 = verts[4]; 389dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com 390aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector ab = b; 391aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com ab -= a; 392aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector ac = c; 393aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com ac -= a; 394aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector cb = b; 395aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com cb -= c; 396aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 397aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // We should have already handled degenerates 398aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(ab.length() > 0 && cb.length() > 0); 399aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 400aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com ab.normalize(); 401aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector abN; 402aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com abN.setOrthog(ab, SkVector::kLeft_Side); 403aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (abN.dot(ac) > 0) { 404aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com abN.negate(); 405aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 406aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 407aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com cb.normalize(); 408aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector cbN; 409aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com cbN.setOrthog(cb, SkVector::kLeft_Side); 410aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (cbN.dot(ac) < 0) { 411aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com cbN.negate(); 412aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 413aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 414aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com a0.fPos = a; 415aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com a0.fPos += abN; 416aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com a1.fPos = a; 417aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com a1.fPos -= abN; 418aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 419aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com c0.fPos = c; 420aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com c0.fPos += cbN; 421aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com c1.fPos = c; 422aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com c1.fPos -= cbN; 423aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 424aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com intersect_lines(a0.fPos, abN, c0.fPos, cbN, &b0.fPos); 425aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 426dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (toSrc) { 427dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toSrc->mapPointsWithStride(&verts[0].fPos, sizeof(Vertex), kVertsPerQuad); 428dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 4291971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com DevToUV.apply<kVertsPerQuad, sizeof(Vertex), sizeof(GrPoint)>(verts); 430aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 431aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 432aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comvoid add_quads(const SkPoint p[3], 433aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int subdiv, 434b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com const SkMatrix* toDevice, 435b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com const SkMatrix* toSrc, 436aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com Vertex** vert) { 437aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(subdiv >= 0); 438aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (subdiv) { 439aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkPoint newP[5]; 440aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkChopQuadAtHalf(p, newP); 441dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com add_quads(newP + 0, subdiv-1, toDevice, toSrc, vert); 442dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com add_quads(newP + 2, subdiv-1, toDevice, toSrc, vert); 443aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 444dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com bloat_quad(p, toDevice, toSrc, *vert); 445aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com *vert += kVertsPerQuad; 446aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 447aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 448aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 449aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.comvoid add_line(const SkPoint p[2], 450aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int rtHeight, 451dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com const SkMatrix* toSrc, 452aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com Vertex** vert) { 453aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const SkPoint& a = p[0]; 454aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com const SkPoint& b = p[1]; 455aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 456aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com SkVector orthVec = b; 457aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com orthVec -= a; 458aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 459aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (orthVec.setLength(SK_Scalar1)) { 460aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com orthVec.setOrthog(orthVec); 461aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 462706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com SkScalar lineC = -(a.dot(orthVec)); 463aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com for (int i = 0; i < kVertsPerLineSeg; ++i) { 464aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[i].fPos = (i < 2) ? a : b; 465aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com if (0 == i || 3 == i) { 466aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[i].fPos -= orthVec; 467aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 468aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[i].fPos += orthVec; 469aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 470706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com (*vert)[i].fLine.fA = orthVec.fX; 471706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com (*vert)[i].fLine.fB = orthVec.fY; 472aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[i].fLine.fC = lineC; 473aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 474dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (NULL != toSrc) { 475dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toSrc->mapPointsWithStride(&(*vert)->fPos, 476dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com sizeof(Vertex), 477dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com kVertsPerLineSeg); 478dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 479aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } else { 480aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // just make it degenerate and likely offscreen 481aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[0].fPos.set(SK_ScalarMax, SK_ScalarMax); 482aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[1].fPos.set(SK_ScalarMax, SK_ScalarMax); 483aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[2].fPos.set(SK_ScalarMax, SK_ScalarMax); 484aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com (*vert)[3].fPos.set(SK_ScalarMax, SK_ScalarMax); 485aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 486aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 487aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com *vert += kVertsPerLineSeg; 488aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 489aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 490aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 491aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 492b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.combool GrAAHairLinePathRenderer::createGeom( 493b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com const SkPath& path, 494b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com GrDrawTarget* target, 495b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com int* lineCnt, 496b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com int* quadCnt, 497b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com GrDrawTarget::AutoReleaseGeometry* arg) { 4989b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com GrDrawState* drawState = target->drawState(); 4999b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com int rtHeight = drawState->getRenderTarget()->height(); 500aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 5017b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com GrIRect devClipBounds; 5029b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com target->getClip()->getConservativeBounds(drawState->getRenderTarget(), 5037b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com &devClipBounds); 504aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 5059b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com // position + edge 5069b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com static const GrVertexAttrib kAttribs[] = { 5073b0d631cdfe2dcf59e7b7ea60d92566eade7bfc0jvanverth@google.com {kVec2f_GrVertexAttribType, 0}, 5083b0d631cdfe2dcf59e7b7ea60d92566eade7bfc0jvanverth@google.com {kVec4f_GrVertexAttribType, sizeof(GrPoint)} 5099b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com }; 5109b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com static const GrAttribBindings kBindings = GrDrawState::kEdge_AttribBindingsBit; 5119b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com SkMatrix viewM = drawState->getViewMatrix(); 512aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 51392669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com PREALLOC_PTARRAY(128) lines; 51492669014aa7ab821cdc09cc9ad610316eb16b490bsalomon@google.com PREALLOC_PTARRAY(128) quads; 515aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com IntArray qSubdivs; 5160f11e1ab5b6e53f6176dde2dbb25a8e3ae34858fbsalomon@google.com *quadCnt = generate_lines_and_quads(path, viewM, devClipBounds, 517dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com &lines, &quads, &qSubdivs); 518aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 519c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com *lineCnt = lines.count() / 2; 520c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com int vertCnt = kVertsPerLineSeg * *lineCnt + kVertsPerQuad * *quadCnt; 521aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 5229b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com target->drawState()->setVertexAttribs(kAttribs, SK_ARRAY_COUNT(kAttribs)); 5239b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com target->drawState()->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0); 5249b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com target->drawState()->setAttribIndex(GrDrawState::kEdge_AttribIndex, 1); 5259b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com target->drawState()->setAttribBindings(kBindings); 526b75b0a0b8492e14c7728e0a0881f87dc64ce60f9jvanverth@google.com GrAssert(sizeof(Vertex) == target->getDrawState().getVertexSize()); 527aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 528b75b0a0b8492e14c7728e0a0881f87dc64ce60f9jvanverth@google.com if (!arg->set(target, vertCnt, 0)) { 529aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return false; 530aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 531dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com 532b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com Vertex* verts = reinterpret_cast<Vertex*>(arg->vertices()); 533b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com 534b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com const SkMatrix* toDevice = NULL; 535b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com const SkMatrix* toSrc = NULL; 536b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com SkMatrix ivm; 537dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com 538dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (viewM.hasPerspective()) { 539dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com if (viewM.invert(&ivm)) { 540dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toDevice = &viewM; 541dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com toSrc = &ivm; 542dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 543dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 544aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 545c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com for (int i = 0; i < *lineCnt; ++i) { 546dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com add_line(&lines[2*i], rtHeight, toSrc, &verts); 547aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 548dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com 549aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int unsubdivQuadCnt = quads.count() / 3; 550aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com for (int i = 0; i < unsubdivQuadCnt; ++i) { 551aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com GrAssert(qSubdivs[i] >= 0); 552dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts); 553aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 554aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 555aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com return true; 556aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 557aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 5588a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.combool GrAAHairLinePathRenderer::canDrawPath(const SkPath& path, 5595f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com const SkStrokeRec& stroke, 5608a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com const GrDrawTarget* target, 5618a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com bool antiAlias) const { 5625f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com if (!stroke.isHairlineStyle() || !antiAlias) { 563c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return false; 564c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com } 565c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 566c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com static const uint32_t gReqDerivMask = SkPath::kCubic_SegmentMask | 567c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com SkPath::kQuad_SegmentMask; 568f66018798099750e639a8fa131fece492a050997bsalomon@google.com if (!target->getCaps().shaderDerivativeSupport() && 569c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com (gReqDerivMask & path.getSegmentMasks())) { 570c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return false; 571c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com } 572c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return true; 573c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com} 574aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 575c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.combool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path, 5765f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com const SkStrokeRec&, 577c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com GrDrawTarget* target, 578c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com bool antiAlias) { 579c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 580c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com int lineCnt; 581c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com int quadCnt; 582b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com GrDrawTarget::AutoReleaseGeometry arg; 583c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com if (!this->createGeom(path, 584c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com target, 585c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com &lineCnt, 586b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com &quadCnt, 587b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com &arg)) { 588c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return false; 589aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 590aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 591a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com GrDrawState::AutoDeviceCoordDraw adcd; 592873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com GrDrawState* drawState = target->drawState(); 593a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com // createGeom transforms the geometry to device space when the matrix does not have 594a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com // perspective. 5958f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com if (!drawState->getViewMatrix().hasPerspective()) { 596a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com adcd.set(drawState); 597a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com if (!adcd.succeeded()) { 598e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com return false; 599dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com } 600aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 601fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 602aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // TODO: See whether rendering lines as degenerate quads improves perf 603aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com // when we have a mix 604a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com 605a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com GrDrawState::VertexEdgeType oldEdgeType = drawState->getVertexEdgeType(); 606a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com 607c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com target->setIndexSourceToBuffer(fLinesIndexBuffer); 608aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int lines = 0; 609aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int nBufLines = fLinesIndexBuffer->maxQuads(); 610a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com drawState->setVertexEdgeType(GrDrawState::kHairLine_EdgeType); 611c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com while (lines < lineCnt) { 612c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com int n = GrMin(lineCnt - lines, nBufLines); 61347059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com target->drawIndexed(kTriangles_GrPrimitiveType, 614c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com kVertsPerLineSeg*lines, // startV 615c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 0, // startI 616c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com kVertsPerLineSeg*n, // vCount 617c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com kIdxsPerLineSeg*n); // iCount 618aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com lines += n; 619aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 620aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com 621c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com target->setIndexSourceToBuffer(fQuadsIndexBuffer); 622aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com int quads = 0; 623a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com drawState->setVertexEdgeType(GrDrawState::kHairQuad_EdgeType); 624c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com while (quads < quadCnt) { 625c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com int n = GrMin(quadCnt - quads, kNumQuadsInIdxBuffer); 62647059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com target->drawIndexed(kTriangles_GrPrimitiveType, 627c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 4 * lineCnt + kVertsPerQuad*quads, // startV 628c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 0, // startI 629c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com kVertsPerQuad*n, // vCount 630c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com kIdxsPerQuad*n); // iCount 631aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com quads += n; 632aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com } 633a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com drawState->setVertexEdgeType(oldEdgeType); 634c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return true; 635aeb2160b1dd34f8e640e8e56544fe407d4ff6311bsalomon@google.com} 636