Add sRGB texture support.

Review URL: https://codereview.chromium.org/791823003
diff --git a/include/core/SkBitmap.h b/include/core/SkBitmap.h
index 7b3cce5..ec0bffc 100644
--- a/include/core/SkBitmap.h
+++ b/include/core/SkBitmap.h
@@ -72,6 +72,7 @@
     int height() const { return fInfo.height(); }
     SkColorType colorType() const { return fInfo.colorType(); }
     SkAlphaType alphaType() const { return fInfo.alphaType(); }
+    SkColorProfileType profileType() const { return fInfo.profileType(); }
 
     /**
      *  Return the number of bytes per pixel based on the colortype. If the colortype is
diff --git a/include/core/SkPixelRef.h b/include/core/SkPixelRef.h
index 275c1f2..109d3c9 100644
--- a/include/core/SkPixelRef.h
+++ b/include/core/SkPixelRef.h
@@ -253,13 +253,14 @@
     /**
      *  Makes a deep copy of this PixelRef, respecting the requested config.
      *  @param colorType Desired colortype.
+     *  @param profileType Desired colorprofiletype.
      *  @param subset Subset of this PixelRef to copy. Must be fully contained within the bounds of
      *         of this PixelRef.
      *  @return A new SkPixelRef, or NULL if either there is an error (e.g. the destination could
      *          not be created with the given config), or this PixelRef does not support deep
      *          copies.
      */
-    virtual SkPixelRef* deepCopy(SkColorType, const SkIRect* /*subset*/) {
+    virtual SkPixelRef* deepCopy(SkColorType, SkColorProfileType, const SkIRect* /*subset*/) {
         return NULL;
     }
 
diff --git a/include/gpu/GrColor.h b/include/gpu/GrColor.h
index 820b915..860d18d 100644
--- a/include/gpu/GrColor.h
+++ b/include/gpu/GrColor.h
@@ -166,6 +166,7 @@
         kRGBA_GrColorComponentFlags,    // kRGBA_4444_GrPixelConfig
         kRGBA_GrColorComponentFlags,    // kRGBA_8888_GrPixelConfig
         kRGBA_GrColorComponentFlags,    // kBGRA_8888_GrPixelConfig
+        kRGBA_GrColorComponentFlags,    // kSRGBA_8888_GrPixelConfig
         kRGB_GrColorComponentFlags,     // kETC1_GrPixelConfig
         kA_GrColorComponentFlag,        // kLATC_GrPixelConfig
         kA_GrColorComponentFlag,        // kR11_EAC_GrPixelConfig
@@ -182,12 +183,13 @@
     GR_STATIC_ASSERT(4  == kRGBA_4444_GrPixelConfig);
     GR_STATIC_ASSERT(5  == kRGBA_8888_GrPixelConfig);
     GR_STATIC_ASSERT(6  == kBGRA_8888_GrPixelConfig);
-    GR_STATIC_ASSERT(7  == kETC1_GrPixelConfig);
-    GR_STATIC_ASSERT(8  == kLATC_GrPixelConfig);
-    GR_STATIC_ASSERT(9  == kR11_EAC_GrPixelConfig);
-    GR_STATIC_ASSERT(10 == kASTC_12x12_GrPixelConfig);
-    GR_STATIC_ASSERT(11 == kRGBA_float_GrPixelConfig);
-    GR_STATIC_ASSERT(12 == kAlpha_half_GrPixelConfig);
+    GR_STATIC_ASSERT(7  == kSRGBA_8888_GrPixelConfig);
+    GR_STATIC_ASSERT(8  == kETC1_GrPixelConfig);
+    GR_STATIC_ASSERT(9  == kLATC_GrPixelConfig);
+    GR_STATIC_ASSERT(10  == kR11_EAC_GrPixelConfig);
+    GR_STATIC_ASSERT(11 == kASTC_12x12_GrPixelConfig);
+    GR_STATIC_ASSERT(12 == kRGBA_float_GrPixelConfig);
+    GR_STATIC_ASSERT(13 == kAlpha_half_GrPixelConfig);
     GR_STATIC_ASSERT(SK_ARRAY_COUNT(kFlags) == kGrPixelConfigCnt);
 }
 
diff --git a/include/gpu/GrTypes.h b/include/gpu/GrTypes.h
index 434d929..c4e374f 100644
--- a/include/gpu/GrTypes.h
+++ b/include/gpu/GrTypes.h
@@ -232,6 +232,10 @@
      */
     kBGRA_8888_GrPixelConfig,
     /**
+     * Premultiplied and sRGB. Byte order is r,g,b,a.
+     */
+    kSRGBA_8888_GrPixelConfig,
+    /**
      * ETC1 Compressed Data
      */
     kETC1_GrPixelConfig,
