OLD | NEW |
---|---|
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 "SkRecordDraw.h" | 8 #include "SkRecordDraw.h" |
9 #include "SkPatchUtils.h" | 9 #include "SkPatchUtils.h" |
10 | 10 |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
114 DRAW(DrawVertices, drawVertices(r.vmode, r.vertexCount, r.vertices, r.texs, r.co lors, | 114 DRAW(DrawVertices, drawVertices(r.vmode, r.vertexCount, r.vertices, r.texs, r.co lors, |
115 r.xmode.get(), r.indices, r.indexCount, r.paint) ); | 115 r.xmode.get(), r.indices, r.indexCount, r.paint) ); |
116 DRAW(DrawData, drawData(r.data, r.length)); | 116 DRAW(DrawData, drawData(r.data, r.length)); |
117 #undef DRAW | 117 #undef DRAW |
118 | 118 |
119 | 119 |
120 // This looks silly, I know. Why not just use SkRect::MakeLargest()? | 120 // This looks silly, I know. Why not just use SkRect::MakeLargest()? |
121 // In practice, this is well large enough, and it has a few extra advantages: | 121 // In practice, this is well large enough, and it has a few extra advantages: |
122 // it fits in an SkIRect, and we can munge it a little in both SkRect and | 122 // it fits in an SkIRect, and we can munge it a little in both SkRect and |
123 // SKIRect space without worrying about overflow. | 123 // SKIRect space without worrying about overflow. |
124 static const SkRect kUnbounded = { -2e9f, -2e9f, 2e9f, 2e9f }; | 124 static const SkRect kUnbounded = { -2e9f, -2e9f, 2e9f, 2e9f }; |
mtklein
2014/10/31 18:21:01
Should be we can do a big find kUnbounded / replac
robertphillips
2014/10/31 18:49:55
Done.
| |
125 | 125 |
126 | 126 |
127 // This is an SkRecord visitor that fills an SkBBoxHierarchy. | 127 // This is an SkRecord visitor that fills an SkBBoxHierarchy. |
128 // | 128 // |
129 // The interesting part here is how to calculate bounds for ops which don't | 129 // The interesting part here is how to calculate bounds for ops which don't |
130 // have intrinsic bounds. What is the bounds of a Save or a Translate? | 130 // have intrinsic bounds. What is the bounds of a Save or a Translate? |
131 // | 131 // |
132 // We answer this by thinking about a particular definition of bounds: if I | 132 // We answer this by thinking about a particular definition of bounds: if I |
133 // don't execute this op, pixels in this rectangle might draw incorrectly. So | 133 // don't execute this op, pixels in this rectangle might draw incorrectly. So |
134 // the bounds of a Save, a Translate, a Restore, etc. are the union of the | 134 // the bounds of a Save, a Translate, a Restore, etc. are the union of the |
135 // bounds of Draw* ops that they might have an effect on. For any given | 135 // bounds of Draw* ops that they might have an effect on. For any given |
136 // Save/Restore block, the bounds of the Save, the Restore, and any other | 136 // Save/Restore block, the bounds of the Save, the Restore, and any other |
137 // non-drawing ("control") ops inside are exactly the union of the bounds of | 137 // non-drawing ("control") ops inside are exactly the union of the bounds of |
138 // the drawing ops inside that block. | 138 // the drawing ops inside that block. |
139 // | 139 // |
140 // To implement this, we keep a stack of active Save blocks. As we consume ops | 140 // To implement this, we keep a stack of active Save blocks. As we consume ops |
141 // inside the Save/Restore block, drawing ops are unioned with the bounds of | 141 // inside the Save/Restore block, drawing ops are unioned with the bounds of |
142 // the block, and control ops are stashed away for later. When we finish the | 142 // the block, and control ops are stashed away for later. When we finish the |
143 // block with a Restore, our bounds are complete, and we go back and fill them | 143 // block with a Restore, our bounds are complete, and we go back and fill them |
144 // in for all the control ops we stashed away. | 144 // in for all the control ops we stashed away. |
145 class FillBounds : SkNoncopyable { | 145 class FillBounds : SkNoncopyable { |
146 public: | 146 public: |
147 FillBounds(const SkRecord& record, SkBBoxHierarchy* bbh) : fBounds(record.co unt()) { | 147 FillBounds(const SkRect& cullRect, const SkRecord& record, SkBBoxHierarchy* bbh) |
148 : fBounds(record.count()) { | |
148 // Calculate bounds for all ops. This won't go quite in order, so we'll need | 149 // Calculate bounds for all ops. This won't go quite in order, so we'll need |
149 // to store the bounds separately then feed them in to the BBH later in order. | 150 // to store the bounds separately then feed them in to the BBH later in order. |
150 fCTM = &SkMatrix::I(); | 151 fCTM = &SkMatrix::I(); |
151 fCurrentClipBounds = kUnbounded; | 152 fCurrentClipBounds = cullRect; |
mtklein
2014/10/31 18:21:01
This seems an orthogonal change. Might stick to k
| |
152 for (fCurrentOp = 0; fCurrentOp < record.count(); fCurrentOp++) { | 153 for (fCurrentOp = 0; fCurrentOp < record.count(); fCurrentOp++) { |
153 record.visit<void>(fCurrentOp, *this); | 154 record.visit<void>(fCurrentOp, *this); |
154 } | 155 } |
155 | 156 |
156 // If we have any lingering unpaired Saves, simulate restores to make | 157 // If we have any lingering unpaired Saves, simulate restores to make |
157 // sure all ops in those Save blocks have their bounds calculated. | 158 // sure all ops in those Save blocks have their bounds calculated. |
158 while (!fSaveStack.isEmpty()) { | 159 while (!fSaveStack.isEmpty()) { |
159 this->popSaveBlock(); | 160 this->popSaveBlock(); |
160 } | 161 } |
161 | 162 |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
246 void trackBounds(const DrawData&) { this->pushControl(); } | 247 void trackBounds(const DrawData&) { this->pushControl(); } |
247 | 248 |
248 // For all other ops, we can calculate and store the bounds directly now. | 249 // For all other ops, we can calculate and store the bounds directly now. |
249 template <typename T> void trackBounds(const T& op) { | 250 template <typename T> void trackBounds(const T& op) { |
250 fBounds[fCurrentOp] = this->bounds(op); | 251 fBounds[fCurrentOp] = this->bounds(op); |
251 this->updateSaveBounds(fBounds[fCurrentOp]); | 252 this->updateSaveBounds(fBounds[fCurrentOp]); |
252 } | 253 } |
253 | 254 |
254 void pushSaveBlock(const SkPaint* paint) { | 255 void pushSaveBlock(const SkPaint* paint) { |
255 // Starting a new Save block. Push a new entry to represent that. | 256 // Starting a new Save block. Push a new entry to represent that. |
256 SaveBounds sb = { 0, Bounds::MakeEmpty(), paint }; | 257 SaveBounds sb; |
258 sb.controlOps = 0; | |
259 // If the paint affects transparent black, the bound shouldn't be smalle r | |
260 // then the current clip bounds.» | |
261 sb.bounds = | |
262 PaintMayAffectTransparentBlack(paint) ? fCurrentClipBounds : Bounds: :MakeEmpty(); | |
263 sb.paint = paint; | |
264 | |
257 fSaveStack.push(sb); | 265 fSaveStack.push(sb); |
258 this->pushControl(); | 266 this->pushControl(); |
259 } | 267 } |
260 | 268 |
261 static bool PaintMayAffectTransparentBlack(const SkPaint* paint) { | 269 static bool PaintMayAffectTransparentBlack(const SkPaint* paint) { |
262 if (paint) { | 270 if (paint) { |
263 // FIXME: this is very conservative | 271 // FIXME: this is very conservative |
264 if (paint->getImageFilter() || paint->getColorFilter()) { | 272 if (paint->getImageFilter() || paint->getColorFilter()) { |
265 return true; | 273 return true; |
266 } | 274 } |
(...skipping 29 matching lines...) Expand all Loading... | |
296 } | 304 } |
297 } | 305 } |
298 return false; | 306 return false; |
299 } | 307 } |
300 | 308 |
301 Bounds popSaveBlock() { | 309 Bounds popSaveBlock() { |
302 // We're done the Save block. Apply the block's bounds to all control o ps inside it. | 310 // We're done the Save block. Apply the block's bounds to all control o ps inside it. |
303 SaveBounds sb; | 311 SaveBounds sb; |
304 fSaveStack.pop(&sb); | 312 fSaveStack.pop(&sb); |
305 | 313 |
306 // If the paint affects transparent black, we can't trust any of our cal culated bounds. | |
307 const Bounds& bounds = | |
308 PaintMayAffectTransparentBlack(sb.paint) ? fCurrentClipBounds : sb.b ounds; | |
309 | |
310 while (sb.controlOps --> 0) { | 314 while (sb.controlOps --> 0) { |
311 this->popControl(bounds); | 315 this->popControl(sb.bounds); |
312 } | 316 } |
313 | 317 |
314 // This whole Save block may be part another Save block. | 318 // This whole Save block may be part another Save block. |
315 this->updateSaveBounds(bounds); | 319 this->updateSaveBounds(sb.bounds); |
316 | 320 |
317 // If called from a real Restore (not a phony one for balance), it'll ne ed the bounds. | 321 // If called from a real Restore (not a phony one for balance), it'll ne ed the bounds. |
318 return bounds; | 322 return sb.bounds; |
319 } | 323 } |
320 | 324 |
321 void pushControl() { | 325 void pushControl() { |
322 fControlIndices.push(fCurrentOp); | 326 fControlIndices.push(fCurrentOp); |
323 if (!fSaveStack.isEmpty()) { | 327 if (!fSaveStack.isEmpty()) { |
324 fSaveStack.top().controlOps++; | 328 fSaveStack.top().controlOps++; |
325 } | 329 } |
326 } | 330 } |
327 | 331 |
328 void popControl(const Bounds& bounds) { | 332 void popControl(const Bounds& bounds) { |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
547 const SkMatrix* fCTM; | 551 const SkMatrix* fCTM; |
548 Bounds fCurrentClipBounds; | 552 Bounds fCurrentClipBounds; |
549 | 553 |
550 // Used to track the bounds of Save/Restore blocks and the control ops insid e them. | 554 // Used to track the bounds of Save/Restore blocks and the control ops insid e them. |
551 SkTDArray<SaveBounds> fSaveStack; | 555 SkTDArray<SaveBounds> fSaveStack; |
552 SkTDArray<unsigned> fControlIndices; | 556 SkTDArray<unsigned> fControlIndices; |
553 }; | 557 }; |
554 | 558 |
555 } // namespace SkRecords | 559 } // namespace SkRecords |
556 | 560 |
557 void SkRecordFillBounds(const SkRecord& record, SkBBoxHierarchy* bbh) { | 561 void SkRecordFillBounds(const SkRect& cullRect, const SkRecord& record, SkBBoxHi erarchy* bbh) { |
558 SkRecords::FillBounds(record, bbh); | 562 SkRecords::FillBounds(cullRect, record, bbh); |
559 } | 563 } |
OLD | NEW |