GrAAConvexPathRenderer.cpp revision c369e7c9992a86151a3ea0516ce5308c211b196b
169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com/* 369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com * Copyright 2012 Google Inc. 469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com * 569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com * Use of this source code is governed by a BSD-style license that can be 669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com * found in the LICENSE file. 769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com */ 869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com#include "GrAAConvexPathRenderer.h" 1069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 1169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com#include "GrContext.h" 1269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com#include "GrDrawState.h" 13c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrDrawTargetCaps.h" 14b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrProcessor.h" 1569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com#include "GrPathUtils.h" 16b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrTBackendProcessorFactory.h" 1769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com#include "SkString.h" 185f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com#include "SkStrokeRec.h" 19933e65d914eb86b1fbbf8ea9cf1da58ac7c42500commit-bot@chromium.org#include "SkTraceEvent.h" 2069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 2147bb38283072dc87dc93220cd2f370ca109972ffjoshualitt#include "gl/builders/GrGLProgramBuilder.h" 22b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "gl/GrGLProcessor.h" 2390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org#include "gl/GrGLSL.h" 24249af15fb82833d2274850c589812b6e69df0033joshualitt#include "gl/GrGLGeometryProcessor.h" 254647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com 26b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrGeometryProcessor.h" 27234d4fba75aac009e34c088037fcd9e244798c40commit-bot@chromium.org 2869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.comGrAAConvexPathRenderer::GrAAConvexPathRenderer() { 2969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com} 3069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 3169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.comstruct Segment { 3269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com enum { 339b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com // These enum values are assumed in member functions below. 349b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com kLine = 0, 359b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com kQuad = 1, 3669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } fType; 379b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com 389aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // line uses one pt, quad uses 2 pts 39972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkPoint fPts[2]; 409aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // normal to edge ending at each pt 41972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkVector fNorms[2]; 429aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // is the corner where the previous segment meets this segment 439aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // sharp. If so, fMid is a normalized bisector facing outward. 44972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkVector fMid; 459aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 469aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int countPoints() { 479b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com GR_STATIC_ASSERT(0 == kLine && 1 == kQuad); 489b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com return fType + 1; 499aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com } 509aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com const SkPoint& endPt() const { 519b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com GR_STATIC_ASSERT(0 == kLine && 1 == kQuad); 529b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com return fPts[fType]; 539aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com }; 549aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com const SkPoint& endNorm() const { 559b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com GR_STATIC_ASSERT(0 == kLine && 1 == kQuad); 569b1517edc7eb3e116902a3b3da447a73aaa56585bsalomon@google.com return fNorms[fType]; 579aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com }; 5869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com}; 5969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 6069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.comtypedef SkTArray<Segment, true> SegmentArray; 6169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 62fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic void center_of_mass(const SegmentArray& segments, SkPoint* c) { 6381712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar area = 0; 646390c72cfb3e371a774a627d5f496dc67558e119vandebo@chromium.org SkPoint center = {0, 0}; 659aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int count = segments.count(); 666390c72cfb3e371a774a627d5f496dc67558e119vandebo@chromium.org SkPoint p0 = {0, 0}; 675b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com if (count > 2) { 685b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com // We translate the polygon so that the first point is at the origin. 695b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com // This avoids some precision issues with small area polygons far away 705b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com // from the origin. 715b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com p0 = segments[0].endPt(); 725b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com SkPoint pi; 735b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com SkPoint pj; 74a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com // the first and last iteration of the below loop would compute 755b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com // zeros since the starting / ending point is (0,0). So instead we start 765b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com // at i=1 and make the last iteration i=count-2. 775b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com pj = segments[1].endPt() - p0; 785b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com for (int i = 1; i < count - 1; ++i) { 795b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com pi = pj; 805b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com const SkPoint pj = segments[i + 1].endPt() - p0; 815b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com 8281712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar t = SkScalarMul(pi.fX, pj.fY) - SkScalarMul(pj.fX, pi.fY); 835b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com area += t; 845b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com center.fX += (pi.fX + pj.fX) * t; 855b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com center.fY += (pi.fY + pj.fY) * t; 865b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com 875b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com } 889aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com } 89278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com // If the poly has no area then we instead return the average of 90278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com // its points. 915b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com if (SkScalarNearlyZero(area)) { 92278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com SkPoint avg; 93278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com avg.set(0, 0); 94278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com for (int i = 0; i < count; ++i) { 95278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com const SkPoint& pt = segments[i].endPt(); 96278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com avg.fX += pt.fX; 97278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com avg.fY += pt.fY; 98278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com } 99278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com SkScalar denom = SK_Scalar1 / count; 100278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com avg.scale(denom); 101278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com *c = avg; 102278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com } else { 103278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com area *= 3; 10481712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com area = SkScalarDiv(SK_Scalar1, area); 10581712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com center.fX = SkScalarMul(center.fX, area); 10681712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com center.fY = SkScalarMul(center.fY, area); 1075b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com // undo the translate of p0 to the origin. 1085b56d9e43fee4393f25f41d400981ce3960cd1aabsalomon@google.com *c = center + p0; 109278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com } 110f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(!SkScalarIsNaN(c->fX) && !SkScalarIsNaN(c->fY)); 1119aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com} 1129aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 113fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic void compute_vectors(SegmentArray* segments, 114fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org SkPoint* fanPt, 115fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org SkPath::Direction dir, 116fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org int* vCount, 117fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org int* iCount) { 1189aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com center_of_mass(*segments, fanPt); 1199aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int count = segments->count(); 1209aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 121278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com // Make the normals point towards the outside 122972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkPoint::Side normSide; 123278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com if (dir == SkPath::kCCW_Direction) { 124972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org normSide = SkPoint::kRight_Side; 125278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com } else { 126972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org normSide = SkPoint::kLeft_Side; 127278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com } 1289aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 1299aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com *vCount = 0; 1309aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com *iCount = 0; 1319aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // compute normals at all points 1329aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com for (int a = 0; a < count; ++a) { 1337d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com Segment& sega = (*segments)[a]; 1349aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int b = (a + 1) % count; 1359aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com Segment& segb = (*segments)[b]; 1369aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 137972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org const SkPoint* prevPt = &sega.endPt(); 1389aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int n = segb.countPoints(); 1399aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com for (int p = 0; p < n; ++p) { 1409aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com segb.fNorms[p] = segb.fPts[p] - *prevPt; 1419aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com segb.fNorms[p].normalize(); 1429aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com segb.fNorms[p].setOrthog(segb.fNorms[p], normSide); 1439aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com prevPt = &segb.fPts[p]; 1449aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com } 1459aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com if (Segment::kLine == segb.fType) { 1469aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com *vCount += 5; 1479aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com *iCount += 9; 1489aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com } else { 1499aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com *vCount += 6; 1509aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com *iCount += 12; 1519aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com } 1529aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com } 1539aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 1549aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // compute mid-vectors where segments meet. TODO: Detect shallow corners 1559aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // and leave out the wedges and close gaps by stitching segments together. 1569aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com for (int a = 0; a < count; ++a) { 1579aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com const Segment& sega = (*segments)[a]; 1589aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int b = (a + 1) % count; 1599aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com Segment& segb = (*segments)[b]; 1609aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com segb.fMid = segb.fNorms[0] + sega.endNorm(); 1619aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com segb.fMid.normalize(); 1629aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // corner wedges 1639aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com *vCount += 4; 1649aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com *iCount += 6; 1659aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com } 1669aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com} 1679aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 1689732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.comstruct DegenerateTestData { 1699732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com DegenerateTestData() { fStage = kInitial; } 1709732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com bool isDegenerate() const { return kNonDegenerate != fStage; } 1719732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com enum { 1729732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com kInitial, 1739732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com kPoint, 1749732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com kLine, 1759732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com kNonDegenerate 1769732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com } fStage; 177972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkPoint fFirstPoint; 178972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkVector fLineNormal; 17981712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar fLineC; 1809732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com}; 1819732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com 182fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic const SkScalar kClose = (SK_Scalar1 / 16); 183fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic const SkScalar kCloseSqd = SkScalarMul(kClose, kClose); 1849732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com 185972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.orgstatic void update_degenerate_test(DegenerateTestData* data, const SkPoint& pt) { 1869732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com switch (data->fStage) { 1879732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com case DegenerateTestData::kInitial: 1889732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com data->fFirstPoint = pt; 1899732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com data->fStage = DegenerateTestData::kPoint; 1909732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com break; 1919732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com case DegenerateTestData::kPoint: 192fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org if (pt.distanceToSqd(data->fFirstPoint) > kCloseSqd) { 1939732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com data->fLineNormal = pt - data->fFirstPoint; 1949732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com data->fLineNormal.normalize(); 1959732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com data->fLineNormal.setOrthog(data->fLineNormal); 1969732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com data->fLineC = -data->fLineNormal.dot(data->fFirstPoint); 1979732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com data->fStage = DegenerateTestData::kLine; 1989732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com } 1999732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com break; 2009732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com case DegenerateTestData::kLine: 201fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org if (SkScalarAbs(data->fLineNormal.dot(pt) + data->fLineC) > kClose) { 2029732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com data->fStage = DegenerateTestData::kNonDegenerate; 2039732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com } 2049732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com case DegenerateTestData::kNonDegenerate: 2059732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com break; 2069732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com default: 20788cb22b6b4816c7a9ca6c5b795965b4606f9eb7bcommit-bot@chromium.org SkFAIL("Unexpected degenerate test stage."); 2089732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com } 2099732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com} 2109732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com 211fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic inline bool get_direction(const SkPath& path, const SkMatrix& m, SkPath::Direction* dir) { 212a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com if (!path.cheapComputeDirection(dir)) { 213a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com return false; 214a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com } 215af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com // check whether m reverses the orientation 216f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(!m.hasPerspective()); 21781712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar det2x2 = SkScalarMul(m.get(SkMatrix::kMScaleX), m.get(SkMatrix::kMScaleY)) - 21881712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalarMul(m.get(SkMatrix::kMSkewX), m.get(SkMatrix::kMSkewY)); 219af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com if (det2x2 < 0) { 22030c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com *dir = SkPath::OppositeDirection(*dir); 221af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com } 222a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com return true; 223af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com} 224af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com 225106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.orgstatic inline void add_line_to_segment(const SkPoint& pt, 226106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org SegmentArray* segments, 227106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org SkRect* devBounds) { 228fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org segments->push_back(); 229fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org segments->back().fType = Segment::kLine; 230fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org segments->back().fPts[0] = pt; 231106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org devBounds->growToInclude(pt.fX, pt.fY); 232fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org} 233fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org 2344b7d6730898abc9e02d1e12c2fd732945f4c1ab4commit-bot@chromium.org#ifdef SK_DEBUG 235106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.orgstatic inline bool contains_inclusive(const SkRect& rect, const SkPoint& p) { 236106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org return p.fX >= rect.fLeft && p.fX <= rect.fRight && p.fY >= rect.fTop && p.fY <= rect.fBottom; 237106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org} 2384b7d6730898abc9e02d1e12c2fd732945f4c1ab4commit-bot@chromium.org#endif 2394b7d6730898abc9e02d1e12c2fd732945f4c1ab4commit-bot@chromium.org 240106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.orgstatic inline void add_quad_segment(const SkPoint pts[3], 241106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org SegmentArray* segments, 242106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org SkRect* devBounds) { 243fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org if (pts[0].distanceToSqd(pts[1]) < kCloseSqd || pts[1].distanceToSqd(pts[2]) < kCloseSqd) { 244fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org if (pts[0] != pts[2]) { 245106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org add_line_to_segment(pts[2], segments, devBounds); 246fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org } 247fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org } else { 248fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org segments->push_back(); 249fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org segments->back().fType = Segment::kQuad; 250fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org segments->back().fPts[0] = pts[1]; 251fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org segments->back().fPts[1] = pts[2]; 252106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org SkASSERT(contains_inclusive(*devBounds, pts[0])); 253106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org devBounds->growToInclude(pts + 1, 2); 254fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org } 255fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org} 256fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org 257fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic inline void add_cubic_segments(const SkPoint pts[4], 258fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org SkPath::Direction dir, 259106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org SegmentArray* segments, 260106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org SkRect* devBounds) { 261fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org SkSTArray<15, SkPoint, true> quads; 262fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org GrPathUtils::convertCubicToQuads(pts, SK_Scalar1, true, dir, &quads); 263fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org int count = quads.count(); 264fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org for (int q = 0; q < count; q += 3) { 265106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org add_quad_segment(&quads[q], segments, devBounds); 266fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org } 267fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org} 268fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org 269fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic bool get_segments(const SkPath& path, 270fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org const SkMatrix& m, 271fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org SegmentArray* segments, 272fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org SkPoint* fanPt, 273fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org int* vCount, 274106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org int* iCount, 275106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org SkRect* devBounds) { 27669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com SkPath::Iter iter(path, true); 27730c174b9ce6b9777ee50ae0d0565a01b2a060f01bsalomon@google.com // This renderer over-emphasizes very thin path regions. We use the distance 2785cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com // to the path from the sample to compute coverage. Every pixel intersected 2795cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com // by the path will be hit and the maximum distance is sqrt(2)/2. We don't 280fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com // notice that the sample may be close to a very thin area of the path and 2815cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com // thus should be very light. This is particularly egregious for degenerate 2825cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com // line paths. We detect paths that are very close to a line (zero area) and 2835cc90d132220a69c1d5734178d851f9c7cd57f16bsalomon@google.com // draw nothing. 2849732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com DegenerateTestData degenerateData; 285a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com SkPath::Direction dir; 286a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com // get_direction can fail for some degenerate paths. 287a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com if (!get_direction(path, m, &dir)) { 288a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com return false; 289a51ab8416db9772a2eae3122f4f69801642daeb5bsalomon@google.com } 2909732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com 29169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com for (;;) { 292972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkPoint pts[4]; 29394b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com SkPath::Verb verb = iter.next(pts); 29494b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com switch (verb) { 29594b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kMove_Verb: 2961a38d5508f7a0e2c186d3aa8ea807045a46b663dbsalomon@google.com m.mapPoints(pts, 1); 2979732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com update_degenerate_test(°enerateData, pts[0]); 298106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org devBounds->set(pts->fX, pts->fY, pts->fX, pts->fY); 2999732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com break; 30094b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kLine_Verb: { 301fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org m.mapPoints(&pts[1], 1); 3021a38d5508f7a0e2c186d3aa8ea807045a46b663dbsalomon@google.com update_degenerate_test(°enerateData, pts[1]); 303106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org add_line_to_segment(pts[1], segments, devBounds); 30469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com break; 30569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 30694b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kQuad_Verb: 307fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org m.mapPoints(pts, 3); 3089732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com update_degenerate_test(°enerateData, pts[1]); 3099732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com update_degenerate_test(°enerateData, pts[2]); 310106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org add_quad_segment(pts, segments, devBounds); 31169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com break; 31294b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kCubic_Verb: { 3131a38d5508f7a0e2c186d3aa8ea807045a46b663dbsalomon@google.com m.mapPoints(pts, 4); 3149732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com update_degenerate_test(°enerateData, pts[1]); 3159732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com update_degenerate_test(°enerateData, pts[2]); 3169732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com update_degenerate_test(°enerateData, pts[3]); 317106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org add_cubic_segments(pts, dir, segments, devBounds); 31869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com break; 31969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com }; 32094b284d719ee5ccd3e2efbd1d7084ec554583bacbsalomon@google.com case SkPath::kDone_Verb: 3219732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com if (degenerateData.isDegenerate()) { 3229732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com return false; 3239732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com } else { 324278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com compute_vectors(segments, fanPt, dir, vCount, iCount); 3259732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com return true; 3269732f62eaec427e0d4a8de06748ebb59450dfe31bsalomon@google.com } 32769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com default: 32869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com break; 32969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 33069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 33169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com} 33269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 33369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.comstruct QuadVertex { 334972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkPoint fPos; 335972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkPoint fUV; 33681712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar fD0; 33781712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar fD1; 33869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com}; 339fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 3407d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.comstruct Draw { 3417d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com Draw() : fVertexCnt(0), fIndexCnt(0) {} 3427d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com int fVertexCnt; 3437d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com int fIndexCnt; 3447d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com}; 3457d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com 3467d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.comtypedef SkTArray<Draw, true> DrawArray; 3477d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com 348fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.orgstatic void create_vertices(const SegmentArray& segments, 349fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org const SkPoint& fanPt, 350fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org DrawArray* draws, 351fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org QuadVertex* verts, 352fdfbb9d5f0d29cb4a956a693c499653f87f04ac4commit-bot@chromium.org uint16_t* idxs) { 3537d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com Draw* draw = &draws->push_back(); 3547d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com // alias just to make vert/index assignments easier to read. 3557d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com int* v = &draw->fVertexCnt; 3567d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com int* i = &draw->fIndexCnt; 35769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 3589aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int count = segments.count(); 3599aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com for (int a = 0; a < count; ++a) { 3609aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com const Segment& sega = segments[a]; 3619aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int b = (a + 1) % count; 3629aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com const Segment& segb = segments[b]; 363fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 3647d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com // Check whether adding the verts for this segment to the current draw would cause index 3657d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com // values to overflow. 3667d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com int vCount = 4; 3677d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com if (Segment::kLine == segb.fType) { 3687d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com vCount += 5; 3697d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com } else { 3707d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com vCount += 6; 3717d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com } 3727d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com if (draw->fVertexCnt + vCount > (1 << 16)) { 3737d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts += *v; 3747d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs += *i; 3757d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com draw = &draws->push_back(); 3767d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com v = &draw->fVertexCnt; 3777d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com i = &draw->fIndexCnt; 3787d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com } 3797d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com 3809aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // FIXME: These tris are inset in the 1 unit arc around the corner 3817d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 0].fPos = sega.endPt(); 3827d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 1].fPos = verts[*v + 0].fPos + sega.endNorm(); 3837d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 2].fPos = verts[*v + 0].fPos + segb.fMid; 3847d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 3].fPos = verts[*v + 0].fPos + segb.fNorms[0]; 3857d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 0].fUV.set(0,0); 3867d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 1].fUV.set(0,-SK_Scalar1); 3877d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 2].fUV.set(0,-SK_Scalar1); 3887d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 3].fUV.set(0,-SK_Scalar1); 3897d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 0].fD0 = verts[*v + 0].fD1 = -SK_Scalar1; 3907d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 1].fD0 = verts[*v + 1].fD1 = -SK_Scalar1; 3917d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 2].fD0 = verts[*v + 2].fD1 = -SK_Scalar1; 3927d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 3].fD0 = verts[*v + 3].fD1 = -SK_Scalar1; 3937d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com 3947d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 0] = *v + 0; 3957d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 1] = *v + 2; 3967d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 2] = *v + 1; 3977d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 3] = *v + 0; 3987d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 4] = *v + 3; 3997d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 5] = *v + 2; 4007d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com 4017d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com *v += 4; 4027d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com *i += 6; 40369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 4049aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com if (Segment::kLine == segb.fType) { 4057d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 0].fPos = fanPt; 4067d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 1].fPos = sega.endPt(); 4077d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 2].fPos = segb.fPts[0]; 4089aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 4097d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 3].fPos = verts[*v + 1].fPos + segb.fNorms[0]; 4107d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 4].fPos = verts[*v + 2].fPos + segb.fNorms[0]; 4119aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 4129aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // we draw the line edge as a degenerate quad (u is 0, v is the 4139aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com // signed distance to the edge) 4147d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com SkScalar dist = fanPt.distanceToLineBetween(verts[*v + 1].fPos, 4157d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 2].fPos); 4167d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 0].fUV.set(0, dist); 4177d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 1].fUV.set(0, 0); 4187d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 2].fUV.set(0, 0); 4197d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 3].fUV.set(0, -SK_Scalar1); 4207d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 4].fUV.set(0, -SK_Scalar1); 4217d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com 4227d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 0].fD0 = verts[*v + 0].fD1 = -SK_Scalar1; 4237d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 1].fD0 = verts[*v + 1].fD1 = -SK_Scalar1; 4247d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 2].fD0 = verts[*v + 2].fD1 = -SK_Scalar1; 4257d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 3].fD0 = verts[*v + 3].fD1 = -SK_Scalar1; 4267d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 4].fD0 = verts[*v + 4].fD1 = -SK_Scalar1; 4277d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com 4287d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 0] = *v + 0; 4297d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 1] = *v + 2; 4307d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 2] = *v + 1; 4317d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com 4327d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 3] = *v + 3; 4337d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 4] = *v + 1; 4347d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 5] = *v + 2; 4357d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com 4367d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 6] = *v + 4; 4377d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 7] = *v + 3; 4387d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 8] = *v + 2; 4397d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com 4407d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com *v += 5; 4417d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com *i += 9; 442068096148179062c4343138c112b87518e4ab3b1bsalomon@google.com } else { 443972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkPoint qpts[] = {sega.endPt(), segb.fPts[0], segb.fPts[1]}; 4449aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 445972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org SkVector midVec = segb.fNorms[0] + segb.fNorms[1]; 4469aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com midVec.normalize(); 4479aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 4487d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 0].fPos = fanPt; 4497d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 1].fPos = qpts[0]; 4507d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 2].fPos = qpts[2]; 4517d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 3].fPos = qpts[0] + segb.fNorms[0]; 4527d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 4].fPos = qpts[2] + segb.fNorms[1]; 4537d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 5].fPos = qpts[1] + midVec; 4549aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 45581712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com SkScalar c = segb.fNorms[0].dot(qpts[0]); 4567d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 0].fD0 = -segb.fNorms[0].dot(fanPt) + c; 4577d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 1].fD0 = 0.f; 4587d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 2].fD0 = -segb.fNorms[0].dot(qpts[2]) + c; 4597d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 3].fD0 = -SK_ScalarMax/100; 4607d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 4].fD0 = -SK_ScalarMax/100; 4617d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 5].fD0 = -SK_ScalarMax/100; 4629aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 4639aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com c = segb.fNorms[1].dot(qpts[2]); 4647d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 0].fD1 = -segb.fNorms[1].dot(fanPt) + c; 4657d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 1].fD1 = -segb.fNorms[1].dot(qpts[0]) + c; 4667d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 2].fD1 = 0.f; 4677d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 3].fD1 = -SK_ScalarMax/100; 4687d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 4].fD1 = -SK_ScalarMax/100; 4697d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com verts[*v + 5].fD1 = -SK_ScalarMax/100; 4709aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 4711971317bb43580330a9e7e9a1c09c5025fe84aacbsalomon@google.com GrPathUtils::QuadUVMatrix toUV(qpts); 472972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org toUV.apply<6, sizeof(QuadVertex), sizeof(SkPoint)>(verts + *v); 4739aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 4747d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 0] = *v + 3; 4757d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 1] = *v + 1; 4767d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 2] = *v + 2; 4777d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 3] = *v + 4; 4787d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 4] = *v + 3; 4797d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 5] = *v + 2; 4809aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 4817d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 6] = *v + 5; 4827d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 7] = *v + 3; 4837d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 8] = *v + 4; 4849aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 4857d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 9] = *v + 0; 4867d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 10] = *v + 2; 4877d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com idxs[*i + 11] = *v + 1; 4889aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com 4897d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com *v += 6; 4907d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com *i += 12; 49169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 49269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 49369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com} 49469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 49590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 49690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 49790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/* 49890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * Quadratic specified by 0=u^2-v canonical coords. u and v are the first 49990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * two components of the vertex attribute. Coverage is based on signed 50090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * distance with negative being inside, positive outside. The edge is specified in 50190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * window space (y-down). If either the third or fourth component of the interpolated 50290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * vertex coord is > 0 then the pixel is considered outside the edge. This is used to 503041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com * attempt to trim to a portion of the infinite quad. 504041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com * Requires shader derivative instruction support. 50590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org */ 50690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 507249af15fb82833d2274850c589812b6e69df0033joshualittclass QuadEdgeEffect : public GrGeometryProcessor { 50890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgpublic: 50990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 510b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt static GrGeometryProcessor* Create() { 51198b33ebe6f66ed59b023cf16a09c0a40eb4510cebsalomon GR_CREATE_STATIC_PROCESSOR(gQuadEdgeEffect, QuadEdgeEffect, ()); 512d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com gQuadEdgeEffect->ref(); 513d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com return gQuadEdgeEffect; 51490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 51590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 51690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org virtual ~QuadEdgeEffect() {} 51790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 51890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org static const char* Name() { return "QuadEdge"; } 51990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 520249af15fb82833d2274850c589812b6e69df0033joshualitt const GrShaderVar& inQuadEdge() const { return fInQuadEdge; } 521249af15fb82833d2274850c589812b6e69df0033joshualitt 522b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt virtual const GrBackendGeometryProcessorFactory& getFactory() const SK_OVERRIDE { 523b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt return GrTBackendGeometryProcessorFactory<QuadEdgeEffect>::getInstance(); 52490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 52590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 526b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt class GLProcessor : public GrGLGeometryProcessor { 52790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org public: 528b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&) 52990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org : INHERITED (factory) {} 53090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 531c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { 53290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org const char *vsName, *fsName; 533c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt args.fPB->addVarying(kVec4f_GrSLType, "QuadEdge", &vsName, &fsName); 53490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 535c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); 53630ba436f04e61d4505fb854d5fc56079636e0788joshualitt 53730ba436f04e61d4505fb854d5fc56079636e0788joshualitt SkAssertResult(fsBuilder->enableFeature( 53830ba436f04e61d4505fb854d5fc56079636e0788joshualitt GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); 53930ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\t\tfloat edgeAlpha;\n"); 54030ba436f04e61d4505fb854d5fc56079636e0788joshualitt 54190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org // keep the derivative instructions outside the conditional 54230ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName); 54330ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName); 54430ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\t\tif (%s.z > 0.0 && %s.w > 0.0) {\n", fsName, fsName); 54590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org // today we know z and w are in device space. We could use derivatives 54630ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\t\t\tedgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);\n", fsName, 54790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org fsName); 54830ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf ("\t\t} else {\n"); 54930ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\t\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n" 55090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org "\t\t\t 2.0*%s.x*duvdy.x - duvdy.y);\n", 55190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org fsName, fsName); 55230ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\t\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, 55390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org fsName); 55430ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\t\t\tedgeAlpha = " 55590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org "clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);\n\t\t}\n"); 55690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 557824c346b6e0e114063c1a8ad4ba7c3a669ee2cffcommit-bot@chromium.org 558c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt fsBuilder->codeAppendf("\t%s = %s;\n", args.fOutput, 559c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt (GrGLSLExpr4(args.fInput) * GrGLSLExpr1("edgeAlpha")).c_str()); 56090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 561c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt const GrShaderVar& inQuadEdge = args.fGP.cast<QuadEdgeEffect>().inQuadEdge(); 562c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); 563249af15fb82833d2274850c589812b6e69df0033joshualitt vsBuilder->codeAppendf("\t%s = %s;\n", vsName, inQuadEdge.c_str()); 56490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 56590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 566b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*) {} 56790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 568b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE {} 56990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 57090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org private: 571249af15fb82833d2274850c589812b6e69df0033joshualitt typedef GrGLGeometryProcessor INHERITED; 57290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org }; 573041e2dbc0614e3341e1349fd0e962744a45b6194skia.committer@gmail.com 57490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgprivate: 575249af15fb82833d2274850c589812b6e69df0033joshualitt QuadEdgeEffect() 576249af15fb82833d2274850c589812b6e69df0033joshualitt : fInQuadEdge(this->addVertexAttrib(GrShaderVar("inQuadEdge", 577249af15fb82833d2274850c589812b6e69df0033joshualitt kVec4f_GrSLType, 578249af15fb82833d2274850c589812b6e69df0033joshualitt GrShaderVar::kAttribute_TypeModifier))) { 57990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 58090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 5810e08fc17e4718f7ce4e38f793695896473e96948bsalomon virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE { 58290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org return true; 58390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 58490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 5851a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel virtual void onComputeInvariantOutput(InvariantOutput* inout) const SK_OVERRIDE { 586ccb2e384a036f29d989d3c1468f879324e81a678egdaniel inout->mulByUnknownAlpha(); 5871a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel } 5881a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel 589249af15fb82833d2274850c589812b6e69df0033joshualitt const GrShaderVar& fInQuadEdge; 590249af15fb82833d2274850c589812b6e69df0033joshualitt 591b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GR_DECLARE_GEOMETRY_PROCESSOR_TEST; 59290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 593b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt typedef GrFragmentProcessor INHERITED; 59490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org}; 59590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 596b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_GEOMETRY_PROCESSOR_TEST(QuadEdgeEffect); 59790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 598b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrGeometryProcessor* QuadEdgeEffect::TestCreate(SkRandom* random, 599b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrContext*, 600b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrDrawTargetCaps& caps, 601b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrTexture*[]) { 60290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org // Doesn't work without derivative instructions. 60390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org return caps.shaderDerivativeSupport() ? QuadEdgeEffect::Create() : NULL; 60490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org} 60590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 60690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 60790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 608e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.combool GrAAConvexPathRenderer::canDrawPath(const SkPath& path, 609e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com const SkStrokeRec& stroke, 6108a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com const GrDrawTarget* target, 6118a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com bool antiAlias) const { 612bcce8926524827775539874346dd424a9510dbc9bsalomon@google.com return (target->caps()->shaderDerivativeSupport() && antiAlias && 613e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com stroke.isFillStyle() && !path.isInverseFillType() && path.isConvex()); 614c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com} 615c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 616429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.comnamespace { 617429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com 618429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com// position + edge 619429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.comextern const GrVertexAttrib gPathAttribs[] = { 620429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, 621b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt {kVec4f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexAttribBinding} 622429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com}; 623429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com 624429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com}; 625429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com 626e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.combool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath, 627e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com const SkStrokeRec&, 628c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com GrDrawTarget* target, 629c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com bool antiAlias) { 630c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com 631e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com const SkPath* path = &origPath; 632af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com if (path->isEmpty()) { 633c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return true; 63469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 6354647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com 636137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com SkMatrix viewMatrix = target->getDrawState().getViewMatrix(); 637137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com GrDrawTarget::AutoStateRestore asr; 638137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com if (!asr.setIdentity(target, GrDrawTarget::kPreserve_ASRInit)) { 639e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com return false; 64069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 641137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com GrDrawState* drawState = target->drawState(); 64269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 643af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com // We use the fact that SkPath::transform path does subdivision based on 644af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com // perspective. Otherwise, we apply the view matrix when copying to the 645af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com // segment representation. 646af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com SkPath tmpPath; 647137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com if (viewMatrix.hasPerspective()) { 648e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com origPath.transform(viewMatrix, &tmpPath); 649af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com path = &tmpPath; 650137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com viewMatrix = SkMatrix::I(); 651af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com } 652af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com 65369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com QuadVertex *verts; 65469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com uint16_t* idxs; 65569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 6569aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int vCount; 6579aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com int iCount; 65868a5b260e2045070ed0796af98624c3769f590c5bsalomon@google.com enum { 65968a5b260e2045070ed0796af98624c3769f590c5bsalomon@google.com kPreallocSegmentCnt = 512 / sizeof(Segment), 6607d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com kPreallocDrawCnt = 4, 66168a5b260e2045070ed0796af98624c3769f590c5bsalomon@google.com }; 66268a5b260e2045070ed0796af98624c3769f590c5bsalomon@google.com SkSTArray<kPreallocSegmentCnt, Segment, true> segments; 6639aed114505a06679bbc7fa836e224aae82b3e5f4bsalomon@google.com SkPoint fanPt; 664af90f7f142a3939ca34f55b39460688e8eb5dc6bbsalomon@google.com 665106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org // We can't simply use the path bounds because we may degenerate cubics to quads which produces 666106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org // new control points outside the original convex hull. 667106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org SkRect devBounds; 668106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org if (!get_segments(*path, viewMatrix, &segments, &fanPt, &vCount, &iCount, &devBounds)) { 669c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return false; 67069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 67169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 672106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org // Our computed verts should all be within one pixel of the segment control points. 673106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org devBounds.outset(SK_Scalar1, SK_Scalar1); 674106655efdf2516f7084c19d6d5a7bc59fd8b866ccommit-bot@chromium.org 6757b3d5ee72c2238aa239bce4d5b3aea98a437ca7aegdaniel drawState->setVertexAttribs<gPathAttribs>(SK_ARRAY_COUNT(gPathAttribs), sizeof(QuadVertex)); 6764647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com 677b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrGeometryProcessor* quadProcessor = QuadEdgeEffect::Create(); 678b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt drawState->setGeometryProcessor(quadProcessor)->unref(); 6794647f9059825c062169d4d454c12640d82ae16c0bsalomon@google.com 680b75b0a0b8492e14c7728e0a0881f87dc64ce60f9jvanverth@google.com GrDrawTarget::AutoReleaseGeometry arg(target, vCount, iCount); 681b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com if (!arg.succeeded()) { 682c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return false; 68369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com } 684b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com verts = reinterpret_cast<QuadVertex*>(arg.vertices()); 685b372942bbc842b5728cbc8e9dd024928a793846absalomon@google.com idxs = reinterpret_cast<uint16_t*>(arg.indices()); 68669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com 6877d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com SkSTArray<kPreallocDrawCnt, Draw, true> draws; 6887d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com create_vertices(segments, fanPt, &draws, verts, idxs); 6897d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com 6901dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com // Check devBounds 691515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org#ifdef SK_DEBUG 6921dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com SkRect tolDevBounds = devBounds; 6931dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com tolDevBounds.outset(SK_Scalar1 / 10000, SK_Scalar1 / 10000); 6941dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com SkRect actualBounds; 6951dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com actualBounds.set(verts[0].fPos, verts[1].fPos); 6961dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com for (int i = 2; i < vCount; ++i) { 6971dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com actualBounds.growToInclude(verts[i].fPos.fX, verts[i].fPos.fY); 6981dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com } 699f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(tolDevBounds.contains(actualBounds)); 7001dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com#endif 7011dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com 7027d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com int vOffset = 0; 7037d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com for (int i = 0; i < draws.count(); ++i) { 7047d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com const Draw& draw = draws[i]; 7057d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com target->drawIndexed(kTriangles_GrPrimitiveType, 7067d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com vOffset, // start vertex 7077d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com 0, // start index 7087d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com draw.fVertexCnt, 7091dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com draw.fIndexCnt, 7101dd9baa6c8faeb4ce837c39d179ce9c9a09719efbsalomon@google.com &devBounds); 7117d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com vOffset += draw.fVertexCnt; 7127d9ffc8a04533d0207efe5511b587e89ecb9d898bsalomon@google.com } 713a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com 714c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com return true; 71569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com} 716