@@ -303,6 +307,7 @@
     switch (config) {
         case kRGBA_8888_GrPixelConfig:
         case kBGRA_8888_GrPixelConfig:
+        case kSRGBA_8888_GrPixelConfig:
             return true;
         default:
             return false;
@@ -333,6 +338,7 @@
             return 2;
         case kRGBA_8888_GrPixelConfig:
         case kBGRA_8888_GrPixelConfig:
+        case kSRGBA_8888_GrPixelConfig:
             return 4;
         case kRGBA_float_GrPixelConfig:
             return 16;
@@ -352,6 +358,7 @@
             return 2;
         case kRGBA_8888_GrPixelConfig:
         case kBGRA_8888_GrPixelConfig:
+        case kSRGBA_8888_GrPixelConfig:
         case kRGBA_float_GrPixelConfig:
             return 4;
         default:
diff --git a/include/gpu/SkGr.h b/include/gpu/SkGr.h
index 7aacea4..06239e6 100644
--- a/include/gpu/SkGr.h
+++ b/include/gpu/SkGr.h
@@ -44,13 +44,13 @@
 
 #include "SkColorPriv.h"
 
-GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType, SkAlphaType);
+GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType, SkAlphaType, SkColorProfileType);
 
 static inline GrPixelConfig SkImageInfo2GrPixelConfig(const SkImageInfo& info) {
-    return SkImageInfo2GrPixelConfig(info.colorType(), info.alphaType());
+    return SkImageInfo2GrPixelConfig(info.colorType(), info.alphaType(), info.profileType());
 }
 
