diff options
-rw-r--r-- | include/core/SkDynamicAnnotations.h | 28 | ||||
-rw-r--r-- | include/core/SkPathRef.h | 13 | ||||
-rw-r--r-- | src/core/SkPathRef.cpp | 18 | ||||
-rw-r--r-- | src/core/SkRecorder.cpp | 13 |
4 files changed, 25 insertions, 47 deletions
diff --git a/include/core/SkDynamicAnnotations.h b/include/core/SkDynamicAnnotations.h index 872a292e5d..2775b38cec 100644 --- a/include/core/SkDynamicAnnotations.h +++ b/include/core/SkDynamicAnnotations.h @@ -82,32 +82,4 @@ private: T fVal; }; -// This is like SkTRacy, but allows you to return the value by reference. -// TSAN is better at suppressing SkTRacy than SkTRacyReffable, so use SkTRacy when possible. -// -// We use this for SkPathRef bounds, which is an SkRect we pass around by reference publically. -template <typename T> -class SkTRacyReffable { -public: - SkTRacyReffable() { SK_ANNOTATE_BENIGN_RACE(&fVal); } - - operator const T&() const { - return fVal; - } - - SkTRacyReffable& operator=(const T& val) { - fVal = val; - return *this; - } - - const T* get() const { return &fVal; } - T* get() { return &fVal; } - - const T* operator->() const { return &fVal; } - T* operator->() { return &fVal; } - -private: - T fVal; -}; - #endif//SkDynamicAnnotations_DEFINED diff --git a/include/core/SkPathRef.h b/include/core/SkPathRef.h index 4b57fc80e4..78c6cd5af7 100644 --- a/include/core/SkPathRef.h +++ b/include/core/SkPathRef.h @@ -9,7 +9,6 @@ #ifndef SkPathRef_DEFINED #define SkPathRef_DEFINED -#include "SkDynamicAnnotations.h" #include "SkMatrix.h" #include "SkPoint.h" #include "SkRect.h" @@ -293,9 +292,9 @@ private: SkDEBUGCODE(this->validate();) // TODO(mtklein): remove fBoundsIsDirty and fIsFinite, // using an inverted rect instead of fBoundsIsDirty and always recalculating fIsFinite. - //SkASSERT(fBoundsIsDirty); + SkASSERT(fBoundsIsDirty); - fIsFinite = ComputePtBounds(fBounds.get(), *this); + fIsFinite = ComputePtBounds(&fBounds, *this); fBoundsIsDirty = false; } @@ -303,7 +302,7 @@ private: SkASSERT(rect.fLeft <= rect.fRight && rect.fTop <= rect.fBottom); fBounds = rect; fBoundsIsDirty = false; - fIsFinite = fBounds->isFinite(); + fIsFinite = fBounds.isFinite(); } /** Makes additional room but does not change the counts or change the genID */ @@ -435,9 +434,9 @@ private: kMinSize = 256, }; - mutable SkTRacyReffable<SkRect> fBounds; - mutable SkTRacy<uint8_t> fBoundsIsDirty; - mutable SkTRacy<SkBool8> fIsFinite; // only meaningful if bounds are valid + mutable SkRect fBounds; + mutable uint8_t fBoundsIsDirty; + mutable SkBool8 fIsFinite; // only meaningful if bounds are valid SkBool8 fIsOval; uint8_t fSegmentMask; diff --git a/src/core/SkPathRef.cpp b/src/core/SkPathRef.cpp index ad85fd06a8..aed6cdaee7 100644 --- a/src/core/SkPathRef.cpp +++ b/src/core/SkPathRef.cpp @@ -87,13 +87,13 @@ void SkPathRef::CreateTransformedCopy(SkAutoTUnref<SkPathRef>* dst, if (canXformBounds) { (*dst)->fBoundsIsDirty = false; if (src.fIsFinite) { - matrix.mapRect((*dst)->fBounds.get(), src.fBounds); - if (!((*dst)->fIsFinite = (*dst)->fBounds->isFinite())) { - (*dst)->fBounds->setEmpty(); + matrix.mapRect(&(*dst)->fBounds, src.fBounds); + if (!((*dst)->fIsFinite = (*dst)->fBounds.isFinite())) { + (*dst)->fBounds.setEmpty(); } } else { (*dst)->fIsFinite = false; - (*dst)->fBounds->setEmpty(); + (*dst)->fBounds.setEmpty(); } } else { (*dst)->fBoundsIsDirty = true; @@ -449,14 +449,14 @@ void SkPathRef::validate() const { SkASSERT(this->currSize() == fFreeSpace + sizeof(SkPoint) * fPointCnt + sizeof(uint8_t) * fVerbCnt); - if (!fBoundsIsDirty && !fBounds->isEmpty()) { + if (!fBoundsIsDirty && !fBounds.isEmpty()) { bool isFinite = true; for (int i = 0; i < fPointCnt; ++i) { SkASSERT(!fPoints[i].isFinite() || ( - fBounds->fLeft - fPoints[i].fX < SK_ScalarNearlyZero && - fPoints[i].fX - fBounds->fRight < SK_ScalarNearlyZero && - fBounds->fTop - fPoints[i].fY < SK_ScalarNearlyZero && - fPoints[i].fY - fBounds->fBottom < SK_ScalarNearlyZero)); + fBounds.fLeft - fPoints[i].fX < SK_ScalarNearlyZero && + fPoints[i].fX - fBounds.fRight < SK_ScalarNearlyZero && + fBounds.fTop - fPoints[i].fY < SK_ScalarNearlyZero && + fPoints[i].fY - fBounds.fBottom < SK_ScalarNearlyZero)); if (!fPoints[i].isFinite()) { isFinite = false; } diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp index 3548851a72..9ca4224a2a 100644 --- a/src/core/SkRecorder.cpp +++ b/src/core/SkRecorder.cpp @@ -74,6 +74,13 @@ private: template <typename T> static Reference<T> delay_copy(const T& x) { return Reference<T>(x); } +// SkPath::getBounds() isn't thread safe unless we precache the bounds in a singlethreaded context. +// Recording is a convenient time to do this, but we could delay it to between record and playback. +static Reference<SkPath> force_path_bounds(const SkPath& p) { + p.updateBoundsCache(); + return Reference<SkPath>(p); +} + // Use copy() only for optional arguments, to be copied if present or skipped if not. // (For most types we just pass by value and let copy constructors do their thing.) template <typename T> @@ -158,7 +165,7 @@ void SkRecorder::onDrawDrawable(SkCanvasDrawable* drawable) { } void SkRecorder::drawPath(const SkPath& path, const SkPaint& paint) { - APPEND(DrawPath, delay_copy(paint), delay_copy(path)); + APPEND(DrawPath, delay_copy(paint), force_path_bounds(path)); } void SkRecorder::drawBitmap(const SkBitmap& bitmap, @@ -244,7 +251,7 @@ void SkRecorder::onDrawTextOnPath(const void* text, size_t byteLength, const SkP delay_copy(paint), this->copy((const char*)text, byteLength), byteLength, - delay_copy(path), + force_path_bounds(path), this->copy(matrix)); } @@ -341,7 +348,7 @@ void SkRecorder::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyl void SkRecorder::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) { INHERITED(onClipPath, path, op, edgeStyle); SkRecords::RegionOpAndAA opAA(op, kSoft_ClipEdgeStyle == edgeStyle); - APPEND(ClipPath, this->devBounds(), delay_copy(path), opAA); + APPEND(ClipPath, this->devBounds(), force_path_bounds(path), opAA); } void SkRecorder::onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op) { |