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 14 void SkMultiPictureDraw::DrawData::draw() { 15 fCanvas->drawPicture(fPicture, &fMatrix, fPaint); 16 } 17 18 void 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 34 void 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 44 SkMultiPictureDraw::SkMultiPictureDraw(int reserve) { 45 if (reserve > 0) { 46 fGPUDrawData.setReserve(reserve); 47 fThreadSafeDrawData.setReserve(reserve); 48 } 49 } 50 51 void SkMultiPictureDraw::reset() { 52 DrawData::Reset(fGPUDrawData); 53 DrawData::Reset(fThreadSafeDrawData); 54 } 55 56 void 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 69 class AutoMPDReset : SkNoncopyable { 70 SkMultiPictureDraw* fMPD; 71 public: 72 AutoMPDReset(SkMultiPictureDraw* mpd) : fMPD(mpd) {} 73 ~AutoMPDReset() { fMPD->reset(); } 74 }; 75 76 //#define FORCE_SINGLE_THREAD_DRAWING_FOR_TESTING 77 78 void 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