| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 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 "PictureRenderer.h" | 8 #include "PictureRenderer.h" |
| 9 #include "picture_utils.h" | 9 #include "picture_utils.h" |
| 10 #include "SamplePipeControllers.h" | 10 #include "SamplePipeControllers.h" |
| (...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 691 if (fTileHeightPercentage > 0) { | 691 if (fTileHeightPercentage > 0) { |
| 692 name.appendf("%.f%%", fTileHeightPercentage); | 692 name.appendf("%.f%%", fTileHeightPercentage); |
| 693 } else { | 693 } else { |
| 694 name.appendf("%i", fTileHeight); | 694 name.appendf("%i", fTileHeight); |
| 695 } | 695 } |
| 696 return name; | 696 return name; |
| 697 } | 697 } |
| 698 | 698 |
| 699 ////////////////////////////////////////////////////////////////////////////////
/////////////// | 699 ////////////////////////////////////////////////////////////////////////////////
/////////////// |
| 700 | 700 |
| 701 // Holds all of the information needed to draw a set of tiles. | |
| 702 class CloneData : public SkRunnable { | |
| 703 | |
| 704 public: | |
| 705 CloneData(SkPicture* clone, SkCanvas* canvas, SkTDArray<SkRect>& rects, int
start, int end, | |
| 706 SkRunnable* done, ImageResultsAndExpectations* jsonSummaryPtr, | |
| 707 bool useChecksumBasedFilenames, bool enableWrites) | |
| 708 : fClone(clone) | |
| 709 , fCanvas(canvas) | |
| 710 , fEnableWrites(enableWrites) | |
| 711 , fRects(rects) | |
| 712 , fStart(start) | |
| 713 , fEnd(end) | |
| 714 , fSuccess(NULL) | |
| 715 , fDone(done) | |
| 716 , fJsonSummaryPtr(jsonSummaryPtr) | |
| 717 , fUseChecksumBasedFilenames(useChecksumBasedFilenames) { | |
| 718 SkASSERT(fDone != NULL); | |
| 719 } | |
| 720 | |
| 721 virtual void run() SK_OVERRIDE { | |
| 722 SkGraphics::SetTLSFontCacheLimit(1024 * 1024); | |
| 723 | |
| 724 SkBitmap bitmap; | |
| 725 if (fBitmap != NULL) { | |
| 726 // All tiles are the same size. | |
| 727 setup_bitmap(&bitmap, SkScalarFloorToInt(fRects[0].width()), SkScala
rFloorToInt(fRects[0].height())); | |
| 728 } | |
| 729 | |
| 730 for (int i = fStart; i < fEnd; i++) { | |
| 731 draw_tile_to_canvas(fCanvas, fRects[i], fClone); | |
| 732 if (fEnableWrites) { | |
| 733 if (!write(fCanvas, fWritePath, fMismatchPath, fInputFilename, f
JsonSummaryPtr, | |
| 734 fUseChecksumBasedFilenames, &i) | |
| 735 && fSuccess != NULL) { | |
| 736 *fSuccess = false; | |
| 737 // If one tile fails to write to a file, do not continue dra
wing the rest. | |
| 738 break; | |
| 739 } | |
| 740 if (fBitmap != NULL) { | |
| 741 if (fCanvas->readPixels(&bitmap, 0, 0)) { | |
| 742 SkAutoLockPixels alp(*fBitmap); | |
| 743 bitmapCopyAtOffset(bitmap, fBitmap, SkScalarFloorToInt(f
Rects[i].left()), | |
| 744 SkScalarFloorToInt(fRects[i].top())); | |
| 745 } else { | |
| 746 *fSuccess = false; | |
| 747 // If one tile fails to read pixels, do not continue dra
wing the rest. | |
| 748 break; | |
| 749 } | |
| 750 } | |
| 751 } | |
| 752 } | |
| 753 fDone->run(); | |
| 754 } | |
| 755 | |
| 756 void setPathsAndSuccess(const SkString& writePath, const SkString& mismatchP
ath, | |
| 757 const SkString& inputFilename, bool* success) { | |
| 758 fWritePath.set(writePath); | |
| 759 fMismatchPath.set(mismatchPath); | |
| 760 fInputFilename.set(inputFilename); | |
| 761 fSuccess = success; | |
| 762 } | |
| 763 | |
| 764 void setBitmap(SkBitmap* bitmap) { | |
| 765 fBitmap = bitmap; | |
| 766 } | |
| 767 | |
| 768 private: | |
| 769 // All pointers unowned. | |
| 770 SkPicture* fClone; // Picture to draw from. Each CloneData has
a unique one which | |
| 771 // is threadsafe. | |
| 772 SkCanvas* fCanvas; // Canvas to draw to. Reused for each tile. | |
| 773 bool fEnableWrites; // TODO(epoger): Temporary hack; see decla
ration of | |
| 774 // fEnableWrites in PictureRenderer.h. | |
| 775 SkString fWritePath; // If not empty, write all results into this
directory. | |
| 776 SkString fMismatchPath; // If not empty, write all unexpected res
ults into this dir. | |
| 777 SkString fInputFilename; // Filename of input SkPicture file. | |
| 778 SkTDArray<SkRect>& fRects; // All tiles of the picture. | |
| 779 const int fStart; // Range of tiles drawn by this thread. | |
| 780 const int fEnd; | |
| 781 bool* fSuccess; // Only meaningful if path is non-null. Shar
ed by all threads, | |
| 782 // and only set to false upon failure to wri
te to a PNG. | |
| 783 SkRunnable* fDone; | |
| 784 SkBitmap* fBitmap; | |
| 785 ImageResultsAndExpectations* fJsonSummaryPtr; | |
| 786 bool fUseChecksumBasedFilenames; | |
| 787 }; | |
| 788 | |
| 789 MultiCorePictureRenderer::MultiCorePictureRenderer(int threadCount) | |
| 790 : fNumThreads(threadCount) | |
| 791 , fThreadPool(threadCount) | |
| 792 , fCountdown(threadCount) { | |
| 793 // Only need to create fNumThreads - 1 clones, since one thread will use the
base | |
| 794 // picture. | |
| 795 fPictureClones = SkNEW_ARRAY(SkPicture, fNumThreads - 1); | |
| 796 fCloneData = SkNEW_ARRAY(CloneData*, fNumThreads); | |
| 797 } | |
| 798 | |
| 799 void MultiCorePictureRenderer::init(SkPicture *pict, const SkString* writePath, | |
| 800 const SkString* mismatchPath, const SkString
* inputFilename, | |
| 801 bool useChecksumBasedFilenames) { | |
| 802 // Set fPicture and the tiles. | |
| 803 this->INHERITED::init(pict, writePath, mismatchPath, inputFilename, useCheck
sumBasedFilenames); | |
| 804 for (int i = 0; i < fNumThreads; ++i) { | |
| 805 *fCanvasPool.append() = this->setupCanvas(this->getTileWidth(), this->ge
tTileHeight()); | |
| 806 } | |
| 807 // Only need to create fNumThreads - 1 clones, since one thread will use the
base picture. | |
| 808 fPicture->clone(fPictureClones, fNumThreads - 1); | |
| 809 // Populate each thread with the appropriate data. | |
| 810 // Group the tiles into nearly equal size chunks, rounding up so we're sure
to cover them all. | |
| 811 const int chunkSize = (fTileRects.count() + fNumThreads - 1) / fNumThreads; | |
| 812 | |
| 813 for (int i = 0; i < fNumThreads; i++) { | |
| 814 SkPicture* pic; | |
| 815 if (i == fNumThreads-1) { | |
| 816 // The last set will use the original SkPicture. | |
| 817 pic = fPicture; | |
| 818 } else { | |
| 819 pic = &fPictureClones[i]; | |
| 820 } | |
| 821 const int start = i * chunkSize; | |
| 822 const int end = SkMin32(start + chunkSize, fTileRects.count()); | |
| 823 fCloneData[i] = SkNEW_ARGS(CloneData, | |
| 824 (pic, fCanvasPool[i], fTileRects, start, end,
&fCountdown, | |
| 825 fJsonSummaryPtr, useChecksumBasedFilenames,
fEnableWrites)); | |
| 826 } | |
| 827 } | |
| 828 | |
| 829 bool MultiCorePictureRenderer::render(SkBitmap** out) { | |
| 830 bool success = true; | |
| 831 if (!fWritePath.isEmpty() || !fMismatchPath.isEmpty()) { | |
| 832 for (int i = 0; i < fNumThreads-1; i++) { | |
| 833 fCloneData[i]->setPathsAndSuccess(fWritePath, fMismatchPath, fInputF
ilename, &success); | |
| 834 } | |
| 835 } | |
| 836 | |
| 837 if (NULL != out) { | |
| 838 *out = SkNEW(SkBitmap); | |
| 839 setup_bitmap(*out, fPicture->width(), fPicture->height()); | |
| 840 for (int i = 0; i < fNumThreads; i++) { | |
| 841 fCloneData[i]->setBitmap(*out); | |
| 842 } | |
| 843 } else { | |
| 844 for (int i = 0; i < fNumThreads; i++) { | |
| 845 fCloneData[i]->setBitmap(NULL); | |
| 846 } | |
| 847 } | |
| 848 | |
| 849 fCountdown.reset(fNumThreads); | |
| 850 for (int i = 0; i < fNumThreads; i++) { | |
| 851 fThreadPool.add(fCloneData[i]); | |
| 852 } | |
| 853 fCountdown.wait(); | |
| 854 | |
| 855 return success; | |
| 856 } | |
| 857 | |
| 858 void MultiCorePictureRenderer::end() { | |
| 859 for (int i = 0; i < fNumThreads - 1; i++) { | |
| 860 SkDELETE(fCloneData[i]); | |
| 861 fCloneData[i] = NULL; | |
| 862 } | |
| 863 | |
| 864 fCanvasPool.unrefAll(); | |
| 865 | |
| 866 this->INHERITED::end(); | |
| 867 } | |
| 868 | |
| 869 MultiCorePictureRenderer::~MultiCorePictureRenderer() { | |
| 870 // Each individual CloneData was deleted in end. | |
| 871 SkDELETE_ARRAY(fCloneData); | |
| 872 SkDELETE_ARRAY(fPictureClones); | |
| 873 } | |
| 874 | |
| 875 SkString MultiCorePictureRenderer::getConfigNameInternal() { | |
| 876 SkString name = this->INHERITED::getConfigNameInternal(); | |
| 877 name.appendf("_multi_%i_threads", fNumThreads); | |
| 878 return name; | |
| 879 } | |
| 880 | |
| 881 ////////////////////////////////////////////////////////////////////////////////
/////////////// | |
| 882 | |
| 883 void PlaybackCreationRenderer::setup() { | 701 void PlaybackCreationRenderer::setup() { |
| 884 SkAutoTDelete<SkBBHFactory> factory(this->getFactory()); | 702 SkAutoTDelete<SkBBHFactory> factory(this->getFactory()); |
| 885 fRecorder.reset(SkNEW(SkPictureRecorder)); | 703 fRecorder.reset(SkNEW(SkPictureRecorder)); |
| 886 SkCanvas* canvas = fRecorder->beginRecording(this->getViewWidth(), this->get
ViewHeight(), | 704 SkCanvas* canvas = fRecorder->beginRecording(this->getViewWidth(), this->get
ViewHeight(), |
| 887 factory.get(), | 705 factory.get(), |
| 888 this->recordFlags()); | 706 this->recordFlags()); |
| 889 this->scaleToScaleFactor(canvas); | 707 this->scaleToScaleFactor(canvas); |
| 890 canvas->drawPicture(fPicture); | 708 canvas->drawPicture(fPicture); |
| 891 } | 709 } |
| 892 | 710 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 934 private: | 752 private: |
| 935 virtual SkString getConfigNameInternal() SK_OVERRIDE { | 753 virtual SkString getConfigNameInternal() SK_OVERRIDE { |
| 936 return SkString("gather_pixelrefs"); | 754 return SkString("gather_pixelrefs"); |
| 937 } | 755 } |
| 938 }; | 756 }; |
| 939 | 757 |
| 940 PictureRenderer* CreateGatherPixelRefsRenderer() { | 758 PictureRenderer* CreateGatherPixelRefsRenderer() { |
| 941 return SkNEW(GatherRenderer); | 759 return SkNEW(GatherRenderer); |
| 942 } | 760 } |
| 943 | 761 |
| 944 /////////////////////////////////////////////////////////////////////////////// | |
| 945 | |
| 946 class PictureCloneRenderer : public PictureRenderer { | |
| 947 public: | |
| 948 virtual bool render(SkBitmap** out = NULL) SK_OVERRIDE { | |
| 949 for (int i = 0; i < 100; ++i) { | |
| 950 SkPicture* clone = fPicture->clone(); | |
| 951 SkSafeUnref(clone); | |
| 952 } | |
| 953 | |
| 954 return (fWritePath.isEmpty()); // we don't have anything to write | |
| 955 } | |
| 956 | |
| 957 private: | |
| 958 virtual SkString getConfigNameInternal() SK_OVERRIDE { | |
| 959 return SkString("picture_clone"); | |
| 960 } | |
| 961 }; | |
| 962 | |
| 963 PictureRenderer* CreatePictureCloneRenderer() { | |
| 964 return SkNEW(PictureCloneRenderer); | |
| 965 } | |
| 966 | |
| 967 } // namespace sk_tools | 762 } // namespace sk_tools |
| OLD | NEW |