Remove _UPM_ GrPixelConfigs
Review URL: http://codereview.appspot.com/6460113/



git-svn-id: http://skia.googlecode.com/svn/trunk@5196 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index 0687dcf..dbb404f 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -465,54 +465,60 @@
      */
     void flush(int flagsBitfield = 0);
 
+   /**
+    * These flags can be used with the read/write pixels functions below.
+    */
+    enum PixelOpsFlags {
+        /** The GrContext will not be flushed. This means that the read or write may occur before
+            previous draws have executed. */
+        kDontFlush_PixelOpsFlag = 0x1,
+        /** The src for write or dst read is unpremultiplied. This is only respected if both the
+            config src and dst configs are an RGBA/BGRA 8888 format. */
+        kUnpremul_PixelOpsFlag  = 0x2,
+    };
+
     /**
      * Reads a rectangle of pixels from a render target.
-     * @param target        the render target to read from. NULL means the
-     *                      current render target.
+     * @param target        the render target to read from. NULL means the current render target.
      * @param left          left edge of the rectangle to read (inclusive)
      * @param top           top edge of the rectangle to read (inclusive)
      * @param width         width of rectangle to read in pixels.
      * @param height        height of rectangle to read in pixels.
      * @param config        the pixel config of the destination buffer
      * @param buffer        memory to read the rectangle into.
-     * @param rowBytes      number of bytes bewtween consecutive rows. Zero
-     *                      means rows are tightly packed.
+     * @param rowBytes      number of bytes bewtween consecutive rows. Zero means rows are tightly
+     *                      packed.
+     * @param pixelOpsFlags see PixelOpsFlags enum above.
      *
-     * @return true if the read succeeded, false if not. The read can fail
-     *              because of an unsupported pixel config or because no render
-     *              target is currently set.
+     * @return true if the read succeeded, false if not. The read can fail because of an unsupported
+     *         pixel config or because no render target is currently set and NULL was passed for
+     *         target.
      */
     bool readRenderTargetPixels(GrRenderTarget* target,
                                 int left, int top, int width, int height,
-                                GrPixelConfig config, void* buffer, 
-                                size_t rowBytes) {
-        return this->internalReadRenderTargetPixels(target, left, top,
-                                                    width, height,
-                                                    config, buffer,
-                                                    rowBytes, 0);
-    }
+                                GrPixelConfig config, void* buffer,
+                                size_t rowBytes = 0,
+                                uint32_t pixelOpsFlags = 0);
 
     /**
-     * Copy the src pixels [buffer, rowbytes, pixelconfig] into a render target
-     * at the specified rectangle.
-     * @param target        the render target to write into. NULL means the
-     *                      current render target.
+     * Copy the src pixels [buffer, rowbytes, pixelconfig] into a render target at the specified
+     * rectangle.
+     * @param target        the render target to write into. NULL means the current render target.
      * @param left          left edge of the rectangle to write (inclusive)
      * @param top           top edge of the rectangle to write (inclusive)
      * @param width         width of rectangle to write in pixels.
      * @param height        height of rectangle to write in pixels.
      * @param config        the pixel config of the source buffer
      * @param buffer        memory to read the rectangle from.
-     * @param rowBytes      number of bytes bewtween consecutive rows. Zero
-     *                      means rows are tightly packed.
+     * @param rowBytes      number of bytes bewtween consecutive rows. Zero means rows are tightly
+     *                      packed.
+     * @param pixelOpsFlags see PixelOpsFlags enum above.
      */
     void writeRenderTargetPixels(GrRenderTarget* target,
                                  int left, int top, int width, int height,
                                  GrPixelConfig config, const void* buffer,
-                                 size_t rowBytes) {
-        this->internalWriteRenderTargetPixels(target, left, top, width, height,
-                                              config, buffer, rowBytes, 0);
-    }
+                                 size_t rowBytes = 0,
+                                 uint32_t pixelOpsFlags = 0);
 
     /**
      * Reads a rectangle of pixels from a texture.
@@ -523,20 +529,18 @@
      * @param height        height of rectangle to read in pixels.
      * @param config        the pixel config of the destination buffer
      * @param buffer        memory to read the rectangle into.
-     * @param rowBytes      number of bytes bewtween consecutive rows. Zero
-     *                      means rows are tightly packed.
+     * @param rowBytes      number of bytes bewtween consecutive rows. Zero means rows are tightly
+     *                      packed.
+     * @param pixelOpsFlags see PixelOpsFlags enum above.
      *
-     * @return true if the read succeeded, false if not. The read can fail
-     *              because of an unsupported pixel config.
+     * @return true if the read succeeded, false if not. The read can fail because of an unsupported
+     *         pixel config.
      */
     bool readTexturePixels(GrTexture* texture,
                            int left, int top, int width, int height,
                            GrPixelConfig config, void* buffer,
-                           size_t rowBytes) {
-        return this->internalReadTexturePixels(texture, left, top,
-                                               width, height,
-                                               config, buffer, rowBytes, 0);
-    }
+                           size_t rowBytes = 0,
+                           uint32_t pixelOpsFlags = 0);
 
     /**
      * Writes a rectangle of pixels to a texture.
@@ -549,14 +553,15 @@
      * @param buffer        memory to read pixels from
      * @param rowBytes      number of bytes bewtween consecutive rows. Zero
      *                      means rows are tightly packed.
+     * @param pixelOpsFlags see PixelOpsFlags enum above.
      */
     void writeTexturePixels(GrTexture* texture,
                             int left, int top, int width, int height,
                             GrPixelConfig config, const void* buffer,
-                            size_t rowBytes) {
-        this->internalWriteTexturePixels(texture, left, top, width, height, 
-                                         config, buffer, rowBytes, 0);
-    }
+                            size_t rowBytes,
+                            uint32_t pixelOpsFlags = 0);
+
+
     /**
      * Copies all texels from one texture to another.
      * @param src           the texture to copy from.
@@ -785,49 +790,12 @@
     void internalDrawPath(const GrPaint& paint, const SkPath& path,
                           GrPathFill fill, const GrPoint* translate);
 
-    /**
-     * Flags to the internal read/write pixels funcs
-     */
-    enum PixelOpsFlags {
-        kDontFlush_PixelOpsFlag = 0x1,
-    };
-
     GrTexture* createResizedTexture(const GrTextureDesc& desc,
                                     const GrCacheData& cacheData,
                                     void* srcData,
                                     size_t rowBytes,
                                     bool needsFiltering);
 
