Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / gpu / gl / GrGLCaps.cpp
index 17e7b69..f577e9d 100644 (file)
@@ -11,8 +11,6 @@
 #include "SkTSearch.h"
 #include "SkTSort.h"
 
-SK_DEFINE_INST_COUNT(GrGLCaps)
-
 GrGLCaps::GrGLCaps() {
     this->reset();
 }
@@ -25,6 +23,8 @@ void GrGLCaps::reset() {
     fStencilVerifiedColorConfigs.reset();
     fMSFBOType = kNone_MSFBOType;
     fFBFetchType = kNone_FBFetchType;
+    fInvalidateFBType = kNone_InvalidateFBType;
+    fMapBufferType = kNone_MapBufferType;
     fMaxFragmentUniformVectors = 0;
     fMaxVertexAttributes = 0;
     fMaxFragmentTextureUnits = 0;
@@ -46,16 +46,15 @@ void GrGLCaps::reset() {
     fVertexArrayObjectSupport = false;
     fUseNonVBOVertexAndIndexDynamicData = false;
     fIsCoreProfile = false;
-    fFixedFunctionSupport = false;
-    fDiscardFBSupport = false;
     fFullClearIsFree = false;
+    fDropsTileOnZeroDivide = false;
 }
 
 GrGLCaps::GrGLCaps(const GrGLCaps& caps) : GrDrawTargetCaps() {
     *this = caps;
 }
 
-GrGLCaps& GrGLCaps::operator = (const GrGLCaps& caps) {
+GrGLCaps& GrGLCaps::operator= (const GrGLCaps& caps) {
     INHERITED::operator=(caps);
     fVerifiedColorConfigs = caps.fVerifiedColorConfigs;
     fStencilFormats = caps.fStencilFormats;
@@ -66,6 +65,8 @@ GrGLCaps& GrGLCaps::operator = (const GrGLCaps& caps) {
     fMaxFixedFunctionTextureCoords = caps.fMaxFixedFunctionTextureCoords;
     fMSFBOType = caps.fMSFBOType;
     fFBFetchType = caps.fFBFetchType;
+    fInvalidateFBType = caps.fInvalidateFBType;
+    fMapBufferType = caps.fMapBufferType;
     fRGBA8RenderbufferSupport = caps.fRGBA8RenderbufferSupport;
     fBGRAFormatSupport = caps.fBGRAFormatSupport;
     fBGRAIsInternalFormat = caps.fBGRAIsInternalFormat;
@@ -83,32 +84,31 @@ GrGLCaps& GrGLCaps::operator = (const GrGLCaps& caps) {
     fVertexArrayObjectSupport = caps.fVertexArrayObjectSupport;
     fUseNonVBOVertexAndIndexDynamicData = caps.fUseNonVBOVertexAndIndexDynamicData;
     fIsCoreProfile = caps.fIsCoreProfile;
-    fFixedFunctionSupport = caps.fFixedFunctionSupport;
-    fDiscardFBSupport = caps.fDiscardFBSupport;
     fFullClearIsFree = caps.fFullClearIsFree;
+    fDropsTileOnZeroDivide = caps.fDropsTileOnZeroDivide;
 
     return *this;
 }
 
-void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
+bool GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
 
     this->reset();
     if (!ctxInfo.isInitialized()) {
-        return;
+        return false;
     }
 
-    GrGLBinding binding = ctxInfo.binding();
+    GrGLStandard standard = ctxInfo.standard();
     GrGLVersion version = ctxInfo.version();
 
     /**************************************************************************
      * Caps specific to GrGLCaps
      **************************************************************************/
 
-    if (kES_GrGLBinding == binding) {
+    if (kGLES_GrGLStandard == standard) {
         GR_GL_GetIntegerv(gli, GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS,
                           &fMaxFragmentUniformVectors);
     } else {
-        SkASSERT(kDesktop_GrGLBinding == binding);
+        SkASSERT(kGL_GrGLStandard == standard);
         GrGLint max;
         GR_GL_GetIntegerv(gli, GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max);
         fMaxFragmentUniformVectors = max / 4;
@@ -118,7 +118,6 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
             fIsCoreProfile = SkToBool(profileMask & GR_GL_CONTEXT_CORE_PROFILE_BIT);
         }
         if (!fIsCoreProfile) {
-            fFixedFunctionSupport = true;
             GR_GL_GetIntegerv(gli, GR_GL_MAX_TEXTURE_COORDS, &fMaxFixedFunctionTextureCoords);
             // Sanity check
             SkASSERT(fMaxFixedFunctionTextureCoords > 0 && fMaxFixedFunctionTextureCoords < 128);
@@ -127,7 +126,7 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
     GR_GL_GetIntegerv(gli, GR_GL_MAX_VERTEX_ATTRIBS, &fMaxVertexAttributes);
     GR_GL_GetIntegerv(gli, GR_GL_MAX_TEXTURE_IMAGE_UNITS, &fMaxFragmentTextureUnits);
 
-    if (kDesktop_GrGLBinding == binding) {
+    if (kGL_GrGLStandard == standard) {
         fRGBA8RenderbufferSupport = true;
     } else {
         fRGBA8RenderbufferSupport = version >= GR_GL_VER(3,0) ||
@@ -135,7 +134,7 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
                                     ctxInfo.hasExtension("GL_ARM_rgba8");
     }
 
-    if (kDesktop_GrGLBinding == binding) {
+    if (kGL_GrGLStandard == standard) {
         fBGRAFormatSupport = version >= GR_GL_VER(1,2) ||
                              ctxInfo.hasExtension("GL_EXT_bgra");
     } else {
@@ -149,14 +148,14 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
                  kSkia8888_GrPixelConfig != kBGRA_8888_GrPixelConfig);
     }
 
-    if (kDesktop_GrGLBinding == binding) {
+    if (kGL_GrGLStandard == standard) {
         fTextureSwizzleSupport = version >= GR_GL_VER(3,3) ||
                                  ctxInfo.hasExtension("GL_ARB_texture_swizzle");
     } else {
         fTextureSwizzleSupport = version >= GR_GL_VER(3,0);
     }
 
-    if (kDesktop_GrGLBinding == binding) {
+    if (kGL_GrGLStandard == standard) {
         fUnpackRowLengthSupport = true;
         fUnpackFlipYSupport = false;
         fPackRowLengthSupport = true;
@@ -171,10 +170,10 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
             ctxInfo.hasExtension("GL_ANGLE_pack_reverse_row_order");
     }
 
-    fTextureUsageSupport = (kES_GrGLBinding == binding) &&
+    fTextureUsageSupport = (kGLES_GrGLStandard == standard) &&
                             ctxInfo.hasExtension("GL_ANGLE_texture_usage");
 
-    if (kDesktop_GrGLBinding == binding) {
+    if (kGL_GrGLStandard == standard) {
         // The EXT version can apply to either GL or GLES.
         fTexStorageSupport = version >= GR_GL_VER(4,2) ||
                              ctxInfo.hasExtension("GL_ARB_texture_storage") ||
@@ -188,7 +187,7 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
 
     // ARB_texture_rg is part of OpenGL 3.0, but mesa doesn't support it if
     // it doesn't have ARB_texture_rg extension.
-    if (kDesktop_GrGLBinding == binding) {
+    if (kGL_GrGLStandard == standard) {
         if (ctxInfo.isMesa()) {
             fTextureRedSupport = ctxInfo.hasExtension("GL_ARB_texture_rg");
         } else {
@@ -200,13 +199,13 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
                               ctxInfo.hasExtension("GL_EXT_texture_rg");
     }
 
-    fImagingSupport = kDesktop_GrGLBinding == binding &&
+    fImagingSupport = kGL_GrGLStandard == standard &&
                       ctxInfo.hasExtension("GL_ARB_imaging");
 
     // ES 2 only guarantees RGBA/uchar + one other format/type combo for
     // ReadPixels. The other format has to checked at run-time since it
     // can change based on which render target is bound
-    fTwoFormatLimit = kES_GrGLBinding == binding;
+    fTwoFormatLimit = kGLES_GrGLStandard == standard;
 
     // Known issue on at least some Intel platforms:
     // http://code.google.com/p/skia/issues/detail?id=946
@@ -224,13 +223,21 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
         fUseNonVBOVertexAndIndexDynamicData = true;
     }
 
-    fDiscardFBSupport = ctxInfo.hasExtension("GL_EXT_discard_framebuffer");
+    if ((kGL_GrGLStandard == standard && version >= GR_GL_VER(4,3)) ||
+        (kGLES_GrGLStandard == standard && version >= GR_GL_VER(3,0)) ||
+        ctxInfo.hasExtension("GL_ARB_invalidate_subdata")) {
+        fDiscardRenderTargetSupport = true;
+        fInvalidateFBType = kInvalidate_InvalidateFBType;
+    } else if (ctxInfo.hasExtension("GL_EXT_discard_framebuffer")) {
+        fDiscardRenderTargetSupport = true;
+        fInvalidateFBType = kDiscard_InvalidateFBType;
+    }
 
     if (kARM_GrGLVendor == ctxInfo.vendor() || kImagination_GrGLVendor == ctxInfo.vendor()) {
         fFullClearIsFree = true;
     }
 
-    if (kDesktop_GrGLBinding == binding) {
+    if (kGL_GrGLStandard == standard) {
         fVertexArrayObjectSupport = version >= GR_GL_VER(3, 0) ||
                                     ctxInfo.hasExtension("GL_ARB_vertex_array_object");
     } else {
@@ -238,7 +245,7 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
                                     ctxInfo.hasExtension("GL_OES_vertex_array_object");
     }
 
-    if (kES_GrGLBinding == binding) {
+    if (kGLES_GrGLStandard == standard) {
         if (ctxInfo.hasExtension("GL_EXT_shader_framebuffer_fetch")) {
             fFBFetchType = kEXT_FBFetchType;
         } else if (ctxInfo.hasExtension("GL_NV_shader_framebuffer_fetch")) {
@@ -246,6 +253,9 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
         }
     }
 
+    // Adreno GPUs have a tendency to drop tiles when there is a divide-by-zero in a shader
+    fDropsTileOnZeroDivide = kQualcomm_GrGLVendor == ctxInfo.vendor();
+
     this->initFSAASupport(ctxInfo, gli);
     this->initStencilFormats(ctxInfo);
 
@@ -265,7 +275,7 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
         }
     }
 
-    if (kDesktop_GrGLBinding == binding) {
+    if (kGL_GrGLStandard == standard) {
         // we could also look for GL_ATI_separate_stencil extension or
         // GL_EXT_stencil_two_side but they use different function signatures
         // than GL2.0+ (and than each other).
@@ -279,37 +289,59 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
         fStencilWrapOpsSupport = true;
     }
 
-    if (kDesktop_GrGLBinding == binding) {
-        fBufferLockSupport = true; // we require VBO support and the desktop VBO extension includes
-                                   // glMapBuffer.
+    if (kGL_GrGLStandard == standard) {
+        fMapBufferFlags = kCanMap_MapFlag; // we require VBO support and the desktop VBO
+                                            // extension includes glMapBuffer.
+        if (version >= GR_GL_VER(3, 0) || ctxInfo.hasExtension("GL_ARB_map_buffer_range")) {
+            fMapBufferFlags |= kSubset_MapFlag;
+            fMapBufferType = kMapBufferRange_MapBufferType;
+        } else {
+            fMapBufferType = kMapBuffer_MapBufferType;
+        }
     } else {
-        fBufferLockSupport = ctxInfo.hasExtension("GL_OES_mapbuffer");
+        // Unextended GLES2 doesn't have any buffer mapping.
+        fMapBufferFlags = kNone_MapBufferType;
+        if (ctxInfo.hasExtension("GL_CHROMIUM_map_sub")) {
+            fMapBufferFlags = kCanMap_MapFlag | kSubset_MapFlag;
+            fMapBufferType = kChromium_MapBufferType;
+        } else if (version >= GR_GL_VER(3, 0) || ctxInfo.hasExtension("GL_EXT_map_buffer_range")) {
+            fMapBufferFlags = kCanMap_MapFlag | kSubset_MapFlag;
+            fMapBufferType = kMapBufferRange_MapBufferType;
+        } else if (ctxInfo.hasExtension("GL_OES_mapbuffer")) {
+            fMapBufferFlags = kCanMap_MapFlag;
+            fMapBufferType = kMapBuffer_MapBufferType;
+        }
     }
 
-    if (kDesktop_GrGLBinding == binding) {
-        if (ctxInfo.version() >= GR_GL_VER(2,0) ||
-            ctxInfo.hasExtension("GL_ARB_texture_non_power_of_two")) {
-            fNPOTTextureTileSupport = true;
-        } else {
-            fNPOTTextureTileSupport = false;
-        }
+    if (kGL_GrGLStandard == standard) {
+        SkASSERT(ctxInfo.version() >= GR_GL_VER(2,0) ||
+                 ctxInfo.hasExtension("GL_ARB_texture_non_power_of_two"));
+        fNPOTTextureTileSupport = true;
+        fMipMapSupport = true;
     } else {
         // Unextended ES2 supports NPOT textures with clamp_to_edge and non-mip filters only
         // ES3 has no limitations.
         fNPOTTextureTileSupport = ctxInfo.version() >= GR_GL_VER(3,0) ||
                                   ctxInfo.hasExtension("GL_OES_texture_npot");
+        // ES2 supports MIP mapping for POT textures but our caps don't allow for limited MIP
+        // support. The OES extension or ES 3.0 allow for MIPS on NPOT textures. So, apparently,
+        // does the undocumented GL_IMG_texture_npot extension. This extension does not seem to
+        // to alllow arbitrary wrap modes, however.
+        fMipMapSupport = fNPOTTextureTileSupport || ctxInfo.hasExtension("GL_IMG_texture_npot");
     }
 
-    fHWAALineSupport = (kDesktop_GrGLBinding == binding);
+    fHWAALineSupport = (kGL_GrGLStandard == standard);
 
     GR_GL_GetIntegerv(gli, GR_GL_MAX_TEXTURE_SIZE, &fMaxTextureSize);
     GR_GL_GetIntegerv(gli, GR_GL_MAX_RENDERBUFFER_SIZE, &fMaxRenderTargetSize);
     // Our render targets are always created with textures as the color
     // attachment, hence this min:
-    fMaxRenderTargetSize = GrMin(fMaxTextureSize, fMaxRenderTargetSize);
+    fMaxRenderTargetSize = SkTMin(fMaxTextureSize, fMaxRenderTargetSize);
 
-    fPathRenderingSupport = GR_GL_USE_NV_PATH_RENDERING &&
-                            ctxInfo.hasExtension("GL_NV_path_rendering");
+    fPathRenderingSupport = ctxInfo.hasExtension("GL_NV_path_rendering") &&
+        ctxInfo.hasExtension("GL_EXT_direct_state_access");
+
+    fGpuTracingSupport = ctxInfo.hasExtension("GL_EXT_debug_marker");
 
     fDstReadInShaderSupport = kNone_FBFetchType != fFBFetchType;
 
@@ -318,7 +350,7 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
                             kQualcomm_GrGLVendor != ctxInfo.vendor();
 
     // Enable supported shader-related caps
-    if (kDesktop_GrGLBinding == binding) {
+    if (kGL_GrGLStandard == standard) {
         fDualSourceBlendingSupport = ctxInfo.version() >= GR_GL_VER(3,3) ||
                                      ctxInfo.hasExtension("GL_ARB_blend_func_extended");
         fShaderDerivativeSupport = true;
@@ -336,6 +368,8 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
     }
 
     this->initConfigRenderableTable(ctxInfo);
+
+    return true;
 }
 
 void GrGLCaps::initConfigRenderableTable(const GrGLContextInfo& ctxInfo) {
@@ -373,7 +407,7 @@ void GrGLCaps::initConfigRenderableTable(const GrGLContextInfo& ctxInfo) {
         kYes_MSAA = 1,
     };
 
-    if (kDesktop_GrGLBinding == ctxInfo.binding()) {
+    if (kGL_GrGLStandard == ctxInfo.standard()) {
         // Post 3.0 we will get R8
         // Prior to 3.0 we will get ALPHA8 (with GL_ARB_framebuffer_object)
         if (ctxInfo.version() >= GR_GL_VER(3,0) ||
@@ -387,7 +421,7 @@ void GrGLCaps::initConfigRenderableTable(const GrGLContextInfo& ctxInfo) {
         fConfigRenderSupport[kAlpha_8_GrPixelConfig][kYes_MSAA] = fTextureRedSupport;
     }
 
-    if (kDesktop_GrGLBinding != ctxInfo.binding()) {
+    if (kGL_GrGLStandard != ctxInfo.standard()) {
         // only available in ES
         fConfigRenderSupport[kRGB_565_GrPixelConfig][kNo_MSAA] = true;
         fConfigRenderSupport[kRGB_565_GrPixelConfig][kYes_MSAA] = true;
@@ -407,7 +441,7 @@ void GrGLCaps::initConfigRenderableTable(const GrGLContextInfo& ctxInfo) {
         // The GL_EXT_texture_format_BGRA8888 extension does not add BGRA to the list of
         // configs that are color-renderable and can be passed to glRenderBufferStorageMultisample.
         // Chromium may have an extension to allow BGRA renderbuffers to work on desktop platforms.
-        if (ctxInfo.extensions().has("GL_CHROMIUM_renderbuffer_format_BGRA8888")) {
+        if (ctxInfo.hasExtension("GL_CHROMIUM_renderbuffer_format_BGRA8888")) {
             fConfigRenderSupport[kBGRA_8888_GrPixelConfig][kYes_MSAA] = true;
         } else {
             fConfigRenderSupport[kBGRA_8888_GrPixelConfig][kYes_MSAA] =
@@ -456,14 +490,14 @@ bool GrGLCaps::readPixelsSupported(const GrGLInterface* intf,
 void GrGLCaps::initFSAASupport(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
 
     fMSFBOType = kNone_MSFBOType;
-    if (kDesktop_GrGLBinding != ctxInfo.binding()) {
+    if (kGL_GrGLStandard != ctxInfo.standard()) {
         // We prefer the EXT/IMG extension over ES3 MSAA because we've observed
         // ES3 driver bugs on at least one device with a tiled GPU (N10).
         if (ctxInfo.hasExtension("GL_EXT_multisampled_render_to_texture")) {
             fMSFBOType = kES_EXT_MsToTexture_MSFBOType;
         } else if (ctxInfo.hasExtension("GL_IMG_multisampled_render_to_texture")) {
             fMSFBOType = kES_IMG_MsToTexture_MSFBOType;
-        } else if (!GR_GL_IGNORE_ES3_MSAA && ctxInfo.version() >= GR_GL_VER(3,0)) {
+        } else if (ctxInfo.version() >= GR_GL_VER(3,0)) {
             fMSFBOType = GrGLCaps::kES_3_0_MSFBOType;
         } else if (ctxInfo.hasExtension("GL_CHROMIUM_framebuffer_multisample")) {
             // chrome's extension is equivalent to the EXT msaa
@@ -504,7 +538,7 @@ void GrGLCaps::initStencilFormats(const GrGLContextInfo& ctxInfo) {
     //  gS     = {GR_GL_STENCIL_INDEX,    kUnknownBitCount, kUnknownBitCount, false},
         gDS    = {GR_GL_DEPTH_STENCIL,    kUnknownBitCount, kUnknownBitCount, true };
 
-    if (kDesktop_GrGLBinding == ctxInfo.binding()) {
+    if (kGL_GrGLStandard == ctxInfo.standard()) {
         bool supportsPackedDS =
             ctxInfo.version() >= GR_GL_VER(3,0) ||
             ctxInfo.hasExtension("GL_EXT_packed_depth_stencil") ||
@@ -560,7 +594,7 @@ void GrGLCaps::markColorConfigAndStencilFormatAsVerified(
             return;
         }
     }
-    GrCrash("Why are we seeing a stencil format that "
+    SkFAIL("Why are we seeing a stencil format that "
             "GrGLCaps doesn't know about.");
 }
 
@@ -581,18 +615,18 @@ bool GrGLCaps::isColorConfigAndStencilFormatVerified(
             return fStencilVerifiedColorConfigs[i].isVerified(config);
         }
     }
-    GrCrash("Why are we seeing a stencil format that "
+    SkFAIL("Why are we seeing a stencil format that "
             "GLCaps doesn't know about.");
     return false;
 }
 
-void GrGLCaps::print() const {
+SkString GrGLCaps::dump() const {
 
-    INHERITED::print();
+    SkString r = INHERITED::dump();
 
-    GrPrintf("--- GL-Specific ---\n");
+    r.appendf("--- GL-Specific ---\n");
     for (int i = 0; i < fStencilFormats.count(); ++i) {
-        GrPrintf("Stencil Format %d, stencil bits: %02d, total bits: %02d\n",
+        r.appendf("Stencil Format %d, stencil bits: %02d, total bits: %02d\n",
                  i,
                  fStencilFormats[i].fStencilBits,
                  fStencilFormats[i].fTotalBits);
@@ -614,7 +648,7 @@ void GrGLCaps::print() const {
     GR_STATIC_ASSERT(4 == kES_Apple_MSFBOType);
     GR_STATIC_ASSERT(5 == kES_IMG_MsToTexture_MSFBOType);
     GR_STATIC_ASSERT(6 == kES_EXT_MsToTexture_MSFBOType);
-    GR_STATIC_ASSERT(GR_ARRAY_COUNT(kMSFBOExtStr) == kLast_MSFBOType + 1);
+    GR_STATIC_ASSERT(SK_ARRAY_COUNT(kMSFBOExtStr) == kLast_MSFBOType + 1);
 
     static const char* kFBFetchTypeStr[] = {
         "None",
@@ -624,38 +658,61 @@ void GrGLCaps::print() const {
     GR_STATIC_ASSERT(0 == kNone_FBFetchType);
     GR_STATIC_ASSERT(1 == kEXT_FBFetchType);
     GR_STATIC_ASSERT(2 == kNV_FBFetchType);
-    GR_STATIC_ASSERT(GR_ARRAY_COUNT(kFBFetchTypeStr) == kLast_FBFetchType + 1);
-
-
-    GrPrintf("Core Profile: %s\n", (fIsCoreProfile ? "YES" : "NO"));
-    GrPrintf("Fixed Function Support: %s\n", (fFixedFunctionSupport ? "YES" : "NO"));
-    GrPrintf("MSAA Type: %s\n", kMSFBOExtStr[fMSFBOType]);
-    GrPrintf("FB Fetch Type: %s\n", kFBFetchTypeStr[fFBFetchType]);
-    GrPrintf("Max FS Uniform Vectors: %d\n", fMaxFragmentUniformVectors);
-    GrPrintf("Max FS Texture Units: %d\n", fMaxFragmentTextureUnits);
-    if (fFixedFunctionSupport) {
-        GrPrintf("Max Fixed Function Texture Coords: %d\n", fMaxFixedFunctionTextureCoords);
-    }
-    GrPrintf("Max Vertex Attributes: %d\n", fMaxVertexAttributes);
-    GrPrintf("Support RGBA8 Render Buffer: %s\n", (fRGBA8RenderbufferSupport ? "YES": "NO"));
-    GrPrintf("BGRA support: %s\n", (fBGRAFormatSupport ? "YES": "NO"));
-    GrPrintf("BGRA is an internal format: %s\n", (fBGRAIsInternalFormat ? "YES": "NO"));
-    GrPrintf("Support texture swizzle: %s\n", (fTextureSwizzleSupport ? "YES": "NO"));
-    GrPrintf("Unpack Row length support: %s\n", (fUnpackRowLengthSupport ? "YES": "NO"));
-    GrPrintf("Unpack Flip Y support: %s\n", (fUnpackFlipYSupport ? "YES": "NO"));
-    GrPrintf("Pack Row length support: %s\n", (fPackRowLengthSupport ? "YES": "NO"));
-    GrPrintf("Pack Flip Y support: %s\n", (fPackFlipYSupport ? "YES": "NO"));
-
-    GrPrintf("Texture Usage support: %s\n", (fTextureUsageSupport ? "YES": "NO"));
-    GrPrintf("Texture Storage support: %s\n", (fTexStorageSupport ? "YES": "NO"));
-    GrPrintf("GL_R support: %s\n", (fTextureRedSupport ? "YES": "NO"));
-    GrPrintf("GL_ARB_imaging support: %s\n", (fImagingSupport ? "YES": "NO"));
-    GrPrintf("Two Format Limit: %s\n", (fTwoFormatLimit ? "YES": "NO"));
-    GrPrintf("Fragment coord conventions support: %s\n",
+    GR_STATIC_ASSERT(SK_ARRAY_COUNT(kFBFetchTypeStr) == kLast_FBFetchType + 1);
+
+    static const char* kInvalidateFBTypeStr[] = {
+        "None",
+        "Discard",
+        "Invalidate",
+    };
+    GR_STATIC_ASSERT(0 == kNone_InvalidateFBType);
+    GR_STATIC_ASSERT(1 == kDiscard_InvalidateFBType);
+    GR_STATIC_ASSERT(2 == kInvalidate_InvalidateFBType);
+    GR_STATIC_ASSERT(SK_ARRAY_COUNT(kInvalidateFBTypeStr) == kLast_InvalidateFBType + 1);
+
+    static const char* kMapBufferTypeStr[] = {
+        "None",
+        "MapBuffer",
+        "MapBufferRange",
+        "Chromium",
+    };
+    GR_STATIC_ASSERT(0 == kNone_MapBufferType);
+    GR_STATIC_ASSERT(1 == kMapBuffer_MapBufferType);
+    GR_STATIC_ASSERT(2 == kMapBufferRange_MapBufferType);
+    GR_STATIC_ASSERT(3 == kChromium_MapBufferType);
+    GR_STATIC_ASSERT(SK_ARRAY_COUNT(kMapBufferTypeStr) == kLast_MapBufferType + 1);
+
+    r.appendf("Core Profile: %s\n", (fIsCoreProfile ? "YES" : "NO"));
+    r.appendf("MSAA Type: %s\n", kMSFBOExtStr[fMSFBOType]);
+    r.appendf("FB Fetch Type: %s\n", kFBFetchTypeStr[fFBFetchType]);
+    r.appendf("Invalidate FB Type: %s\n", kInvalidateFBTypeStr[fInvalidateFBType]);
+    r.appendf("Map Buffer Type: %s\n", kMapBufferTypeStr[fMapBufferType]);
+    r.appendf("Max FS Uniform Vectors: %d\n", fMaxFragmentUniformVectors);
+    r.appendf("Max FS Texture Units: %d\n", fMaxFragmentTextureUnits);
+    if (!fIsCoreProfile) {
+        r.appendf("Max Fixed Function Texture Coords: %d\n", fMaxFixedFunctionTextureCoords);
+    }
+    r.appendf("Max Vertex Attributes: %d\n", fMaxVertexAttributes);
+    r.appendf("Support RGBA8 Render Buffer: %s\n", (fRGBA8RenderbufferSupport ? "YES": "NO"));
+    r.appendf("BGRA support: %s\n", (fBGRAFormatSupport ? "YES": "NO"));
+    r.appendf("BGRA is an internal format: %s\n", (fBGRAIsInternalFormat ? "YES": "NO"));
+    r.appendf("Support texture swizzle: %s\n", (fTextureSwizzleSupport ? "YES": "NO"));
+    r.appendf("Unpack Row length support: %s\n", (fUnpackRowLengthSupport ? "YES": "NO"));
+    r.appendf("Unpack Flip Y support: %s\n", (fUnpackFlipYSupport ? "YES": "NO"));
+    r.appendf("Pack Row length support: %s\n", (fPackRowLengthSupport ? "YES": "NO"));
+    r.appendf("Pack Flip Y support: %s\n", (fPackFlipYSupport ? "YES": "NO"));
+
+    r.appendf("Texture Usage support: %s\n", (fTextureUsageSupport ? "YES": "NO"));
+    r.appendf("Texture Storage support: %s\n", (fTexStorageSupport ? "YES": "NO"));
+    r.appendf("GL_R support: %s\n", (fTextureRedSupport ? "YES": "NO"));
+    r.appendf("GL_ARB_imaging support: %s\n", (fImagingSupport ? "YES": "NO"));
+    r.appendf("Two Format Limit: %s\n", (fTwoFormatLimit ? "YES": "NO"));
+    r.appendf("Fragment coord conventions support: %s\n",
              (fFragCoordsConventionSupport ? "YES": "NO"));
-    GrPrintf("Vertex array object support: %s\n", (fVertexArrayObjectSupport ? "YES": "NO"));
-    GrPrintf("Use non-VBO for dynamic data: %s\n",
+    r.appendf("Vertex array object support: %s\n", (fVertexArrayObjectSupport ? "YES": "NO"));
+    r.appendf("Use non-VBO for dynamic data: %s\n",
              (fUseNonVBOVertexAndIndexDynamicData ? "YES" : "NO"));
-    GrPrintf("Discard FrameBuffer support: %s\n", (fDiscardFBSupport ? "YES" : "NO"));
-    GrPrintf("Full screen clear is free: %s\n", (fFullClearIsFree ? "YES" : "NO"));
+    r.appendf("Full screen clear is free: %s\n", (fFullClearIsFree ? "YES" : "NO"));
+    r.appendf("Drops tile on zero divide: %s\n", (fDropsTileOnZeroDivide ? "YES" : "NO"));
+    return r;
 }