text: /*
   * Copyright 2015 Google Inc.
   *
   * Use of this source code is governed by a BSD-style license that can be
   * found in the LICENSE file.
   */
  
  #include "GrCaps.h"
  #include "GrContextOptions.h"
  #include "GrWindowRectangles.h"
  
  static const char* pixel_config_name(GrPixelConfig config) {
      switch (config) {
          case kUnknown_GrPixelConfig: return "Unknown";
          case kAlpha_8_GrPixelConfig: return "Alpha8";
          case kGray_8_GrPixelConfig: return "Gray8";
          case kRGB_565_GrPixelConfig: return "RGB565";
          case kRGBA_4444_GrPixelConfig: return "RGBA444";
          case kRGBA_8888_GrPixelConfig: return "RGBA8888";
          case kBGRA_8888_GrPixelConfig: return "BGRA8888";
          case kSRGBA_8888_GrPixelConfig: return "SRGBA8888";
          case kSBGRA_8888_GrPixelConfig: return "SBGRA8888";
          case kRGBA_8888_sint_GrPixelConfig: return "RGBA8888_sint";
          case kRGBA_float_GrPixelConfig: return "RGBAFloat";
          case kRG_float_GrPixelConfig: return "RGFloat";
          case kAlpha_half_GrPixelConfig: return "AlphaHalf";
          case kRGBA_half_GrPixelConfig: return "RGBAHalf";
      }
      SkFAIL("Invalid pixel config");
      return "<invalid>";
  }
  
  GrCaps::GrCaps(const GrContextOptions& options) {
      fMipMapSupport = false;
      fNPOTTextureTileSupport = false;
      fSRGBSupport = false;
      fSRGBWriteControl = false;
      fDiscardRenderTargetSupport = false;
      fReuseScratchTextures = true;
      fReuseScratchBuffers = true;
      fGpuTracingSupport = false;
      fOversizedStencilSupport = false;
      fTextureBarrierSupport = false;
      fSampleLocationsSupport = false;
      fMultisampleDisableSupport = false;
      fInstanceAttribSupport = false;
      fUsesMixedSamples = false;
      fPreferClientSideDynamicBuffers = false;
      fFullClearIsFree = false;
      fMustClearUploadedBufferData = false;
      fSampleShadingSupport = false;
      fFenceSyncSupport = false;
      fCrossContextTextureSupport = false;
  
      fUseDrawInsteadOfClear = false;
  
      fInstancedSupport = InstancedSupport::kNone;
  
      fBlendEquationSupport = kBasic_BlendEquationSupport;
      fAdvBlendEqBlacklist = 0;
  
      fMapBufferFlags = kNone_MapFlags;
  
      fMaxVertexAttributes = 0;
      fMaxRenderTargetSize = 1;
      fMaxTextureSize = 1;
      fMaxColorSampleCount = 0;
      fMaxStencilSampleCount = 0;
      fMaxRasterSamples = 0;
      fMaxWindowRectangles = 0;
  
      fSuppressPrints = options.fSuppressPrints;
      fWireframeMode = options.fWireframeMode;
      fBufferMapThreshold = options.fBufferMapThreshold;
      fAvoidInstancedDrawsToFPTargets = false;
      fAvoidStencilBuffers = false;
  
      fPreferVRAMUseOverFlushes = true;
  }
  
  void GrCaps::applyOptionsOverrides(const GrContextOptions& options) {
      this->onApplyOptionsOverrides(options);
      fMaxTextureSize = SkTMin(fMaxTextureSize, options.fMaxTextureSizeOverride);
      // If the max tile override is zero, it means we should use the max texture size.
      if (!options.fMaxTileSizeOverride || options.fMaxTileSizeOverride > fMaxTextureSize) {
          fMaxTileSize = fMaxTextureSize;
      } else {
          fMaxTileSize = options.fMaxTileSizeOverride;
      }
      if (fMaxWindowRectangles > GrWindowRectangles::kMaxWindows) {
          SkDebugf("WARNING: capping window rectangles at %i. HW advertises support for %i.\n",
                   GrWindowRectangles::kMaxWindows, fMaxWindowRectangles);
          fMaxWindowRectangles = GrWindowRectangles::kMaxWindows;
      }
      fAvoidStencilBuffers = options.fAvoidStencilBuffers;
  }
  
  static SkString map_flags_to_string(uint32_t flags) {
      SkString str;
      if (GrCaps::kNone_MapFlags == flags) {
          str = "none";
      } else {
          SkASSERT(GrCaps::kCanMap_MapFlag & flags);
          SkDEBUGCODE(flags &= ~GrCaps::kCanMap_MapFlag);
          str = "can_map";
  
          if (GrCaps::kSubset_MapFlag & flags) {
              str.append(" partial");
          } else {
              str.append(" full");
          }
          SkDEBUGCODE(flags &= ~GrCaps::kSubset_MapFlag);
      }
      SkASSERT(0 == flags); // Make sure we handled all the flags.
      return str;
  }
  
  SkString GrCaps::dump() const {
      SkString r;
      static const char* gNY[] = {"NO", "YES"};
      r.appendf("MIP Map Support                    : %s\n", gNY[fMipMapSupport]);
      r.appendf("NPOT Texture Tile Support          : %s\n", gNY[fNPOTTextureTileSupport]);
      r.appendf("sRGB Support                       : %s\n", gNY[fSRGBSupport]);
      r.appendf("sRGB Write Control                 : %s\n", gNY[fSRGBWriteControl]);
      r.appendf("Discard Render Target Support      : %s\n", gNY[fDiscardRenderTargetSupport]);
      r.appendf("Reuse Scratch Textures             : %s\n", gNY[fReuseScratchTextures]);
      r.appendf("Reuse Scratch Buffers              : %s\n", gNY[fReuseScratchBuffers]);
      r.appendf("Gpu Tracing Support                : %s\n", gNY[fGpuTracingSupport]);
      r.appendf("Oversized Stencil Support          : %s\n", gNY[fOversizedStencilSupport]);
      r.appendf("Texture Barrier Support            : %s\n", gNY[fTextureBarrierSupport]);
      r.appendf("Sample Locations Support           : %s\n", gNY[fSampleLocationsSupport]);
      r.appendf("Multisample disable support        : %s\n", gNY[fMultisampleDisableSupport]);
      r.appendf("Instance Attrib Support            : %s\n", gNY[fInstanceAttribSupport]);
      r.appendf("Uses Mixed Samples                 : %s\n", gNY[fUsesMixedSamples]);
      r.appendf("Prefer client-side dynamic buffers : %s\n", gNY[fPreferClientSideDynamicBuffers]);
      r.appendf("Full screen clear is free          : %s\n", gNY[fFullClearIsFree]);
      r.appendf("Must clear buffer memory           : %s\n", gNY[fMustClearUploadedBufferData]);
      r.appendf("Sample shading support             : %s\n", gNY[fSampleShadingSupport]);
      r.appendf("Fence sync support                 : %s\n", gNY[fFenceSyncSupport]);
      r.appendf("Cross context texture support      : %s\n", gNY[fCrossContextTextureSupport]);
  
      r.appendf("Draw Instead of Clear [workaround] : %s\n", gNY[fUseDrawInsteadOfClear]);
      r.appendf("Prefer VRAM Use over flushes [workaround] : %s\n", gNY[fPreferVRAMUseOverFlushes]);
  
      if (this->advancedBlendEquationSupport()) {
          r.appendf("Advanced Blend Equation Blacklist  : 0x%x\n", fAdvBlendEqBlacklist);
      }
  
      r.appendf("Max Vertex Attributes              : %d\n", fMaxVertexAttributes);
      r.appendf("Max Texture Size                   : %d\n", fMaxTextureSize);
      r.appendf("Max Render Target Size             : %d\n", fMaxRenderTargetSize);
      r.appendf("Max Color Sample Count             : %d\n", fMaxColorSampleCount);
      r.appendf("Max Stencil Sample Count           : %d\n", fMaxStencilSampleCount);
      r.appendf("Max Raster Samples                 : %d\n", fMaxRasterSamples);
      r.appendf("Max Window Rectangles              : %d\n", fMaxWindowRectangles);
  
      static const char* kInstancedSupportNames[] = {
          "None",
          "Basic",
          "Multisampled",
          "Mixed Sampled",
      };
      GR_STATIC_ASSERT(0 == (int)InstancedSupport::kNone);
      GR_STATIC_ASSERT(1 == (int)InstancedSupport::kBasic);
      GR_STATIC_ASSERT(2 == (int)InstancedSupport::kMultisampled);
      GR_STATIC_ASSERT(3 == (int)InstancedSupport::kMixedSampled);
      GR_STATIC_ASSERT(4 == SK_ARRAY_COUNT(kInstancedSupportNames));
  
      r.appendf("Instanced Support                  : %s\n",
                kInstancedSupportNames[(int)fInstancedSupport]);
  
      static const char* kBlendEquationSupportNames[] = {
          "Basic",
          "Advanced",
          "Advanced Coherent",
      };
      GR_STATIC_ASSERT(0 == kBasic_BlendEquationSupport);
      GR_STATIC_ASSERT(1 == kAdvanced_BlendEquationSupport);
      GR_STATIC_ASSERT(2 == kAdvancedCoherent_BlendEquationSupport);
      GR_STATIC_ASSERT(SK_ARRAY_COUNT(kBlendEquationSupportNames) == kLast_BlendEquationSupport + 1);
  
      r.appendf("Blend Equation Support             : %s\n",
                kBlendEquationSupportNames[fBlendEquationSupport]);
      r.appendf("Map Buffer Support                 : %s\n",
                map_flags_to_string(fMapBufferFlags).c_str());
  
      SkASSERT(!this->isConfigRenderable(kUnknown_GrPixelConfig, false));
      SkASSERT(!this->isConfigRenderable(kUnknown_GrPixelConfig, true));
  
      for (size_t i = 1; i < kGrPixelConfigCnt; ++i)  {
          GrPixelConfig config = static_cast<GrPixelConfig>(i);
          r.appendf("%s is renderable: %s, with MSAA: %s\n",
                    pixel_config_name(config),
                    gNY[this->isConfigRenderable(config, false)],
                    gNY[this->isConfigRenderable(config, true)]);
      }
  
      SkASSERT(!this->isConfigTexturable(kUnknown_GrPixelConfig));
  
      for (size_t i = 1; i < kGrPixelConfigCnt; ++i)  {
          GrPixelConfig config = static_cast<GrPixelConfig>(i);
          r.appendf("%s is uploadable to a texture: %s\n",
                    pixel_config_name(config),
                    gNY[this->isConfigTexturable(config)]);
      }
  
      return r;
  }
  