Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/gpu/GrAAHairLinePathRenderer.cpp

Issue 876673002: Hairline batch (Closed) Base URL: https://skia.googlesource.com/skia.git@2_defer
Patch Set: cleanup Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/GrAAHairLinePathRenderer.h ('k') | src/gpu/GrAARectRenderer.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2011 Google Inc. 2 * Copyright 2011 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "GrAAHairLinePathRenderer.h" 8 #include "GrAAHairLinePathRenderer.h"
9 9
10 #include "GrBatch.h"
11 #include "GrBatchTarget.h"
12 #include "GrBufferAllocPool.h"
10 #include "GrContext.h" 13 #include "GrContext.h"
11 #include "GrDefaultGeoProcFactory.h" 14 #include "GrDefaultGeoProcFactory.h"
12 #include "GrDrawTargetCaps.h" 15 #include "GrDrawTargetCaps.h"
13 #include "GrGpu.h" 16 #include "GrGpu.h"
14 #include "GrIndexBuffer.h" 17 #include "GrIndexBuffer.h"
15 #include "GrPathUtils.h" 18 #include "GrPathUtils.h"
16 #include "GrPipelineBuilder.h" 19 #include "GrPipelineBuilder.h"
17 #include "GrProcessor.h" 20 #include "GrProcessor.h"
18 #include "SkGeometry.h" 21 #include "SkGeometry.h"
19 #include "SkStroke.h" 22 #include "SkStroke.h"
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 249
247 /** 250 /**
248 * Generates the lines and quads to be rendered. Lines are always recorded in 251 * Generates the lines and quads to be rendered. Lines are always recorded in
249 * device space. We will do a device space bloat to account for the 1pixel 252 * device space. We will do a device space bloat to account for the 1pixel
250 * thickness. 253 * thickness.
251 * Quads are recorded in device space unless m contains 254 * Quads are recorded in device space unless m contains
252 * perspective, then in they are in src space. We do this because we will 255 * perspective, then in they are in src space. We do this because we will
253 * subdivide large quads to reduce over-fill. This subdivision has to be 256 * subdivide large quads to reduce over-fill. This subdivision has to be
254 * performed before applying the perspective matrix. 257 * performed before applying the perspective matrix.
255 */ 258 */
256 int generate_lines_and_quads(const SkPath& path, 259 int gather_lines_and_quads(const SkPath& path,
257 const SkMatrix& m, 260 const SkMatrix& m,
258 const SkIRect& devClipBounds, 261 const SkIRect& devClipBounds,
259 GrAAHairLinePathRenderer::PtArray* lines, 262 GrAAHairLinePathRenderer::PtArray* lines,
260 GrAAHairLinePathRenderer::PtArray* quads, 263 GrAAHairLinePathRenderer::PtArray* quads,
261 GrAAHairLinePathRenderer::PtArray* conics, 264 GrAAHairLinePathRenderer::PtArray* conics,
262 GrAAHairLinePathRenderer::IntArray* quadSubdivCnts, 265 GrAAHairLinePathRenderer::IntArray* quadSubdivCnts,
263 GrAAHairLinePathRenderer::FloatArray* conicWeights) { 266 GrAAHairLinePathRenderer::FloatArray* conicWeights) {
264 SkPath::Iter iter(path, false); 267 SkPath::Iter iter(path, false);
265 268
266 int totalQuadCount = 0; 269 int totalQuadCount = 0;
267 SkRect bounds; 270 SkRect bounds;
268 SkIRect ibounds; 271 SkIRect ibounds;
269 272
270 bool persp = m.hasPerspective(); 273 bool persp = m.hasPerspective();
271 274
272 for (;;) { 275 for (;;) {
273 SkPoint pathPts[4]; 276 SkPoint pathPts[4];
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
462 result->fY = SkScalarMul(result->fY, wInv); 465 result->fY = SkScalarMul(result->fY, wInv);
463 } 466 }
464 467
465 void set_uv_quad(const SkPoint qpts[3], BezierVertex verts[kQuadNumVertices]) { 468 void set_uv_quad(const SkPoint qpts[3], BezierVertex verts[kQuadNumVertices]) {
466 // this should be in the src space, not dev coords, when we have perspective 469 // this should be in the src space, not dev coords, when we have perspective
467 GrPathUtils::QuadUVMatrix DevToUV(qpts); 470 GrPathUtils::QuadUVMatrix DevToUV(qpts);
468 DevToUV.apply<kQuadNumVertices, sizeof(BezierVertex), sizeof(SkPoint)>(verts ); 471 DevToUV.apply<kQuadNumVertices, sizeof(BezierVertex), sizeof(SkPoint)>(verts );
469 } 472 }
470 473
471 void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice, 474 void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice,
472 const SkMatrix* toSrc, BezierVertex verts[kQuadNumVertices], 475 const SkMatrix* toSrc, BezierVertex verts[kQuadNumVertices]) {
473 SkRect* devBounds) {
474 SkASSERT(!toDevice == !toSrc); 476 SkASSERT(!toDevice == !toSrc);
475 // original quad is specified by tri a,b,c 477 // original quad is specified by tri a,b,c
476 SkPoint a = qpts[0]; 478 SkPoint a = qpts[0];
477 SkPoint b = qpts[1]; 479 SkPoint b = qpts[1];
478 SkPoint c = qpts[2]; 480 SkPoint c = qpts[2];
479 481
480 if (toDevice) { 482 if (toDevice) {
481 toDevice->mapPoints(&a, 1); 483 toDevice->mapPoints(&a, 1);
482 toDevice->mapPoints(&b, 1); 484 toDevice->mapPoints(&b, 1);
483 toDevice->mapPoints(&c, 1); 485 toDevice->mapPoints(&c, 1);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
528 a0.fPos += abN; 530 a0.fPos += abN;
529 a1.fPos = a; 531 a1.fPos = a;
530 a1.fPos -= abN; 532 a1.fPos -= abN;
531 533
532 c0.fPos = c; 534 c0.fPos = c;
533 c0.fPos += cbN; 535 c0.fPos += cbN;
534 c1.fPos = c; 536 c1.fPos = c;
535 c1.fPos -= cbN; 537 c1.fPos -= cbN;
536 538
537 intersect_lines(a0.fPos, abN, c0.fPos, cbN, &b0.fPos); 539 intersect_lines(a0.fPos, abN, c0.fPos, cbN, &b0.fPos);
538 devBounds->growToInclude(&verts[0].fPos, sizeof(BezierVertex), kQuadNumVerti ces);
539 540
540 if (toSrc) { 541 if (toSrc) {
541 toSrc->mapPointsWithStride(&verts[0].fPos, sizeof(BezierVertex), kQuadNu mVertices); 542 toSrc->mapPointsWithStride(&verts[0].fPos, sizeof(BezierVertex), kQuadNu mVertices);
542 } 543 }
543 } 544 }
544 545
545 // Equations based off of Loop-Blinn Quadratic GPU Rendering 546 // Equations based off of Loop-Blinn Quadratic GPU Rendering
546 // Input Parametric: 547 // Input Parametric:
547 // P(t) = (P0*(1-t)^2 + 2*w*P1*t*(1-t) + P2*t^2) / (1-t)^2 + 2*w*t*(1-t) + t^2) 548 // P(t) = (P0*(1-t)^2 + 2*w*P1*t*(1-t) + P2*t^2) / (1-t)^2 + 2*w*t*(1-t) + t^2)
548 // Output Implicit: 549 // Output Implicit:
(...skipping 11 matching lines...) Expand all
560 verts[i].fConic.fK = pnt.fX * klm[0] + pnt.fY * klm[1] + klm[2]; 561 verts[i].fConic.fK = pnt.fX * klm[0] + pnt.fY * klm[1] + klm[2];
561 verts[i].fConic.fL = pnt.fX * klm[3] + pnt.fY * klm[4] + klm[5]; 562 verts[i].fConic.fL = pnt.fX * klm[3] + pnt.fY * klm[4] + klm[5];
562 verts[i].fConic.fM = pnt.fX * klm[6] + pnt.fY * klm[7] + klm[8]; 563 verts[i].fConic.fM = pnt.fX * klm[6] + pnt.fY * klm[7] + klm[8];
563 } 564 }
564 } 565 }
565 566
566 void add_conics(const SkPoint p[3], 567 void add_conics(const SkPoint p[3],
567 const SkScalar weight, 568 const SkScalar weight,
568 const SkMatrix* toDevice, 569 const SkMatrix* toDevice,
569 const SkMatrix* toSrc, 570 const SkMatrix* toSrc,
570 BezierVertex** vert, 571 BezierVertex** vert) {
571 SkRect* devBounds) { 572 bloat_quad(p, toDevice, toSrc, *vert);
572 bloat_quad(p, toDevice, toSrc, *vert, devBounds);
573 set_conic_coeffs(p, *vert, weight); 573 set_conic_coeffs(p, *vert, weight);
574 *vert += kQuadNumVertices; 574 *vert += kQuadNumVertices;
575 } 575 }
576 576
577 void add_quads(const SkPoint p[3], 577 void add_quads(const SkPoint p[3],
578 int subdiv, 578 int subdiv,
579 const SkMatrix* toDevice, 579 const SkMatrix* toDevice,
580 const SkMatrix* toSrc, 580 const SkMatrix* toSrc,
581 BezierVertex** vert, 581 BezierVertex** vert) {
582 SkRect* devBounds) {
583 SkASSERT(subdiv >= 0); 582 SkASSERT(subdiv >= 0);
584 if (subdiv) { 583 if (subdiv) {
585 SkPoint newP[5]; 584 SkPoint newP[5];
586 SkChopQuadAtHalf(p, newP); 585 SkChopQuadAtHalf(p, newP);
587 add_quads(newP + 0, subdiv-1, toDevice, toSrc, vert, devBounds); 586 add_quads(newP + 0, subdiv-1, toDevice, toSrc, vert);
588 add_quads(newP + 2, subdiv-1, toDevice, toSrc, vert, devBounds); 587 add_quads(newP + 2, subdiv-1, toDevice, toSrc, vert);
589 } else { 588 } else {
590 bloat_quad(p, toDevice, toSrc, *vert, devBounds); 589 bloat_quad(p, toDevice, toSrc, *vert);
591 set_uv_quad(p, *vert); 590 set_uv_quad(p, *vert);
592 *vert += kQuadNumVertices; 591 *vert += kQuadNumVertices;
593 } 592 }
594 } 593 }
595 594
596 void add_line(const SkPoint p[2], 595 void add_line(const SkPoint p[2],
597 const SkMatrix* toSrc, 596 const SkMatrix* toSrc,
598 uint8_t coverage, 597 uint8_t coverage,
599 LineVertex** vert) { 598 LineVertex** vert) {
600 const SkPoint& a = p[0]; 599 const SkPoint& a = p[0];
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
635 } 634 }
636 } 635 }
637 636
638 *vert += kLineSegNumVertices; 637 *vert += kLineSegNumVertices;
639 } 638 }
640 639
641 } 640 }
642 641
643 /////////////////////////////////////////////////////////////////////////////// 642 ///////////////////////////////////////////////////////////////////////////////
644 643
645 bool GrAAHairLinePathRenderer::createLineGeom(GrDrawTarget* target,
646 GrPipelineBuilder* pipelineBuilder ,
647 const SkMatrix& viewMatrix,
648 uint8_t coverage,
649 size_t vertexStride,
650 GrDrawTarget::AutoReleaseGeometry* arg,
651 SkRect* devBounds,
652 const SkPath& path,
653 const PtArray& lines,
654 int lineCnt) {
655 int vertCnt = kLineSegNumVertices * lineCnt;
656
657 SkASSERT(vertexStride == sizeof(LineVertex));
658 if (!arg->set(target, vertCnt, vertexStride, 0)) {
659 return false;
660 }
661
662 LineVertex* verts = reinterpret_cast<LineVertex*>(arg->vertices());
663
664 const SkMatrix* toSrc = NULL;
665 SkMatrix ivm;
666
667 if (viewMatrix.hasPerspective()) {
668 if (viewMatrix.invert(&ivm)) {
669 toSrc = &ivm;
670 }
671 }
672 devBounds->set(lines.begin(), lines.count());
673 for (int i = 0; i < lineCnt; ++i) {
674 add_line(&lines[2*i], toSrc, coverage, &verts);
675 }
676 // All the verts computed by add_line are within sqrt(1^2 + 0.5^2) of the en d points.
677 static const SkScalar kSqrtOfOneAndAQuarter = 1.118f;
678 // Add a little extra to account for vector normalization precision.
679 static const SkScalar kOutset = kSqrtOfOneAndAQuarter + SK_Scalar1 / 20;
680 devBounds->outset(kOutset, kOutset);
681
682 return true;
683 }
684
685 bool GrAAHairLinePathRenderer::createBezierGeom(GrDrawTarget* target,
686 GrPipelineBuilder* pipelineBuild er,
687 const SkMatrix& viewMatrix,
688 GrDrawTarget::AutoReleaseGeometr y* arg,
689 SkRect* devBounds,
690 const SkPath& path,
691 const PtArray& quads,
692 int quadCnt,
693 const PtArray& conics,
694 int conicCnt,
695 const IntArray& qSubdivs,
696 const FloatArray& cWeights,
697 size_t vertexStride) {
698 int vertCnt = kQuadNumVertices * quadCnt + kQuadNumVertices * conicCnt;
699
700 if (!arg->set(target, vertCnt, vertexStride, 0)) {
701 return false;
702 }
703
704 BezierVertex* verts = reinterpret_cast<BezierVertex*>(arg->vertices());
705
706 const SkMatrix* toDevice = NULL;
707 const SkMatrix* toSrc = NULL;
708 SkMatrix ivm;
709
710 if (viewMatrix.hasPerspective()) {
711 if (viewMatrix.invert(&ivm)) {
712 toDevice = &viewMatrix;
713 toSrc = &ivm;
714 }
715 }
716
717 // Seed the dev bounds with some pts known to be inside. Each quad and conic grows the bounding
718 // box to include its vertices.
719 SkPoint seedPts[2];
720 if (quadCnt) {
721 seedPts[0] = quads[0];
722 seedPts[1] = quads[2];
723 } else if (conicCnt) {
724 seedPts[0] = conics[0];
725 seedPts[1] = conics[2];
726 }
727 if (toDevice) {
728 toDevice->mapPoints(seedPts, 2);
729 }
730 devBounds->set(seedPts[0], seedPts[1]);
731
732 int unsubdivQuadCnt = quads.count() / 3;
733 for (int i = 0; i < unsubdivQuadCnt; ++i) {
734 SkASSERT(qSubdivs[i] >= 0);
735 add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts, devBounds);
736 }
737
738 // Start Conics
739 for (int i = 0; i < conicCnt; ++i) {
740 add_conics(&conics[3*i], cWeights[i], toDevice, toSrc, &verts, devBounds );
741 }
742 return true;
743 }
744
745 bool GrAAHairLinePathRenderer::canDrawPath(const GrDrawTarget* target, 644 bool GrAAHairLinePathRenderer::canDrawPath(const GrDrawTarget* target,
746 const GrPipelineBuilder* pipelineBuil der, 645 const GrPipelineBuilder* pipelineBuil der,
747 const SkMatrix& viewMatrix, 646 const SkMatrix& viewMatrix,
748 const SkPath& path, 647 const SkPath& path,
749 const SkStrokeRec& stroke, 648 const SkStrokeRec& stroke,
750 bool antiAlias) const { 649 bool antiAlias) const {
751 if (!antiAlias) { 650 if (!antiAlias) {
752 return false; 651 return false;
753 } 652 }
754 653
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
793 actualBounds.growToInclude(pos.fX, pos.fY); 692 actualBounds.growToInclude(pos.fX, pos.fY);
794 } 693 }
795 } 694 }
796 if (!first) { 695 if (!first) {
797 return tolDevBounds.contains(actualBounds); 696 return tolDevBounds.contains(actualBounds);
798 } 697 }
799 698
800 return true; 699 return true;
801 } 700 }
802 701
702 class AAHairlineBatch : public GrBatch {
703 public:
704 struct Geometry {
705 GrColor fColor;
706 uint8_t fCoverage;
707 SkMatrix fViewMatrix;
708 SkPath fPath;
709 SkDEBUGCODE(SkRect fDevBounds;)
710 SkIRect fDevClipBounds;
711 };
712
713 // TODO Batch itself should not hold on to index buffers. Instead, these sh ould live in the
714 // cache.
715 static GrBatch* Create(const Geometry& geometry, const GrIndexBuffer* linesI ndexBuffer,
716 const GrIndexBuffer* quadsIndexBuffer) {
717 return SkNEW_ARGS(AAHairlineBatch, (geometry, linesIndexBuffer, quadsInd exBuffer));
718 }
719
720 const char* name() const SK_OVERRIDE { return "AAHairlineBatch"; }
721
722 void getInvariantOutputColor(GrInitInvariantOutput* out) const SK_OVERRIDE {
723 // When this is called on a batch, there is only one geometry bundle
724 out->setKnownFourComponents(fGeoData[0].fColor);
725 }
726 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRID E {
727 out->setUnknownSingleComponent();
728 }
729
730 void initBatchOpt(const GrBatchOpt& batchOpt) {
731 fBatchOpt = batchOpt;
732 }
733
734 void initBatchTracker(const GrPipelineInfo& init) SK_OVERRIDE {
735 // Handle any color overrides
736 if (init.fColorIgnored) {
737 fGeoData[0].fColor = GrColor_ILLEGAL;
738 } else if (GrColor_ILLEGAL != init.fOverrideColor) {
739 fGeoData[0].fColor = init.fOverrideColor;
740 }
741
742 // setup batch properties
743 fBatch.fColorIgnored = init.fColorIgnored;
744 fBatch.fColor = fGeoData[0].fColor;
745 fBatch.fUsesLocalCoords = init.fUsesLocalCoords;
746 fBatch.fCoverageIgnored = init.fCoverageIgnored;
747 fBatch.fCoverage = fGeoData[0].fCoverage;
748 SkDEBUGCODE(fBatch.fDevBounds = fGeoData[0].fDevBounds;)
749 }
750
751 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline ) SK_OVERRIDE;
752
753 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
754
755 private:
756 typedef SkTArray<SkPoint, true> PtArray;
757 typedef SkTArray<int, true> IntArray;
758 typedef SkTArray<float, true> FloatArray;
759
760 AAHairlineBatch(const Geometry& geometry, const GrIndexBuffer* linesIndexBuf fer,
761 const GrIndexBuffer* quadsIndexBuffer)
762 : fLinesIndexBuffer(linesIndexBuffer)
763 , fQuadsIndexBuffer(quadsIndexBuffer) {
764 SkASSERT(linesIndexBuffer && quadsIndexBuffer);
765 this->initClassID<AAHairlineBatch>();
766 fGeoData.push_back(geometry);
767 }
768
769 bool onCombineIfPossible(GrBatch* t) SK_OVERRIDE {
770 AAHairlineBatch* that = t->cast<AAHairlineBatch>();
771
772 if (this->viewMatrix().hasPerspective() != that->viewMatrix().hasPerspec tive()) {
773 return false;
774 }
775
776 // We go to identity if we don't have perspective
777 if (this->viewMatrix().hasPerspective() &&
778 !this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
779 return false;
780 }
781
782 // TODO we can actually batch hairlines if they are the same color in a kind of bulk method
783 // but we haven't implemented this yet
784 // TODO investigate going to vertex color and coverage?
785 if (this->coverage() != that->coverage()) {
786 return false;
787 }
788
789 if (this->color() != that->color()) {
790 return false;
791 }
792
793 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords());
794 if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->vi ewMatrix())) {
795 return false;
796 }
797
798 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ;
799 return true;
800 }
801
802 GrColor color() const { return fBatch.fColor; }
803 uint8_t coverage() const { return fBatch.fCoverage; }
804 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
805 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
806
807 struct BatchTracker {
808 GrColor fColor;
809 uint8_t fCoverage;
810 SkRect fDevBounds;
811 bool fUsesLocalCoords;
812 bool fColorIgnored;
813 bool fCoverageIgnored;
814 };
815
816 GrBatchOpt fBatchOpt;
817 BatchTracker fBatch;
818 SkSTArray<1, Geometry, true> fGeoData;
819 const GrIndexBuffer* fLinesIndexBuffer;
820 const GrIndexBuffer* fQuadsIndexBuffer;
821 };
822
823 void AAHairlineBatch::generateGeometry(GrBatchTarget* batchTarget, const GrPipel ine* pipeline) {
824 // Setup the viewmatrix and localmatrix for the GrGeometryProcessor.
825 SkMatrix invert;
826 if (!this->viewMatrix().invert(&invert)) {
827 return;
828 }
829
830 // we will transform to identity space if the viewmatrix does not have persp ective
831 bool hasPerspective = this->viewMatrix().hasPerspective();
832 const SkMatrix* geometryProcessorViewM = &SkMatrix::I();
833 const SkMatrix* geometryProcessorLocalM = &invert;
834 const SkMatrix* toDevice = NULL;
835 const SkMatrix* toSrc = NULL;
836 if (hasPerspective) {
837 geometryProcessorViewM = &this->viewMatrix();
838 geometryProcessorLocalM = &SkMatrix::I();
839 toDevice = &this->viewMatrix();
840 toSrc = &invert;
841 }
842
843 // Setup geometry processors for worst case
844 uint32_t gpFlags = GrDefaultGeoProcFactory::kPosition_GPType |
845 GrDefaultGeoProcFactory::kCoverage_GPType;
846
847 SkAutoTUnref<const GrGeometryProcessor> lineGP(
848 GrDefaultGeoProcFactory::Create(gpFlags,
849 this->color(),
850 *geometryProcessorViewM,
851 *geometryProcessorLocalM,
852 false,
853 this->coverage()));
854
855 SkAutoTUnref<const GrGeometryProcessor> quadGP(
856 GrQuadEffect::Create(this->color(),
857 *geometryProcessorViewM,
858 kHairlineAA_GrProcessorEdgeType,
859 batchTarget->caps(),
860 *geometryProcessorLocalM,
861 this->coverage()));
862
863 SkAutoTUnref<const GrGeometryProcessor> conicGP(
864 GrConicEffect::Create(this->color(),
865 *geometryProcessorViewM,
866 kHairlineAA_GrProcessorEdgeType,
867 batchTarget->caps(),
868 *geometryProcessorLocalM,
869 this->coverage()));
870
871 // This is hand inlined for maximum performance.
872 PREALLOC_PTARRAY(128) lines;
873 PREALLOC_PTARRAY(128) quads;
874 PREALLOC_PTARRAY(128) conics;
875 IntArray qSubdivs;
876 FloatArray cWeights;
877
878 int instanceCount = fGeoData.count();
879 for (int i = 0; i < instanceCount; i++) {
880 const Geometry& args = fGeoData[i];
881 gather_lines_and_quads(args.fPath, args.fViewMatrix, args.fDevClipBounds ,
882 &lines, &quads, &conics, &qSubdivs, &cWeights);
883 }
884
885 int quadCount = quads.count() / 3;
886 int lineCount = lines.count() / 2;
887 int conicCount = conics.count() / 3;
888
889 // do lines first
890 if (lineCount) {
891 batchTarget->initDraw(lineGP, pipeline);
892
893 // TODO remove this when batch is everywhere
894 GrPipelineInfo init;
895 init.fColorIgnored = fBatch.fColorIgnored;
896 init.fOverrideColor = GrColor_ILLEGAL;
897 init.fCoverageIgnored = fBatch.fCoverageIgnored;
898 init.fUsesLocalCoords = this->usesLocalCoords();
899 lineGP->initBatchTracker(batchTarget->currentBatchTracker(), init);
900
901 const GrVertexBuffer* vertexBuffer;
902 int firstVertex;
903
904 size_t vertexStride = lineGP->getVertexStride();
905 int vertexCount = kLineSegNumVertices * lineCount;
906 void *vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
907 vertexCount,
908 &vertexBuffer,
909 &firstVertex);
910
911 SkASSERT(lineGP->getVertexStride() == sizeof(LineVertex));
912
913 LineVertex* verts = reinterpret_cast<LineVertex*>(vertices);
914 for (int i = 0; i < lineCount; ++i) {
915 add_line(&lines[2*i], toSrc, this->coverage(), &verts);
916 }
917
918 {
919 GrDrawTarget::DrawInfo info;
920 info.setVertexBuffer(vertexBuffer);
921 info.setIndexBuffer(fLinesIndexBuffer);
922 info.setPrimitiveType(kTriangles_GrPrimitiveType);
923 info.setStartIndex(0);
924
925 int lines = 0;
926 while (lines < lineCount) {
927 int n = SkTMin(lineCount - lines, kLineSegsNumInIdxBuffer);
928
929 info.setStartVertex(kLineSegNumVertices*lines + firstVertex);
930 info.setVertexCount(kLineSegNumVertices*n);
931 info.setIndexCount(kIdxsPerLineSeg*n);
932 batchTarget->draw(info);
933
934 lines += n;
935 }
936 }
937 }
938
939 if (quadCount || conicCount) {
940 const GrVertexBuffer* vertexBuffer;
941 int firstVertex;
942
943 size_t vertexStride = sizeof(BezierVertex);
944 int vertexCount = kQuadNumVertices * quadCount + kQuadNumVertices * coni cCount;
945 void *vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
946 vertexCount,
947 &vertexBuffer,
948 &firstVertex);
949
950 // Setup vertices
951 BezierVertex* verts = reinterpret_cast<BezierVertex*>(vertices);
952
953 // is this the same as quadcount? TODO
954 int unsubdivQuadCnt = quads.count() / 3;
955 for (int i = 0; i < unsubdivQuadCnt; ++i) {
956 SkASSERT(qSubdivs[i] >= 0);
957 add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts);
958 }
959
960 // Start Conics
961 for (int i = 0; i < conicCount; ++i) {
962 add_conics(&conics[3*i], cWeights[i], toDevice, toSrc, &verts);
963 }
964
965 if (quadCount > 0) {
966 batchTarget->initDraw(quadGP, pipeline);
967
968 // TODO remove this when batch is everywhere
969 GrPipelineInfo init;
970 init.fColorIgnored = fBatch.fColorIgnored;
971 init.fOverrideColor = GrColor_ILLEGAL;
972 init.fCoverageIgnored = fBatch.fCoverageIgnored;
973 init.fUsesLocalCoords = this->usesLocalCoords();
974 quadGP->initBatchTracker(batchTarget->currentBatchTracker(), init);
975
976 {
977 GrDrawTarget::DrawInfo info;
978 info.setVertexBuffer(vertexBuffer);
979 info.setIndexBuffer(fQuadsIndexBuffer);
980 info.setPrimitiveType(kTriangles_GrPrimitiveType);
981 info.setStartIndex(0);
982
983 int quads = 0;
984 while (quads < quadCount) {
985 int n = SkTMin(quadCount - quads, kQuadsNumInIdxBuffer);
986
987 info.setStartVertex(kQuadNumVertices*quads + firstVertex);
988 info.setVertexCount(kQuadNumVertices*n);
989 info.setIndexCount(kIdxsPerQuad*n);
990 batchTarget->draw(info);
991
992 quads += n;
993 }
994 }
995 }
996
997 if (conicCount > 0) {
998 batchTarget->initDraw(conicGP, pipeline);
999
1000 // TODO remove this when batch is everywhere
1001 GrPipelineInfo init;
1002 init.fColorIgnored = fBatch.fColorIgnored;
1003 init.fOverrideColor = GrColor_ILLEGAL;
1004 init.fCoverageIgnored = fBatch.fCoverageIgnored;
1005 init.fUsesLocalCoords = this->usesLocalCoords();
1006 conicGP->initBatchTracker(batchTarget->currentBatchTracker(), init);
1007
1008 {
1009 GrDrawTarget::DrawInfo info;
1010 info.setVertexBuffer(vertexBuffer);
1011 info.setIndexBuffer(fQuadsIndexBuffer);
1012 info.setPrimitiveType(kTriangles_GrPrimitiveType);
1013 info.setStartIndex(0);
1014
1015 int conics = 0;
1016 while (conics < conicCount) {
1017 int n = SkTMin(conicCount - conics, kQuadsNumInIdxBuffer);
1018
1019 info.setStartVertex(kQuadNumVertices*(quadCount + conics) + firstVertex);
1020 info.setVertexCount(kQuadNumVertices*n);
1021 info.setIndexCount(kIdxsPerQuad*n);
1022 batchTarget->draw(info);
1023
1024 conics += n;
1025 }
1026 }
1027 }
1028 }
1029 }
1030
803 bool GrAAHairLinePathRenderer::onDrawPath(GrDrawTarget* target, 1031 bool GrAAHairLinePathRenderer::onDrawPath(GrDrawTarget* target,
804 GrPipelineBuilder* pipelineBuilder, 1032 GrPipelineBuilder* pipelineBuilder,
805 GrColor color, 1033 GrColor color,
806 const SkMatrix& viewMatrix, 1034 const SkMatrix& viewMatrix,
807 const SkPath& path, 1035 const SkPath& path,
808 const SkStrokeRec& stroke, 1036 const SkStrokeRec& stroke,
809 bool antiAlias) { 1037 bool) {
810 SkScalar hairlineCoverage; 1038 SkScalar hairlineCoverage;
811 uint8_t newCoverage = 0xff; 1039 uint8_t newCoverage = 0xff;
812 if (IsStrokeHairlineOrEquivalent(stroke, viewMatrix, &hairlineCoverage)) { 1040 if (IsStrokeHairlineOrEquivalent(stroke, viewMatrix, &hairlineCoverage)) {
813 newCoverage = SkScalarRoundToInt(hairlineCoverage * 0xff); 1041 newCoverage = SkScalarRoundToInt(hairlineCoverage * 0xff);
814 } 1042 }
815 1043
816 SkIRect devClipBounds; 1044 SkIRect devClipBounds;
817 target->getClip()->getConservativeBounds(pipelineBuilder->getRenderTarget(), &devClipBounds); 1045 target->getClip()->getConservativeBounds(pipelineBuilder->getRenderTarget(), &devClipBounds);
818 1046
819 int lineCnt; 1047 // This outset was determined experimentally by running skps and gms. It pr obably could be a
820 int quadCnt; 1048 // bit tighter
821 int conicCnt; 1049 SkRect devRect = path.getBounds();
822 PREALLOC_PTARRAY(128) lines; 1050 viewMatrix.mapRect(&devRect);
823 PREALLOC_PTARRAY(128) quads; 1051 devRect.outset(2, 2);
824 PREALLOC_PTARRAY(128) conics; 1052
825 IntArray qSubdivs; 1053 AAHairlineBatch::Geometry geometry;
826 FloatArray cWeights; 1054 geometry.fColor = color;
827 quadCnt = generate_lines_and_quads(path, viewMatrix, devClipBounds, 1055 geometry.fCoverage = newCoverage;
828 &lines, &quads, &conics, &qSubdivs, &cWei ghts); 1056 geometry.fViewMatrix = viewMatrix;
829 lineCnt = lines.count() / 2; 1057 geometry.fPath = path;
830 conicCnt = conics.count() / 3; 1058 SkDEBUGCODE(geometry.fDevBounds = devRect;)
831 1059 geometry.fDevClipBounds = devClipBounds;
832 // createGeom transforms the geometry to device space when the matrix does n ot have 1060
833 // perspective. 1061 GrBatch* batch = AAHairlineBatch::Create(geometry, fLinesIndexBuffer, fQuads IndexBuffer);
834 SkMatrix vm = viewMatrix; 1062 target->drawBatch(pipelineBuilder, batch, &devRect);
835 SkMatrix invert = SkMatrix::I();
836 if (!viewMatrix.hasPerspective()) {
837 vm = SkMatrix::I();
838 if (!viewMatrix.invert(&invert)) {
839 return false;
840 }
841 }
842
843 // do lines first
844 if (lineCnt) {
845 GrDrawTarget::AutoReleaseGeometry arg;
846 SkRect devBounds;
847
848 GrPipelineBuilder::AutoRestoreEffects are(pipelineBuilder);
849 uint32_t gpFlags = GrDefaultGeoProcFactory::kPosition_GPType |
850 GrDefaultGeoProcFactory::kCoverage_GPType;
851 SkAutoTUnref<const GrGeometryProcessor> gp(GrDefaultGeoProcFactory::Crea te(gpFlags,
852 color,
853 vm,
854 invert,
855 false,
856 newCoverage));
857
858 if (!this->createLineGeom(target,
859 pipelineBuilder,
860 viewMatrix,
861 newCoverage,
862 gp->getVertexStride(),
863 &arg,
864 &devBounds,
865 path,
866 lines,
867 lineCnt)) {
868 return false;
869 }
870
871 // Check devBounds
872 SkASSERT(check_bounds<LineVertex>(viewMatrix.hasPerspective() ? viewMatr ix : SkMatrix::I(),
873 devBounds,
874 arg.vertices(),
875 kLineSegNumVertices * lineCnt));
876
877 {
878 target->setIndexSourceToBuffer(fLinesIndexBuffer);
879 int lines = 0;
880 while (lines < lineCnt) {
881 int n = SkTMin(lineCnt - lines, kLineSegsNumInIdxBuffer);
882 target->drawIndexed(pipelineBuilder,
883 gp,
884 kTriangles_GrPrimitiveType,
885 kLineSegNumVertices*lines, // startV
886 0, // startI
887 kLineSegNumVertices*n, // vCount
888 kIdxsPerLineSeg*n, // iCount
889 &devBounds);
890 lines += n;
891 }
892 }
893 }
894
895 // then quadratics/conics
896 if (quadCnt || conicCnt) {
897 GrDrawTarget::AutoReleaseGeometry arg;
898 SkRect devBounds;
899
900 if (!this->createBezierGeom(target,
901 pipelineBuilder,
902 viewMatrix,
903 &arg,
904 &devBounds,
905 path,
906 quads,
907 quadCnt,
908 conics,
909 conicCnt,
910 qSubdivs,
911 cWeights,
912 sizeof(BezierVertex))) {
913 return false;
914 }
915
916 // Check devBounds
917 SkASSERT(check_bounds<BezierVertex>(viewMatrix.hasPerspective() ? viewMa trix :
918 SkMatr ix::I(),
919 devBounds,
920 arg.vertices(),
921 kQuadNumVertices * quadCnt +
922 kQuadNumVertices * conicCnt));
923
924 if (quadCnt > 0) {
925 SkAutoTUnref<GrGeometryProcessor> hairQuadProcessor(
926 GrQuadEffect::Create(color,
927 vm,
928 kHairlineAA_GrProcessorEdgeType,
929 *target->caps(),
930 invert,
931 newCoverage));
932 SkASSERT(hairQuadProcessor);
933 GrPipelineBuilder::AutoRestoreEffects are(pipelineBuilder);
934 target->setIndexSourceToBuffer(fQuadsIndexBuffer);
935
936 int quads = 0;
937 while (quads < quadCnt) {
938 int n = SkTMin(quadCnt - quads, kQuadsNumInIdxBuffer);
939 target->drawIndexed(pipelineBuilder,
940 hairQuadProcessor,
941 kTriangles_GrPrimitiveType,
942 kQuadNumVertices*quads, // sta rtV
943 0, // sta rtI
944 kQuadNumVertices*n, // vCo unt
945 kIdxsPerQuad*n, // iCo unt
946 &devBounds);
947 quads += n;
948 }
949 }
950
951 if (conicCnt > 0) {
952 SkAutoTUnref<GrGeometryProcessor> hairConicProcessor(
953 GrConicEffect::Create(color, vm, kHairlineAA_GrProcessorEdge Type,
954 *target->caps(), invert, newCoverage)) ;
955 SkASSERT(hairConicProcessor);
956 GrPipelineBuilder::AutoRestoreEffects are(pipelineBuilder);
957 target->setIndexSourceToBuffer(fQuadsIndexBuffer);
958
959 int conics = 0;
960 while (conics < conicCnt) {
961 int n = SkTMin(conicCnt - conics, kQuadsNumInIdxBuffer);
962 target->drawIndexed(pipelineBuilder,
963 hairConicProcessor,
964 kTriangles_GrPrimitiveType,
965 kQuadNumVertices*(quadCnt + conics), // sta rtV
966 0, // sta rtI
967 kQuadNumVertices*n, // vCo unt
968 kIdxsPerQuad*n, // iCo unt
969 &devBounds);
970 conics += n;
971 }
972 }
973 }
974
975 target->resetIndexSource();
976 1063
977 return true; 1064 return true;
978 } 1065 }
OLDNEW
« no previous file with comments | « src/gpu/GrAAHairLinePathRenderer.h ('k') | src/gpu/GrAARectRenderer.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698