1/* 2 * Copyright 2014 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "SkCanvas.h" 9#include "SkCanvasPriv.h" 10#include "SkMultiPictureDraw.h" 11#include "SkPicture.h" 12#include "SkTaskGroup.h" 13 14void SkMultiPictureDraw::DrawData::draw() { 15 fCanvas->drawPicture(fPicture, &fMatrix, fPaint); 16} 17 18void SkMultiPictureDraw::DrawData::init(SkCanvas* canvas, const SkPicture* picture, 19 const SkMatrix* matrix, const SkPaint* paint) { 20 fPicture = SkRef(picture); 21 fCanvas = canvas; 22 if (matrix) { 23 fMatrix = *matrix; 24 } else { 25 fMatrix.setIdentity(); 26 } 27 if (paint) { 28 fPaint = new SkPaint(*paint); 29 } else { 30 fPaint = nullptr; 31 } 32} 33 34void SkMultiPictureDraw::DrawData::Reset(SkTDArray<DrawData>& data) { 35 for (int i = 0; i < data.count(); ++i) { 36 data[i].fPicture->unref(); 37 delete data[i].fPaint; 38 } 39 data.rewind(); 40} 41 42////////////////////////////////////////////////////////////////////////////////////// 43 44SkMultiPictureDraw::SkMultiPictureDraw(int reserve) { 45 if (reserve > 0) { 46 fGPUDrawData.setReserve(reserve); 47 fThreadSafeDrawData.setReserve(reserve); 48 } 49} 50 51void SkMultiPictureDraw::reset() { 52 DrawData::Reset(fGPUDrawData); 53 DrawData::Reset(fThreadSafeDrawData); 54} 55 56void SkMultiPictureDraw::add(SkCanvas* canvas, 57 const SkPicture* picture, 58 const SkMatrix* matrix, 59 const SkPaint* paint) { 60 if (nullptr == canvas || nullptr == picture) { 61 SkDEBUGFAIL("parameters to SkMultiPictureDraw::add should be non-nullptr"); 62 return; 63 } 64 65 SkTDArray<DrawData>& array = canvas->getGrContext() ? fGPUDrawData : fThreadSafeDrawData; 66 array.append()->init(canvas, picture, matrix, paint); 67} 68 69class AutoMPDReset : SkNoncopyable { 70 SkMultiPictureDraw* fMPD; 71public: 72 AutoMPDReset(SkMultiPictureDraw* mpd) : fMPD(mpd) {} 73 ~AutoMPDReset() { fMPD->reset(); } 74}; 75 76//#define FORCE_SINGLE_THREAD_DRAWING_FOR_TESTING 77 78void SkMultiPictureDraw::draw(bool flush) { 79 AutoMPDReset mpdreset(this); 80 81#ifdef FORCE_SINGLE_THREAD_DRAWING_FOR_TESTING 82 for (int i = 0; i < fThreadSafeDrawData.count(); ++i) { 83 fThreadSafeDrawData[i].draw(); 84 } 85#else 86 SkTaskGroup().batch(fThreadSafeDrawData.count(), [&](int i) { 87 fThreadSafeDrawData[i].draw(); 88 }); 89#endif 90 91 // N.B. we could get going on any GPU work from this main thread while the CPU work runs. 92 // But in practice, we've either got GPU work or CPU work, not both. 93 94 const int count = fGPUDrawData.count(); 95 if (0 == count) { 96 return; 97 } 98 99 for (int i = 0; i < count; ++i) { 100 const DrawData& data = fGPUDrawData[i]; 101 SkCanvas* canvas = data.fCanvas; 102 const SkPicture* picture = data.fPicture; 103 104 canvas->drawPicture(picture, &data.fMatrix, data.fPaint); 105 if (flush) { 106 canvas->flush(); 107 } 108 } 109} 110