-    bool internalReadRenderTargetPixels(GrRenderTarget* target,
-                                        int left, int top,
-                                        int width, int height,
-                                        GrPixelConfig config, void* buffer, 
-                                        size_t rowBytes, uint32_t flags);
-
-    void internalWriteRenderTargetPixels(GrRenderTarget* target,
-                                        int left, int top,
-                                        int width, int height,
-                                        GrPixelConfig, const void* buffer,
-                                        size_t rowBytes, uint32_t flags);
-
-    bool internalReadTexturePixels(GrTexture* texture,
-                                   int left, int top,
-                                   int width, int height,
-                                   GrPixelConfig config, void* buffer,
-                                   size_t rowBytes, uint32_t flags);
-
-    void internalWriteTexturePixels(GrTexture* texture,
-                                    int left, int top,
-                                    int width, int height,
-                                    GrPixelConfig config, const void* buffer,
-                                    size_t rowBytes, uint32_t flags);
-    // needed for access to internalWriteTexturePixels. TODO: make GrContext
-    // be a facade for an internal class. Then functions that are public on the 
-    // internal class would have only be callable in src/gpu. The facade would
-    // only have to functions necessary for clients.
-    friend class GrAtlas;
-    friend class GrTextureStripAtlas;
-
     // Needed so GrTexture's returnToCache helper function can call
     // addExistingTextureToCache
     friend class GrTexture;
diff --git a/include/gpu/GrRenderTarget.h b/include/gpu/GrRenderTarget.h
index d69e5ca..33df8c6 100644
--- a/include/gpu/GrRenderTarget.h
+++ b/include/gpu/GrRenderTarget.h
@@ -53,39 +53,17 @@
         return this; 
     }
 
-    /**
-     * Reads a rectangle of pixels from the render target.
-     * @param left          left edge of the rectangle to read (inclusive)
-     * @param top           top edge of the rectangle to read (inclusive)
-     * @param width         width of rectangle to read in pixels.
-     * @param height        height of rectangle to read in pixels.
-     * @param config        the pixel config of the destination buffer
-     * @param buffer        memory to read the rectangle into.
-     * @param rowBytes      number of bytes bewtween consecutive rows. Zero
-     *                      means rows are tightly packed.
-     *
-     * @return true if the read succeeded, false if not. The read can fail
-     *              because of an unsupported pixel config.
-     */
     virtual bool readPixels(int left, int top, int width, int height,
-                            GrPixelConfig config, void* buffer, 
-                            size_t rowBytes) SK_OVERRIDE;
+                            GrPixelConfig config,
+                            void* buffer,
+                            size_t rowBytes = 0,
+                            uint32_t pixelOpsFlags = 0) SK_OVERRIDE;
 
-    /**
-     * Copy the src pixels [buffer, rowbytes, pixelconfig] into the render
-     * target at the specified rectangle.
-     * @param left          left edge of the rectangle to write (inclusive)
-     * @param top           top edge of the rectangle to write (inclusive)
-     * @param width         width of rectangle to write in pixels.
-     * @param height        height of rectangle to write in pixels.
-     * @param config        the pixel config of the source buffer
-     * @param buffer        memory to read the rectangle from.
-     * @param rowBytes      number of bytes bewtween consecutive rows. Zero
-     *                      means rows are tightly packed.
-     */
     virtual void writePixels(int left, int top, int width, int height,
-                             GrPixelConfig config, const void* buffer, 
-                             size_t rowBytes) SK_OVERRIDE;
+                             GrPixelConfig config,
+                             const void* buffer,
+                             size_t rowBytes = 0,
+                             uint32_t pixelOpsFlags = 0) SK_OVERRIDE;
 
     // GrRenderTarget
     /**
diff --git a/include/gpu/GrSamplerState.h b/include/gpu/GrSamplerState.h
index dcd5b66..f87b9b4 100644
--- a/include/gpu/GrSamplerState.h
+++ b/include/gpu/GrSamplerState.h
@@ -130,6 +130,7 @@
 
     const GrMatrix& getMatrix() const { return fMatrix; }
     bool swapsRAndB() const { return fSwapRAndB; }
+    bool premultiply() const { return fPremultiply; }
 
     GrTextureParams* textureParams() { return &fTextureParams; }
     const GrTextureParams& getTextureParams() const { return fTextureParams; }
@@ -146,6 +147,12 @@
     void setRAndBSwap(bool swap) { fSwapRAndB = swap; }
 
     /**
+     * If the texture is RGBA/BGRA 8888 config then its rgb components will be
+     * multiplied by its a component after the texture read.
+     **/
+    void setPremultiply(bool premul) { fPremultiply = premul; }
+
+    /**
      *  Multiplies the current sampler matrix  a matrix
      *
      *  After this call M' = M*m where M is the old matrix, m is the parameter
@@ -163,6 +170,7 @@
         fTextureParams.reset(tileXAndY, filter);
         fMatrix = matrix;
         fSwapRAndB = false;
+        fPremultiply = false;
         GrSafeSetNull(fCustomStage);
     }
     void reset(SkShader::TileMode wrapXAndY, bool filter) {
@@ -184,6 +192,7 @@
 private:
     GrTextureParams     fTextureParams;
     bool                fSwapRAndB;
+    bool                fPremultiply; // temporary, will be replaced soon by a custom stage.
     GrMatrix            fMatrix;
 
     GrCustomStage*      fCustomStage;
diff --git a/include/gpu/GrSurface.h b/include/gpu/GrSurface.h
index 2d39b5e..aa237ae 100644
--- a/include/gpu/GrSurface.h
+++ b/include/gpu/GrSurface.h
@@ -66,34 +66,40 @@
      * @param height        height of rectangle to read in pixels.
      * @param config        the pixel config of the destination buffer
      * @param buffer        memory to read the rectangle into.
-     * @param rowBytes      number of bytes bewtween consecutive rows. Zero
-     *                      means rows are tightly packed.
+     * @param rowBytes      number of bytes bewtween consecutive rows. Zero means rows are tightly
+     *                      packed.
+     * @param pixelOpsFlags See the GrContext::PixelOpsFlags enum.
      *
-     * @return true if the read succeeded, false if not. The read can fail
-     *              because of an unsupported pixel config.
+     * @return true if the read succeeded, false if not. The read can fail because of an unsupported
+     *              pixel config.
      */
     virtual bool readPixels(int left, int top, int width, int height,
-                            GrPixelConfig config, void* buffer, 
-                            size_t rowBytes) = 0;
+                            GrPixelConfig config,
+                            void* buffer,
+                            size_t rowBytes = 0,
+                            uint32_t pixelOpsFlags = 0) = 0;
 
     /**
-     * Copy the src pixels [buffer, rowbytes, pixelconfig] into the surface
-     * at the specified rectangle.
+     * Copy the src pixels [buffer, rowbytes, pixelconfig] into the surface at the specified
+     * rectangle.
      * @param left          left edge of the rectangle to write (inclusive)
      * @param top           top edge of the rectangle to write (inclusive)
      * @param width         width of rectangle to write in pixels.
      * @param height        height of rectangle to write in pixels.
      * @param config        the pixel config of the source buffer
      * @param buffer        memory to read the rectangle from.
-     * @param rowBytes      number of bytes bewtween consecutive rows. Zero
-     *                      means rows are tightly packed.
+     * @param rowBytes      number of bytes bewtween consecutive rows. Zero means rows are tightly
+     *                      packed.
+     * @param pixelOpsFlags See the GrContext::PixelOpsFlags enum.
      */
     virtual void writePixels(int left, int top, int width, int height,
-                             GrPixelConfig config, const void* buffer, 
-                             size_t rowBytes) = 0;
+                             GrPixelConfig config,
+                             const void* buffer,
+                             size_t rowBytes = 0,
+                             uint32_t pixelOpsFlags = 0) = 0;
 
 protected:
