зеркало из https://github.com/mozilla/moz-skia.git
Fix cull nesting assertion.
Cull rects are in local coordinates and cannot be compared directly. No wonder it was so hard enforcing this in Blink :o This moves the validation logic into SkCanvas, using a device-space cull stack (debug build only). There are still some Blink bugs causing violations, so for now I'd like to keep this as an error message only. R=reed@google.com, robertphillips@google.com Author: fmalita@chromium.org Review URL: https://codereview.chromium.org/200923008 git-svn-id: http://skia.googlecode.com/svn/trunk@13885 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
Родитель
933e65d914
Коммит
520cf8b33e
|
@ -1063,20 +1063,13 @@ public:
|
|||
* is not enforced, but the information might be used to quick-reject command blocks,
|
||||
* so an incorrect bounding box may result in incomplete rendering.
|
||||
*/
|
||||
void pushCull(const SkRect& cullRect) {
|
||||
++fCullCount;
|
||||
this->onPushCull(cullRect);
|
||||
}
|
||||
void pushCull(const SkRect& cullRect);
|
||||
|
||||
/**
|
||||
* Terminates the current culling block, and restores the previous one (if any).
|
||||
*/
|
||||
void popCull() {
|
||||
if (fCullCount > 0) {
|
||||
--fCullCount;
|
||||
this->onPopCull();
|
||||
}
|
||||
}
|
||||
void popCull();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** Get the current bounder object.
|
||||
|
@ -1394,6 +1387,9 @@ private:
|
|||
};
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
// The cull stack rects are in device-space
|
||||
SkTDArray<SkIRect> fCullStack;
|
||||
void validateCull(const SkIRect&);
|
||||
void validateClip() const;
|
||||
#else
|
||||
void validateClip() const {}
|
||||
|
|
|
@ -1161,6 +1161,60 @@ void SkCanvas::onPopCull() {
|
|||
// do nothing. Subclasses may do something
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef SK_DEBUG
|
||||
// Ensure that cull rects are monotonically nested in device space.
|
||||
void SkCanvas::validateCull(const SkIRect& devCull) {
|
||||
if (fCullStack.isEmpty()
|
||||
|| devCull.isEmpty()
|
||||
|| fCullStack.top().contains(devCull)) {
|
||||
return;
|
||||
}
|
||||
|
||||
SkDEBUGF(("Invalid cull: [%d %d %d %d] (previous cull: [%d %d %d %d])\n",
|
||||
devCull.x(), devCull.y(), devCull.right(), devCull.bottom(),
|
||||
fCullStack.top().x(), fCullStack.top().y(),
|
||||
fCullStack.top().right(), fCullStack.top().bottom()));
|
||||
|
||||
#ifdef ASSERT_NESTED_CULLING
|
||||
SkDEBUGFAIL("Invalid cull.");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void SkCanvas::pushCull(const SkRect& cullRect) {
|
||||
++fCullCount;
|
||||
this->onPushCull(cullRect);
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
// Map the cull rect into device space.
|
||||
SkRect mappedCull;
|
||||
this->getTotalMatrix().mapRect(&mappedCull, cullRect);
|
||||
|
||||
// Take clipping into account.
|
||||
SkIRect devClip, devCull;
|
||||
mappedCull.roundOut(&devCull);
|
||||
this->getClipDeviceBounds(&devClip);
|
||||
if (!devCull.intersect(devClip)) {
|
||||
devCull.setEmpty();
|
||||
}
|
||||
|
||||
this->validateCull(devCull);
|
||||
fCullStack.push(devCull); // balanced in popCull
|
||||
#endif
|
||||
}
|
||||
|
||||
void SkCanvas::popCull() {
|
||||
SkASSERT(fCullStack.count() == fCullCount);
|
||||
|
||||
if (fCullCount > 0) {
|
||||
--fCullCount;
|
||||
this->onPopCull();
|
||||
|
||||
SkDEBUGCODE(fCullStack.pop());
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap,
|
||||
|
|
|
@ -1559,18 +1559,6 @@ void SkPictureRecord::endCommentGroup() {
|
|||
// [op/size] [rect] [skip offset]
|
||||
static const uint32_t kPushCullOpSize = 2 * kUInt32Size + sizeof(SkRect);
|
||||
void SkPictureRecord::onPushCull(const SkRect& cullRect) {
|
||||
// Skip identical cull rects.
|
||||
if (!fCullOffsetStack.isEmpty()) {
|
||||
const SkRect& prevCull = fWriter.readTAt<SkRect>(fCullOffsetStack.top() - sizeof(SkRect));
|
||||
if (prevCull == cullRect) {
|
||||
// Skipped culls are tracked on the stack, but they point to the previous offset.
|
||||
fCullOffsetStack.push(fCullOffsetStack.top());
|
||||
return;
|
||||
}
|
||||
|
||||
SkASSERT(prevCull.contains(cullRect));
|
||||
}
|
||||
|
||||
uint32_t size = kPushCullOpSize;
|
||||
size_t initialOffset = this->addDraw(PUSH_CULL, &size);
|
||||
// PUSH_CULL's size should stay constant (used to rewind).
|
||||
|
@ -1588,11 +1576,6 @@ void SkPictureRecord::onPopCull() {
|
|||
uint32_t cullSkipOffset = fCullOffsetStack.top();
|
||||
fCullOffsetStack.pop();
|
||||
|
||||
// Skipped push, do the same for pop.
|
||||
if (!fCullOffsetStack.isEmpty() && cullSkipOffset == fCullOffsetStack.top()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Collapse empty push/pop pairs.
|
||||
if ((size_t)(cullSkipOffset + kUInt32Size) == fWriter.bytesWritten()) {
|
||||
SkASSERT(fWriter.bytesWritten() >= kPushCullOpSize);
|
||||
|
|
Загрузка…
Ссылка в новой задаче