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

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

Issue 894273002: Revert of Hairline batch (Closed) Base URL: https://skia.googlesource.com/skia.git@2_defer
Patch Set: 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"
13 #include "GrContext.h" 10 #include "GrContext.h"
14 #include "GrDefaultGeoProcFactory.h" 11 #include "GrDefaultGeoProcFactory.h"
15 #include "GrDrawTargetCaps.h" 12 #include "GrDrawTargetCaps.h"
16 #include "GrGpu.h" 13 #include "GrGpu.h"
17 #include "GrIndexBuffer.h" 14 #include "GrIndexBuffer.h"
18 #include "GrPathUtils.h" 15 #include "GrPathUtils.h"
19 #include "GrPipelineBuilder.h" 16 #include "GrPipelineBuilder.h"
20 #include "GrProcessor.h" 17 #include "GrProcessor.h"
21 #include "SkGeometry.h" 18 #include "SkGeometry.h"
22 #include "SkStroke.h" 19 #include "SkStroke.h"
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
249 246
250 /** 247 /**
251 * Generates the lines and quads to be rendered. Lines are always recorded in 248 * Generates the lines and quads to be rendered. Lines are always recorded in
252 * device space. We will do a device space bloat to account for the 1pixel 249 * device space. We will do a device space bloat to account for the 1pixel
253 * thickness. 250 * thickness.
254 * Quads are recorded in device space unless m contains 251 * Quads are recorded in device space unless m contains
255 * perspective, then in they are in src space. We do this because we will 252 * perspective, then in they are in src space. We do this because we will
256 * subdivide large quads to reduce over-fill. This subdivision has to be 253 * subdivide large quads to reduce over-fill. This subdivision has to be
257 * performed before applying the perspective matrix. 254 * performed before applying the perspective matrix.
258 */ 255 */
259 int gather_lines_and_quads(const SkPath& path, 256 int generate_lines_and_quads(const SkPath& path,
260 const SkMatrix& m, 257 const SkMatrix& m,
261 const SkIRect& devClipBounds, 258 const SkIRect& devClipBounds,
262 GrAAHairLinePathRenderer::PtArray* lines, 259 GrAAHairLinePathRenderer::PtArray* lines,
263 GrAAHairLinePathRenderer::PtArray* quads, 260 GrAAHairLinePathRenderer::PtArray* quads,
264 GrAAHairLinePathRenderer::PtArray* conics, 261 GrAAHairLinePathRenderer::PtArray* conics,
265 GrAAHairLinePathRenderer::IntArray* quadSubdivCnts, 262 GrAAHairLinePathRenderer::IntArray* quadSubdivCnts,
266 GrAAHairLinePathRenderer::FloatArray* conicWeights) { 263 GrAAHairLinePathRenderer::FloatArray* conicWeights) {
267 SkPath::Iter iter(path, false); 264 SkPath::Iter iter(path, false);
268 265
269 int totalQuadCount = 0; 266 int totalQuadCount = 0;
270 SkRect bounds; 267 SkRect bounds;
271 SkIRect ibounds; 268 SkIRect ibounds;
272 269
273 bool persp = m.hasPerspective(); 270 bool persp = m.hasPerspective();
274 271
275 for (;;) { 272 for (;;) {
276 SkPoint pathPts[4]; 273 SkPoint pathPts[4];
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
465 result->fY = SkScalarMul(result->fY, wInv); 462 result->fY = SkScalarMul(result->fY, wInv);
466 } 463 }
467 464
468 void set_uv_quad(const SkPoint qpts[3], BezierVertex verts[kQuadNumVertices]) { 465 void set_uv_quad(const SkPoint qpts[3], BezierVertex verts[kQuadNumVertices]) {
469 // this should be in the src space, not dev coords, when we have perspective 466 // this should be in the src space, not dev coords, when we have perspective
470 GrPathUtils::QuadUVMatrix DevToUV(qpts); 467 GrPathUtils::QuadUVMatrix DevToUV(qpts);
471 DevToUV.apply<kQuadNumVertices, sizeof(BezierVertex), sizeof(SkPoint)>(verts ); 468 DevToUV.apply<kQuadNumVertices, sizeof(BezierVertex), sizeof(SkPoint)>(verts );
472 } 469 }
473 470
474 void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice, 471 void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice,
475 const SkMatrix* toSrc, BezierVertex verts[kQuadNumVertices]) { 472 const SkMatrix* toSrc, BezierVertex verts[kQuadNumVertices],
473 SkRect* devBounds) {
476 SkASSERT(!toDevice == !toSrc); 474 SkASSERT(!toDevice == !toSrc);
477 // original quad is specified by tri a,b,c 475 // original quad is specified by tri a,b,c
478 SkPoint a = qpts[0]; 476 SkPoint a = qpts[0];
479 SkPoint b = qpts[1]; 477 SkPoint b = qpts[1];
480 SkPoint c = qpts[2]; 478 SkPoint c = qpts[2];
481 479
482 if (toDevice) { 480 if (toDevice) {
483 toDevice->mapPoints(&a, 1); 481 toDevice->mapPoints(&a, 1);
484 toDevice->mapPoints(&b, 1); 482 toDevice->mapPoints(&b, 1);
485 toDevice->mapPoints(&c, 1); 483 toDevice->mapPoints(&c, 1);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
530 a0.fPos += abN; 528 a0.fPos += abN;
531 a1.fPos = a; 529 a1.fPos = a;
532 a1.fPos -= abN; 530 a1.fPos -= abN;
533 531
534 c0.fPos = c; 532 c0.fPos = c;
535 c0.fPos += cbN; 533 c0.fPos += cbN;
536 c1.fPos = c; 534 c1.fPos = c;
537 c1.fPos -= cbN; 535 c1.fPos -= cbN;
538 536
539 intersect_lines(a0.fPos, abN, c0.fPos, cbN, &b0.fPos); 537 intersect_lines(a0.fPos, abN, c0.fPos, cbN, &b0.fPos);
538 devBounds->growToInclude(&verts[0].fPos, sizeof(BezierVertex), kQuadNumVerti ces);
540 539
541 if (toSrc) { 540 if (toSrc) {
542 toSrc->mapPointsWithStride(&verts[0].fPos, sizeof(BezierVertex), kQuadNu mVertices); 541 toSrc->mapPointsWithStride(&verts[0].fPos, sizeof(BezierVertex), kQuadNu mVertices);
543 } 542 }
544 } 543 }
545 544
546 // Equations based off of Loop-Blinn Quadratic GPU Rendering 545 // Equations based off of Loop-Blinn Quadratic GPU Rendering
547 // Input Parametric: 546 // Input Parametric:
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) 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)
549 // Output Implicit: 548 // Output Implicit:
(...skipping 11 matching lines...) Expand all
561 verts[i].fConic.fK = pnt.fX * klm[0] + pnt.fY * klm[1] + klm[2]; 560 verts[i].fConic.fK = pnt.fX * klm[0] + pnt.fY * klm[1] + klm[2];
562 verts[i].fConic.fL = pnt.fX * klm[3] + pnt.fY * klm[4] + klm[5]; 561 verts[i].fConic.fL = pnt.fX * klm[3] + pnt.fY * klm[4] + klm[5];
563 verts[i].fConic.fM = pnt.fX * klm[6] + pnt.fY * klm[7] + klm[8]; 562 verts[i].fConic.fM = pnt.fX * klm[6] + pnt.fY * klm[7] + klm[8];
564 } 563 }
565 } 564 }
566 565
567 void add_conics(const SkPoint p[3], 566 void add_conics(const SkPoint p[3],
568 const SkScalar weight, 567 const SkScalar weight,
569 const SkMatrix* toDevice, 568 const SkMatrix* toDevice,
570 const SkMatrix* toSrc, 569 const SkMatrix* toSrc,
571 BezierVertex** vert) { 570 BezierVertex** vert,
572 bloat_quad(p, toDevice, toSrc, *vert); 571 SkRect* devBounds) {
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) {
582 SkASSERT(subdiv >= 0); 583 SkASSERT(subdiv >= 0);
583 if (subdiv) { 584 if (subdiv) {
584 SkPoint newP[5]; 585 SkPoint newP[5];
585 SkChopQuadAtHalf(p, newP); 586 SkChopQuadAtHalf(p, newP);
586 add_quads(newP + 0, subdiv-1, toDevice, toSrc, vert); 587 add_quads(newP + 0, subdiv-1, toDevice, toSrc, vert, devBounds);
587 add_quads(newP + 2, subdiv-1, toDevice, toSrc, vert); 588 add_quads(newP + 2, subdiv-1, toDevice, toSrc, vert, devBounds);
588 } else { 589 } else {
589 bloat_quad(p, toDevice, toSrc, *vert); 590 bloat_quad(p, toDevice, toSrc, *vert, devBounds);
590 set_uv_quad(p, *vert); 591 set_uv_quad(p, *vert);
591 *vert += kQuadNumVertices; 592 *vert += kQuadNumVertices;
592 } 593 }
593 } 594 }
594 595
595 void add_line(const SkPoint p[2], 596 void add_line(const SkPoint p[2],
596 const SkMatrix* toSrc, 597 const SkMatrix* toSrc,
597 uint8_t coverage, 598 uint8_t coverage,
598 LineVertex** vert) { 599 LineVertex** vert) {
599 const SkPoint& a = p[0]; 600 const SkPoint& a = p[0];
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
634 } 635 }
635 } 636 }
636 637
637 *vert += kLineSegNumVertices; 638 *vert += kLineSegNumVertices;
638 } 639 }
639 640
640 } 641 }
641 642
642 /////////////////////////////////////////////////////////////////////////////// 643 ///////////////////////////////////////////////////////////////////////////////
643 644
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
644 bool GrAAHairLinePathRenderer::canDrawPath(const GrDrawTarget* target, 745 bool GrAAHairLinePathRenderer::canDrawPath(const GrDrawTarget* target,
645 const GrPipelineBuilder* pipelineBuil der, 746 const GrPipelineBuilder* pipelineBuil der,
646 const SkMatrix& viewMatrix, 747 const SkMatrix& viewMatrix,
647 const SkPath& path, 748 const SkPath& path,
648 const SkStrokeRec& stroke, 749 const SkStrokeRec& stroke,
649 bool antiAlias) const { 750 bool antiAlias) const {
650 if (!antiAlias) { 751 if (!antiAlias) {
651 return false; 752 return false;
652 } 753 }
653 754
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
692 actualBounds.growToInclude(pos.fX, pos.fY); 793 actualBounds.growToInclude(pos.fX, pos.fY);
693 } 794 }
694 } 795 }
695 if (!first) { 796 if (!first) {
696 return tolDevBounds.contains(actualBounds); 797 return tolDevBounds.contains(actualBounds);
697 } 798 }
698 799
699 return true; 800 return true;
700 } 801 }
701 802
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
870 // TODO remove this when batch is everywhere
871 GrPipelineInfo init;
872 init.fColorIgnored = fBatch.fColorIgnored;
873 init.fOverrideColor = GrColor_ILLEGAL;
874 init.fCoverageIgnored = fBatch.fCoverageIgnored;
875 init.fUsesLocalCoords = this->usesLocalCoords();
876 gp->initBatchTracker(batchTarget->currentBatchTracker(), init);
877
878 const GrVertexBuffer* vertexBuffer;
879 int firstVertex;
880
881 size_t vertexStride = gp->getVertexStride();
882 int vertexCount = kLineSegNumVertices * lineCnt;
883 void *vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
884 vertexCount,
885 &vertexBuffer,
886 &firstVertex);
887
888 SkASSERT(gp->getVertexStride() == sizeof(LineVertex));
889
890 // generate lines
891 const SkMatrix* toSrc = NULL;
892 if (args.fViewMatrix.hasPerspective()) {
893 SkMatrix perspectiveInvert;
894 if (!args.fViewMatrix.invert(&perspectiveInvert)) {
895 return;
896 }
897 toSrc = &perspectiveInvert;
898 }
899
900 LineVertex* verts = reinterpret_cast<LineVertex*>(vertices);
901 for (int i = 0; i < lineCnt; ++i) {
902 add_line(&lines[2*i], toSrc, args.fCoverage, &verts);
903 }
904
905 // Check devBounds
906 SkASSERT(check_bounds<LineVertex>(viewMatrix.hasPerspective() ? viewMatr ix : SkMatrix::I(),
907 args.fDevBounds,
908 vertices,
909 kLineSegNumVertices * lineCnt));
910
911 {
912 GrDrawTarget::DrawInfo info;
913 info.setVertexBuffer(vertexBuffer);
914 info.setIndexBuffer(fLinesIndexBuffer);
915 info.setPrimitiveType(kTriangles_GrPrimitiveType);
916 info.setStartIndex(0);
917
918 int lines = 0;
919 while (lines < lineCnt) {
920 int n = SkTMin(lineCnt - lines, kLineSegsNumInIdxBuffer);
921
922 info.setStartVertex(kLineSegNumVertices*lines + firstVertex);
923 info.setVertexCount(kLineSegNumVertices*n);
924 info.setIndexCount(kIdxsPerLineSeg*n);
925 batchTarget->draw(info);
926
927 lines += n;
928 }
929 }
930 }
931
932 void generateQuadsAndConics(GrBatchTarget* batchTarget,
933 const GrPipeline* pipeline,
934 const Geometry& args,
935 const PREALLOC_PTARRAY(128)& quads,
936 int quadCount,
937 const PREALLOC_PTARRAY(128)& conics,
938 int conicCount,
939 const IntArray& qSubdivs,
940 const FloatArray& cWeights,
941 const SkMatrix& vm,
942 const SkMatrix& invert) {
943 const GrVertexBuffer* vertexBuffer;
944 int firstVertex;
945
946 size_t vertexStride = sizeof(BezierVertex);
947 int vertexCount = kQuadNumVertices * quadCount + kQuadNumVertices * coni cCount;
948 void *vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
949 vertexCount,
950 &vertexBuffer,
951 &firstVertex);
952
953 if (!this->createBezierGeom(vertices,
954 args.fViewMatrix,
955 args.fPath,
956 quads,
957 quadCount,
958 conics,
959 conicCount,
960 qSubdivs,
961 cWeights,
962 vertexStride)) {
963 SkDebugf("Couldn't create bezier geometry\n");
964 return;
965 }
966
967 // Check devBounds
968 SkASSERT(check_bounds<BezierVertex>(vm,
969 args.fDevBounds,
970 vertices,
971 kQuadNumVertices * quadCount +
972 kQuadNumVertices * conicCount));
973
974 if (quadCount > 0) {
975 SkAutoTUnref<GrGeometryProcessor> hairQuadProcessor(
976 GrQuadEffect::Create(args.fColor,
977 vm,
978 kHairlineAA_GrProcessorEdgeType,
979 batchTarget->caps(),
980 invert,
981 args.fCoverage));
982
983 batchTarget->initDraw(hairQuadProcessor, pipeline);
984
985 // TODO remove this when batch is everywhere
986 GrPipelineInfo init;
987 init.fColorIgnored = fBatch.fColorIgnored;
988 init.fOverrideColor = GrColor_ILLEGAL;
989 init.fCoverageIgnored = fBatch.fCoverageIgnored;
990 init.fUsesLocalCoords = this->usesLocalCoords();
991 hairQuadProcessor->initBatchTracker(batchTarget->currentBatchTracker (), init);
992
993 this->drawBeziers(batchTarget,
994 hairQuadProcessor,
995 pipeline,
996 vertexBuffer,
997 firstVertex,
998 quadCount);
999 }
1000
1001 if (conicCount > 0) {
1002 SkAutoTUnref<GrGeometryProcessor> hairConicProcessor(
1003 GrConicEffect::Create(args.fColor,
1004 vm,
1005 kHairlineAA_GrProcessorEdgeType,
1006 batchTarget->caps(),
1007 invert,
1008 args.fCoverage));
1009
1010 batchTarget->initDraw(hairConicProcessor, pipeline);
1011
1012 // TODO remove this when batch is everywhere
1013 GrPipelineInfo init;
1014 init.fColorIgnored = fBatch.fColorIgnored;
1015 init.fOverrideColor = GrColor_ILLEGAL;
1016 init.fCoverageIgnored = fBatch.fCoverageIgnored;
1017 init.fUsesLocalCoords = this->usesLocalCoords();
1018 hairConicProcessor->initBatchTracker(batchTarget->currentBatchTracke r(), init);
1019
1020 this->drawConics(batchTarget,
1021 hairConicProcessor,
1022 pipeline,
1023 vertexBuffer,
1024 firstVertex,
1025 conicCount,
1026 quadCount);
1027 }
1028 }
1029
1030 bool createBezierGeom(void* vertices,
1031 const SkMatrix& viewMatrix,
1032 const SkPath& path,
1033 const PtArray& quads,
1034 int quadCnt,
1035 const PtArray& conics,
1036 int conicCnt,
1037 const IntArray& qSubdivs,
1038 const FloatArray& cWeights,
1039 size_t vertexStride) {
1040 BezierVertex* verts = reinterpret_cast<BezierVertex*>(vertices);
1041
1042 const SkMatrix* toDevice = NULL;
1043 const SkMatrix* toSrc = NULL;
1044 SkMatrix ivm;
1045
1046 if (viewMatrix.hasPerspective()) {
1047 if (viewMatrix.invert(&ivm)) {
1048 toDevice = &viewMatrix;
1049 toSrc = &ivm;
1050 }
1051 }
1052
1053 int unsubdivQuadCnt = quads.count() / 3;
1054 for (int i = 0; i < unsubdivQuadCnt; ++i) {
1055 SkASSERT(qSubdivs[i] >= 0);
1056 add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts);
1057 }
1058
1059 // Start Conics
1060 for (int i = 0; i < conicCnt; ++i) {
1061 add_conics(&conics[3*i], cWeights[i], toDevice, toSrc, &verts);
1062 }
1063 return true;
1064 }
1065
1066 void drawBeziers(GrBatchTarget* batchTarget,
1067 const GrGeometryProcessor* hairQuadProcessor,
1068 const GrPipeline* pipeline,
1069 const GrVertexBuffer* vertexBuffer,
1070 int firstVertex,
1071 int quadCount) {
1072 GrDrawTarget::DrawInfo info;
1073 info.setVertexBuffer(vertexBuffer);
1074 info.setIndexBuffer(fQuadsIndexBuffer);
1075 info.setPrimitiveType(kTriangles_GrPrimitiveType);
1076 info.setStartIndex(0);
1077
1078 int quads = 0;
1079 while (quads < quadCount) {
1080 int n = SkTMin(quadCount - quads, kQuadsNumInIdxBuffer);
1081
1082 info.setStartVertex(kQuadNumVertices*quads + firstVertex);
1083 info.setVertexCount(kQuadNumVertices*n);
1084 info.setIndexCount(kIdxsPerQuad*n);
1085 batchTarget->draw(info);
1086
1087 quads += n;
1088 }
1089 }
1090
1091 void drawConics(GrBatchTarget* batchTarget,
1092 const GrGeometryProcessor* hairConicProcessor,
1093 const GrPipeline* pipeline,
1094 const GrVertexBuffer* vertexBuffer,
1095 int firstVertex,
1096 int conicCount,
1097 int quadCount) {
1098 GrDrawTarget::DrawInfo info;
1099 info.setVertexBuffer(vertexBuffer);
1100 info.setIndexBuffer(fQuadsIndexBuffer);
1101 info.setPrimitiveType(kTriangles_GrPrimitiveType);
1102 info.setStartIndex(0);
1103
1104 int conics = 0;
1105 while (conics < conicCount) {
1106 int n = SkTMin(conicCount - conics, kQuadsNumInIdxBuffer);
1107
1108 info.setStartVertex(kQuadNumVertices*(quadCount + conics) + firstVer tex);
1109 info.setVertexCount(kQuadNumVertices*n);
1110 info.setIndexCount(kIdxsPerQuad*n);
1111 batchTarget->draw(info);
1112
1113 conics += n;
1114 }
1115 }
1116
1117 struct BatchTracker {
1118 GrColor fColor;
1119 uint8_t fCoverage;
1120 SkRect fDevBounds;
1121 bool fUsesLocalCoords;
1122 bool fColorIgnored;
1123 bool fCoverageIgnored;
1124 };
1125
1126 GrBatchOpt fBatchOpt;
1127 BatchTracker fBatch;
1128 SkSTArray<1, Geometry, true> fGeoData;
1129 const GrIndexBuffer* fLinesIndexBuffer;
1130 const GrIndexBuffer* fQuadsIndexBuffer;
1131 };
1132
1133 bool GrAAHairLinePathRenderer::onDrawPath(GrDrawTarget* target, 803 bool GrAAHairLinePathRenderer::onDrawPath(GrDrawTarget* target,
1134 GrPipelineBuilder* pipelineBuilder, 804 GrPipelineBuilder* pipelineBuilder,
1135 GrColor color, 805 GrColor color,
1136 const SkMatrix& viewMatrix, 806 const SkMatrix& viewMatrix,
1137 const SkPath& path, 807 const SkPath& path,
1138 const SkStrokeRec& stroke, 808 const SkStrokeRec& stroke,
1139 bool) { 809 bool antiAlias) {
1140 SkScalar hairlineCoverage; 810 SkScalar hairlineCoverage;
1141 uint8_t newCoverage = 0xff; 811 uint8_t newCoverage = 0xff;
1142 if (IsStrokeHairlineOrEquivalent(stroke, viewMatrix, &hairlineCoverage)) { 812 if (IsStrokeHairlineOrEquivalent(stroke, viewMatrix, &hairlineCoverage)) {
1143 newCoverage = SkScalarRoundToInt(hairlineCoverage * 0xff); 813 newCoverage = SkScalarRoundToInt(hairlineCoverage * 0xff);
1144 } 814 }
1145 815
1146 SkIRect devClipBounds; 816 SkIRect devClipBounds;
1147 target->getClip()->getConservativeBounds(pipelineBuilder->getRenderTarget(), &devClipBounds); 817 target->getClip()->getConservativeBounds(pipelineBuilder->getRenderTarget(), &devClipBounds);
1148 818
1149 // This outset was determined experimentally by running skps and gms. It pr obably could be a 819 int lineCnt;
1150 // bit tighter 820 int quadCnt;
1151 SkRect devRect = path.getBounds(); 821 int conicCnt;
1152 devRect.outset(7, 7); 822 PREALLOC_PTARRAY(128) lines;
1153 viewMatrix.mapRect(&devRect); 823 PREALLOC_PTARRAY(128) quads;
824 PREALLOC_PTARRAY(128) conics;
825 IntArray qSubdivs;
826 FloatArray cWeights;
827 quadCnt = generate_lines_and_quads(path, viewMatrix, devClipBounds,
828 &lines, &quads, &conics, &qSubdivs, &cWei ghts);
829 lineCnt = lines.count() / 2;
830 conicCnt = conics.count() / 3;
1154 831
1155 AAHairlineBatch::Geometry geometry; 832 // createGeom transforms the geometry to device space when the matrix does n ot have
1156 geometry.fColor = color; 833 // perspective.
1157 geometry.fCoverage = newCoverage; 834 SkMatrix vm = viewMatrix;
1158 geometry.fViewMatrix = viewMatrix; 835 SkMatrix invert = SkMatrix::I();
1159 geometry.fPath = path; 836 if (!viewMatrix.hasPerspective()) {
1160 SkDEBUGCODE(geometry.fDevBounds = devRect;) 837 vm = SkMatrix::I();
1161 geometry.fDevClipBounds = devClipBounds; 838 if (!viewMatrix.invert(&invert)) {
839 return false;
840 }
841 }
1162 842
1163 GrBatch* batch = AAHairlineBatch::Create(geometry, fLinesIndexBuffer, fQuads IndexBuffer); 843 // do lines first
1164 target->drawBatch(pipelineBuilder, batch, &devRect); 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();
1165 976
1166 return true; 977 return true;
1167 } 978 }
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