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

Side by Side Diff: src/core/SkRecordDraw.cpp

Issue 732653004: option to return drawable from recording (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years 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/core/SkRecordDraw.h ('k') | src/core/SkRecorder.h » ('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 2014 Google Inc. 2 * Copyright 2014 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 "SkLayerInfo.h" 8 #include "SkLayerInfo.h"
9 #include "SkRecordDraw.h" 9 #include "SkRecordDraw.h"
10 #include "SkPatchUtils.h" 10 #include "SkPatchUtils.h"
11 11
12 void SkRecordDraw(const SkRecord& record, 12 void SkRecordDraw(const SkRecord& record,
13 SkCanvas* canvas, 13 SkCanvas* canvas,
14 SkPicture const* const drawablePicts[], int drawableCount, 14 SkPicture const* const drawablePicts[],
15 SkCanvasDrawable* const drawables[],
16 int drawableCount,
15 const SkBBoxHierarchy* bbh, 17 const SkBBoxHierarchy* bbh,
16 SkDrawPictureCallback* callback) { 18 SkDrawPictureCallback* callback) {
17 SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/); 19 SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/);
18 20
19 if (bbh) { 21 if (bbh) {
20 // Draw only ops that affect pixels in the canvas's current clip. 22 // Draw only ops that affect pixels in the canvas's current clip.
21 // The SkRecord and BBH were recorded in identity space. This canvas 23 // The SkRecord and BBH were recorded in identity space. This canvas
22 // is not necessarily in that same space. getClipBounds() returns us 24 // is not necessarily in that same space. getClipBounds() returns us
23 // this canvas' clip bounds transformed back into identity space, which 25 // this canvas' clip bounds transformed back into identity space, which
24 // lets us query the BBH. 26 // lets us query the BBH.
25 SkRect query; 27 SkRect query;
26 if (!canvas->getClipBounds(&query)) { 28 if (!canvas->getClipBounds(&query)) {
27 // We want to make sure our query rectangle is never totally empty. 29 // We want to make sure our query rectangle is never totally empty.
28 // Clear ignores the clip, so it must draw even if the clip is logic ally empty. 30 // Clear ignores the clip, so it must draw even if the clip is logic ally empty.
29 query = SkRect::MakeWH(SK_ScalarNearlyZero, SK_ScalarNearlyZero); 31 query = SkRect::MakeWH(SK_ScalarNearlyZero, SK_ScalarNearlyZero);
30 } 32 }
31 33
32 SkTDArray<unsigned> ops; 34 SkTDArray<unsigned> ops;
33 bbh->search(query, &ops); 35 bbh->search(query, &ops);
34 36
35 SkRecords::Draw draw(canvas, drawablePicts, drawableCount); 37 SkRecords::Draw draw(canvas, drawablePicts, drawables, drawableCount);
36 for (int i = 0; i < ops.count(); i++) { 38 for (int i = 0; i < ops.count(); i++) {
37 if (callback && callback->abortDrawing()) { 39 if (callback && callback->abortDrawing()) {
38 return; 40 return;
39 } 41 }
40 // This visit call uses the SkRecords::Draw::operator() to call 42 // This visit call uses the SkRecords::Draw::operator() to call
41 // methods on the |canvas|, wrapped by methods defined with the 43 // methods on the |canvas|, wrapped by methods defined with the
42 // DRAW() macro. 44 // DRAW() macro.
43 record.visit<void>(ops[i], draw); 45 record.visit<void>(ops[i], draw);
44 } 46 }
45 } else { 47 } else {
46 // Draw all ops. 48 // Draw all ops.
47 SkRecords::Draw draw(canvas, drawablePicts, drawableCount); 49 SkRecords::Draw draw(canvas, drawablePicts, drawables, drawableCount);
48 for (unsigned i = 0; i < record.count(); i++) { 50 for (unsigned i = 0; i < record.count(); i++) {
49 if (callback && callback->abortDrawing()) { 51 if (callback && callback->abortDrawing()) {
50 return; 52 return;
51 } 53 }
52 // This visit call uses the SkRecords::Draw::operator() to call 54 // This visit call uses the SkRecords::Draw::operator() to call
53 // methods on the |canvas|, wrapped by methods defined with the 55 // methods on the |canvas|, wrapped by methods defined with the
54 // DRAW() macro. 56 // DRAW() macro.
55 record.visit<void>(i, draw); 57 record.visit<void>(i, draw);
56 } 58 }
57 } 59 }
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 DRAW(DrawTextBlob, drawTextBlob(r.blob, r.x, r.y, r.paint)); 128 DRAW(DrawTextBlob, drawTextBlob(r.blob, r.x, r.y, r.paint));
127 DRAW(DrawTextOnPath, drawTextOnPath(r.text, r.byteLength, r.path, r.matrix, r.pa int)); 129 DRAW(DrawTextOnPath, drawTextOnPath(r.text, r.byteLength, r.path, r.matrix, r.pa int));
128 DRAW(DrawVertices, drawVertices(r.vmode, r.vertexCount, r.vertices, r.texs, r.co lors, 130 DRAW(DrawVertices, drawVertices(r.vmode, r.vertexCount, r.vertices, r.texs, r.co lors,
129 r.xmode.get(), r.indices, r.indexCount, r.paint) ); 131 r.xmode.get(), r.indices, r.indexCount, r.paint) );
130 DRAW(DrawData, drawData(r.data, r.length)); 132 DRAW(DrawData, drawData(r.data, r.length));
131 #undef DRAW 133 #undef DRAW
132 134
133 template <> void Draw::draw(const DrawDrawable& r) { 135 template <> void Draw::draw(const DrawDrawable& r) {
134 SkASSERT(r.index >= 0); 136 SkASSERT(r.index >= 0);
135 SkASSERT(r.index < fDrawableCount); 137 SkASSERT(r.index < fDrawableCount);
136 fCanvas->drawPicture(fDrawablePicts[r.index]); 138 if (fDrawables) {
139 SkASSERT(NULL == fDrawablePicts);
140 fCanvas->EXPERIMENTAL_drawDrawable(fDrawables[r.index]);
141 } else {
142 fCanvas->drawPicture(fDrawablePicts[r.index]);
143 }
137 } 144 }
138 145
139 // This is an SkRecord visitor that fills an SkBBoxHierarchy. 146 // This is an SkRecord visitor that fills an SkBBoxHierarchy.
140 // 147 //
141 // The interesting part here is how to calculate bounds for ops which don't 148 // The interesting part here is how to calculate bounds for ops which don't
142 // have intrinsic bounds. What is the bounds of a Save or a Translate? 149 // have intrinsic bounds. What is the bounds of a Save or a Translate?
143 // 150 //
144 // We answer this by thinking about a particular definition of bounds: if I 151 // We answer this by thinking about a particular definition of bounds: if I
145 // don't execute this op, pixels in this rectangle might draw incorrectly. So 152 // don't execute this op, pixels in this rectangle might draw incorrectly. So
146 // the bounds of a Save, a Translate, a Restore, etc. are the union of the 153 // the bounds of a Save, a Translate, a Restore, etc. are the union of the
147 // bounds of Draw* ops that they might have an effect on. For any given 154 // bounds of Draw* ops that they might have an effect on. For any given
148 // Save/Restore block, the bounds of the Save, the Restore, and any other 155 // Save/Restore block, the bounds of the Save, the Restore, and any other
149 // non-drawing ("control") ops inside are exactly the union of the bounds of 156 // non-drawing ("control") ops inside are exactly the union of the bounds of
150 // the drawing ops inside that block. 157 // the drawing ops inside that block.
151 // 158 //
152 // To implement this, we keep a stack of active Save blocks. As we consume ops 159 // To implement this, we keep a stack of active Save blocks. As we consume ops
153 // inside the Save/Restore block, drawing ops are unioned with the bounds of 160 // inside the Save/Restore block, drawing ops are unioned with the bounds of
154 // the block, and control ops are stashed away for later. When we finish the 161 // the block, and control ops are stashed away for later. When we finish the
155 // block with a Restore, our bounds are complete, and we go back and fill them 162 // block with a Restore, our bounds are complete, and we go back and fill them
156 // in for all the control ops we stashed away. 163 // in for all the control ops we stashed away.
157 class FillBounds : SkNoncopyable { 164 class FillBounds : SkNoncopyable {
158 public: 165 public:
159 FillBounds(const SkRect& cullRect, const SkRecord& record) 166 FillBounds(const SkRect& cullRect, const SkRecord& record)
160 : fNumRecords(record.count()) 167 : fNumRecords(record.count())
161 , fCullRect(cullRect) 168 , fCullRect(cullRect)
162 , fBounds(record.count()) { 169 , fBounds(record.count())
170 {
163 // Calculate bounds for all ops. This won't go quite in order, so we'll need 171 // Calculate bounds for all ops. This won't go quite in order, so we'll need
164 // to store the bounds separately then feed them in to the BBH later in order. 172 // to store the bounds separately then feed them in to the BBH later in order.
165 fCTM = &SkMatrix::I(); 173 fCTM = &SkMatrix::I();
166 fCurrentClipBounds = fCullRect; 174 fCurrentClipBounds = fCullRect;
167 } 175 }
168 176
169 void setCurrentOp(unsigned currentOp) { fCurrentOp = currentOp; } 177 void setCurrentOp(unsigned currentOp) { fCurrentOp = currentOp; }
170 178
171 void cleanUp(SkBBoxHierarchy* bbh) { 179 void cleanUp(SkBBoxHierarchy* bbh) {
172 // If we have any lingering unpaired Saves, simulate restores to make 180 // If we have any lingering unpaired Saves, simulate restores to make
(...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after
584 Bounds fCurrentClipBounds; 592 Bounds fCurrentClipBounds;
585 593
586 // Used to track the bounds of Save/Restore blocks and the control ops insid e them. 594 // Used to track the bounds of Save/Restore blocks and the control ops insid e them.
587 SkTDArray<SaveBounds> fSaveStack; 595 SkTDArray<SaveBounds> fSaveStack;
588 SkTDArray<unsigned> fControlIndices; 596 SkTDArray<unsigned> fControlIndices;
589 }; 597 };
590 598
591 // SkRecord visitor to gather saveLayer/restore information. 599 // SkRecord visitor to gather saveLayer/restore information.
592 class CollectLayers : SkNoncopyable { 600 class CollectLayers : SkNoncopyable {
593 public: 601 public:
594 CollectLayers(const SkRect& cullRect, const SkRecord& record, SkLayerInfo* a ccelData) 602 CollectLayers(const SkRect& cullRect, const SkRecord& record,
603 const SkPicture::SnapshotArray* pictList, SkLayerInfo* accelDa ta)
595 : fSaveLayersInStack(0) 604 : fSaveLayersInStack(0)
596 , fAccelData(accelData) 605 , fAccelData(accelData)
597 , fFillBounds(cullRect, record) { 606 , fPictList(pictList)
598 } 607 , fFillBounds(cullRect, record)
608 {}
599 609
600 void setCurrentOp(unsigned currentOp) { fFillBounds.setCurrentOp(currentOp); } 610 void setCurrentOp(unsigned currentOp) { fFillBounds.setCurrentOp(currentOp); }
601 611
602 void cleanUp(SkBBoxHierarchy* bbh) { 612 void cleanUp(SkBBoxHierarchy* bbh) {
603 // fFillBounds must perform its cleanUp first so that all the bounding 613 // fFillBounds must perform its cleanUp first so that all the bounding
604 // boxes associated with unbalanced restores are updated (prior to 614 // boxes associated with unbalanced restores are updated (prior to
605 // fetching their bound in popSaveLayerInfo). 615 // fetching their bound in popSaveLayerInfo).
606 fFillBounds.cleanUp(bbh); 616 fFillBounds.cleanUp(bbh);
607 617
608 while (!fSaveLayerStack.isEmpty()) { 618 while (!fSaveLayerStack.isEmpty()) {
(...skipping 22 matching lines...) Expand all
631 const SkPaint* fPaint; 641 const SkPaint* fPaint;
632 }; 642 };
633 643
634 template <typename T> void trackSaveLayers(const T& op) { 644 template <typename T> void trackSaveLayers(const T& op) {
635 /* most ops aren't involved in saveLayers */ 645 /* most ops aren't involved in saveLayers */
636 } 646 }
637 void trackSaveLayers(const Save& s) { this->pushSaveLayerInfo(false, NULL); } 647 void trackSaveLayers(const Save& s) { this->pushSaveLayerInfo(false, NULL); }
638 void trackSaveLayers(const SaveLayer& sl) { this->pushSaveLayerInfo(true, sl .paint); } 648 void trackSaveLayers(const SaveLayer& sl) { this->pushSaveLayerInfo(true, sl .paint); }
639 void trackSaveLayers(const Restore& r) { this->popSaveLayerInfo(); } 649 void trackSaveLayers(const Restore& r) { this->popSaveLayerInfo(); }
640 650
641 void trackSaveLayers(const DrawPicture& dp) { 651 void trackSaveLayersForPicture(const SkPicture* picture, const SkPaint* pain t) {
642 // For sub-pictures, we wrap their layer information within the parent 652 // For sub-pictures, we wrap their layer information within the parent
643 // picture's rendering hierarchy 653 // picture's rendering hierarchy
644 SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey(); 654 SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey();
645 655
646 const SkLayerInfo* childData = 656 const SkLayerInfo* childData =
647 static_cast<const SkLayerInfo*>(dp.picture->EXPERIMENTAL_getAccelDat a(key)); 657 static_cast<const SkLayerInfo*>(picture->EXPERIMENTAL_getAccelData(k ey));
648 if (!childData) { 658 if (!childData) {
649 // If the child layer hasn't been generated with saveLayer data we 659 // If the child layer hasn't been generated with saveLayer data we
650 // assume the worst (i.e., that it does contain layers which nest 660 // assume the worst (i.e., that it does contain layers which nest
651 // inside existing layers). Layers within sub-pictures that don't 661 // inside existing layers). Layers within sub-pictures that don't
652 // have saveLayer data cannot be hoisted. 662 // have saveLayer data cannot be hoisted.
653 // TODO: could the analysis data be use to fine tune this? 663 // TODO: could the analysis data be use to fine tune this?
654 this->updateStackForSaveLayer(); 664 this->updateStackForSaveLayer();
655 return; 665 return;
656 } 666 }
657 667
658 for (int i = 0; i < childData->numBlocks(); ++i) { 668 for (int i = 0; i < childData->numBlocks(); ++i) {
659 const SkLayerInfo::BlockInfo& src = childData->block(i); 669 const SkLayerInfo::BlockInfo& src = childData->block(i);
660 670
661 FillBounds::Bounds newBound = fFillBounds.adjustAndMap(src.fBounds, dp.paint); 671 FillBounds::Bounds newBound = fFillBounds.adjustAndMap(src.fBounds, paint);
662 if (newBound.isEmpty()) { 672 if (newBound.isEmpty()) {
663 continue; 673 continue;
664 } 674 }
665 675
666 this->updateStackForSaveLayer(); 676 this->updateStackForSaveLayer();
667 677
668 SkLayerInfo::BlockInfo& dst = fAccelData->addBlock(); 678 SkLayerInfo::BlockInfo& dst = fAccelData->addBlock();
669 679
670 // If src.fPicture is NULL the layer is in dp.picture; otherwise 680 // If src.fPicture is NULL the layer is in dp.picture; otherwise
671 // it belongs to a sub-picture. 681 // it belongs to a sub-picture.
672 dst.fPicture = src.fPicture ? src.fPicture : static_cast<const SkPic ture*>(dp.picture); 682 dst.fPicture = src.fPicture ? src.fPicture : picture;
673 dst.fPicture->ref(); 683 dst.fPicture->ref();
674 dst.fBounds = newBound; 684 dst.fBounds = newBound;
675 dst.fLocalMat = src.fLocalMat; 685 dst.fLocalMat = src.fLocalMat;
676 dst.fPreMat = src.fPreMat; 686 dst.fPreMat = src.fPreMat;
677 dst.fPreMat.postConcat(fFillBounds.ctm()); 687 dst.fPreMat.postConcat(fFillBounds.ctm());
678 if (src.fPaint) { 688 if (src.fPaint) {
679 dst.fPaint = SkNEW_ARGS(SkPaint, (*src.fPaint)); 689 dst.fPaint = SkNEW_ARGS(SkPaint, (*src.fPaint));
680 } 690 }
681 dst.fSaveLayerOpID = src.fSaveLayerOpID; 691 dst.fSaveLayerOpID = src.fSaveLayerOpID;
682 dst.fRestoreOpID = src.fRestoreOpID; 692 dst.fRestoreOpID = src.fRestoreOpID;
683 dst.fHasNestedLayers = src.fHasNestedLayers; 693 dst.fHasNestedLayers = src.fHasNestedLayers;
684 dst.fIsNested = fSaveLayersInStack > 0 || src.fIsNested; 694 dst.fIsNested = fSaveLayersInStack > 0 || src.fIsNested;
685 } 695 }
686 } 696 }
687 697
698 void trackSaveLayers(const DrawPicture& dp) {
699 this->trackSaveLayersForPicture(dp.picture, dp.paint);
700 }
701
702 void trackSaveLayers(const DrawDrawable& dp) {
703 SkASSERT(fPictList);
704 SkASSERT(dp.index >= 0 && dp.index < fPictList->count());
705 const SkPaint* paint = NULL; // drawables don't get a side-car paint
706 this->trackSaveLayersForPicture(fPictList->begin()[dp.index], paint);
707 }
708
688 // Inform all the saveLayers already on the stack that they now have a 709 // Inform all the saveLayers already on the stack that they now have a
689 // nested saveLayer inside them 710 // nested saveLayer inside them
690 void updateStackForSaveLayer() { 711 void updateStackForSaveLayer() {
691 for (int index = fSaveLayerStack.count() - 1; index >= 0; --index) { 712 for (int index = fSaveLayerStack.count() - 1; index >= 0; --index) {
692 if (fSaveLayerStack[index].fHasNestedSaveLayer) { 713 if (fSaveLayerStack[index].fHasNestedSaveLayer) {
693 break; 714 break;
694 } 715 }
695 fSaveLayerStack[index].fHasNestedSaveLayer = true; 716 fSaveLayerStack[index].fHasNestedSaveLayer = true;
696 if (fSaveLayerStack[index].fIsSaveLayer) { 717 if (fSaveLayerStack[index].fIsSaveLayer) {
697 break; 718 break;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
736 block.fSaveLayerOpID = sli.fStartIndex; 757 block.fSaveLayerOpID = sli.fStartIndex;
737 block.fRestoreOpID = fFillBounds.currentOp(); 758 block.fRestoreOpID = fFillBounds.currentOp();
738 block.fHasNestedLayers = sli.fHasNestedSaveLayer; 759 block.fHasNestedLayers = sli.fHasNestedSaveLayer;
739 block.fIsNested = fSaveLayersInStack > 0; 760 block.fIsNested = fSaveLayersInStack > 0;
740 } 761 }
741 762
742 // Used to collect saveLayer information for layer hoisting 763 // Used to collect saveLayer information for layer hoisting
743 int fSaveLayersInStack; 764 int fSaveLayersInStack;
744 SkTDArray<SaveLayerInfo> fSaveLayerStack; 765 SkTDArray<SaveLayerInfo> fSaveLayerStack;
745 SkLayerInfo* fAccelData; 766 SkLayerInfo* fAccelData;
767 const SkPicture::SnapshotArray* fPictList;
746 768
747 SkRecords::FillBounds fFillBounds; 769 SkRecords::FillBounds fFillBounds;
748 }; 770 };
749 771
750 } // namespace SkRecords 772 } // namespace SkRecords
751 773
752 void SkRecordFillBounds(const SkRect& cullRect, const SkRecord& record, SkBBoxHi erarchy* bbh) { 774 void SkRecordFillBounds(const SkRect& cullRect, const SkRecord& record, SkBBoxHi erarchy* bbh) {
753 SkRecords::FillBounds visitor(cullRect, record); 775 SkRecords::FillBounds visitor(cullRect, record);
754 776
755 for (unsigned curOp = 0; curOp < record.count(); curOp++) { 777 for (unsigned curOp = 0; curOp < record.count(); curOp++) {
756 visitor.setCurrentOp(curOp); 778 visitor.setCurrentOp(curOp);
757 record.visit<void>(curOp, visitor); 779 record.visit<void>(curOp, visitor);
758 } 780 }
759 781
760 visitor.cleanUp(bbh); 782 visitor.cleanUp(bbh);
761 } 783 }
762 784
763 void SkRecordComputeLayers(const SkRect& cullRect, const SkRecord& record, 785 void SkRecordComputeLayers(const SkRect& cullRect, const SkRecord& record,
764 SkBBoxHierarchy* bbh, SkLayerInfo* data) { 786 const SkPicture::SnapshotArray* pictList, SkBBoxHiera rchy* bbh,
765 SkRecords::CollectLayers visitor(cullRect, record, data); 787 SkLayerInfo* data) {
788 SkRecords::CollectLayers visitor(cullRect, record, pictList, data);
766 789
767 for (unsigned curOp = 0; curOp < record.count(); curOp++) { 790 for (unsigned curOp = 0; curOp < record.count(); curOp++) {
768 visitor.setCurrentOp(curOp); 791 visitor.setCurrentOp(curOp);
769 record.visit<void>(curOp, visitor); 792 record.visit<void>(curOp, visitor);
770 } 793 }
771 794
772 visitor.cleanUp(bbh); 795 visitor.cleanUp(bbh);
773 } 796 }
774 797
OLDNEW
« no previous file with comments | « src/core/SkRecordDraw.h ('k') | src/core/SkRecorder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698