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

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: update 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 int instanceCount = fGeoData.count();
753 for (int i = 0; i < instanceCount; i++) {
754 const Geometry& args = fGeoData[i];
755
756 // createGeom transforms the geometry to device space when the matri x does not have
757 // perspective.
758 SkMatrix vm = args.fViewMatrix;
759 SkMatrix invert = SkMatrix::I();
760 if (!args.fViewMatrix.hasPerspective()) {
761 vm = SkMatrix::I();
762 if (!args.fViewMatrix.invert(&invert)) {
763 return;
764 }
765 }
766
767 int lineCount;
768 int quadCount;
769 int conicCount;
770 PREALLOC_PTARRAY(128) lines;
771 PREALLOC_PTARRAY(128) quads;
772 PREALLOC_PTARRAY(128) conics;
773 IntArray qSubdivs;
774 FloatArray cWeights;
775 quadCount = gather_lines_and_quads(args.fPath, args.fViewMatrix, arg s.fDevClipBounds,
776 &lines, &quads, &conics, &qSubdiv s, &cWeights);
777
778 lineCount = lines.count() / 2;
779 conicCount = conics.count() / 3;
780
781 // do lines first
782 if (lineCount) {
783 this->generateLines(batchTarget, pipeline, args, vm, invert, lin es, lineCount);
784 }
785
786 if (quadCount || conicCount) {
787 this->generateQuadsAndConics(batchTarget,
788 pipeline,
789 args,
790 quads,
791 quadCount,
792 conics,
793 conicCount,
794 qSubdivs,
795 cWeights,
796 vm,
797 invert);
798 }
799 }
800 }
801
802 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
803
804 private:
805 typedef SkTArray<SkPoint, true> PtArray;
806 typedef SkTArray<int, true> IntArray;
807 typedef SkTArray<float, true> FloatArray;
808
809 AAHairlineBatch(const Geometry& geometry, const GrIndexBuffer* linesIndexBuf fer,
810 const GrIndexBuffer* quadsIndexBuffer)
811 : fLinesIndexBuffer(linesIndexBuffer)
812 , fQuadsIndexBuffer(quadsIndexBuffer) {
813 SkASSERT(linesIndexBuffer && quadsIndexBuffer);
814 this->initClassID<AAHairlineBatch>();
815 fGeoData.push_back(geometry);
816 }
817
818 bool onCombineIfPossible(GrBatch* t) SK_OVERRIDE {
819 AAHairlineBatch* that = t->cast<AAHairlineBatch>();
820
821 // We go to identity if we don't have perspective
822 if (this->viewMatrix().hasPerspective() &&
823 !this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
824 return false;
825 }
826
827 // TODO we can actually batch hairlines if they are the same color in a kind of bulk method
828 // but we haven't implemented this yet
829 // TODO investigate going to vertex color and coverage?
830 if (this->coverage() != that->coverage()) {
831 return false;
832 }
833
834 if (this->color() != that->color()) {
835 return false;
836 }
837
838 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords());
839 if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->vi ewMatrix())) {
840 return false;
841 }
842
843 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ;
844 return true;
845 }
846
847 GrColor color() const { return fBatch.fColor; }
848 uint8_t coverage() const { return fBatch.fCoverage; }
849 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
850 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
851
852 void generateLines(GrBatchTarget* batchTarget,
853 const GrPipeline* pipeline,
854 const Geometry& args,
855 const SkMatrix& viewMatrix,
856 const SkMatrix& invert,
857 const PtArray& lines,
858 int lineCnt) {
859 uint32_t gpFlags = GrDefaultGeoProcFactory::kPosition_GPType |
860 GrDefaultGeoProcFactory::kCoverage_GPType;
861 SkAutoTUnref<const GrGeometryProcessor> gp(GrDefaultGeoProcFactory::Crea te(gpFlags,
862 args.fColor,
863 viewMatrix,
864 invert,
865 false,
866 args.fCoverage));
867
868 batchTarget->initDraw(gp, pipeline);
869 fBatchesGenerated++;
bsalomon 2015/02/02 21:01:13 seems to me like batch target should track this, n
870
871 // TODO remove this when batch is everywhere
872 GrPipelineInfo init;
873 init.fColorIgnored = fBatch.fColorIgnored;
874 init.fOverrideColor = GrColor_ILLEGAL;
875 init.fCoverageIgnored = fBatch.fCoverageIgnored;
876 init.fUsesLocalCoords = this->usesLocalCoords();
877 gp->initBatchTracker(batchTarget->currentBatchTracker(), init);
878
879 const GrVertexBuffer* vertexBuffer;
880 int firstVertex;
881
882 size_t vertexStride = gp->getVertexStride();
883 int vertexCount = kLineSegNumVertices * lineCnt;
884 void *vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
885 vertexCount,
886 &vertexBuffer,
887 &firstVertex);
888
889 SkASSERT(gp->getVertexStride() == sizeof(LineVertex));
890
891 // generate lines
892 const SkMatrix* toSrc = NULL;
893 if (args.fViewMatrix.hasPerspective()) {
894 SkMatrix perspectiveInvert;
895 if (!args.fViewMatrix.invert(&perspectiveInvert)) {
896 return;
897 }
898 toSrc = &perspectiveInvert;
899 }
900
901 LineVertex* verts = reinterpret_cast<LineVertex*>(vertices);
902 for (int i = 0; i < lineCnt; ++i) {
903 add_line(&lines[2*i], toSrc, args.fCoverage, &verts);
904 }
905
906 // Check devBounds
907 SkASSERT(check_bounds<LineVertex>(viewMatrix.hasPerspective() ? viewMatr ix : SkMatrix::I(),
908 args.fDevBounds,
909 vertices,
910 kLineSegNumVertices * lineCnt));
911
912 {
913 GrDrawTarget::DrawInfo info;
914 info.setVertexBuffer(vertexBuffer);
915 info.setIndexBuffer(fLinesIndexBuffer);
916 info.setPrimitiveType(kTriangles_GrPrimitiveType);
917 info.setStartIndex(0);
918
919 int lines = 0;
920 while (lines < lineCnt) {
921 int n = SkTMin(lineCnt - lines, kLineSegsNumInIdxBuffer);
922
923 info.setStartVertex(kLineSegNumVertices*lines + firstVertex);
924 info.setVertexCount(kLineSegNumVertices*n);
925 info.setIndexCount(kIdxsPerLineSeg*n);
926 batchTarget->draw(info);
927
928 lines += n;
929 }
930 }
931 }
932
933 void generateQuadsAndConics(GrBatchTarget* batchTarget,
934 const GrPipeline* pipeline,
935 const Geometry& args,
936 const PREALLOC_PTARRAY(128)& quads,
937 int quadCount,
938 const PREALLOC_PTARRAY(128)& conics,
939 int conicCount,
940 const IntArray& qSubdivs,
941 const FloatArray& cWeights,
942 const SkMatrix& vm,
943 const SkMatrix& invert) {
944 const GrVertexBuffer* vertexBuffer;
945 int firstVertex;
946
947 size_t vertexStride = sizeof(BezierVertex);
948 int vertexCount = kQuadNumVertices * quadCount + kQuadNumVertices * coni cCount;
949 void *vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
950 vertexCount,
951 &vertexBuffer,
952 &firstVertex);
953
954 if (!this->createBezierGeom(vertices,
955 args.fViewMatrix,
956 args.fPath,
957 quads,
958 quadCount,
959 conics,
960 conicCount,
961 qSubdivs,
962 cWeights,
963 vertexStride)) {
964 SkDebugf("Couldn't create bezier geometry\n");
965 return;
966 }
967
968 // Check devBounds
969 SkASSERT(check_bounds<BezierVertex>(vm,
970 args.fDevBounds,
971 vertices,
972 kQuadNumVertices * quadCount +
973 kQuadNumVertices * conicCount));
974
975 if (quadCount > 0) {
976 SkAutoTUnref<GrGeometryProcessor> hairQuadProcessor(
977 GrQuadEffect::Create(args.fColor,
978 vm,
979 kHairlineAA_GrProcessorEdgeType,
980 batchTarget->caps(),
981 invert,
982 args.fCoverage));
983
984 batchTarget->initDraw(hairQuadProcessor, pipeline);
985 fBatchesGenerated++;
986
987 // TODO remove this when batch is everywhere
988 GrPipelineInfo init;
989 init.fColorIgnored = fBatch.fColorIgnored;
990 init.fOverrideColor = GrColor_ILLEGAL;
991 init.fCoverageIgnored = fBatch.fCoverageIgnored;
992 init.fUsesLocalCoords = this->usesLocalCoords();
993 hairQuadProcessor->initBatchTracker(batchTarget->currentBatchTracker (), init);
994
995 this->drawBeziers(batchTarget,
996 hairQuadProcessor,
997 pipeline,
998 vertexBuffer,
999 firstVertex,
1000 quadCount);
1001 }
1002
1003 if (conicCount > 0) {
1004 SkAutoTUnref<GrGeometryProcessor> hairConicProcessor(
1005 GrConicEffect::Create(args.fColor,
1006 vm,
1007 kHairlineAA_GrProcessorEdgeType,
1008 batchTarget->caps(),
1009 invert,
1010 args.fCoverage));
1011
1012 batchTarget->initDraw(hairConicProcessor, pipeline);
1013 fBatchesGenerated++;
1014
1015 // TODO remove this when batch is everywhere
1016 GrPipelineInfo init;
1017 init.fColorIgnored = fBatch.fColorIgnored;
1018 init.fOverrideColor = GrColor_ILLEGAL;
1019 init.fCoverageIgnored = fBatch.fCoverageIgnored;
1020 init.fUsesLocalCoords = this->usesLocalCoords();
1021 hairConicProcessor->initBatchTracker(batchTarget->currentBatchTracke r(), init);
1022
1023 this->drawConics(batchTarget,
1024 hairConicProcessor,
1025 pipeline,
1026 vertexBuffer,
1027 firstVertex,
1028 conicCount,
1029 quadCount);
1030 }
1031 }
1032
1033 bool createBezierGeom(void* vertices,
1034 const SkMatrix& viewMatrix,
1035 const SkPath& path,
1036 const PtArray& quads,
1037 int quadCnt,
1038 const PtArray& conics,
1039 int conicCnt,
1040 const IntArray& qSubdivs,
1041 const FloatArray& cWeights,
1042 size_t vertexStride) {
1043 BezierVertex* verts = reinterpret_cast<BezierVertex*>(vertices);
1044
1045 const SkMatrix* toDevice = NULL;
1046 const SkMatrix* toSrc = NULL;
1047 SkMatrix ivm;
1048
1049 if (viewMatrix.hasPerspective()) {
1050 if (viewMatrix.invert(&ivm)) {
1051 toDevice = &viewMatrix;
1052 toSrc = &ivm;
1053 }
1054 }
1055
1056 int unsubdivQuadCnt = quads.count() / 3;
1057 for (int i = 0; i < unsubdivQuadCnt; ++i) {
1058 SkASSERT(qSubdivs[i] >= 0);
1059 add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts);
1060 }
1061
1062 // Start Conics
1063 for (int i = 0; i < conicCnt; ++i) {
1064 add_conics(&conics[3*i], cWeights[i], toDevice, toSrc, &verts);
1065 }
1066 return true;
1067 }
1068
1069 void drawBeziers(GrBatchTarget* batchTarget,
1070 const GrGeometryProcessor* hairQuadProcessor,
1071 const GrPipeline* pipeline,
1072 const GrVertexBuffer* vertexBuffer,
1073 int firstVertex,
1074 int quadCount) {
1075 GrDrawTarget::DrawInfo info;
1076 info.setVertexBuffer(vertexBuffer);
1077 info.setIndexBuffer(fQuadsIndexBuffer);
1078 info.setPrimitiveType(kTriangles_GrPrimitiveType);
1079 info.setStartIndex(0);
1080
1081 int quads = 0;
1082 while (quads < quadCount) {
1083 int n = SkTMin(quadCount - quads, kQuadsNumInIdxBuffer);
1084
1085 info.setStartVertex(kQuadNumVertices*quads + firstVertex);
1086 info.setVertexCount(kQuadNumVertices*n);
1087 info.setIndexCount(kIdxsPerQuad*n);
1088 batchTarget->draw(info);
1089
1090 quads += n;
1091 }
1092 }
1093
1094 void drawConics(GrBatchTarget* batchTarget,
1095 const GrGeometryProcessor* hairConicProcessor,
1096 const GrPipeline* pipeline,
1097 const GrVertexBuffer* vertexBuffer,
1098 int firstVertex,
1099 int conicCount,
1100 int quadCount) {
1101 GrDrawTarget::DrawInfo info;
1102 info.setVertexBuffer(vertexBuffer);
1103 info.setIndexBuffer(fQuadsIndexBuffer);
1104 info.setPrimitiveType(kTriangles_GrPrimitiveType);
1105 info.setStartIndex(0);
1106
1107 int conics = 0;
1108 while (conics < conicCount) {
1109 int n = SkTMin(conicCount - conics, kQuadsNumInIdxBuffer);
1110
1111 info.setStartVertex(kQuadNumVertices*(quadCount + conics) + firstVer tex);
1112 info.setVertexCount(kQuadNumVertices*n);
1113 info.setIndexCount(kIdxsPerQuad*n);
1114 batchTarget->draw(info);
1115
1116 conics += n;
1117 }
1118 }
1119
1120 struct BatchTracker {
1121 GrColor fColor;
1122 uint8_t fCoverage;
1123 SkRect fDevBounds;
1124 bool fUsesLocalCoords;
1125 bool fColorIgnored;
1126 bool fCoverageIgnored;
1127 };
1128
1129 GrBatchOpt fBatchOpt;
1130 BatchTracker fBatch;
1131 SkSTArray<1, Geometry, true> fGeoData;
1132 const GrIndexBuffer* fLinesIndexBuffer;
1133 const GrIndexBuffer* fQuadsIndexBuffer;
1134 };
1135
803 bool GrAAHairLinePathRenderer::onDrawPath(GrDrawTarget* target, 1136 bool GrAAHairLinePathRenderer::onDrawPath(GrDrawTarget* target,
804 GrPipelineBuilder* pipelineBuilder, 1137 GrPipelineBuilder* pipelineBuilder,
805 GrColor color, 1138 GrColor color,
806 const SkMatrix& viewMatrix, 1139 const SkMatrix& viewMatrix,
807 const SkPath& path, 1140 const SkPath& path,
808 const SkStrokeRec& stroke, 1141 const SkStrokeRec& stroke,
809 bool antiAlias) { 1142 bool) {
810 SkScalar hairlineCoverage; 1143 SkScalar hairlineCoverage;
811 uint8_t newCoverage = 0xff; 1144 uint8_t newCoverage = 0xff;
812 if (IsStrokeHairlineOrEquivalent(stroke, viewMatrix, &hairlineCoverage)) { 1145 if (IsStrokeHairlineOrEquivalent(stroke, viewMatrix, &hairlineCoverage)) {
813 newCoverage = SkScalarRoundToInt(hairlineCoverage * 0xff); 1146 newCoverage = SkScalarRoundToInt(hairlineCoverage * 0xff);
814 } 1147 }
815 1148
816 SkIRect devClipBounds; 1149 SkIRect devClipBounds;
817 target->getClip()->getConservativeBounds(pipelineBuilder->getRenderTarget(), &devClipBounds); 1150 target->getClip()->getConservativeBounds(pipelineBuilder->getRenderTarget(), &devClipBounds);
818 1151
819 int lineCnt; 1152 // This outset was determined experimentally by running skps and gms. It pr obably could be a
820 int quadCnt; 1153 // bit tighter
821 int conicCnt; 1154 SkRect devRect = path.getBounds();
822 PREALLOC_PTARRAY(128) lines; 1155 devRect.outset(3, 3);
823 PREALLOC_PTARRAY(128) quads; 1156 viewMatrix.mapRect(&devRect);
824 PREALLOC_PTARRAY(128) conics; 1157
825 IntArray qSubdivs; 1158 AAHairlineBatch::Geometry geometry;
826 FloatArray cWeights; 1159 geometry.fColor = color;
827 quadCnt = generate_lines_and_quads(path, viewMatrix, devClipBounds, 1160 geometry.fCoverage = newCoverage;
828 &lines, &quads, &conics, &qSubdivs, &cWei ghts); 1161 geometry.fViewMatrix = viewMatrix;
829 lineCnt = lines.count() / 2; 1162 geometry.fPath = path;
830 conicCnt = conics.count() / 3; 1163 SkDEBUGCODE(geometry.fDevBounds = devRect;)
831 1164 geometry.fDevClipBounds = devClipBounds;
832 // createGeom transforms the geometry to device space when the matrix does n ot have 1165
833 // perspective. 1166 GrBatch* batch = AAHairlineBatch::Create(geometry, fLinesIndexBuffer, fQuads IndexBuffer);
834 SkMatrix vm = viewMatrix; 1167 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 1168
977 return true; 1169 return true;
978 } 1170 }
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