Perform multi core rendering in bench_pictures.
Add a flag in SkGPipeWriter for threadsafe drawing.
Add a deferred pipe controller to SamplePipeControllers, which can
be called to play back in multiple threads.
Depends on http://codereview.appspot.com/6459105/
Review URL: https://codereview.appspot.com/6482068
git-svn-id: http://skia.googlecode.com/svn/trunk@5371 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/tools/PictureRenderer.cpp b/tools/PictureRenderer.cpp
index b7958e2..d5b72ab 100644
--- a/tools/PictureRenderer.cpp
+++ b/tools/PictureRenderer.cpp
@@ -6,22 +6,24 @@
*/
#include "PictureRenderer.h"
+#include "picture_utils.h"
#include "SamplePipeControllers.h"
#include "SkCanvas.h"
#include "SkDevice.h"
-#include "SkImageEncoder.h"
#include "SkGPipe.h"
+#if SK_SUPPORT_GPU
+#include "SkGpuDevice.h"
+#endif
+#include "SkGraphics.h"
+#include "SkImageEncoder.h"
#include "SkMatrix.h"
#include "SkPicture.h"
#include "SkScalar.h"
#include "SkString.h"
+#include "SkTemplates.h"
#include "SkTDArray.h"
+#include "SkThreadUtils.h"
#include "SkTypes.h"
-#include "picture_utils.h"
-
-#if SK_SUPPORT_GPU
-#include "SkGpuDevice.h"
-#endif
namespace sk_tools {
@@ -156,7 +158,9 @@
}
TiledPictureRenderer::TiledPictureRenderer()
- : fTileWidth(kDefaultTileWidth)
+ : fMultiThreaded(false)
+ , fUsePipe(false)
+ , fTileWidth(kDefaultTileWidth)
, fTileHeight(kDefaultTileHeight)
, fTileMinPowerOf2Width(0)
, fTileHeightPercentage(0.0)
@@ -236,7 +240,7 @@
// constraints are that every tile must have a pixel width that is a power of
// two and also be of some minimal width (that is also a power of two).
//
-// This is sovled by first taking our picture size and rounding it up to the
+// This is solved by first taking our picture size and rounding it up to the
// multiple of the minimal width. The binary representation of this rounded
// value gives us the tiles we need: a bit of value one means we need a tile of
// that size.
@@ -275,9 +279,93 @@
fTiles.reset();
}
+///////////////////////////////////////////////////////////////////////////////////////////////
+// Draw using Pipe
+
+struct TileData {
+ TileData(SkCanvas* canvas, DeferredPipeController* controller);
+ SkCanvas* fCanvas;
+ DeferredPipeController* fController;
+ SkThread fThread;
+};
+
+static void DrawTile(void* data) {
+ SkGraphics::SetTLSFontCacheLimit(1 * 1024 * 1024);
+ TileData* tileData = static_cast<TileData*>(data);
+ tileData->fController->playback(tileData->fCanvas);
+}
+
+TileData::TileData(SkCanvas* canvas, DeferredPipeController* controller)
+: fCanvas(canvas)
+, fController(controller)
+, fThread(&DrawTile, static_cast<void*>(this)) {}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+// Draw using Picture
+
+struct CloneData {
+ CloneData(SkCanvas* target, SkPicture* original);
+ SkCanvas* fCanvas;
+ SkPicture* fClone;
+ SkThread fThread;
+};
+
+static void DrawClonedTile(void* data) {
+ SkGraphics::SetTLSFontCacheLimit(1 * 1024 * 1024);
+ CloneData* cloneData = static_cast<CloneData*>(data);
+ cloneData->fCanvas->drawPicture(*cloneData->fClone);
+}
+
+CloneData::CloneData(SkCanvas* target, SkPicture* clone)
+: fCanvas(target)
+, fClone(clone)
+, fThread(&DrawClonedTile, static_cast<void*>(this)) {}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
void TiledPictureRenderer::drawTiles() {
- for (int i = 0; i < fTiles.count(); ++i) {
- fTiles[i]->drawPicture(*(fPicture));
+ if (fMultiThreaded) {
+ if (fUsePipe) {
+ // First, draw into a pipe controller
+ SkGPipeWriter writer;
+ DeferredPipeController controller(fTiles.count());
+ SkCanvas* pipeCanvas = writer.startRecording(&controller,
+ SkGPipeWriter::kSimultaneousReaders_Flag);
+ pipeCanvas->drawPicture(*(fPicture));
+ writer.endRecording();
+
+ // Create and start the threads.
+ TileData* tileData[fTiles.count()];
+ for (int i = 0; i < fTiles.count(); i++) {
+ tileData[i] = SkNEW_ARGS(TileData, (fTiles[i], &controller));
+ if (!tileData[i]->fThread.start()) {
+ SkDebugf("could not start thread %i\n", i);
+ }
+ }
+ for (int i = 0; i < fTiles.count(); i++) {
+ tileData[i]->fThread.join();
+ SkDELETE(tileData[i]);
+ }
+ } else {
+ SkPicture* clones = SkNEW_ARRAY(SkPicture, fTiles.count());
+ SkAutoTDeleteArray<SkPicture> autodelete(clones);
+ fPicture->clone(clones, fTiles.count());
+ CloneData* cloneData[fTiles.count()];
+ for (int i = 0; i < fTiles.count(); i++) {
+ cloneData[i] = SkNEW_ARGS(CloneData, (fTiles[i], &clones[i]));
+ if (!cloneData[i]->fThread.start()) {
+ SkDebugf("Could not start picture thread %i\n", i);
+ }
+ }
+ for (int i = 0; i < fTiles.count(); i++) {
+ cloneData[i]->fThread.join();
+ SkDELETE(cloneData[i]);
+ }
+ }
+ } else {
+ for (int i = 0; i < fTiles.count(); ++i) {
+ fTiles[i]->drawPicture(*(fPicture));
+ }
}
}