-    GrTextureDesc     fDesc;
+    GrTextureDesc fDesc;
 
     GrSurface(GrGpu* gpu, const GrTextureDesc& desc)
     : INHERITED(gpu)
diff --git a/include/gpu/GrTexture.h b/include/gpu/GrTexture.h
index a1b7eab..c7bfb8c 100644
--- a/include/gpu/GrTexture.h
+++ b/include/gpu/GrTexture.h
@@ -55,39 +55,18 @@
                         GrBytesPerPixel(fDesc.fConfig);
     }
 
-    // from GrSurface
-    /**
-     * Read a rectangle of pixels from the texture.
-     * @param left          left edge of the rectangle to read (inclusive)
-     * @param top           top edge of the rectangle to read (inclusive)
-     * @param width         width of rectangle to read in pixels.
-     * @param height        height of rectangle to read in pixels.
-     * @param config        the pixel config of the destination buffer
-     * @param buffer        memory to read the rectangle into.
-     * @param rowBytes      number of bytes bewtween consecutive rows. Zero
-     *                      means rows are tightly packed.
-     *
-     * @return true if the read succeeded, false if not. The read can fail
-     *              because of a unsupported pixel config.
-     */
+    // GrSurface overrides
     virtual bool readPixels(int left, int top, int width, int height,
-                            GrPixelConfig config, void* buffer,
-                            size_t rowBytes) SK_OVERRIDE;
+                            GrPixelConfig config,
+                            void* buffer,
+                            size_t rowBytes = 0,
+                            uint32_t pixelOpsFlags = 0) SK_OVERRIDE;
 
-    /**
-     * Writes a rectangle of pixels to the texture.
-     * @param left          left edge of the rectangle to write (inclusive)
-     * @param top           top edge of the rectangle to write (inclusive)
-     * @param width         width of rectangle to write in pixels.
-     * @param height        height of rectangle to write in pixels.
-     * @param config        the pixel config of the source buffer
-     * @param buffer        memory to read pixels from
-     * @param rowBytes      number of bytes between consecutive rows. Zero
-     *                      means rows are tightly packed.
-     */
     virtual void writePixels(int left, int top, int width, int height,
-                             GrPixelConfig config, const void* buffer,
-                             size_t rowBytes) SK_OVERRIDE;
+                             GrPixelConfig config,
+                             const void* buffer,
+                             size_t rowBytes = 0,
+                             uint32_t pixelOpsFlags = 0) SK_OVERRIDE;
 
     /**
      * @return this texture
diff --git a/include/gpu/GrTypes.h b/include/gpu/GrTypes.h
index 9fbdb74..58f8968 100644
--- a/include/gpu/GrTypes.h
+++ b/include/gpu/GrTypes.h
@@ -276,13 +276,6 @@
 
 /**
  * Pixel configurations.
- *
- * Unpremultiplied configs are intended for converting pixel data in and out
- * from skia. Surfaces with these configs have limited support. As an input
- * (GrPaint texture) the corresponding GrSamplerState must have its filter set
- * to kNearest_Filter. Otherwise, the draw will fail. When the render target
- * has an unpremultiplied config draws must use blend coeffs 1,0 (AKA src-mode).
- * Other coeffs will cause the draw to fail.
  */
 enum GrPixelConfig {
     kUnknown_GrPixelConfig,
@@ -294,47 +287,39 @@
      */
     kRGBA_4444_GrPixelConfig,
     /**
-     * Premultiplied. Byte order is r,g,b,a
+     * Premultiplied. Byte order is r,g,b,a.
      */
-    kRGBA_8888_PM_GrPixelConfig,
+    kRGBA_8888_GrPixelConfig,
     /**
-     * Unpremultiplied. Byte order is r,g,b,a
+     * Premultiplied. Byte order is b,g,r,a.
      */
-    kRGBA_8888_UPM_GrPixelConfig,
-    /**
-     * Premultiplied. Byte order is b,g,r,a
-     */
-    kBGRA_8888_PM_GrPixelConfig,
-    /**
-     * Unpremultiplied. Byte order is b,g,r,a
-     */
-    kBGRA_8888_UPM_GrPixelConfig,
+    kBGRA_8888_GrPixelConfig,
 
     kGrPixelConfigCount
 };
 
-// Aliases for pixel configs that match skia's byte order
+// Aliases for pixel configs that match skia's byte order. 
 #ifndef SK_CPU_LENDIAN
     #error "Skia gpu currently assumes little endian"
 #endif
 #if 24 == SK_A32_SHIFT && 16 == SK_R32_SHIFT && \
      8 == SK_G32_SHIFT &&  0 == SK_B32_SHIFT
-    static const GrPixelConfig kSkia8888_PM_GrPixelConfig = kBGRA_8888_PM_GrPixelConfig;
-    static const GrPixelConfig kSkia8888_UPM_GrPixelConfig = kBGRA_8888_UPM_GrPixelConfig;
+    static const GrPixelConfig kSkia8888_GrPixelConfig = kBGRA_8888_GrPixelConfig;
 #elif 24 == SK_A32_SHIFT && 16 == SK_B32_SHIFT && \
        8 == SK_G32_SHIFT &&  0 == SK_R32_SHIFT
-    static const GrPixelConfig kSkia8888_PM_GrPixelConfig = kRGBA_8888_PM_GrPixelConfig;
-    static const GrPixelConfig kSkia8888_UPM_GrPixelConfig = kRGBA_8888_UPM_GrPixelConfig;
+    static const GrPixelConfig kSkia8888_GrPixelConfig = kRGBA_8888_GrPixelConfig;
 #else
     #error "SK_*32_SHIFT values must correspond to GL_BGRA or GL_RGBA format."
 #endif
 
