Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(279)

Side by Side Diff: src/gpu/GrRecordReplaceDraw.cpp

Issue 597293002: Fix sub-picture layer rendering bugs (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Update to ToT Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/GrRecordReplaceDraw.h ('k') | tests/RecordReplaceDrawTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2014 Google Inc. 2 * Copyright 2014 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "GrRecordReplaceDraw.h" 8 #include "GrRecordReplaceDraw.h"
9 #include "SkImage.h" 9 #include "SkImage.h"
10 #include "SkRecordDraw.h" 10 #include "SkRecordDraw.h"
11 #include "SkRecords.h"
12 #include "SkCanvasPriv.h"
11 13
12 GrReplacements::ReplacementInfo* GrReplacements::push() { 14 GrReplacements::ReplacementInfo* GrReplacements::newReplacement(uint32_t picture ID,
13 SkDEBUGCODE(this->validate()); 15 unsigned int sta rt,
14 return fReplacements.push(); 16 const SkMatrix& ctm) {
17 ReplacementInfo* replacement = SkNEW_ARGS(ReplacementInfo, (pictureID, start , ctm, true));
18 fReplacementHash.add(replacement);
19 return replacement;
15 } 20 }
16 21
17 void GrReplacements::freeAll() { 22 void GrReplacements::freeAll() {
18 for (int i = 0; i < fReplacements.count(); ++i) { 23 SkTDynamicHash<ReplacementInfo, ReplacementInfo::Key>::Iter iter(&fReplaceme ntHash);
19 fReplacements[i].fImage->unref(); 24
20 SkDELETE(fReplacements[i].fPaint); 25 for (; !iter.done(); ++iter) {
26 ReplacementInfo* replacement = &(*iter);
27 SkDELETE(replacement);
21 } 28 }
22 fReplacements.reset(); 29
30 fReplacementHash.reset();
23 } 31 }
24 32
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* 33 const GrReplacements::ReplacementInfo*
40 GrReplacements::lookupByStart(size_t start, int* searchStart) const { 34 GrReplacements::lookupByStart(uint32_t pictureID, size_t start, const SkMatrix& ctm) const {
41 SkDEBUGCODE(this->validate()); 35 return fReplacementHash.find(ReplacementInfo::Key(pictureID, start, ctm, tru e));
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-ove rlapping
48 }
49 }
50
51 return NULL;
52 } 36 }
53 37
54 static inline void draw_replacement_bitmap(const GrReplacements::ReplacementInfo * ri, 38 static inline void draw_replacement_bitmap(const GrReplacements::ReplacementInfo * ri,
55 SkCanvas* canvas, 39 SkCanvas* canvas,
56 const SkMatrix& initialMatrix) { 40 const SkMatrix& initialMatrix) {
57 SkRect src = SkRect::Make(ri->fSrcRect); 41 SkRect src = SkRect::Make(ri->fSrcRect);
58 SkRect dst = SkRect::MakeXYWH(SkIntToScalar(ri->fPos.fX), 42 SkRect dst = SkRect::MakeXYWH(SkIntToScalar(ri->fPos.fX),
59 SkIntToScalar(ri->fPos.fY), 43 SkIntToScalar(ri->fPos.fY),
60 SkIntToScalar(ri->fSrcRect.width()), 44 SkIntToScalar(ri->fSrcRect.width()),
61 SkIntToScalar(ri->fSrcRect.height())); 45 SkIntToScalar(ri->fSrcRect.height()));
62 46
63 canvas->save(); 47 canvas->save();
64 canvas->setMatrix(initialMatrix); 48 canvas->setMatrix(initialMatrix);
65 canvas->drawImageRect(ri->fImage, &src, dst, ri->fPaint); 49 canvas->drawImageRect(ri->fImage, &src, dst, ri->fPaint);
66 canvas->restore(); 50 canvas->restore();
67 } 51 }
68 52
53 // Used by GrRecordReplaceDraw. It intercepts nested drawPicture calls and
54 // also draws them with replaced layers.
55 class ReplaceDraw : public SkRecords::Draw {
56 public:
57 ReplaceDraw(SkCanvas* canvas,
58 const GrReplacements* replacements,
59 const SkMatrix& initialMatrix,
60 SkDrawPictureCallback* callback,
61 const SkRecord* record,
62 uint32_t pictureID)
63 : INHERITED(canvas)
64 , fCanvas(canvas)
65 , fReplacements(replacements)
66 , fInitialMatrix(initialMatrix)
67 , fCallback(callback)
68 , fIndex(0)
69 , fRecord(record)
70 , fPictureID(pictureID) {
71 }
72
73 bool done() const { return fIndex >= fRecord->count(); }
74 void drawCur() { fRecord->visit<void>(fIndex, *this); fIndex++; }
75
76 // Same as Draw for all ops except DrawPicture.
77 template <typename T> void operator()(const T& r) {
78 this->INHERITED::operator()(r);
79 }
80 void operator()(const SkRecords::DrawPicture& dp) {
81 SkAutoCanvasMatrixPaint acmp(fCanvas, dp.matrix, dp.paint, dp.picture->c ullRect());
82
83 GrRecordReplaceDraw(dp.picture,
84 fCanvas,
85 fReplacements,
86 fInitialMatrix,
87 fCallback);
88 }
89 void operator()(const SkRecords::SaveLayer& sl) {
90 const GrReplacements::ReplacementInfo* ri;
91
92 ri = fReplacements->lookupByStart(fPictureID, fIndex, fCanvas->getTotalM atrix());
93 if (ri) {
94 draw_replacement_bitmap(ri, fCanvas, fInitialMatrix);
95 fIndex = ri->fStop;
96 return;
97 }
98
99 // This is a fail for layer hoisting
100 this->INHERITED::operator()(sl);
101 }
102
103 private:
104 SkCanvas* fCanvas;
105 const GrReplacements* fReplacements;
106 const SkMatrix fInitialMatrix;
107 SkDrawPictureCallback* fCallback;
108 unsigned int fIndex;
109 const SkRecord* fRecord;
110 uint32_t fPictureID;
111
112 typedef Draw INHERITED;
113 };
114
69 void GrRecordReplaceDraw(const SkPicture* picture, 115 void GrRecordReplaceDraw(const SkPicture* picture,
70 SkCanvas* canvas, 116 SkCanvas* canvas,
71 const GrReplacements* replacements, 117 const GrReplacements* replacements,
72 const SkMatrix& initialMatrix, 118 const SkMatrix& initialMatrix,
73 SkDrawPictureCallback* callback) { 119 SkDrawPictureCallback* callback) {
74 SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/); 120 SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/);
75 121
76 const SkBBoxHierarchy* bbh = picture->fBBH.get(); 122 const SkBBoxHierarchy* bbh = picture->fBBH.get();
77 const SkRecord* record = picture->fRecord.get(); 123 const SkRecord* record = picture->fRecord.get();
78 if (NULL == record) { 124 if (NULL == record) {
79 return; 125 return;
80 } 126 }
81 127
82 SkRecords::Draw draw(canvas); 128 ReplaceDraw draw(canvas, replacements, initialMatrix, callback, record, pict ure->uniqueID());
83 const GrReplacements::ReplacementInfo* ri = NULL; 129 const GrReplacements::ReplacementInfo* ri = NULL;
84 int searchStart = 0;
85 130
86 if (bbh) { 131 if (bbh) {
87 // Draw only ops that affect pixels in the canvas's current clip. 132 // Draw only ops that affect pixels in the canvas's current clip.
88 // The SkRecord and BBH were recorded in identity space. This canvas 133 // The SkRecord and BBH were recorded in identity space. This canvas
89 // is not necessarily in that same space. getClipBounds() returns us 134 // is not necessarily in that same space. getClipBounds() returns us
90 // this canvas' clip bounds transformed back into identity space, which 135 // this canvas' clip bounds transformed back into identity space, which
91 // lets us query the BBH. 136 // lets us query the BBH.
92 SkRect query = { 0, 0, 0, 0 }; 137 SkRect query = { 0, 0, 0, 0 };
93 (void)canvas->getClipBounds(&query); 138 (void)canvas->getClipBounds(&query);
94 139
95 SkTDArray<void*> ops; 140 SkTDArray<void*> ops;
96 bbh->search(query, &ops); 141 bbh->search(query, &ops);
97 142
98 for (int i = 0; i < ops.count(); i++) { 143 for (int i = 0; i < ops.count(); i++) {
99 if (callback && callback->abortDrawing()) { 144 if (callback && callback->abortDrawing()) {
100 return; 145 return;
101 } 146 }
102 ri = replacements->lookupByStart((uintptr_t)ops[i], &searchStart); 147 ri = replacements->lookupByStart(picture->uniqueID(),
148 (uintptr_t)ops[i],
149 canvas->getTotalMatrix());
103 if (ri) { 150 if (ri) {
104 draw_replacement_bitmap(ri, canvas, initialMatrix); 151 draw_replacement_bitmap(ri, canvas, initialMatrix);
105 152
106 while ((uintptr_t)ops[i] < ri->fStop) { 153 while ((uintptr_t)ops[i] < ri->fStop) {
107 ++i; 154 ++i;
108 } 155 }
109 SkASSERT((uintptr_t)ops[i] == ri->fStop); 156 SkASSERT((uintptr_t)ops[i] == ri->fStop);
110 continue; 157 continue;
111 } 158 }
112 159
113 record->visit<void>((uintptr_t)ops[i], draw); 160 record->visit<void>((uintptr_t)ops[i], draw);
114 } 161 }
115 } else { 162 } else {
116 for (unsigned int i = 0; i < record->count(); ++i) { 163 while (!draw.done()) {
117 if (callback && callback->abortDrawing()) { 164 if (callback && callback->abortDrawing()) {
118 return; 165 return;
119 } 166 }
120 ri = replacements->lookupByStart(i, &searchStart);
121 if (ri) {
122 draw_replacement_bitmap(ri, canvas, initialMatrix);
123 i = ri->fStop;
124 continue;
125 }
126 167
127 record->visit<void>(i, draw); 168 draw.drawCur();
128 } 169 }
129 } 170 }
130 } 171 }
OLDNEW
« no previous file with comments | « src/gpu/GrRecordReplaceDraw.h ('k') | tests/RecordReplaceDrawTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698