Enforce thread-safety of bitmaps in pictures via the type.
authormtklein <mtklein@chromium.org>
Thu, 11 Dec 2014 20:43:04 +0000 (12:43 -0800)
committerCommit bot <commit-bot@chromium.org>
Thu, 11 Dec 2014 20:43:04 +0000 (12:43 -0800)
No runtime difference here, but it makes it impossible to forget to make
a shallow copy; you can't get at the full bitmap without it.

NOTREECHECKS=true

BUG=skia:

Review URL: https://codereview.chromium.org/799603002

src/core/SkRecordDraw.cpp
src/core/SkRecords.h

index 7f575d1..b714e75 100644 (file)
@@ -74,11 +74,6 @@ void SkRecordPartialDraw(const SkRecord& record, SkCanvas* canvas,
 
 namespace SkRecords {
 
-// FIXME: SkBitmaps are stateful, so we need to copy them to play back in multiple threads.
-static SkBitmap shallow_copy(const SkBitmap& bitmap) {
-    return bitmap;
-}
-
 // NoOps draw nothing.
 template <> void Draw::draw(const NoOp&) {}
 
@@ -100,13 +95,13 @@ DRAW(BeginCommentGroup, beginCommentGroup(r.description));
 DRAW(AddComment, addComment(r.key, r.value));
 DRAW(EndCommentGroup, endCommentGroup());
 
-DRAW(DrawBitmap, drawBitmap(shallow_copy(r.bitmap), r.left, r.top, r.paint));
-DRAW(DrawBitmapNine, drawBitmapNine(shallow_copy(r.bitmap), r.center, r.dst, r.paint));
+DRAW(DrawBitmap, drawBitmap(r.bitmap.shallowCopy(), r.left, r.top, r.paint));
+DRAW(DrawBitmapNine, drawBitmapNine(r.bitmap.shallowCopy(), r.center, r.dst, r.paint));
 DRAW(DrawBitmapRectToRect,
-        drawBitmapRectToRect(shallow_copy(r.bitmap), r.src, r.dst, r.paint,
+        drawBitmapRectToRect(r.bitmap.shallowCopy(), r.src, r.dst, r.paint,
                              SkCanvas::kNone_DrawBitmapRectFlag));
 DRAW(DrawBitmapRectToRectBleed,
-        drawBitmapRectToRect(shallow_copy(r.bitmap), r.src, r.dst, r.paint,
+        drawBitmapRectToRect(r.bitmap.shallowCopy(), r.src, r.dst, r.paint,
                              SkCanvas::kBleed_DrawBitmapRectFlag));
 DRAW(DrawDRRect, drawDRRect(r.outer, r.inner, r.paint));
 DRAW(DrawImage, drawImage(r.image, r.left, r.top, r.paint));
@@ -121,7 +116,7 @@ DRAW(DrawPosText, drawPosText(r.text, r.byteLength, r.pos, r.paint));
 DRAW(DrawPosTextH, drawPosTextH(r.text, r.byteLength, r.xpos, r.y, r.paint));
 DRAW(DrawRRect, drawRRect(r.rrect, r.paint));
 DRAW(DrawRect, drawRect(r.rect, r.paint));
-DRAW(DrawSprite, drawSprite(shallow_copy(r.bitmap), r.left, r.top, r.paint));
+DRAW(DrawSprite, drawSprite(r.bitmap.shallowCopy(), r.left, r.top, r.paint));
 DRAW(DrawText, drawText(r.text, r.byteLength, r.x, r.y, r.paint));
 DRAW(DrawTextBlob, drawTextBlob(r.blob, r.x, r.y, r.paint));
 DRAW(DrawTextOnPath, drawTextOnPath(r.text, r.byteLength, r.path, &r.matrix, r.paint));
index d6fc723..d8dfb2b 100644 (file)
@@ -183,15 +183,24 @@ private:
 
 // Like SkBitmap, but deep copies pixels if they're not immutable.
 // Using this, we guarantee the immutability of all bitmaps we record.
-struct ImmutableBitmap : public SkBitmap {
+class ImmutableBitmap : SkNoncopyable {
+public:
     explicit ImmutableBitmap(const SkBitmap& bitmap) {
         if (bitmap.isImmutable()) {
-            *(SkBitmap*)this = bitmap;
+            fBitmap = bitmap;
         } else {
-            bitmap.copyTo(this);
+            bitmap.copyTo(&fBitmap);
         }
-        this->setImmutable();
+        fBitmap.setImmutable();
     }
+
+    int width()  const { return fBitmap.width();  }
+    int height() const { return fBitmap.height(); }
+
+    // While the pixels are immutable, SkBitmap itself is not thread-safe, so return a copy.
+    SkBitmap shallowCopy() const { return fBitmap; }
+private:
+    SkBitmap fBitmap;
 };
 
 // SkPath::getBounds() isn't thread safe unless we precache the bounds in a singlethreaded context.