PixelRef now returns (nearly) everything that is currently in SkBitmap. The goal is to refactor bitmap later to remove redundancy, and more interestingly, remove the chance for a disconnect between the actual (pixelref) rowbytes and config, and the one claimed by the bitmap.""""

BUG=

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

git-svn-id: http://skia.googlecode.com/svn/trunk/include@12622 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/core/SkBitmapDevice.h b/core/SkBitmapDevice.h
index 83f480c..f3d40d0 100644
--- a/core/SkBitmapDevice.h
+++ b/core/SkBitmapDevice.h
@@ -258,6 +258,8 @@
 
     friend class SkSurface_Raster;
 
+    void init(SkBitmap::Config config, int width, int height, bool isOpaque);
+
     // used to change the backend's pixels (and possibly config/rowbytes)
     // but cannot change the width/height, so there should be no change to
     // any clip information.
diff --git a/core/SkMallocPixelRef.h b/core/SkMallocPixelRef.h
index 100a15d..5ef70d6 100644
--- a/core/SkMallocPixelRef.h
+++ b/core/SkMallocPixelRef.h
@@ -17,33 +17,52 @@
 */
 class SkMallocPixelRef : public SkPixelRef {
 public:
-    /** Allocate the specified buffer for pixels. The memory is freed when the
-        last owner of this pixelref is gone. If addr is NULL, sk_malloc_throw()
-        is called to allocate it.
+    /**
+     *  Return a new SkMallocPixelRef with the provided pixel storage, rowBytes,
+     *  and optional colortable. The caller is responsible for managing the
+     *  lifetime of the pixel storage buffer, as the pixelref will not try
+     *  to delete the storage.
+     *
+     *  This pixelref will ref() the specified colortable (if not NULL).
+     *
+     *  Returns NULL on failure.
      */
-    SkMallocPixelRef(void* addr, size_t size, SkColorTable* ctable, bool ownPixels = true);
-    virtual ~SkMallocPixelRef();
+    static SkMallocPixelRef* NewDirect(const SkImageInfo&, void* addr,
+                                       size_t rowBytes, SkColorTable*);
+
+    /**
+     *  Return a new SkMallocPixelRef, automatically allocating storage for the
+     *  pixels. If rowBytes are 0, an optimal value will be chosen automatically.
+     *  If rowBytes is > 0, then it will be respected, or NULL will be returned
+     *  if rowBytes is invalid for the specified info.
+     *
+     *  This pixelref will ref() the specified colortable (if not NULL).
+     *
+     *  Returns NULL on failure.
+     */
+    static SkMallocPixelRef* NewAllocate(const SkImageInfo& info,
+                                         size_t rowBytes, SkColorTable*);
 
     void* getAddr() const { return fStorage; }
 
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkMallocPixelRef)
 
 protected:
-    // overrides from SkPixelRef
-    virtual void* onLockPixels(SkColorTable**);
-    virtual void onUnlockPixels();
+    virtual bool onNewLockPixels(LockRec*) SK_OVERRIDE;
+    virtual void onUnlockPixels() SK_OVERRIDE;
+    virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+    virtual size_t getAllocatedSizeInBytes() const SK_OVERRIDE;
 
     SkMallocPixelRef(SkFlattenableReadBuffer& buffer);
-    virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
-
-    // Returns the allocation size for the pixels
-    virtual size_t getAllocatedSizeInBytes() const SK_OVERRIDE { return fSize; }
+    SkMallocPixelRef(const SkImageInfo&, void* addr, size_t rb, SkColorTable*,
+                     bool ownsPixels);
+    virtual ~SkMallocPixelRef();
 
 private:
-    void*           fStorage;
-    size_t          fSize;
-    SkColorTable*   fCTable;
-    bool            fOwnPixels;
+    void*               fStorage;
+    SkColorTable*       fCTable;
+    size_t              fRB;
+    const bool          fOwnPixels;
 
     typedef SkPixelRef INHERITED;
 };
diff --git a/core/SkPicture.h b/core/SkPicture.h
index bce343e..cd6b3bc 100644
--- a/core/SkPicture.h
+++ b/core/SkPicture.h
@@ -220,10 +220,11 @@
     // V14: Add flags word to PathRef serialization
     // V15: Remove A1 bitmpa config (and renumber remaining configs)
     // V16: Move SkPath's isOval flag to SkPathRef
+    // V17: Changes to PixelRef to store SkImageInfo
 #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
     static const uint32_t PRIOR_PICTURE_VERSION = 15;  // TODO: remove when .skps regenerated
 #endif
-    static const uint32_t PICTURE_VERSION = 16;
+    static const uint32_t PICTURE_VERSION = 17;
 
     // fPlayback, fRecord, fWidth & fHeight are protected to allow derived classes to
     // install their own SkPicturePlayback-derived players,SkPictureRecord-derived
diff --git a/core/SkPixelRef.h b/core/SkPixelRef.h
index b87b0dc..472599e 100644
--- a/core/SkPixelRef.h
+++ b/core/SkPixelRef.h
@@ -14,9 +14,12 @@
 #include "SkRefCnt.h"
 #include "SkString.h"
 #include "SkFlattenable.h"
+#include "SkImageInfo.h"
 #include "SkTDArray.h"
 
-#define SK_SUPPORT_LEGACY_PIXELREF_CONSTRUCTOR
+//#define SK_SUPPORT_LEGACY_PIXELREF_CONSTRUCTOR
+
+#define SK_SUPPORT_LEGACY_ONLOCKPIXELS
 
 #ifdef SK_DEBUG
     /**
@@ -67,23 +70,44 @@
     /** Return the pixel memory returned from lockPixels, or null if the
         lockCount is 0.
     */
-    void* pixels() const { return fPixels; }
+    void* pixels() const { return fRec.fPixels; }
 
     /** Return the current colorTable (if any) if pixels are locked, or null.
     */
-    SkColorTable* colorTable() const { return fColorTable; }
+    SkColorTable* colorTable() const { return fRec.fColorTable; }
 
     /**
+     *  To access the actual pixels of a pixelref, it must be "locked".
+     *  Calling lockPixels returns a LockRec struct (on success).
+     */
+    struct LockRec {
+        void*           fPixels;
+        SkColorTable*   fColorTable;
+        size_t          fRowBytes;
+        
+        void zero() { sk_bzero(this, sizeof(*this)); }
+    };
+    
+    /**
      *  Returns true if the lockcount > 0
      */
     bool isLocked() const { return fLockCount > 0; }
 
     SkDEBUGCODE(int getLockCount() const { return fLockCount; })
 
-    /** Call to access the pixel memory, which is returned. Balance with a call
-        to unlockPixels().
-    */
-    void lockPixels();
+    /**
+     *  Call to access the pixel memory. Return true on success. Balance this
+     *  with a call to unlockPixels().
+     */
+    bool lockPixels();
+
+    /**
+     *  Call to access the pixel memory. On success, return true and fill out
+     *  the specified rec. On failure, return false and ignore the rec parameter.
+     *  Balance this with a call to unlockPixels().
+     */
+    bool lockPixels(LockRec* rec);
+
     /** Call to balanace a previous call to lockPixels(). Returns the pixels
         (or null) after the unlock. NOTE: lock calls can be nested, but the
         matching number of unlock calls must be made in order to free the
@@ -240,14 +264,28 @@
     void addGenIDChangeListener(GenIDChangeListener* listener);
 
 protected:
-    /** Called when the lockCount goes from 0 to 1. The caller will have already
-        acquire a mutex for thread safety, so this method need not do that.
-    */
-    virtual void* onLockPixels(SkColorTable**) = 0;
-    /** Called when the lock count goes from 1 to 0. The caller will have
-        already acquire a mutex for thread safety, so this method need not do
-        that.
-    */
+#ifdef SK_SUPPORT_LEGACY_ONLOCKPIXELS
+    virtual void* onLockPixels(SkColorTable**);
+    virtual bool onNewLockPixels(LockRec*);
+#else
+    /**
+     *  On success, returns true and fills out the LockRec for the pixels. On
+     *  failure returns false and ignores the LockRec parameter.
+     *
+     *  The caller will have already acquired a mutex for thread safety, so this
+     *  method need not do that.
+     */
+    virtual bool onNewLockPixels(LockRec*) = 0;
+#endif
+
+    /**
+     *  Balancing the previous successful call to onNewLockPixels. The locked
+     *  pixel address will no longer be referenced, so the subclass is free to
+     *  move or discard that memory.
+     *
+     *  The caller will have already acquired a mutex for thread safety, so this
+     *  method need not do that.
+     */
     virtual void onUnlockPixels() = 0;
 
     /** Default impl returns true */
@@ -291,14 +329,14 @@
     // only call from constructor. Flags this to always be locked, removing
     // the need to grab the mutex and call onLockPixels/onUnlockPixels.
     // Performance tweak to avoid those calls (esp. in multi-thread use case).
-    void setPreLocked(void* pixels, SkColorTable* ctable);
+    void setPreLocked(void*, size_t rowBytes, SkColorTable*);
 
 private:
     SkBaseMutex*    fMutex; // must remain in scope for the life of this object
     SkImageInfo     fInfo;
-
-    void*           fPixels;
-    SkColorTable*   fColorTable;    // we do not track ownership, subclass does
+    
+    // LockRec is only valid if we're in a locked state (isLocked())
+    LockRec         fRec;
     int             fLockCount;
 
     mutable uint32_t fGenerationID;
diff --git a/gpu/GrSurface.h b/gpu/GrSurface.h
index c401a90..15e44ab 100644
--- a/gpu/GrSurface.h
+++ b/gpu/GrSurface.h
@@ -15,6 +15,7 @@
 
 class GrTexture;
 class GrRenderTarget;
+struct SkImageInfo;
 
 class GrSurface : public GrResource {
 public:
@@ -58,6 +59,8 @@
      */
     const GrTextureDesc& desc() const { return fDesc; }
 
+    void asImageInfo(SkImageInfo*) const;
+
     /**
      * @return the texture associated with the surface, may be NULL.
      */
diff --git a/gpu/SkGr.h b/gpu/SkGr.h
index 5e5ca4b..db08548 100644
--- a/gpu/SkGr.h
+++ b/gpu/SkGr.h
@@ -50,6 +50,7 @@
  *  kUnknown_PixelConfig if the conversion cannot be done.
  */
 GrPixelConfig SkBitmapConfig2GrPixelConfig(SkBitmap::Config);
+bool GrPixelConfig2ColorType(GrPixelConfig, SkColorType*);
 
 static inline GrColor SkColor2GrColor(SkColor c) {
     SkPMColor pm = SkPreMultiplyColor(c);
diff --git a/gpu/SkGrPixelRef.h b/gpu/SkGrPixelRef.h
index c29c27f..4d33b9d 100644
--- a/gpu/SkGrPixelRef.h
+++ b/gpu/SkGrPixelRef.h
@@ -23,14 +23,13 @@
  */
 class SK_API SkROLockPixelsPixelRef : public SkPixelRef {
 public:
-    SkROLockPixelsPixelRef();
+    SkROLockPixelsPixelRef(const SkImageInfo&);
     virtual ~SkROLockPixelsPixelRef();
 
 protected:
-    // override from SkPixelRef
-    virtual void* onLockPixels(SkColorTable** ptr);
-    virtual void onUnlockPixels();
-    virtual bool onLockPixelsAreWritable() const;   // return false;
+    virtual bool onNewLockPixels(LockRec*) SK_OVERRIDE;
+    virtual void onUnlockPixels() SK_OVERRIDE;
+    virtual bool onLockPixelsAreWritable() const SK_OVERRIDE;   // return false;
 
 private:
     SkBitmap    fBitmap;
@@ -47,7 +46,6 @@
      * cache and would like the pixel ref to unlock it in its destructor then transferCacheLock
      * should be set to true.
      */
-    SkGrPixelRef(GrSurface*, bool transferCacheLock = false);
     SkGrPixelRef(const SkImageInfo&, GrSurface*, bool transferCacheLock = false);
     virtual ~SkGrPixelRef();
 
diff --git a/images/SkImageRef.h b/images/SkImageRef.h
index 0599a8d..36f95e6 100644
--- a/images/SkImageRef.h
+++ b/images/SkImageRef.h
@@ -34,7 +34,7 @@
         @param config The preferred config of the decoded bitmap.
         @param sampleSize Requested sampleSize for decoding. Defaults to 1.
     */
-    SkImageRef(SkStreamRewindable*, SkBitmap::Config config, int sampleSize = 1,
+    SkImageRef(const SkImageInfo&, SkStreamRewindable*, int sampleSize = 1,
                SkBaseMutex* mutex = NULL);
     virtual ~SkImageRef();
 
@@ -72,9 +72,9 @@
         When these are called, we will have already acquired the mutex!
      */
 
-    virtual void* onLockPixels(SkColorTable**);
+    virtual bool onNewLockPixels(LockRec*) SK_OVERRIDE;
     // override this in your subclass to clean up when we're unlocking pixels
-    virtual void onUnlockPixels() {}
+    virtual void onUnlockPixels() SK_OVERRIDE {}
 
     SkImageRef(SkFlattenableReadBuffer&, SkBaseMutex* mutex = NULL);
     virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
@@ -89,7 +89,6 @@
 
     SkImageDecoderFactory*  fFactory;    // may be null
     SkStreamRewindable*     fStream;
-    SkBitmap::Config        fConfig;
     int                     fSampleSize;
     bool                    fDoDither;
     bool                    fErrorInDecoding;
diff --git a/images/SkImageRef_GlobalPool.h b/images/SkImageRef_GlobalPool.h
index 3adc0f6..caaf248 100644
--- a/images/SkImageRef_GlobalPool.h
+++ b/images/SkImageRef_GlobalPool.h
@@ -15,7 +15,7 @@
 class SkImageRef_GlobalPool : public SkImageRef {
 public:
     // if pool is null, use the global pool
-    SkImageRef_GlobalPool(SkStreamRewindable*, SkBitmap::Config,
+    SkImageRef_GlobalPool(const SkImageInfo&, SkStreamRewindable*,
                           int sampleSize = 1);
     virtual ~SkImageRef_GlobalPool();