+// This alias is deprecated and will be removed.
+static const GrPixelConfig kSkia8888_PM_GrPixelConfig = kSkia8888_GrPixelConfig;
+
 // Returns true if the pixel config has 8bit r,g,b,a components in that byte
 // order
 static inline bool GrPixelConfigIsRGBA8888(GrPixelConfig config) {
     switch (config) {
-        case kRGBA_8888_PM_GrPixelConfig:
-        case kRGBA_8888_UPM_GrPixelConfig:
+        case kRGBA_8888_GrPixelConfig:
             return true;
         default:
             return false;
@@ -345,8 +330,7 @@
 // order
 static inline bool GrPixelConfigIsBGRA8888(GrPixelConfig config) {
     switch (config) {
-        case kBGRA_8888_PM_GrPixelConfig:
-        case kBGRA_8888_UPM_GrPixelConfig:
+        case kBGRA_8888_GrPixelConfig:
             return true;
         default:
             return false;
@@ -356,10 +340,8 @@
 // Returns true if the pixel config is 32 bits per pixel
 static inline bool GrPixelConfigIs32Bit(GrPixelConfig config) {
     switch (config) {
-        case kRGBA_8888_PM_GrPixelConfig:
-        case kRGBA_8888_UPM_GrPixelConfig:
-        case kBGRA_8888_PM_GrPixelConfig:
-        case kBGRA_8888_UPM_GrPixelConfig:
+        case kRGBA_8888_GrPixelConfig:
+        case kBGRA_8888_GrPixelConfig:
             return true;
         default:
             return false;
@@ -370,14 +352,10 @@
 // swapped if such a config exists. Otherwise, kUnknown_GrPixelConfig
 static inline GrPixelConfig GrPixelConfigSwapRAndB(GrPixelConfig config) {
     switch (config) {
-        case kBGRA_8888_PM_GrPixelConfig:
-            return kRGBA_8888_PM_GrPixelConfig;
-        case kBGRA_8888_UPM_GrPixelConfig:
-            return kRGBA_8888_UPM_GrPixelConfig;
-        case kRGBA_8888_PM_GrPixelConfig:
-            return kBGRA_8888_PM_GrPixelConfig;
-        case kRGBA_8888_UPM_GrPixelConfig:
-            return kBGRA_8888_UPM_GrPixelConfig;
+        case kBGRA_8888_GrPixelConfig:
+            return kRGBA_8888_GrPixelConfig;
+        case kRGBA_8888_GrPixelConfig:
+            return kBGRA_8888_GrPixelConfig;
         default:
             return kUnknown_GrPixelConfig;
     }
@@ -391,10 +369,8 @@
         case kRGB_565_GrPixelConfig:
         case kRGBA_4444_GrPixelConfig:
             return 2;
-        case kRGBA_8888_PM_GrPixelConfig:
-        case kRGBA_8888_UPM_GrPixelConfig:
-        case kBGRA_8888_PM_GrPixelConfig:
-        case kBGRA_8888_UPM_GrPixelConfig:
+        case kRGBA_8888_GrPixelConfig:
+        case kBGRA_8888_GrPixelConfig:
             return 4;
         default:
             return 0;
@@ -410,20 +386,6 @@
     }
 }
 
-/**
- * Premultiplied alpha is the usual for skia. Therefore, configs that are
- * ambiguous (alpha-only or color-only) are considered premultiplied.
- */
-static inline bool GrPixelConfigIsUnpremultiplied(GrPixelConfig config) {
-    switch (config) {
-        case kRGBA_8888_UPM_GrPixelConfig:
-        case kBGRA_8888_UPM_GrPixelConfig:
-            return true;
-        default:
-            return false;
-    }
-}
-
 static inline bool GrPixelConfigIsAlphaOnly(GrPixelConfig config) {
     switch (config) {
         case kAlpha_8_GrPixelConfig:
diff --git a/src/gpu/GrAtlas.cpp b/src/gpu/GrAtlas.cpp
index 2b76d13..491f6cf 100644
--- a/src/gpu/GrAtlas.cpp
+++ b/src/gpu/GrAtlas.cpp
@@ -111,13 +111,13 @@
     }
     adjustForPlot(loc, fPlot);
     GrContext* context = fTexture->getContext();
-    // We call the internal version so that we don't force a flush. We assume
-    // our caller is smart and hasn't referenced the part of the texture we're
-    // about to update since the last flush.
-    context->internalWriteTexturePixels(fTexture, loc->fX, loc->fY,
-                                        dstW, dstH, fTexture->config(),
-                                        image, 0,
-                                        GrContext::kDontFlush_PixelOpsFlag);
+    // We pass the flag that does not force a flush. We assume our caller is
+    // smart and hasn't referenced the part of the texture we're about to update
+    // since the last flush.
+    context->writeTexturePixels(fTexture,
+                                loc->fX, loc->fY, dstW, dstH,
+                                fTexture->config(), image, 0,
+                                GrContext::kDontFlush_PixelOpsFlag);
 
     // now tell the caller to skip the top/left BORDER
     loc->fX += BORDER;
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 89537ad..49d220f 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -1185,46 +1185,39 @@
     }
 }
 
-void GrContext::internalWriteTexturePixels(GrTexture* texture,
-                                           int left, int top,
-                                           int width, int height,
-                                           GrPixelConfig config,
-                                           const void* buffer,
-                                           size_t rowBytes,
-                                           uint32_t flags) {
+void GrContext::writeTexturePixels(GrTexture* texture,
+                                   int left, int top, int width, int height,
+                                   GrPixelConfig config, const void* buffer, size_t rowBytes,
+                                   uint32_t flags) {
     SK_TRACE_EVENT0("GrContext::writeTexturePixels");
     ASSERT_OWNED_RESOURCE(texture);
 
+    // TODO: use scratch texture to perform conversion
+    if (kUnpremul_PixelOpsFlag & flags) {
+        return;
+    }
     if (!(kDontFlush_PixelOpsFlag & flags)) {
         this->flush();
     }
-    // TODO: use scratch texture to perform conversion
-    if (GrPixelConfigIsUnpremultiplied(texture->config()) !=
-        GrPixelConfigIsUnpremultiplied(config)) {
-        return;
-    }
 
     fGpu->writeTexturePixels(texture, left, top, width, height, 
                              config, buffer, rowBytes);
 }
 
-bool GrContext::internalReadTexturePixels(GrTexture* texture,
-                                          int left, int top,
-                                          int width, int height,
-                                          GrPixelConfig config,
-                                          void* buffer,
-                                          size_t rowBytes,
-                                          uint32_t flags) {
+bool GrContext::readTexturePixels(GrTexture* texture,
+                                  int left, int top, int width, int height,
+                                  GrPixelConfig config, void* buffer, size_t rowBytes,
+                                  uint32_t flags) {
     SK_TRACE_EVENT0("GrContext::readTexturePixels");
     ASSERT_OWNED_RESOURCE(texture);
 
     // TODO: code read pixels for textures that aren't also rendertargets
     GrRenderTarget* target = texture->asRenderTarget();
     if (NULL != target) {
-        return this->internalReadRenderTargetPixels(target,
-                                                    left, top, width, height,
-                                                    config, buffer, rowBytes,
-                                                    flags);
+        return this->readRenderTargetPixels(target,
+                                            left, top, width, height,
+                                            config, buffer, rowBytes,
+                                            flags);
     } else {
         return false;
     }
@@ -1239,19 +1232,22 @@
  * if the GrPixelConfig has no equivalent Config8888.
  */
 bool grconfig_to_config8888(GrPixelConfig config,
+                            bool unpremul,
                             SkCanvas::Config8888* config8888) {
     switch (config) {
-        case kRGBA_8888_PM_GrPixelConfig:
-            *config8888 = SkCanvas::kRGBA_Premul_Config8888;
+        case kRGBA_8888_GrPixelConfig:
+            if (unpremul) {
+                *config8888 = SkCanvas::kRGBA_Unpremul_Config8888;
+            } else {
+                *config8888 = SkCanvas::kRGBA_Premul_Config8888;
+            }
             return true;
-        case kRGBA_8888_UPM_GrPixelConfig:
-            *config8888 = SkCanvas::kRGBA_Unpremul_Config8888;
-            return true;
-        case kBGRA_8888_PM_GrPixelConfig:
-            *config8888 = SkCanvas::kBGRA_Premul_Config8888;
-            return true;
-        case kBGRA_8888_UPM_GrPixelConfig:
-            *config8888 = SkCanvas::kBGRA_Unpremul_Config8888;
+        case kBGRA_8888_GrPixelConfig:
+            if (unpremul) {
+                *config8888 = SkCanvas::kBGRA_Unpremul_Config8888;
+            } else {
+                *config8888 = SkCanvas::kBGRA_Premul_Config8888;
+            }
             return true;
         default:
             return false;
@@ -1259,13 +1255,10 @@
 }
 }
 
-bool GrContext::internalReadRenderTargetPixels(GrRenderTarget* target,
-                                               int left, int top,
-                                               int width, int height,
-                                               GrPixelConfig config,
-                                               void* buffer,
-                                               size_t rowBytes,
-                                               uint32_t flags) {
+bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
+                                       int left, int top, int width, int height,
+                                       GrPixelConfig config, void* buffer, size_t rowBytes,
+                                       uint32_t flags) {
     SK_TRACE_EVENT0("GrContext::readRenderTargetPixels");
     ASSERT_OWNED_RESOURCE(target);
 
@@ -1280,21 +1273,21 @@
         this->flush();
     }
 
-    if (!GrPixelConfigIsUnpremultiplied(target->config()) &&
-        GrPixelConfigIsUnpremultiplied(config) &&
+    if ((kUnpremul_PixelOpsFlag & flags) &&
         !fGpu->canPreserveReadWriteUnpremulPixels()) {
+
         SkCanvas::Config8888 srcConfig8888, dstConfig8888;
-        if (!grconfig_to_config8888(target->config(), &srcConfig8888) ||
-            !grconfig_to_config8888(config, &dstConfig8888)) {
+        if (!grconfig_to_config8888(target->config(), false, &srcConfig8888) ||
+            !grconfig_to_config8888(config, true, &dstConfig8888)) {
             return false;
         }
         // do read back using target's own config
-        this->internalReadRenderTargetPixels(target,
-                                             left, top,
-                                             width, height,
-                                             target->config(),
-                                             buffer, rowBytes,
-                                             kDontFlush_PixelOpsFlag);
+        this->readRenderTargetPixels(target,
+                                     left, top,
+                                     width, height,
+                                     target->config(),
+                                     buffer, rowBytes,
+                                     kDontFlush_PixelOpsFlag); // we already flushed
         // sw convert the pixels to unpremul config
         uint32_t* pixels = reinterpret_cast<uint32_t*>(buffer);
         SkConvertConfig8888Pixels(pixels, rowBytes, dstConfig8888,
@@ -1312,10 +1305,9 @@
                  fGpu->readPixelsWillPayForYFlip(target, left, top,
                                                  width, height, config,
                                                  rowBytes);
-    bool alphaConversion = (!GrPixelConfigIsUnpremultiplied(target->config()) &&
-                             GrPixelConfigIsUnpremultiplied(config));
+    bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags);
 
-    if (NULL == src && alphaConversion) {
+    if (NULL == src && unpremul) {
         // we should fallback to cpu conversion here. This could happen when
         // we were given an external render target by the client that is not
         // also a texture (e.g. FBO 0 in GL)
@@ -1323,7 +1315,7 @@
     }
     // we draw to a scratch texture if any of these conversion are applied
     GrAutoScratchTexture ast;
-    if (flipY || swapRAndB || alphaConversion) {
+    if (flipY || swapRAndB || unpremul) {
         GrAssert(NULL != src);
         if (swapRAndB) {
             config = GrPixelConfigSwapRAndB(config);
@@ -1363,6 +1355,10 @@
         GrDrawState* drawState = fGpu->drawState();
         drawState->setRenderTarget(target);
 
+        if (unpremul) {
+            drawState->enableState(GrDrawState::kUnpremultiply_StageBit);
+        }
+
         GrMatrix matrix;
         if (flipY) {
             matrix.setTranslate(SK_Scalar1 * left,
@@ -1421,13 +1417,12 @@
     fGpu->drawSimpleRect(rect, NULL);
 }
 
-void GrContext::internalWriteRenderTargetPixels(GrRenderTarget* target, 
-                                                int left, int top,
-                                                int width, int height,
-                                                GrPixelConfig config,
-                                                const void* buffer,
-                                                size_t rowBytes,
-                                                uint32_t flags) {
+void GrContext::writeRenderTargetPixels(GrRenderTarget* target, 
+                                        int left, int top, int width, int height,
+                                        GrPixelConfig config,
+                                        const void* buffer,
+                                        size_t rowBytes,
+                                        uint32_t flags) {
     SK_TRACE_EVENT0("GrContext::writeRenderTargetPixels");
     ASSERT_OWNED_RESOURCE(target);
 
@@ -1441,30 +1436,26 @@
     // TODO: when underlying api has a direct way to do this we should use it
     // (e.g. glDrawPixels on desktop GL).
 
-    // If the RT is also a texture and we don't have to do PM/UPM conversion
-    // then take the texture path, which we expect to be at least as fast or
-    // faster since it doesn't use an intermediate texture as we do below.
+    // If the RT is also a texture and we don't have to premultiply then take the texture path.
+    // We expect to be at least as fast or faster since it doesn't use an intermediate texture as
+    // we do below.
     
 #if !GR_MAC_BUILD
     // At least some drivers on the Mac get confused when glTexImage2D is called
     // on a texture attached to an FBO. The FBO still sees the old image. TODO:
     // determine what OS versions and/or HW is affected.
-    if (NULL != target->asTexture() &&
-        GrPixelConfigIsUnpremultiplied(target->config()) ==
-        GrPixelConfigIsUnpremultiplied(config)) {
-
-        this->internalWriteTexturePixels(target->asTexture(),
-                                         left, top, width, height,
-                                         config, buffer, rowBytes, flags);
+    if (NULL != target->asTexture() && !(kUnpremul_PixelOpsFlag & flags)) {
+        this->writeTexturePixels(target->asTexture(),
+                                 left, top, width, height,
+                                 config, buffer, rowBytes, flags);
         return;
     }
 #endif
-    if (!GrPixelConfigIsUnpremultiplied(target->config()) &&
-        GrPixelConfigIsUnpremultiplied(config) &&
+    if ((kUnpremul_PixelOpsFlag & flags) &&
         !fGpu->canPreserveReadWriteUnpremulPixels()) {
         SkCanvas::Config8888 srcConfig8888, dstConfig8888;
-        if (!grconfig_to_config8888(config, &srcConfig8888) ||
-            !grconfig_to_config8888(target->config(), &dstConfig8888)) {
+        if (!grconfig_to_config8888(config, true, &srcConfig8888) ||
+            !grconfig_to_config8888(target->config(), false, &dstConfig8888)) {
             return;
         }
         // allocate a tmp buffer and sw convert the pixels to premul
@@ -1474,11 +1465,13 @@
                                   src, rowBytes, srcConfig8888,
                                   width, height);
         // upload the already premul pixels
-        this->internalWriteRenderTargetPixels(target,
-                                             left, top,
-                                             width, height,
-                                             target->config(),
-                                             tmpPixels, 4 * width, flags);
+        flags &= ~kUnpremul_PixelOpsFlag;
+        this->writeRenderTargetPixels(target,
+                                      left, top,
+                                      width, height,
+                                      target->config(),
+                                      tmpPixels, 4 * width,
+                                      flags);
         return;
     }
 
@@ -1498,8 +1491,8 @@
     if (NULL == texture) {
         return;
     }
-    this->internalWriteTexturePixels(texture, 0, 0, width, height,
-                                     config, buffer, rowBytes, flags);
+    this->writeTexturePixels(texture, 0, 0, width, height,
+                             config, buffer, rowBytes, flags & ~kUnpremul_PixelOpsFlag);
 
     GrDrawTarget::AutoStateRestore  asr(fGpu, GrDrawTarget::kReset_ASRInit);
     GrDrawState* drawState = fGpu->drawState();
@@ -1513,6 +1506,7 @@
     drawState->sampler(0)->reset(matrix);
     drawState->createTextureEffect(0, texture);
     drawState->sampler(0)->setRAndBSwap(swapRAndB);
+    drawState->sampler(0)->setPremultiply(SkToBool(kUnpremul_PixelOpsFlag & flags));
 
     static const GrVertexLayout layout = 0;
     static const int VCOUNT = 4;
@@ -1755,8 +1749,8 @@
 
     AutoClip acs(this, srcRect);
 
-    GrAssert(kBGRA_8888_PM_GrPixelConfig == srcTexture->config() ||
-             kRGBA_8888_PM_GrPixelConfig == srcTexture->config() ||
+    GrAssert(kBGRA_8888_GrPixelConfig == srcTexture->config() ||
+             kRGBA_8888_GrPixelConfig == srcTexture->config() ||
              kAlpha_8_GrPixelConfig == srcTexture->config());
 
     GrTextureDesc desc;
@@ -1875,7 +1869,7 @@
     desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
     desc.fWidth = SkScalarCeilToInt(rect.width());
     desc.fHeight = SkScalarCeilToInt(rect.height());
-    desc.fConfig = kRGBA_8888_PM_GrPixelConfig;
+    desc.fConfig = kRGBA_8888_GrPixelConfig;
     if (radius.fWidth > 0) {
         GrAutoScratchTexture ast(this, desc);
         this->setRenderTarget(ast.texture()->asRenderTarget());
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index 0d81019..cc68aed 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -668,7 +668,14 @@
          * Draws will apply the color matrix, otherwise the color matrix is
          * ignored.
          */
-        kColorMatrix_StateBit   = 0x20,
+        kColorMatrix_StateBit   = 0x10,
+
+        /**
+         * The pixels written to the render target should be unpremultiplied.
+         * This flag is temporary and will be removed when this functionality is
+         * captured in a custom stage.
+         */
+         kUnpremultiply_StageBit = 0x20,
 
         // Users of the class may add additional bits to the vector
         kDummyStateBit,
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index f0f1864..5b90480 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -760,29 +760,6 @@
     if (NULL == drawState.getRenderTarget()) {
         return false;
     }
-    if (GrPixelConfigIsUnpremultiplied(drawState.getRenderTarget()->config())) {
-        if (kOne_GrBlendCoeff != drawState.getSrcBlendCoeff() ||
-            kZero_GrBlendCoeff != drawState.getDstBlendCoeff()) {
-            return false;
-        }
-    }
-    // We don't support using unpremultiplied textures with bilerp. Alpha-multiplication is not
-    // distributive with respect to filtering. We'd have to alpha-mul each texel before filtering.
-    // Until Skia itself supports unpremultiplied configs there is no pressure to implement this.
-    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
-        if (drawState.isStageEnabled(s)) {
-            const GrCustomStage* stage = drawState.getSampler(s).getCustomStage();
-            int numTextures = stage->numTextures();
-            for (int t = 0; t < numTextures; ++t) {
-                GrTexture* texture = stage->texture(t);
-                GrAssert(NULL != texture);
-                if (GrPixelConfigIsUnpremultiplied(texture->config()) &&
-                    drawState.getSampler(s).getTextureParams().isBilerp()) {
-                    return false;
-                }
-            }
-        }
-    }
     return true;
 }
 
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index c159f5e..923f711 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -263,8 +263,6 @@
                        int left, int top, int width, int height,
                        GrPixelConfig config, void* buffer,
                        size_t rowBytes, bool invertY) {
-    GrAssert(GrPixelConfigIsUnpremultiplied(config) ==
-             GrPixelConfigIsUnpremultiplied(target->config()));
     this->handleDirtyContext();
     return this->onReadPixels(target, left, top, width, height,
                               config, buffer, rowBytes, invertY);
@@ -274,8 +272,6 @@
                                int left, int top, int width, int height,
                                GrPixelConfig config, const void* buffer,
                                size_t rowBytes) {
-    GrAssert(GrPixelConfigIsUnpremultiplied(config) ==
-             GrPixelConfigIsUnpremultiplied(texture->config()));
     this->handleDirtyContext();
     this->onWriteTexturePixels(texture, left, top, width, height,
                                config, buffer, rowBytes);
diff --git a/src/gpu/GrRenderTarget.cpp b/src/gpu/GrRenderTarget.cpp
index 071c885..816a633 100644
--- a/src/gpu/GrRenderTarget.cpp
+++ b/src/gpu/GrRenderTarget.cpp
@@ -16,31 +16,35 @@
 SK_DEFINE_INST_COUNT(GrRenderTarget)
 
 bool GrRenderTarget::readPixels(int left, int top, int width, int height,
-                                GrPixelConfig config, void* buffer,
-                                size_t rowBytes) {
+                                GrPixelConfig config,
+                                void* buffer,
+                                size_t rowBytes,
+                                uint32_t pixelOpsFlags) {
     // go through context so that all necessary flushing occurs
     GrContext* context = this->getContext();
     if (NULL == context) {
         return false;
     }
     return context->readRenderTargetPixels(this,
-                                           left, top,
-                                           width, height,
-                                           config, buffer, rowBytes);
+                                           left, top, width, height,
+                                           config, buffer, rowBytes,
+                                           pixelOpsFlags);
 }
 
 void GrRenderTarget::writePixels(int left, int top, int width, int height,
-                                 GrPixelConfig config, const void* buffer,
-                                 size_t rowBytes) {
+                                 GrPixelConfig config,
+                                 const void* buffer,
+                                 size_t rowBytes,
+                                 uint32_t pixelOpsFlags) {
     // go through context so that all necessary flushing occurs
     GrContext* context = this->getContext();
     if (NULL == context) {
         return;
     }
     context->writeRenderTargetPixels(this,
-                                     left, top,
-                                     width, height,
-                                     config, buffer, rowBytes);
+                                     left, top, width, height,
+                                     config, buffer, rowBytes,
+                                     pixelOpsFlags);
 }
 
 void GrRenderTarget::resolve() {
diff --git a/src/gpu/GrTexture.cpp b/src/gpu/GrTexture.cpp
index d2e2736..182c90e 100644
--- a/src/gpu/GrTexture.cpp
+++ b/src/gpu/GrTexture.cpp
@@ -41,30 +41,30 @@
 
 bool GrTexture::readPixels(int left, int top, int width, int height,
                            GrPixelConfig config, void* buffer,
-                           size_t rowBytes) {
+                           size_t rowBytes, uint32_t pixelOpsFlags) {
     // go through context so that all necessary flushing occurs
     GrContext* context = this->getContext();
     if (NULL == context) {
         return false;
     }
     return context->readTexturePixels(this,
-                                      left, top,
-                                      width, height,
-                                      config, buffer, rowBytes);
+                                      left, top, width, height,
+                                      config, buffer, rowBytes,
+                                      pixelOpsFlags);
 }
 
 void GrTexture::writePixels(int left, int top, int width, int height,
                             GrPixelConfig config, const void* buffer,
-                            size_t rowBytes) {
+                            size_t rowBytes, uint32_t pixelOpsFlags) {
     // go through context so that all necessary flushing occurs
     GrContext* context = this->getContext();
     if (NULL == context) {
         return;
     }
     context->writeTexturePixels(this,
-                                left, top,
-                                width, height,
-                                config, buffer, rowBytes);
+                                left, top, width, height,
+                                config, buffer, rowBytes,
+                                pixelOpsFlags);
 }
 
 void GrTexture::releaseRenderTarget() {
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 14e4ff9..1eb9e49 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -291,20 +291,26 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 namespace {
-GrPixelConfig config8888_to_gr_config(SkCanvas::Config8888 config8888) {
+GrPixelConfig config8888_to_grconfig_and_flags(SkCanvas::Config8888 config8888, uint32_t* flags) {
     switch (config8888) {
         case SkCanvas::kNative_Premul_Config8888:
-            return kSkia8888_PM_GrPixelConfig;
+            *flags = 0;
+            return kSkia8888_GrPixelConfig;
         case SkCanvas::kNative_Unpremul_Config8888:
-            return kSkia8888_UPM_GrPixelConfig;
+            *flags = GrContext::kUnpremul_PixelOpsFlag;
+            return kSkia8888_PM_GrPixelConfig;
         case SkCanvas::kBGRA_Premul_Config8888:
-            return kBGRA_8888_PM_GrPixelConfig;
+            *flags = 0;
+            return kBGRA_8888_GrPixelConfig;
         case SkCanvas::kBGRA_Unpremul_Config8888:
-            return kBGRA_8888_UPM_GrPixelConfig;
+            *flags = GrContext::kUnpremul_PixelOpsFlag;
+            return kBGRA_8888_GrPixelConfig;
         case SkCanvas::kRGBA_Premul_Config8888:
-            return kRGBA_8888_PM_GrPixelConfig;
+            *flags = 0;
+            return kRGBA_8888_GrPixelConfig;
         case SkCanvas::kRGBA_Unpremul_Config8888:
-            return kRGBA_8888_UPM_GrPixelConfig;
+            *flags = GrContext::kUnpremul_PixelOpsFlag;
+            return kRGBA_8888_GrPixelConfig;
         default:
             GrCrash("Unexpected Config8888.");
             return kSkia8888_PM_GrPixelConfig;
@@ -322,14 +328,16 @@
 
     SkAutoLockPixels alp(bitmap);
     GrPixelConfig config;
-    config = config8888_to_gr_config(config8888);
+    uint32_t flags;
+    config = config8888_to_grconfig_and_flags(config8888, &flags);
     return fContext->readRenderTargetPixels(fRenderTarget,
                                             x, y,
                                             bitmap.width(),
                                             bitmap.height(),
                                             config,
                                             bitmap.getPixels(),
-                                            bitmap.rowBytes());
+                                            bitmap.rowBytes(),
+                                            flags);
 }
 
 void SkGpuDevice::writePixels(const SkBitmap& bitmap, int x, int y,
@@ -340,14 +348,16 @@
     }
 
     GrPixelConfig config;
+    uint32_t flags;
     if (SkBitmap::kARGB_8888_Config == bitmap.config()) {
-        config = config8888_to_gr_config(config8888);
+        config = config8888_to_grconfig_and_flags(config8888, &flags);
     } else {
+        flags = 0;
         config= SkBitmapConfig2GrPixelConfig(bitmap.config());
     }
 
     fRenderTarget->writePixels(x, y, bitmap.width(), bitmap.height(),
-                               config, bitmap.getPixels(), bitmap.rowBytes());
+                               config, bitmap.getPixels(), bitmap.rowBytes(), flags);
 }
 
 namespace {
@@ -874,7 +884,7 @@
     desc.fHeight = SkScalarCeilToInt(srcRect.height());
     // We actually only need A8, but it often isn't supported as a
     // render target so default to RGBA_8888
-    desc.fConfig = kRGBA_8888_PM_GrPixelConfig;
+    desc.fConfig = kRGBA_8888_GrPixelConfig;
 
     if (context->isConfigRenderable(kAlpha_8_GrPixelConfig)) {
         desc.fConfig = kAlpha_8_GrPixelConfig;
@@ -1527,7 +1537,7 @@
     desc.fFlags = kRenderTarget_GrTextureFlagBit,
     desc.fWidth = SkScalarCeilToInt(rect.width());
     desc.fHeight = SkScalarCeilToInt(rect.height());
-    desc.fConfig = kRGBA_8888_PM_GrPixelConfig;
+    desc.fConfig = kRGBA_8888_GrPixelConfig;
     GrCustomStage* stage;
 
     if (filter->canFilterImageGPU()) {
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index a98b8fd..2052b77 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -100,7 +100,7 @@
                                           GrContext::kExact_ScratchTexMatch);
                 result->writePixels(0, 0, bitmap->width(), 
                                     bitmap->height(), desc.fConfig,
-                                    storage.get(), 0);
+                                    storage.get());
                 return result;
             }
 
diff --git a/src/gpu/effects/GrTextureStripAtlas.cpp b/src/gpu/effects/GrTextureStripAtlas.cpp
index f31d7d7..3462e92 100644
--- a/src/gpu/effects/GrTextureStripAtlas.cpp
+++ b/src/gpu/effects/GrTextureStripAtlas.cpp
@@ -137,13 +137,13 @@
 
         // Pass in the kDontFlush flag, since we know we're writing to a part of this texture
         // that is not currently in use
-        fDesc.fContext->internalWriteTexturePixels(fTexture, 0, 
-                                                   rowNumber * fDesc.fRowHeight, 
-                                                   fDesc.fWidth,
-                                                   fDesc.fRowHeight, 
-                                                   SkBitmapConfig2GrPixelConfig(data.config()),
-                                                   data.getPixels(), data.rowBytes(),
-                                                   GrContext::kDontFlush_PixelOpsFlag);
+        fDesc.fContext->writeTexturePixels(fTexture,
+                                           0,  rowNumber * fDesc.fRowHeight,
+                                           fDesc.fWidth, fDesc.fRowHeight, 
+                                           SkBitmapConfig2GrPixelConfig(data.config()),
+                                           data.getPixels(),
+                                           data.rowBytes(),
+                                           GrContext::kDontFlush_PixelOpsFlag);
     }
 
     GrAssert(rowNumber >= 0);
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 0afbe57..2682eb2 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -109,7 +109,7 @@
             fBGRAIsInternalFormat = true;
         }
         GrAssert(fBGRAFormatSupport ||
-                 kSkia8888_PM_GrPixelConfig != kBGRA_8888_PM_GrPixelConfig);
+                 kSkia8888_GrPixelConfig != kBGRA_8888_GrPixelConfig);
     }
 
     if (kDesktop_GrGLBinding == binding) {
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index 8089d10..03462e7 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -335,18 +335,12 @@
     fConfigRenderSupport[kRGBA_4444_GrPixelConfig] = true;
 
     if (this->glCaps().rgba8RenderbufferSupport()) {
-        fConfigRenderSupport[kRGBA_8888_PM_GrPixelConfig] = true;
+        fConfigRenderSupport[kRGBA_8888_GrPixelConfig] = true;
     }
 
     if (this->glCaps().bgraFormatSupport()) {
-        fConfigRenderSupport[kBGRA_8888_PM_GrPixelConfig] = true;
+        fConfigRenderSupport[kBGRA_8888_GrPixelConfig] = true;
     }
-
-    // the un-premultiplied formats just inherit the premultiplied setting
-    fConfigRenderSupport[kRGBA_8888_UPM_GrPixelConfig] = 
-                fConfigRenderSupport[kRGBA_8888_PM_GrPixelConfig];
-    fConfigRenderSupport[kBGRA_8888_UPM_GrPixelConfig] = 
-                fConfigRenderSupport[kBGRA_8888_PM_GrPixelConfig];
 }
 
 bool GrGpuGL::canPreserveReadWriteUnpremulPixels() {
@@ -375,7 +369,7 @@
                          kNoStencil_GrTextureFlagBit;
         dstDesc.fWidth = 256;
         dstDesc.fHeight = 256;
-        dstDesc.fConfig = kRGBA_8888_PM_GrPixelConfig;
+        dstDesc.fConfig = kRGBA_8888_GrPixelConfig;
 
         SkAutoTUnref<GrTexture> dstTex(this->createTexture(dstDesc, NULL, 0));
         if (!dstTex.get()) {
@@ -397,16 +391,20 @@
             fUnpremulConversion = gMethods[i];
             rt->writePixels(0, 0,
                             256, 256,
-                            kRGBA_8888_UPM_GrPixelConfig, srcData, 0);
+                            kRGBA_8888_GrPixelConfig, srcData, 0,
+                            GrContext::kUnpremul_PixelOpsFlag);
             rt->readPixels(0, 0,
                            256, 256,
-                           kRGBA_8888_UPM_GrPixelConfig, firstRead, 0);
+                           kRGBA_8888_GrPixelConfig, firstRead, 0,
+                           GrContext::kUnpremul_PixelOpsFlag);
             rt->writePixels(0, 0,
                             256, 256,
-                            kRGBA_8888_UPM_GrPixelConfig, firstRead, 0);
+                            kRGBA_8888_GrPixelConfig, firstRead, 0,
+                            GrContext::kUnpremul_PixelOpsFlag);
             rt->readPixels(0, 0,
                            256, 256,
-                           kRGBA_8888_UPM_GrPixelConfig, secondRead, 0);
+                           kRGBA_8888_GrPixelConfig, secondRead, 0,
+                           GrContext::kUnpremul_PixelOpsFlag);
             failed = false;
             for (int j = 0; j < 256 * 256; ++j) {
                 if (firstRead[j] != secondRead[j]) {
@@ -1397,9 +1395,6 @@
     static const GrGLfloat scale255 = 1.f / 255.f;
     a = GrColorUnpackA(color) * scale255;
     GrGLfloat scaleRGB = scale255;
-    if (GrPixelConfigIsUnpremultiplied(rt->config())) {
-        scaleRGB *= a;
-    }
     r = GrColorUnpackR(color) * scaleRGB;
     g = GrColorUnpackG(color) * scaleRGB;
     b = GrColorUnpackB(color) * scaleRGB;
@@ -2321,8 +2316,7 @@
     }
 
     switch (config) {
-        case kRGBA_8888_PM_GrPixelConfig:
-        case kRGBA_8888_UPM_GrPixelConfig:
+        case kRGBA_8888_GrPixelConfig:
             *internalFormat = GR_GL_RGBA;
             *externalFormat = GR_GL_RGBA;
             if (getSizedInternalFormat) {
@@ -2332,8 +2326,7 @@
             }
             *externalType = GR_GL_UNSIGNED_BYTE;
             break;
-        case kBGRA_8888_PM_GrPixelConfig:
-        case kBGRA_8888_UPM_GrPixelConfig:
+        case kBGRA_8888_GrPixelConfig:
             if (!this->glCaps().bgraFormatSupport()) {
                 return false;
             }
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index c959f66..c1eb36e 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -733,7 +733,7 @@
                         stage.fInConfigFlags |= StageDesc::kSwapRAndB_InConfigFlag;
                     }
                 }
-                if (GrPixelConfigIsUnpremultiplied(texture->config())) {
+                if (sampler.premultiply()) {
                     // Assert that if we're doing a premul conversion that the texture is 1 byte
                     // per color component. The rounding performed by the shader generator (in
                     // normalized float color space) assumes this.
@@ -758,7 +758,7 @@
         }
     }
 
-    if (GrPixelConfigIsUnpremultiplied(drawState.getRenderTarget()->config())) {
+    if (drawState.isStateFlagEnabled(GrDrawState::kUnpremultiply_StageBit)) {
         // The shader generator assumes that color channels are bytes
         // when rounding.
         GrAssert(4 == GrBytesPerPixel(drawState.getRenderTarget()->config()));
diff --git a/tests/PremulAlphaRoundTripTest.cpp b/tests/PremulAlphaRoundTripTest.cpp
index a22ff5a..f2f1613 100644
--- a/tests/PremulAlphaRoundTripTest.cpp
+++ b/tests/PremulAlphaRoundTripTest.cpp
@@ -95,10 +95,11 @@
                 reinterpret_cast<uint32_t*>(readBmp1.getPixels());
             uint32_t* pixels2 =
                 reinterpret_cast<uint32_t*>(readBmp2.getPixels());
-            for (int y = 0; y < 256; ++y) {
-                for (int x = 0; x < 256; ++x) {
+            bool success = true;
+            for (int y = 0; y < 256 && success; ++y) {
+                for (int x = 0; x < 256 && success; ++x) {
                     int i = y * 256 + x;
-                    REPORTER_ASSERT(reporter, pixels1[i] == pixels2[i]);
+                    REPORTER_ASSERT(reporter, success = pixels1[i] == pixels2[i]);
                 }
             }
         }