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 |