diff options
author | reed <reed@google.com> | 2014-10-29 12:36:45 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-10-29 12:36:45 -0700 |
commit | 89889b69391a730f0ba2a1efb549864b7762263f (patch) | |
tree | 85e8cb00c41ae79cf4a693491138acd7853b0dfb /src | |
parent | 8f3937d9fcb28018ec14db6697d41b645716d589 (diff) |
MultiPictureDraw is taskgroup aware.
SampleApp is multipicturedraw aware.
BUG=skia:
Review URL: https://codereview.chromium.org/684923002
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkMultiPictureDraw.cpp | 137 | ||||
-rw-r--r-- | src/core/SkTaskGroup.cpp (renamed from src/utils/SkTaskGroup.cpp) | 1 | ||||
-rw-r--r-- | src/core/SkTaskGroup.h (renamed from src/utils/SkTaskGroup.h) | 3 |
3 files changed, 88 insertions, 53 deletions
diff --git a/src/core/SkMultiPictureDraw.cpp b/src/core/SkMultiPictureDraw.cpp index 5fe3c0ea52..b59b63bffc 100644 --- a/src/core/SkMultiPictureDraw.cpp +++ b/src/core/SkMultiPictureDraw.cpp @@ -13,21 +13,49 @@ #include "SkCanvas.h" #include "SkMultiPictureDraw.h" #include "SkPicture.h" +#include "SkTaskGroup.h" + +void SkMultiPictureDraw::DrawData::draw() { + fCanvas->drawPicture(fPicture, &fMatrix, fPaint); +} + +void SkMultiPictureDraw::DrawData::init(SkCanvas* canvas, const SkPicture* picture, + const SkMatrix* matrix, const SkPaint* paint) { + fPicture = SkRef(picture); + fCanvas = SkRef(canvas); + if (matrix) { + fMatrix = *matrix; + } else { + fMatrix.setIdentity(); + } + if (paint) { + fPaint = SkNEW_ARGS(SkPaint, (*paint)); + } else { + fPaint = NULL; + } +} + +void SkMultiPictureDraw::DrawData::Reset(SkTDArray<DrawData>& data) { + for (int i = 0; i < data.count(); ++i) { + data[i].fPicture->unref(); + data[i].fCanvas->unref(); + SkDELETE(data[i].fPaint); + } + data.rewind(); +} + +////////////////////////////////////////////////////////////////////////////////////// SkMultiPictureDraw::SkMultiPictureDraw(int reserve) { if (reserve > 0) { - fDrawData.setReserve(reserve); + fGPUDrawData.setReserve(reserve); + fThreadSafeDrawData.setReserve(reserve); } } void SkMultiPictureDraw::reset() { - for (int i = 0; i < fDrawData.count(); ++i) { - fDrawData[i].picture->unref(); - fDrawData[i].canvas->unref(); - SkDELETE(fDrawData[i].paint); - } - - fDrawData.rewind(); + DrawData::Reset(fGPUDrawData); + DrawData::Reset(fThreadSafeDrawData); } void SkMultiPictureDraw::add(SkCanvas* canvas, @@ -39,47 +67,58 @@ void SkMultiPictureDraw::add(SkCanvas* canvas, return; } - DrawData* data = fDrawData.append(); - - data->picture = SkRef(picture); - data->canvas = SkRef(canvas); - if (matrix) { - data->matrix = *matrix; - } else { - data->matrix.setIdentity(); - } - if (paint) { - data->paint = SkNEW_ARGS(SkPaint, (*paint)); - } else { - data->paint = NULL; - } + SkTDArray<DrawData>& array = canvas->getGrContext() ? fGPUDrawData : fThreadSafeDrawData; + array.append()->init(canvas, picture, matrix, paint); } #undef SK_IGNORE_GPU_LAYER_HOISTING #define SK_IGNORE_GPU_LAYER_HOISTING 1 +class AutoMPDReset : SkNoncopyable { + SkMultiPictureDraw* fMPD; +public: + AutoMPDReset(SkMultiPictureDraw* mpd) : fMPD(mpd) {} + ~AutoMPDReset() { fMPD->reset(); } +}; + void SkMultiPictureDraw::draw() { + AutoMPDReset mpdreset(this); + // we place the taskgroup after the MPDReset, to ensure that we don't delete the DrawData + // objects until after we're finished the tasks (which have pointers to the data). + + SkTaskGroup group; + for (int i = 0; i < fThreadSafeDrawData.count(); ++i) { + group.add(DrawData::Run, &fThreadSafeDrawData[i]); + } + // we deliberately don't call wait() here, since the destructor will do that, this allows us + // to continue processing gpu-data without having to wait on the cpu tasks. + + const int count = fGPUDrawData.count(); + if (0 == count) { + return; + } #ifndef SK_IGNORE_GPU_LAYER_HOISTING - GrContext* context = NULL; + GrContext* context = fGPUDrawData[0].fCanvas->getGrContext(); + SkASSERT(context); - // Start by collecting all the layers that are going to be atlased and render + // Start by collecting all the layers that are going to be atlased and render // them (if necessary). Hoisting the free floating layers is deferred until // drawing the canvas that requires them. SkTDArray<GrHoistedLayer> atlasedNeedRendering, atlasedRecycled; - for (int i = 0; i < fDrawData.count(); ++i) { - if (fDrawData[i].canvas->getGrContext() && - !fDrawData[i].paint && fDrawData[i].matrix.isIdentity()) { - SkASSERT(NULL == context || context == fDrawData[i].canvas->getGrContext()); - context = fDrawData[i].canvas->getGrContext(); + for (int i = 0; i < count; ++i) { + const DrawData& data = fGPUDrawData[i]; + // we only expect 1 context for all the canvases + SkASSERT(data.canvas->getGrContext() == context); + if (!data.fPaint && data.fMatrix.isIdentity()) { // TODO: this path always tries to optimize pictures. Should we // switch to this API approach (vs. SkCanvas::EXPERIMENTAL_optimize)? - fDrawData[i].canvas->EXPERIMENTAL_optimize(fDrawData[i].picture); + data.fCanvas->EXPERIMENTAL_optimize(data.fPicture); SkRect clipBounds; - if (!fDrawData[i].canvas->getClipBounds(&clipBounds)) { + if (!data.fCanvas->getClipBounds(&clipBounds)) { continue; } @@ -87,32 +126,33 @@ void SkMultiPictureDraw::draw() { // would improve the packing and reduce the number of swaps // TODO: another optimization would be to make a first pass to // lock any required layer that is already in the atlas - GrLayerHoister::FindLayersToAtlas(context, fDrawData[i].picture, + GrLayerHoister::FindLayersToAtlas(context, data.fPicture, clipBounds, &atlasedNeedRendering, &atlasedRecycled); } } - if (NULL != context) { - GrLayerHoister::DrawLayersToAtlas(context, atlasedNeedRendering); - } + GrLayerHoister::DrawLayersToAtlas(context, atlasedNeedRendering); SkTDArray<GrHoistedLayer> needRendering, recycled; #endif - for (int i = 0; i < fDrawData.count(); ++i) { + for (int i = 0; i < count; ++i) { + const DrawData& data = fGPUDrawData[i]; + SkCanvas* canvas = data.fCanvas; + const SkPicture* picture = data.fPicture; + #ifndef SK_IGNORE_GPU_LAYER_HOISTING - if (fDrawData[i].canvas->getGrContext() && - !fDrawData[i].paint && fDrawData[i].matrix.isIdentity()) { + if (!data.fPaint && data.fMatrix.isIdentity()) { SkRect clipBounds; - if (!fDrawData[i].canvas->getClipBounds(&clipBounds)) { + if (!canvas->getClipBounds(&clipBounds)) { continue; } // Find the layers required by this canvas. It will return atlased // layers in the 'recycled' list since they have already been drawn. - GrLayerHoister::FindLayersToHoist(context, fDrawData[i].picture, + GrLayerHoister::FindLayersToHoist(context, picture, clipBounds, &needRendering, &recycled); GrLayerHoister::DrawLayers(context, needRendering); @@ -122,11 +162,10 @@ void SkMultiPictureDraw::draw() { GrLayerHoister::ConvertLayersToReplacements(needRendering, &replacements); GrLayerHoister::ConvertLayersToReplacements(recycled, &replacements); - const SkMatrix initialMatrix = fDrawData[i].canvas->getTotalMatrix(); + const SkMatrix initialMatrix = canvas->getTotalMatrix(); // Render the entire picture using new layers - GrRecordReplaceDraw(fDrawData[i].picture, fDrawData[i].canvas, - &replacements, initialMatrix, NULL); + GrRecordReplaceDraw(picture, canvas, &replacements, initialMatrix, NULL); GrLayerHoister::UnlockLayers(context, needRendering); GrLayerHoister::UnlockLayers(context, recycled); @@ -136,19 +175,13 @@ void SkMultiPictureDraw::draw() { } else #endif { - fDrawData[i].canvas->drawPicture(fDrawData[i].picture, - &fDrawData[i].matrix, - fDrawData[i].paint); + canvas->drawPicture(picture, &data.fMatrix, data.fPaint); } } #ifndef SK_IGNORE_GPU_LAYER_HOISTING - if (NULL != context) { - GrLayerHoister::UnlockLayers(context, atlasedNeedRendering); - GrLayerHoister::UnlockLayers(context, atlasedRecycled); - } + GrLayerHoister::UnlockLayers(context, atlasedNeedRendering); + GrLayerHoister::UnlockLayers(context, atlasedRecycled); #endif - - this->reset(); } diff --git a/src/utils/SkTaskGroup.cpp b/src/core/SkTaskGroup.cpp index f1ec7f4278..dd12538743 100644 --- a/src/utils/SkTaskGroup.cpp +++ b/src/core/SkTaskGroup.cpp @@ -1,6 +1,7 @@ #include "SkTaskGroup.h" #include "SkCondVar.h" +#include "SkRunnable.h" #include "SkTDArray.h" #include "SkThread.h" #include "SkThreadUtils.h" diff --git a/src/utils/SkTaskGroup.h b/src/core/SkTaskGroup.h index c60ceda52e..75443c37cb 100644 --- a/src/utils/SkTaskGroup.h +++ b/src/core/SkTaskGroup.h @@ -9,7 +9,8 @@ #define SkTaskGroup_DEFINED #include "SkTypes.h" -#include "SkRunnable.h" + +struct SkRunnable; class SkTaskGroup : SkNoncopyable { public: |