aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/core/SkDynamicAnnotations.h28
-rw-r--r--include/core/SkPathRef.h13
-rw-r--r--src/core/SkPathRef.cpp18
-rw-r--r--src/core/SkRecorder.cpp13
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) {