Properly handle extracted bitmaps in cross process/shared addr space SkGPipe.

Use the pixel ref which we have already copied and the appropriate pixel ref
offset.

Turn SampleDrawBitmap into a GM to test this functionality.

Review URL: https://codereview.appspot.com/6348059

git-svn-id: http://skia.googlecode.com/svn/trunk@4417 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/samplecode/SampleDrawBitmap.cpp b/gm/extractbitmap.cpp
similarity index 76%
rename from samplecode/SampleDrawBitmap.cpp
rename to gm/extractbitmap.cpp
index aaf1123..5002f1b 100644
--- a/samplecode/SampleDrawBitmap.cpp
+++ b/gm/extractbitmap.cpp
@@ -5,12 +5,13 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
-#include "SampleCode.h"
-#include "SkView.h"
+#include "gm.h"
+#include "SkBitmap.h"
 #include "SkCanvas.h"
-#include "SkShader.h"
-#include "SkUtils.h"
 #include "SkDevice.h"
+#include "SkString.h"
+
+namespace skiagm {
 
 static void create_bitmap(SkBitmap* bitmap) {
     const int W = 100;
@@ -25,22 +26,21 @@
     canvas.drawCircle(SkIntToScalar(W)/2, SkIntToScalar(H)/2, SkIntToScalar(W)/2, paint);
 }
 
-class DrawBitmapView : public SampleView {
-    SkPath fPath;
+class ExtractBitmapGM : public GM {
 public:
-	DrawBitmapView() {}
+    ExtractBitmapGM() {}
     
 protected:
     // overrides from SkEventSink
-    virtual bool onQuery(SkEvent* evt) {
-        if (SampleCode::TitleQ(*evt)) {
-            SampleCode::TitleR(evt, "DrawBitmap");
-            return true;
-        }
-        return this->INHERITED::onQuery(evt);
+    virtual SkString onShortName() SK_OVERRIDE {
+        return SkString("extractbitmap");
     }
-    
-    virtual void onDrawContent(SkCanvas* canvas) {
+
+    virtual SkISize onISize() SK_OVERRIDE {
+        return make_isize(600, 600);
+    }
+
+    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
         SkBitmap bitmap;
         create_bitmap(&bitmap);
         int x = bitmap.width() / 2;
@@ -75,10 +75,12 @@
     }
     
 private:
-    typedef SampleView INHERITED;
+    typedef GM INHERITED;
 };
 
 //////////////////////////////////////////////////////////////////////////////
 
-static SkView* MyFactory() { return new DrawBitmapView; }
-static SkViewRegister reg(MyFactory);
+static GM* MyFactory(void*) { return new ExtractBitmapGM; }
+static GMRegistry reg(MyFactory);
+
+}
diff --git a/gyp/SampleApp.gyp b/gyp/SampleApp.gyp
index 4f0ad51..bc128be 100644
--- a/gyp/SampleApp.gyp
+++ b/gyp/SampleApp.gyp
@@ -48,7 +48,6 @@
         '../samplecode/SampleDegenerateTwoPtRadials.cpp',
         '../samplecode/SampleDither.cpp',
         '../samplecode/SampleDitherBitmap.cpp',
-        '../samplecode/SampleDrawBitmap.cpp',
         '../samplecode/SampleDrawLooper.cpp',
         '../samplecode/SampleEffects.cpp',
         '../samplecode/SampleEmboss.cpp',
diff --git a/gyp/gmslides.gypi b/gyp/gmslides.gypi
index 7c64844..45dab51 100644
--- a/gyp/gmslides.gypi
+++ b/gyp/gmslides.gypi
@@ -20,6 +20,7 @@
     '../gm/degeneratesegments.cpp',
     '../gm/dashing.cpp',
     '../gm/drawbitmaprect.cpp',
+    '../gm/extractbitmap.cpp',
     '../gm/emptypath.cpp',
     '../gm/filltypes.cpp',
     '../gm/filltypespersp.cpp',
diff --git a/src/pipe/SkGPipeWrite.cpp b/src/pipe/SkGPipeWrite.cpp
index 6b48bca..066159f 100644
--- a/src/pipe/SkGPipeWrite.cpp
+++ b/src/pipe/SkGPipeWrite.cpp
@@ -81,10 +81,19 @@
      * @return void* Pointer to the heap's copy of the bitmap. If NULL,
      *               the bitmap could not be copied.
      */
-    const SkBitmap* addBitmap(const SkBitmap& bm) {
-        const uint32_t genID = bm.getGenerationID();
+    const SkBitmap* addBitmap(const SkBitmap& orig) {
+        const uint32_t genID = orig.getGenerationID();
+        SkPixelRef* sharedPixelRef = NULL;
         for (int i = fBitmaps.count() - 1; i >= 0; i--) {
             if (genID == fBitmaps[i].fGenID) {
+                if (orig.pixelRefOffset() != fBitmaps[i].fBitmap->pixelRefOffset()) {
+                    // In this case, the bitmaps share a pixelRef, but have
+                    // different offsets. Keep track of the other bitmap so that
+                    // instead of making another copy of the pixelRef we can use
+                    // the copy we already made.
+                    sharedPixelRef = fBitmaps[i].fBitmap->pixelRef();
+                    break;
+                }
                 return fBitmaps[i].fBitmap;
             }
         }
@@ -92,13 +101,21 @@
         // If the bitmap is mutable, we still need to do a deep copy, since the
         // caller may modify it afterwards. That said, if the bitmap is mutable,
         // but has no pixelRef, the copy constructor actually does a deep copy.
-        if (fCanDoShallowCopies && (bm.isImmutable() || !bm.pixelRef())) {
-            copy = new SkBitmap(bm);
+        if (fCanDoShallowCopies && (orig.isImmutable() || !orig.pixelRef())) {
+            copy = new SkBitmap(orig);
         } else {
-            copy = new SkBitmap();
-            if (!bm.copyTo(copy, bm.getConfig())) {
-                delete copy;
-                return NULL;
+            if (sharedPixelRef != NULL) {
+                // Do a shallow copy of the bitmap to get the width, height, etc
+                copy = new SkBitmap(orig);
+                // Replace the pixelRef with the copy that was already made, and
+                // use the appropriate offset.
+                copy->setPixelRef(sharedPixelRef, orig.pixelRefOffset());
+            } else {
+                copy = new SkBitmap();
+                if (!orig.copyTo(copy, orig.getConfig())) {
+                    delete copy;
+                    return NULL;
+                }
             }
         }
         BitmapInfo* info = fBitmaps.append();