Chromium Code Reviews| 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 |