Index: third_party/WebKit/Source/platform/graphics/skia/SkiaUtils.h |
diff --git a/third_party/WebKit/Source/platform/graphics/skia/SkiaUtils.h b/third_party/WebKit/Source/platform/graphics/skia/SkiaUtils.h |
index 3c3781bc87a3a63ba77324fec711ceb68d8e1fdb..9cb06f92a26ad9f942dcad7a3fe4efe85b11fb1f 100644 |
--- a/third_party/WebKit/Source/platform/graphics/skia/SkiaUtils.h |
+++ b/third_party/WebKit/Source/platform/graphics/skia/SkiaUtils.h |
@@ -38,6 +38,7 @@ |
#include "platform/graphics/Image.h" |
#include "platform/transforms/AffineTransform.h" |
#include "third_party/skia/include/core/SkCanvas.h" |
+#include "third_party/skia/include/core/SkRefCnt.h" |
#include "wtf/MathExtras.h" |
namespace blink { |
@@ -126,6 +127,85 @@ inline SkCanvas::SrcRectConstraint WebCoreClampingModeToSkiaRectConstraint(Image |
: SkCanvas::kFast_SrcRectConstraint; |
} |
+ |
+// Skia's smart pointer APIs are preferable over their legacy raw pointer counterparts. |
+// The following helpers ensure interoperability between Skia's SkRefCnt wrapper sk_sp<T> and |
+// Blink's RefPtr<T>/PassRefPtr<T>. |
+// |
+// - adoptRef(sk_sp<T>&&): adopts an sk_sp rvalue into a PassRefPtr (to be used when |
+// transferring ownership from Skia to Blink). |
+// - adoptSkSp(PassRefPtr<T>&&): adopts a PassRefPtr rvalue into a sk_sp (to be used when |
+// transferring ownership from Blink to Skia). |
+// |
+// General guidelines |
+// |
+// When receiving ref counted objects from Skia: |
+// |
+// 1) use sk_sp-based Skia factories if available (e.g. SkShader::MakeFoo() instead of |
+// SkShader::CreateFoo()) |
+// |
+// 2) use sk_sp<T> locals for temporary objects (to be immediately transferred back to Skia) |
+// |
+// 3) use RefPtr<T>/PassRefPtr<T> for objects to be retained in Blink, use |
+// adoptRef(sk_sp<T>&&) to convert |
+// |
+// When passing ref counted objects to Skia: |
+// |
+// 1) use sk_sk-based Skia APIs when available (e.g. SkPaint::setShader(sk_sp<SkShader>) |
+// instead of SkPaint::setShader(SkShader*)) |
+// |
+// 2) if the object ownership is being passed to Skia, use std::move(sk_sp<T>) or |
+// adoptSkSp(PassRefPtr<T>&&) to transfer without refcount churn |
+// |
+// 3) if the object ownership is shared with Skia (Blink retains a reference), use |
+// sk_ref_sp(RefPtr<T>::get()) |
+// |
+// Example (creating a SkShader and setting it on SkPaint): |
+// |
+// a) legacy/old style |
+// |
+// RefPtr<SkShader> shader = adoptRef(SkShader::CreateFoo(...)); |
+// paint.setShader(shader.get()); |
+// |
+// (Note: the legacy approach introduces refcount churn as Skia grabs a ref while Blink is |
+// temporarily holding on to its own) |
+// |
+// b) new style, ownership transferred |
+// |
+// // using Skia smart pointer locals |
+// sk_sp<SkShader> shader = SkShader::MakeFoo(...); |
+// paint.setShader(std::move(shader)); |
+// |
+// // using Blink smart pointer locals |
+// RefPtr<SkShader> shader = adoptRef(SkShader::MakeFoo(...)); |
+// paint.setShader(adoptSkSp(shader.release()); |
+// |
+// // using no locals |
+// paint.setShader(SkShader::MakeFoo(...)); |
+// |
+// (Note: while all these variants avoid ref count churn, the last/inlined-factory version |
+// is preferred when feasible because it also skips the adopt/move op) |
jbroman
2016/03/16 14:43:08
Why? The adopt/move will presumably be elided by t
f(malita)
2016/03/16 16:51:45
Experimentally, the first example above does not e
|
+// |
+// c) new style, shared ownership |
+// |
+// // using sk_ref_sp |
+// RefPtr<SkShader> m_shader = adoptRef(SkShader::MakeFoo(...)); |
+// paint.setShader(sk_ref_sp(m_shader.get())); |
+// |
+// // using a temp PassRefPtr and sk_sp adoption |
+// RefPtr<SkShader> m_shader = adoptRef(SkShader::MakeFoo(...)); |
+// paint.setShader(adoptSkSp(PassRefPtr<SkShader>(m_shader))); |
+// |
+template <typename T> PassRefPtr<T> adoptRef(sk_sp<T>&& sp) |
jbroman
2016/03/16 14:43:08
I also think taking the sk_sp by value is probably
f(malita)
2016/03/16 16:51:45
We've had a little discussion regarding val vs. rv
danakj
2016/03/16 17:54:53
(google style guide also says not to do write && e
|
+{ |
+ return adoptRef(sp.release()); |
+} |
+ |
+template <typename T> sk_sp<T> adoptSkSp(PassRefPtr<T>&& ref) |
jbroman
2016/03/16 14:43:08
To be consistent with other usage of PassRefPtr, I
f(malita)
2016/03/16 16:51:45
Makes sense, done.
|
+{ |
+ return sk_sp<T>(ref.leakRef()); |
+} |
+ |
} // namespace blink |
#endif // SkiaUtils_h |