Home | History | Annotate | Download | only in core
      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