Home | History | Annotate | Download | only in gpu
      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 "GrRecordReplaceDraw.h"
      9 #include "SkImage.h"
     10 #include "SkRecordDraw.h"
     11 
     12 GrReplacements::ReplacementInfo* GrReplacements::push() {
     13     SkDEBUGCODE(this->validate());
     14     return fReplacements.push();
     15 }
     16 
     17 void GrReplacements::freeAll() {
     18     for (int i = 0; i < fReplacements.count(); ++i) {
     19         fReplacements[i].fImage->unref();
     20         SkDELETE(fReplacements[i].fPaint);
     21     }
     22     fReplacements.reset();
     23 }
     24 
     25 #ifdef SK_DEBUG
     26 void GrReplacements::validate() const {
     27     // Check that the ranges are monotonically increasing and non-overlapping
     28     if (fReplacements.count() > 0) {
     29         SkASSERT(fReplacements[0].fStart < fReplacements[0].fStop);
     30 
     31         for (int i = 1; i < fReplacements.count(); ++i) {
     32             SkASSERT(fReplacements[i].fStart < fReplacements[i].fStop);
     33             SkASSERT(fReplacements[i - 1].fStop < fReplacements[i].fStart);
     34         }
     35     }
     36 }
     37 #endif
     38 
     39 const GrReplacements::ReplacementInfo*
     40 GrReplacements::lookupByStart(size_t start, int* searchStart) const {
     41     SkDEBUGCODE(this->validate());
     42     for (int i = *searchStart; i < fReplacements.count(); ++i) {
     43         if (start == fReplacements[i].fStart) {
     44             *searchStart = i + 1;
     45             return &fReplacements[i];
     46         } else if (start < fReplacements[i].fStart) {
     47             return NULL;  // the ranges are monotonically increasing and non-overlapping
     48         }
     49     }
     50 
     51     return NULL;
     52 }
     53 
     54 static inline void draw_replacement_bitmap(const GrReplacements::ReplacementInfo* ri,
     55                                            SkCanvas* canvas,
     56                                            const SkMatrix& initialMatrix) {
     57     SkRect src = SkRect::Make(ri->fSrcRect);
     58     SkRect dst = SkRect::MakeXYWH(SkIntToScalar(ri->fPos.fX),
     59                                   SkIntToScalar(ri->fPos.fY),
     60                                   SkIntToScalar(ri->fSrcRect.width()),
     61                                   SkIntToScalar(ri->fSrcRect.height()));
     62 
     63     canvas->save();
     64     canvas->setMatrix(initialMatrix);
     65     canvas->drawImageRect(ri->fImage, &src, dst, ri->fPaint);
     66     canvas->restore();
     67 }
     68 
     69 void GrRecordReplaceDraw(const SkRecord& record,
     70                          SkCanvas* canvas,
     71                          const SkBBoxHierarchy* bbh,
     72                          const GrReplacements* replacements,
     73                          SkDrawPictureCallback* callback) {
     74     SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/);
     75 
     76     SkRecords::Draw draw(canvas);
     77     const GrReplacements::ReplacementInfo* ri = NULL;
     78     int searchStart = 0;
     79 
     80     const SkMatrix initialMatrix = canvas->getTotalMatrix();
     81 
     82     if (bbh) {
     83         // Draw only ops that affect pixels in the canvas's current clip.
     84         // The SkRecord and BBH were recorded in identity space.  This canvas
     85         // is not necessarily in that same space.  getClipBounds() returns us
     86         // this canvas' clip bounds transformed back into identity space, which
     87         // lets us query the BBH.
     88         SkRect query = { 0, 0, 0, 0 };
     89         (void)canvas->getClipBounds(&query);
     90 
     91         SkTDArray<void*> ops;
     92         bbh->search(query, &ops);
     93 
     94         for (int i = 0; i < ops.count(); i++) {
     95             if (callback && callback->abortDrawing()) {
     96                 return;
     97             }
     98             ri = replacements->lookupByStart((uintptr_t)ops[i], &searchStart);
     99             if (ri) {
    100                 draw_replacement_bitmap(ri, canvas, initialMatrix);
    101 
    102                 while ((uintptr_t)ops[i] < ri->fStop) {
    103                     ++i;
    104                 }
    105                 SkASSERT((uintptr_t)ops[i] == ri->fStop);
    106                 continue;
    107             }
    108 
    109             record.visit<void>((uintptr_t)ops[i], draw);
    110         }
    111     } else {
    112         for (unsigned int i = 0; i < record.count(); ++i) {
    113             if (callback && callback->abortDrawing()) {
    114                 return;
    115             }
    116             ri = replacements->lookupByStart(i, &searchStart);
    117             if (ri) {
    118                 draw_replacement_bitmap(ri, canvas, initialMatrix);
    119                 i = ri->fStop;
    120                 continue;
    121             }
    122 
    123             record.visit<void>(i, draw);
    124         }
    125     }
    126 }
    127