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

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

Issue 716913003: Move SkRecordComputeLayers and CollectLayers into SkRecordDraw.cpp (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Address code review issues Created 6 years, 1 month 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/GrPictureUtils.h ('k') | tests/PictureTest.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 "GrPictureUtils.h" 8 #include "GrPictureUtils.h"
9 9
10 #include "SkBBoxHierarchy.h" 10 #include "SkBBoxHierarchy.h"
11 #include "SkPaintPriv.h" 11 #include "SkPaintPriv.h"
12 #include "SkPatchUtils.h" 12 #include "SkPatchUtils.h"
13 #include "SkRecord.h" 13 #include "SkRecord.h"
14 #include "SkRecords.h" 14 #include "SkRecords.h"
15 15
16 SkPicture::AccelData::Key GrAccelData::ComputeAccelDataKey() { 16 SkPicture::AccelData::Key GrAccelData::ComputeAccelDataKey() {
17 static const SkPicture::AccelData::Key gGPUID = SkPicture::AccelData::Genera teDomain(); 17 static const SkPicture::AccelData::Key gGPUID = SkPicture::AccelData::Genera teDomain();
18 18
19 return gGPUID; 19 return gGPUID;
20 } 20 }
21 21
22 // This looks silly, I know. Why not just use SkRect::MakeLargest()?
23 // In practice, this is well large enough, and it has a few extra advantages:
24 // it fits in an SkIRect, and we can munge it a little in both SkRect and
25 // SKIRect space without worrying about overflow.
26 static const SkRect kUnbounded = { -2e9f, -2e9f, 2e9f, 2e9f };
27
28 namespace SkRecords {
29
30 // SkRecord visitor to gather saveLayer/restore information.
31 class CollectLayers : SkNoncopyable {
32 public:
33 CollectLayers(const SkRect& cullRect, const SkRecord& record,
34 SkBBoxHierarchy* bbh, GrAccelData* accelData)
35 : fSaveLayersInStack(0)
36 , fAccelData(accelData) {
37
38 // Calculate bounds for all ops. This won't go quite in order, so we'll need
39 // to store the bounds separately then feed them in to the BBH later in order.
40 fCTM = &SkMatrix::I();
41 fCurrentClipBounds = kUnbounded;
42
43 fBounds.reset(record.count());
44
45 for (fCurrentOp = 0; fCurrentOp < record.count(); ++fCurrentOp) {
46 record.visit<void>(fCurrentOp, *this);
47 }
48
49 // If we have any lingering unpaired Saves, simulate restores to make
50 // sure all ops in those Save blocks have their bounds calculated.
51 while (!fSaveStack.isEmpty()) {
52 this->popSaveBlock();
53 }
54
55 // Any control ops not part of any Save/Restore block draw everywhere.
56 while (!fControlIndices.isEmpty()) {
57 this->popControl(kUnbounded);
58 }
59
60 //--------- LAYER HOISTING
61 while (!fSaveLayerStack.isEmpty()) {
62 this->popSaveLayerInfo();
63 }
64 //--------- LAYER HOISTING
65
66 // Finally feed all stored bounds into the BBH. They'll be returned in this order.
67 SkASSERT(bbh);
68 bbh->insert(&fBounds, record.count());
69 }
70
71 template <typename T> void operator()(const T& op) {
72 this->updateCTM(op);
73 this->updateClipBounds(op);
74 this->trackBounds(op);
75 //--------- LAYER HOISTING
76 this->trackSaveLayers(op);
77 //--------- LAYER HOISTING
78 }
79
80 private:
81 // In this file, SkRect are in local coordinates, Bounds are translated back to identity space.
82 typedef SkRect Bounds;
83
84 struct SaveBounds {
85 int controlOps; // Number of control ops in this Save block, incl uding the Save.
86 Bounds bounds; // Bounds of everything in the block.
87 const SkPaint* paint; // Unowned. If set, adjusts the bounds of all op s in this block.
88 };
89
90 //--------- LAYER HOISTING
91 class SaveLayerInfo {
92 public:
93 SaveLayerInfo() { }
94 SaveLayerInfo(int opIndex, bool isSaveLayer, const SkPaint* paint, const Bounds& clipBound)
95 : fStartIndex(opIndex)
96 , fIsSaveLayer(isSaveLayer)
97 , fHasNestedSaveLayer(false)
98 , fPaint(paint)
99 , fClipBound(clipBound) {
100 }
101
102 int fStartIndex;
103 bool fIsSaveLayer;
104 bool fHasNestedSaveLayer;
105 const SkPaint* fPaint;
106 Bounds fClipBound;
107 };
108 //--------- LAYER HOISTING
109
110 // Only Restore and SetMatrix change the CTM.
111 template <typename T> void updateCTM(const T&) {}
112 void updateCTM(const Restore& op) { fCTM = &op.matrix; }
113 void updateCTM(const SetMatrix& op) { fCTM = &op.matrix; }
114
115 // Most ops don't change the clip.
116 template <typename T> void updateClipBounds(const T&) {}
117
118 // Clip{Path,RRect,Rect,Region} obviously change the clip. They all know th eir bounds already.
119 void updateClipBounds(const ClipPath& op) { this->updateClipBoundsForClipO p(op.devBounds); }
120 void updateClipBounds(const ClipRRect& op) { this->updateClipBoundsForClipO p(op.devBounds); }
121 void updateClipBounds(const ClipRect& op) { this->updateClipBoundsForClipO p(op.devBounds); }
122 void updateClipBounds(const ClipRegion& op) { this->updateClipBoundsForClipO p(op.devBounds); }
123
124 // The bounds of clip ops need to be adjusted for the paints of saveLayers t hey're inside.
125 void updateClipBoundsForClipOp(const SkIRect& devBounds) {
126 Bounds clip = SkRect::Make(devBounds);
127 // We don't call adjustAndMap() because as its last step it would inters ect the adjusted
128 // clip bounds with the previous clip, exactly what we can't do when the clip grows.
129 fCurrentClipBounds = this->adjustForSaveLayerPaints(&clip) ? clip : kUnb ounded;
130 }
131
132 // Restore holds the devBounds for the clip after the {save,saveLayer}/resto re block completes.
133 void updateClipBounds(const Restore& op) {
134 // This is just like the clip ops above, but we need to skip the effects (if any) of our
135 // paired saveLayer (if it is one); it has not yet been popped off the s ave stack. Our
136 // devBounds reflect the state of the world after the saveLayer/restore block is done,
137 // so they are not affected by the saveLayer's paint.
138 const int kSavesToIgnore = 1;
139 Bounds clip = SkRect::Make(op.devBounds);
140 fCurrentClipBounds =
141 this->adjustForSaveLayerPaints(&clip, kSavesToIgnore) ? clip : kUnbo unded;
142 }
143
144 // We also take advantage of SaveLayer bounds when present to further cut th e clip down.
145 void updateClipBounds(const SaveLayer& op) {
146 if (op.bounds) {
147 // adjustAndMap() intersects these layer bounds with the previous cl ip for us.
148 fCurrentClipBounds = this->adjustAndMap(*op.bounds, op.paint);
149 }
150 }
151
152 // The bounds of these ops must be calculated when we hit the Restore
153 // from the bounds of the ops in the same Save block.
154 void trackBounds(const Save&) { this->pushSaveBlock(NULL); }
155 void trackBounds(const SaveLayer& op) { this->pushSaveBlock(op.paint); }
156 void trackBounds(const Restore&) { fBounds[fCurrentOp] = this->popSaveBlock( ); }
157
158 void trackBounds(const SetMatrix&) { this->pushControl(); }
159 void trackBounds(const ClipRect&) { this->pushControl(); }
160 void trackBounds(const ClipRRect&) { this->pushControl(); }
161 void trackBounds(const ClipPath&) { this->pushControl(); }
162 void trackBounds(const ClipRegion&) { this->pushControl(); }
163 void trackBounds(const PushCull&) { this->pushControl(); }
164 void trackBounds(const PopCull&) { this->pushControl(); }
165 void trackBounds(const BeginCommentGroup&) { this->pushControl(); }
166 void trackBounds(const AddComment&) { this->pushControl(); }
167 void trackBounds(const EndCommentGroup&) { this->pushControl(); }
168 void trackBounds(const DrawData&) { this->pushControl(); }
169
170 // For all other ops, we can calculate and store the bounds directly now.
171 template <typename T> void trackBounds(const T& op) {
172 fBounds[fCurrentOp] = this->bounds(op);
173 this->updateSaveBounds(fBounds[fCurrentOp]);
174 }
175
176 void pushSaveBlock(const SkPaint* paint) {
177 // Starting a new Save block. Push a new entry to represent that.
178 SaveBounds sb = { 0, Bounds::MakeEmpty(), paint };
179 fSaveStack.push(sb);
180 this->pushControl();
181 }
182
183 static bool PaintMayAffectTransparentBlack(const SkPaint* paint) {
184 if (paint) {
185 // FIXME: this is very conservative
186 if (paint->getImageFilter() || paint->getColorFilter()) {
187 return true;
188 }
189
190 // Unusual Xfermodes require us to process a saved layer
191 // even with operations outisde the clip.
192 // For example, DstIn is used by masking layers.
193 // https://code.google.com/p/skia/issues/detail?id=1291
194 // https://crbug.com/401593
195 SkXfermode* xfermode = paint->getXfermode();
196 SkXfermode::Mode mode;
197 // SrcOver is ok, and is also the common case with a NULL xfermode.
198 // So we should make that the fast path and bypass the mode extracti on
199 // and test.
200 if (xfermode && xfermode->asMode(&mode)) {
201 switch (mode) {
202 // For each of the following transfer modes, if the source
203 // alpha is zero (our transparent black), the resulting
204 // blended alpha is not necessarily equal to the original
205 // destination alpha.
206 case SkXfermode::kClear_Mode:
207 case SkXfermode::kSrc_Mode:
208 case SkXfermode::kSrcIn_Mode:
209 case SkXfermode::kDstIn_Mode:
210 case SkXfermode::kSrcOut_Mode:
211 case SkXfermode::kDstATop_Mode:
212 case SkXfermode::kModulate_Mode:
213 return true;
214 break;
215 default:
216 break;
217 }
218 }
219 }
220 return false;
221 }
222
223 Bounds popSaveBlock() {
224 // We're done the Save block. Apply the block's bounds to all control o ps inside it.
225 SaveBounds sb;
226 fSaveStack.pop(&sb);
227
228 // If the paint affects transparent black, we can't trust any of our cal culated bounds.
229 const Bounds& bounds =
230 PaintMayAffectTransparentBlack(sb.paint) ? fCurrentClipBounds : sb.b ounds;
231
232 while (sb.controlOps-- > 0) {
233 this->popControl(bounds);
234 }
235
236 // This whole Save block may be part another Save block.
237 this->updateSaveBounds(bounds);
238
239 // If called from a real Restore (not a phony one for balance), it'll ne ed the bounds.
240 return bounds;
241 }
242
243 void pushControl() {
244 fControlIndices.push(fCurrentOp);
245 if (!fSaveStack.isEmpty()) {
246 fSaveStack.top().controlOps++;
247 }
248 }
249
250 void popControl(const Bounds& bounds) {
251 fBounds[fControlIndices.top()] = bounds;
252 fControlIndices.pop();
253 }
254
255 void updateSaveBounds(const Bounds& bounds) {
256 // If we're in a Save block, expand its bounds to cover these bounds too .
257 if (!fSaveStack.isEmpty()) {
258 fSaveStack.top().bounds.join(bounds);
259 }
260 }
261
262 // FIXME: this method could use better bounds
263 Bounds bounds(const DrawText&) const { return fCurrentClipBounds; }
264
265 Bounds bounds(const Clear&) const { return kUnbounded; } // Igno res the clip.
266 Bounds bounds(const DrawPaint&) const { return fCurrentClipBounds; }
267 Bounds bounds(const NoOp&) const { return Bounds::MakeEmpty(); } // NoOp s don't draw.
268
269 Bounds bounds(const DrawSprite& op) const {
270 const SkBitmap& bm = op.bitmap;
271
272 return Bounds::Make(SkIRect::MakeXYWH(op.left, op.top, bm.width(), bm.he ight())); // Ignores the matrix.
273 }
274
275 Bounds bounds(const DrawRect& op) const { return this->adjustAndMap(op.rect, &op.paint); }
276 Bounds bounds(const DrawOval& op) const { return this->adjustAndMap(op.oval, &op.paint); }
277 Bounds bounds(const DrawRRect& op) const {
278 return this->adjustAndMap(op.rrect.rect(), &op.paint);
279 }
280 Bounds bounds(const DrawDRRect& op) const {
281 return this->adjustAndMap(op.outer.rect(), &op.paint);
282 }
283 Bounds bounds(const DrawImage& op) const {
284 const SkImage* image = op.image;
285 SkRect rect = SkRect::MakeXYWH(op.left, op.top,
286 SkIntToScalar(image->width()), SkIntToSc alar(image->height()));
287
288 return this->adjustAndMap(rect, op.paint);
289 }
290 Bounds bounds(const DrawImageRect& op) const {
291 return this->adjustAndMap(op.dst, op.paint);
292 }
293 Bounds bounds(const DrawBitmapRectToRect& op) const {
294 return this->adjustAndMap(op.dst, op.paint);
295 }
296 Bounds bounds(const DrawBitmapNine& op) const {
297 return this->adjustAndMap(op.dst, op.paint);
298 }
299 Bounds bounds(const DrawBitmap& op) const {
300 const SkBitmap& bm = op.bitmap;
301 return this->adjustAndMap(SkRect::MakeXYWH(op.left, op.top, SkIntToScala r(bm.width()), SkIntToScalar(bm.height())),
302 op.paint);
303 }
304 Bounds bounds(const DrawBitmapMatrix& op) const {
305 const SkBitmap& bm = op.bitmap;
306 SkRect dst = SkRect::Make(SkIRect::MakeWH(bm.width(), bm.height()));
307 op.matrix.mapRect(&dst);
308 return this->adjustAndMap(dst, op.paint);
309 }
310
311 Bounds bounds(const DrawPath& op) const {
312 return op.path.isInverseFillType() ? fCurrentClipBounds
313 : this->adjustAndMap(op.path.getBounds(), &op.paint);
314 }
315 Bounds bounds(const DrawPoints& op) const {
316 SkRect dst;
317 dst.set(op.pts, op.count);
318
319 // Pad the bounding box a little to make sure hairline points' bounds ar en't empty.
320 SkScalar stroke = SkMaxScalar(op.paint.getStrokeWidth(), 0.01f);
321 dst.outset(stroke / 2, stroke / 2);
322
323 return this->adjustAndMap(dst, &op.paint);
324 }
325 Bounds bounds(const DrawPatch& op) const {
326 SkRect dst;
327 dst.set(op.cubics, SkPatchUtils::kNumCtrlPts);
328 return this->adjustAndMap(dst, &op.paint);
329 }
330 Bounds bounds(const DrawVertices& op) const {
331 SkRect dst;
332 dst.set(op.vertices, op.vertexCount);
333 return this->adjustAndMap(dst, &op.paint);
334 }
335
336 Bounds bounds(const DrawPicture& op) const {
337 SkRect dst = op.picture->cullRect();
338 if (op.matrix) {
339 op.matrix->mapRect(&dst);
340 }
341 return this->adjustAndMap(dst, op.paint);
342 }
343
344 Bounds bounds(const DrawPosText& op) const {
345 const int N = op.paint.countText(op.text, op.byteLength);
346 if (N == 0) {
347 return Bounds::MakeEmpty();
348 }
349
350 SkRect dst;
351 dst.set(op.pos, N);
352 AdjustTextForFontMetrics(&dst, op.paint);
353 return this->adjustAndMap(dst, &op.paint);
354 }
355 Bounds bounds(const DrawPosTextH& op) const {
356 const int N = op.paint.countText(op.text, op.byteLength);
357 if (N == 0) {
358 return Bounds::MakeEmpty();
359 }
360
361 SkScalar left = op.xpos[0], right = op.xpos[0];
362 for (int i = 1; i < N; i++) {
363 left = SkMinScalar(left, op.xpos[i]);
364 right = SkMaxScalar(right, op.xpos[i]);
365 }
366 SkRect dst = { left, op.y, right, op.y };
367 AdjustTextForFontMetrics(&dst, op.paint);
368 return this->adjustAndMap(dst, &op.paint);
369 }
370 Bounds bounds(const DrawTextOnPath& op) const {
371 SkRect dst = op.path.getBounds();
372
373 // Pad all sides by the maximum padding in any direction we'd normally a pply.
374 SkRect pad = { 0, 0, 0, 0 };
375 AdjustTextForFontMetrics(&pad, op.paint);
376
377 // That maximum padding happens to always be the right pad today.
378 SkASSERT(pad.fLeft == -pad.fRight);
379 SkASSERT(pad.fTop == -pad.fBottom);
380 SkASSERT(pad.fRight > pad.fBottom);
381 dst.outset(pad.fRight, pad.fRight);
382
383 return this->adjustAndMap(dst, &op.paint);
384 }
385
386 Bounds bounds(const DrawTextBlob& op) const {
387 SkRect dst = op.blob->bounds();
388 dst.offset(op.x, op.y);
389 return this->adjustAndMap(dst, &op.paint);
390 }
391
392 static void AdjustTextForFontMetrics(SkRect* rect, const SkPaint& paint) {
393 #ifdef SK_DEBUG
394 SkRect correct = *rect;
395 #endif
396 // crbug.com/373785 ~~> xPad = 4x yPad
397 // crbug.com/424824 ~~> bump yPad from 2x text size to 2.5x
398 const SkScalar yPad = 2.5f * paint.getTextSize(),
399 xPad = 4.0f * yPad;
400 rect->outset(xPad, yPad);
401 #ifdef SK_DEBUG
402 SkPaint::FontMetrics metrics;
403 paint.getFontMetrics(&metrics);
404 correct.fLeft += metrics.fXMin;
405 correct.fTop += metrics.fTop;
406 correct.fRight += metrics.fXMax;
407 correct.fBottom += metrics.fBottom;
408 // See skia:2862 for why we ignore small text sizes.
409 SkASSERTF(paint.getTextSize() < 0.001f || rect->contains(correct),
410 "%f %f %f %f vs. %f %f %f %f\n",
411 -xPad, -yPad, +xPad, +yPad,
412 metrics.fXMin, metrics.fTop, metrics.fXMax, metrics.fBottom) ;
413 #endif
414 }
415
416 //--------- LAYER HOISTING
417 template <typename T> void trackSaveLayers(const T& op) {
418 /* most ops aren't involved in saveLayers */
419 }
420 void trackSaveLayers(const Save& s) { this->pushSaveLayerInfo(false, NULL); }
421 void trackSaveLayers(const SaveLayer& sl) {
422 this->pushSaveLayerInfo(true, sl.paint);
423 }
424 void trackSaveLayers(const Restore& r) { this->popSaveLayerInfo(); }
425 void trackSaveLayers(const DrawPicture& dp) {
426 // For sub-pictures, we wrap their layer information within the parent
427 // picture's rendering hierarchy
428 SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey();
429
430 const GrAccelData* childData =
431 static_cast<const GrAccelData*>(dp.picture->EXPERIMENTAL_getAccelDat a(key));
432 if (!childData) {
433 // If the child layer hasn't been generated with saveLayer data we
434 // assume the worst (i.e., that it does contain layers which nest
435 // inside existing layers). Layers within sub-pictures that don't
436 // have saveLayer data cannot be hoisted.
437 // TODO: could the analysis data be use to fine tune this?
438 this->updateStackForSaveLayer();
439 return;
440 }
441
442 for (int i = 0; i < childData->numSaveLayers(); ++i) {
443 const GrAccelData::SaveLayerInfo& src = childData->saveLayerInfo(i);
444
445 Bounds newClip(fCurrentClipBounds);
446
447 if (!newClip.intersect(this->adjustAndMap(src.fBounds, dp.paint))) {
448 continue;
449 }
450
451 this->updateStackForSaveLayer();
452
453 GrAccelData::SaveLayerInfo& dst = fAccelData->addSaveLayerInfo();
454
455 // If src.fPicture is NULL the layer is in dp.picture; otherwise
456 // it belongs to a sub-picture.
457 dst.fPicture = src.fPicture ? src.fPicture : static_cast<const SkPic ture*>(dp.picture);
458 dst.fPicture->ref();
459 dst.fBounds = newClip;
460 dst.fLocalMat = src.fLocalMat;
461 dst.fPreMat = src.fPreMat;
462 dst.fPreMat.postConcat(*fCTM);
463 if (src.fPaint) {
464 dst.fPaint = SkNEW_ARGS(SkPaint, (*src.fPaint));
465 }
466 dst.fSaveLayerOpID = src.fSaveLayerOpID;
467 dst.fRestoreOpID = src.fRestoreOpID;
468 dst.fHasNestedLayers = src.fHasNestedLayers;
469 dst.fIsNested = fSaveLayersInStack > 0 || src.fIsNested;
470 }
471 }
472
473 // Inform all the saveLayers already on the stack that they now have a
474 // nested saveLayer inside them
475 void updateStackForSaveLayer() {
476 for (int index = fSaveLayerStack.count() - 1; index >= 0; --index) {
477 if (fSaveLayerStack[index].fHasNestedSaveLayer) {
478 break;
479 }
480 fSaveLayerStack[index].fHasNestedSaveLayer = true;
481 if (fSaveLayerStack[index].fIsSaveLayer) {
482 break;
483 }
484 }
485 }
486
487 void pushSaveLayerInfo(bool isSaveLayer, const SkPaint* paint) {
488 if (isSaveLayer) {
489 this->updateStackForSaveLayer();
490 ++fSaveLayersInStack;
491 }
492
493 fSaveLayerStack.push(SaveLayerInfo(fCurrentOp, isSaveLayer, paint, fCurr entClipBounds));
494 }
495
496 void popSaveLayerInfo() {
497 if (fSaveLayerStack.count() <= 0) {
498 SkASSERT(false);
499 return;
500 }
501
502 SaveLayerInfo sli;
503 fSaveLayerStack.pop(&sli);
504
505 if (!sli.fIsSaveLayer) {
506 return;
507 }
508
509 --fSaveLayersInStack;
510
511 GrAccelData::SaveLayerInfo& slInfo = fAccelData->addSaveLayerInfo();
512
513 SkASSERT(NULL == slInfo.fPicture); // This layer is in the top-most pic ture
514
515 slInfo.fBounds = fBounds[sli.fStartIndex];
516 slInfo.fBounds.intersect(sli.fClipBound);
517 slInfo.fLocalMat = *fCTM;
518 slInfo.fPreMat = SkMatrix::I();
519 if (sli.fPaint) {
520 slInfo.fPaint = SkNEW_ARGS(SkPaint, (*sli.fPaint));
521 }
522 slInfo.fSaveLayerOpID = sli.fStartIndex;
523 slInfo.fRestoreOpID = fCurrentOp;
524 slInfo.fHasNestedLayers = sli.fHasNestedSaveLayer;
525 slInfo.fIsNested = fSaveLayersInStack > 0;
526 }
527 //--------- LAYER HOISTING
528
529 // Returns true if rect was meaningfully adjusted for the effects of paint,
530 // false if the paint could affect the rect in unknown ways.
531 static bool AdjustForPaint(const SkPaint* paint, SkRect* rect) {
532 if (paint) {
533 if (paint->canComputeFastBounds()) {
534 *rect = paint->computeFastBounds(*rect, rect);
535 return true;
536 }
537 return false;
538 }
539 return true;
540 }
541
542 bool adjustForSaveLayerPaints(SkRect* rect, int savesToIgnore = 0) const {
543 for (int i = fSaveStack.count() - 1 - savesToIgnore; i >= 0; i--) {
544 if (!AdjustForPaint(fSaveStack[i].paint, rect)) {
545 return false;
546 }
547 }
548 return true;
549 }
550
551 // Adjust rect for all paints that may affect its geometry, then map it to i dentity space.
552 Bounds adjustAndMap(SkRect rect, const SkPaint* paint) const {
553 // Inverted rectangles really confuse our BBHs.
554 rect.sort();
555
556 // Adjust the rect for its own paint.
557 if (!AdjustForPaint(paint, &rect)) {
558 // The paint could do anything to our bounds. The only safe answer is the current clip.
559 return fCurrentClipBounds;
560 }
561
562 // Adjust rect for all the paints from the SaveLayers we're inside.
563 if (!this->adjustForSaveLayerPaints(&rect)) {
564 // Same deal as above.
565 return fCurrentClipBounds;
566 }
567
568 // Map the rect back to identity space.
569 fCTM->mapRect(&rect);
570
571 // Nothing can draw outside the current clip.
572 // (Only bounded ops call into this method, so oddballs like Clear don't matter here.)
573 rect.intersect(fCurrentClipBounds);
574 return rect;
575 }
576
577 // Conservative identity-space bounds for each op in the SkRecord.
578 SkAutoTMalloc<Bounds> fBounds;
579
580 // We walk fCurrentOp through the SkRecord, as we go using updateCTM()
581 // and updateClipBounds() to maintain the exact CTM (fCTM) and conservative
582 // identity-space bounds of the current clip (fCurrentClipBounds).
583 unsigned fCurrentOp;
584 const SkMatrix* fCTM;
585 Bounds fCurrentClipBounds;
586
587 // Used to track the bounds of Save/Restore blocks and the control ops insid e them.
588 SkTDArray<SaveBounds> fSaveStack;
589 SkTDArray<unsigned> fControlIndices;
590
591 //--------- LAYER HOISTING
592 // Used to collect saveLayer information for layer hoisting
593 int fSaveLayersInStack;
594 SkTDArray<SaveLayerInfo> fSaveLayerStack;
595 GrAccelData* fAccelData;
596 //--------- LAYER HOISTING
597 };
598
599 } // namespace SkRecords
600
601 void SkRecordComputeLayers(const SkRect& cullRect, const SkRecord& record,
602 SkBBoxHierarchy* bbh, GrAccelData* data) {
603 SkRecords::CollectLayers collector(cullRect, record, bbh, data);
604 }
605
606
OLDNEW
« no previous file with comments | « src/gpu/GrPictureUtils.h ('k') | tests/PictureTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698