-bool GrPixelConfig2ColorType(GrPixelConfig, SkColorType*);
+bool GrPixelConfig2ColorAndProfileType(GrPixelConfig, SkColorType*, SkColorProfileType*);
 
 static inline GrColor SkColor2GrColor(SkColor c) {
     SkPMColor pm = SkPreMultiplyColor(c);
diff --git a/include/gpu/SkGrPixelRef.h b/include/gpu/SkGrPixelRef.h
index 9a81be6..96125ba 100644
--- a/include/gpu/SkGrPixelRef.h
+++ b/include/gpu/SkGrPixelRef.h
@@ -52,7 +52,8 @@
 protected:
     // overrides from SkPixelRef
     virtual bool onReadPixels(SkBitmap* dst, const SkIRect* subset) SK_OVERRIDE;
-    virtual SkPixelRef* deepCopy(SkColorType, const SkIRect* subset) SK_OVERRIDE;
+    virtual SkPixelRef* deepCopy(SkColorType, SkColorProfileType,
+                                 const SkIRect* subset) SK_OVERRIDE;
 
 private:
     GrSurface*  fSurface;
diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp
index 3d2aa7c..29b7d11 100644
--- a/samplecode/SampleApp.cpp
+++ b/samplecode/SampleApp.cpp
@@ -301,7 +301,8 @@
                 const SkBitmap& bm = win->getBitmap();
                 fCurRenderTarget->writePixels(0, 0, bm.width(), bm.height(),
                                              SkImageInfo2GrPixelConfig(bm.colorType(),
-                                                                       bm.alphaType()),
+                                                                       bm.alphaType(),
+                                                                       bm.profileType()),
                                              bm.getPixels(),
                                              bm.rowBytes(),
                                              GrContext::kFlushWrites_PixelOp);
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp
index c1add1f..9db596d 100644
--- a/src/core/SkBitmap.cpp
+++ b/src/core/SkBitmap.cpp
@@ -765,7 +765,7 @@
 
     if (fPixelRef->getTexture() != NULL) {
         // Do a deep copy
-        SkPixelRef* pixelRef = fPixelRef->deepCopy(this->colorType(), &subset);
+        SkPixelRef* pixelRef = fPixelRef->deepCopy(this->colorType(), this->profileType(), &subset);
         if (pixelRef != NULL) {
             SkBitmap dst;
             dst.setInfo(SkImageInfo::Make(subset.width(), subset.height(),
@@ -976,6 +976,7 @@
 
 bool SkBitmap::deepCopyTo(SkBitmap* dst) const {
     const SkColorType dstCT = this->colorType();
+    const SkColorProfileType dstPT = this->profileType();
 
     if (!this->canCopyTo(dstCT)) {
         return false;
@@ -984,10 +985,10 @@
     // If we have a PixelRef, and it supports deep copy, use it.
     // Currently supported only by texture-backed bitmaps.
     if (fPixelRef) {
-        SkPixelRef* pixelRef = fPixelRef->deepCopy(dstCT, NULL);
+        SkPixelRef* pixelRef = fPixelRef->deepCopy(dstCT, dstPT, NULL);
         if (pixelRef) {
             uint32_t rowBytes;
-            if (this->colorType() == dstCT) {
+            if (this->colorType() == dstCT && this->profileType() == dstPT) {
                 // Since there is no subset to pass to deepCopy, and deepCopy
                 // succeeded, the new pixel ref must be identical.
                 SkASSERT(fPixelRef->info() == pixelRef->info());
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index cc6a637..c637101 100755
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -1222,7 +1222,7 @@
 bool sw_convert_to_premul(GrPixelConfig srcConfig, int width, int height, size_t inRowBytes,
                           const void* inPixels, size_t outRowBytes, void* outPixels) {
     SkSrcPixelInfo srcPI;
-    if (!GrPixelConfig2ColorType(srcConfig, &srcPI.fColorType)) {
+    if (!GrPixelConfig2ColorAndProfileType(srcConfig, &srcPI.fColorType, NULL)) {
         return false;
     }
     srcPI.fAlphaType = kUnpremul_SkAlphaType;
@@ -1483,7 +1483,7 @@
     // Perform any conversions we weren't able to perform using a scratch texture.
     if (unpremul || swapRAndB) {
         SkDstPixelInfo dstPI;
-        if (!GrPixelConfig2ColorType(dstConfig, &dstPI.fColorType)) {
+        if (!GrPixelConfig2ColorAndProfileType(dstConfig, &dstPI.fColorType, NULL)) {
             return false;
         }
         dstPI.fAlphaType = kUnpremul_SkAlphaType;
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index 9ba9265..18ea72c 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -1139,6 +1139,7 @@
         "RGBA444",  // kRGBA_4444_GrPixelConfig,
         "RGBA8888", // kRGBA_8888_GrPixelConfig,
         "BGRA8888", // kBGRA_8888_GrPixelConfig,
+        "SRGBA8888",// kSRGBA_8888_GrPixelConfig,
         "ETC1",     // kETC1_GrPixelConfig,
         "LATC",     // kLATC_GrPixelConfig,
         "R11EAC",   // kR11_EAC_GrPixelConfig,
@@ -1153,12 +1154,13 @@
     GR_STATIC_ASSERT(4  == kRGBA_4444_GrPixelConfig);
     GR_STATIC_ASSERT(5  == kRGBA_8888_GrPixelConfig);
     GR_STATIC_ASSERT(6  == kBGRA_8888_GrPixelConfig);
-    GR_STATIC_ASSERT(7  == kETC1_GrPixelConfig);
-    GR_STATIC_ASSERT(8  == kLATC_GrPixelConfig);
-    GR_STATIC_ASSERT(9  == kR11_EAC_GrPixelConfig);
-    GR_STATIC_ASSERT(10 == kASTC_12x12_GrPixelConfig);
-    GR_STATIC_ASSERT(11 == kRGBA_float_GrPixelConfig);
-    GR_STATIC_ASSERT(12 == kAlpha_half_GrPixelConfig);
+    GR_STATIC_ASSERT(7  == kSRGBA_8888_GrPixelConfig);
+    GR_STATIC_ASSERT(8  == kETC1_GrPixelConfig);
+    GR_STATIC_ASSERT(9  == kLATC_GrPixelConfig);
+    GR_STATIC_ASSERT(10  == kR11_EAC_GrPixelConfig);
+    GR_STATIC_ASSERT(11 == kASTC_12x12_GrPixelConfig);
+    GR_STATIC_ASSERT(12 == kRGBA_float_GrPixelConfig);
+    GR_STATIC_ASSERT(13 == kAlpha_half_GrPixelConfig);
     GR_STATIC_ASSERT(SK_ARRAY_COUNT(kConfigNames) == kGrPixelConfigCnt);
 
     SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][0]);
diff --git a/src/gpu/GrSurface.cpp b/src/gpu/GrSurface.cpp
index 1ca305b..678755a 100644
--- a/src/gpu/GrSurface.cpp
+++ b/src/gpu/GrSurface.cpp
@@ -43,10 +43,12 @@
 
 SkImageInfo GrSurface::info() const {
     SkColorType colorType;
-    if (!GrPixelConfig2ColorType(this->config(), &colorType)) {
+    SkColorProfileType profileType;
+    if (!GrPixelConfig2ColorAndProfileType(this->config(), &colorType, &profileType)) {
         sk_throw();
     }
-    return SkImageInfo::Make(this->width(), this->height(), colorType, kPremul_SkAlphaType);
+    return SkImageInfo::Make(this->width(), this->height(), colorType, kPremul_SkAlphaType,
+                             profileType);
 }
 
 // TODO: This should probably be a non-member helper function. It might only be needed in
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index ff74fe9..4a2b90e 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -426,7 +426,7 @@
 
 // alphatype is ignore for now, but if GrPixelConfig is expanded to encompass
 // alpha info, that will be considered.
-GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType ct, SkAlphaType) {
+GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType ct, SkAlphaType, SkColorProfileType pt) {
     switch (ct) {
         case kUnknown_SkColorType:
             return kUnknown_GrPixelConfig;
@@ -437,6 +437,9 @@
         case kARGB_4444_SkColorType:
             return kRGBA_4444_GrPixelConfig;
         case kRGBA_8888_SkColorType:
+            if (kSRGB_SkColorProfileType == pt) {
+                return kSRGBA_8888_GrPixelConfig;
+            }
             return kRGBA_8888_GrPixelConfig;
         case kBGRA_8888_SkColorType:
             return kBGRA_8888_GrPixelConfig;
@@ -447,8 +450,10 @@
     return kUnknown_GrPixelConfig;
 }
 
-bool GrPixelConfig2ColorType(GrPixelConfig config, SkColorType* ctOut) {
+bool GrPixelConfig2ColorAndProfileType(GrPixelConfig config, SkColorType* ctOut,
+                                       SkColorProfileType* ptOut) {
     SkColorType ct;
+    SkColorProfileType pt = kLinear_SkColorProfileType;
     switch (config) {
         case kAlpha_8_GrPixelConfig:
             ct = kAlpha_8_SkColorType;
@@ -468,12 +473,19 @@
         case kBGRA_8888_GrPixelConfig:
             ct = kBGRA_8888_SkColorType;
             break;
+        case kSRGBA_8888_GrPixelConfig:
+            ct = kRGBA_8888_SkColorType;
+            pt = kSRGB_SkColorProfileType;
+            break;
         default:
             return false;
     }
     if (ctOut) {
         *ctOut = ct;
     }
+    if (ptOut) {
+        *ptOut = pt;
+    }
     return true;
 }
 
diff --git a/src/gpu/SkGrPixelRef.cpp b/src/gpu/SkGrPixelRef.cpp
index 1784d55..f752bf0 100644
--- a/src/gpu/SkGrPixelRef.cpp
+++ b/src/gpu/SkGrPixelRef.cpp
@@ -54,7 +54,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 static SkGrPixelRef* copy_to_new_texture_pixelref(GrTexture* texture, SkColorType dstCT,
-                                                  const SkIRect* subset) {
+                                                  SkColorProfileType dstPT, const SkIRect* subset) {
     if (NULL == texture || kUnknown_SkColorType == dstCT) {
         return NULL;
     }
@@ -78,7 +78,7 @@
         srcRect = *subset;
     }
     desc.fFlags = kRenderTarget_GrSurfaceFlag | kNoStencil_GrSurfaceFlag;
-    desc.fConfig = SkImageInfo2GrPixelConfig(dstCT, kPremul_SkAlphaType);
+    desc.fConfig = SkImageInfo2GrPixelConfig(dstCT, kPremul_SkAlphaType, dstPT);
 
     GrTexture* dst = context->createUncachedTexture(desc, NULL, 0);
     if (NULL == dst) {
@@ -91,7 +91,8 @@
     context->copySurface(dst->asRenderTarget(), texture, srcRect, SkIPoint::Make(0,0),
                          GrContext::kFlushWrites_PixelOp);
   
-    SkImageInfo info = SkImageInfo::Make(desc.fWidth, desc.fHeight, dstCT, kPremul_SkAlphaType);
+    SkImageInfo info = SkImageInfo::Make(desc.fWidth, desc.fHeight, dstCT, kPremul_SkAlphaType,
+                                         dstPT);
     SkGrPixelRef* pixelRef = SkNEW_ARGS(SkGrPixelRef, (info, dst));
     SkSafeUnref(dst);
     return pixelRef;
@@ -125,7 +126,8 @@
     return NULL;
 }
 
-SkPixelRef* SkGrPixelRef::deepCopy(SkColorType dstCT, const SkIRect* subset) {
+SkPixelRef* SkGrPixelRef::deepCopy(SkColorType dstCT, SkColorProfileType dstPT,
+                                   const SkIRect* subset) {
     if (NULL == fSurface) {
         return NULL;
     }
@@ -136,7 +138,7 @@
     // a GrTexture owned elsewhere (e.g., SkGpuDevice), and cannot live
     // independently of that texture.  Texture-backed pixel refs, on the other
     // hand, own their GrTextures, and are thus self-contained.
-    return copy_to_new_texture_pixelref(fSurface->asTexture(), dstCT, subset);
+    return copy_to_new_texture_pixelref(fSurface->asTexture(), dstCT, dstPT, subset);
 }
 
 static bool tryAllocBitmapPixels(SkBitmap* bitmap) {
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index cfb9558..b729820 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -478,6 +478,23 @@
         }
     }
 
+    if (this->fRGBA8RenderbufferSupport && this->isConfigTexturable(kSRGBA_8888_GrPixelConfig)) {
+        if (kGL_GrGLStandard == standard) {
+            if (ctxInfo.version() >= GR_GL_VER(3,0) ||
+                ctxInfo.hasExtension("GL_ARB_framebuffer_sRGB") ||
+                ctxInfo.hasExtension("GL_EXT_framebuffer_sRGB")) {
+                fConfigRenderSupport[kSRGBA_8888_GrPixelConfig][kNo_MSAA] = true;
+                fConfigRenderSupport[kSRGBA_8888_GrPixelConfig][kYes_MSAA] = true;
+            }
+        } else {
+            if (ctxInfo.version() >= GR_GL_VER(3,0) ||
+                ctxInfo.hasExtension("GL_EXT_sRGB")) {
+                fConfigRenderSupport[kSRGBA_8888_GrPixelConfig][kNo_MSAA] = true;
+                fConfigRenderSupport[kSRGBA_8888_GrPixelConfig][kYes_MSAA] = true;
+            }
+        }
+    }
+    
     if (this->isConfigTexturable(kRGBA_float_GrPixelConfig)) {
         if (kGL_GrGLStandard == standard) {
             fConfigRenderSupport[kRGBA_float_GrPixelConfig][kNo_MSAA] = true;
@@ -560,6 +577,15 @@
                  kSkia8888_GrPixelConfig != kBGRA_8888_GrPixelConfig);
     }
 
+    // Check for sRGBA
+    if (kGL_GrGLStandard == standard) {
+        fConfigTextureSupport[kSRGBA_8888_GrPixelConfig] =
+            (version >= GR_GL_VER(3,0) || ctxInfo.hasExtension("GL_EXT_texture_sRGB"));
+    } else {
+        fConfigTextureSupport[kSRGBA_8888_GrPixelConfig] =
+            (version >= GR_GL_VER(3,0) || ctxInfo.hasExtension("GL_EXT_sRGB"));
+    }
+    
     // Compressed texture support
 
     // glCompressedTexImage2D is available on all OpenGL ES devices...
diff --git a/src/gpu/gl/GrGLDefines.h b/src/gpu/gl/GrGLDefines.h
index 0eb5149..fc44252 100644
--- a/src/gpu/gl/GrGLDefines.h
+++ b/src/gpu/gl/GrGLDefines.h
@@ -770,6 +770,8 @@
 #define GR_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL         0x8CD2
 #define GR_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
 #define GR_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER         0x8CD4
+#define GR_GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING        0x8210
+#define GR_GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE        0x8211
 #define GR_GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE              0x8212
 #define GR_GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE            0x8213
 #define GR_GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE             0x8214
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index b36e887..96af8af 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -2310,6 +2310,16 @@
             *externalFormat = GR_GL_BGRA;
             *externalType = GR_GL_UNSIGNED_BYTE;
             break;
+        case kSRGBA_8888_GrPixelConfig:
+            *internalFormat = GR_GL_SRGB_ALPHA;
+            *externalFormat = GR_GL_SRGB_ALPHA;
+            if (getSizedInternalFormat) {
+                *internalFormat = GR_GL_SRGB8_ALPHA8;
+            } else {
+                *internalFormat = GR_GL_SRGB_ALPHA;
+            }
+            *externalType = GR_GL_UNSIGNED_BYTE;
+            break;
         case kRGB_565_GrPixelConfig:
             *internalFormat = GR_GL_RGB;
             *externalFormat = GR_GL_RGB;