text: "use strict";
  /**
   * @license
   * Copyright 2018 Google LLC. All Rights Reserved.
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   * =============================================================================
   */
  Object.defineProperty(exports, "__esModule", { value: true });
  var canvas_util_1 = require("./canvas_util");
  var Type;
  (function (Type) {
      Type[Type["NUMBER"] = 0] = "NUMBER";
      Type[Type["BOOLEAN"] = 1] = "BOOLEAN";
      Type[Type["STRING"] = 2] = "STRING";
  })(Type = exports.Type || (exports.Type = {}));
  exports.URL_PROPERTIES = [
      { name: 'DEBUG', type: Type.BOOLEAN },
      { name: 'IS_BROWSER', type: Type.BOOLEAN },
      { name: 'WEBGL_LAZILY_UNPACK', type: Type.BOOLEAN },
      { name: 'WEBGL_CPU_FORWARD', type: Type.BOOLEAN },
      { name: 'WEBGL_PACK', type: Type.BOOLEAN },
      { name: 'WEBGL_PACK_BATCHNORMALIZATION', type: Type.BOOLEAN },
      { name: 'WEBGL_PACK_CLIP', type: Type.BOOLEAN },
      { name: 'WEBGL_PACK_DEPTHWISECONV', type: Type.BOOLEAN },
      { name: 'WEBGL_PACK_BINARY_OPERATIONS', type: Type.BOOLEAN },
      { name: 'WEBGL_PACK_ARRAY_OPERATIONS', type: Type.BOOLEAN },
      { name: 'WEBGL_PACK_IMAGE_OPERATIONS', type: Type.BOOLEAN },
      { name: 'WEBGL_PACK_REDUCE', type: Type.BOOLEAN },
      { name: 'WEBGL_CONV_IM2COL', type: Type.BOOLEAN },
      { name: 'WEBGL_MAX_TEXTURE_SIZE', type: Type.NUMBER },
      { name: 'WEBGL_NUM_MB_BEFORE_PAGING', type: Type.NUMBER },
      { name: 'WEBGL_MAX_TEXTURES_IN_SHADER', type: Type.NUMBER },
      { name: 'WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION', type: Type.NUMBER },
      { name: 'WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_RELIABLE', type: Type.BOOLEAN },
      { name: 'WEBGL_VERSION', type: Type.NUMBER },
      { name: 'WEBGL_RENDER_FLOAT32_ENABLED', type: Type.BOOLEAN },
      { name: 'WEBGL_DOWNLOAD_FLOAT_ENABLED', type: Type.BOOLEAN },
      { name: 'WEBGL_FENCE_API_ENABLED', type: Type.BOOLEAN },
      { name: 'WEBGL_SIZE_UPLOAD_UNIFORM', type: Type.NUMBER },
      { name: 'BACKEND', type: Type.STRING },
      { name: 'EPSILON', type: Type.NUMBER },
      { name: 'PROD', type: Type.BOOLEAN },
      { name: 'TENSORLIKE_CHECK_SHAPE_CONSISTENCY', type: Type.BOOLEAN },
      { name: 'DEPRECATION_WARNINGS_ENABLED', type: Type.BOOLEAN },
  ];
  function isWebGLVersionEnabled(webGLVersion) {
      try {
          var gl = canvas_util_1.getWebGLContext(webGLVersion);
          if (gl != null) {
              return true;
          }
      }
      catch (e) {
          return false;
      }
      return false;
  }
  exports.isWebGLVersionEnabled = isWebGLVersionEnabled;
  // We cache webgl params because the environment gets reset between
  // unit tests and we don't want to constantly query the WebGLContext for
  // MAX_TEXTURE_SIZE.
  var MAX_TEXTURE_SIZE;
  var MAX_TEXTURES_IN_SHADER;
  function getWebGLMaxTextureSize(webGLVersion) {
      if (MAX_TEXTURE_SIZE == null) {
          var gl = canvas_util_1.getWebGLContext(webGLVersion);
          MAX_TEXTURE_SIZE = gl.getParameter(gl.MAX_TEXTURE_SIZE);
      }
      return MAX_TEXTURE_SIZE;
  }
  exports.getWebGLMaxTextureSize = getWebGLMaxTextureSize;
  function getMaxTexturesInShader(webGLVersion) {
      if (MAX_TEXTURES_IN_SHADER == null) {
          var gl = canvas_util_1.getWebGLContext(webGLVersion);
          MAX_TEXTURES_IN_SHADER = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
      }
      // We cap at 16 to avoid spurious runtime "memory exhausted" error.
      return Math.min(16, MAX_TEXTURES_IN_SHADER);
  }
  exports.getMaxTexturesInShader = getMaxTexturesInShader;
  function getWebGLDisjointQueryTimerVersion(webGLVersion) {
      if (webGLVersion === 0) {
          return 0;
      }
      var queryTimerVersion;
      var gl = canvas_util_1.getWebGLContext(webGLVersion);
      if (hasExtension(gl, 'EXT_disjoint_timer_query_webgl2') &&
          webGLVersion === 2) {
          queryTimerVersion = 2;
      }
      else if (hasExtension(gl, 'EXT_disjoint_timer_query')) {
          queryTimerVersion = 1;
      }
      else {
          queryTimerVersion = 0;
      }
      return queryTimerVersion;
  }
  exports.getWebGLDisjointQueryTimerVersion = getWebGLDisjointQueryTimerVersion;
  function isRenderToFloatTextureEnabled(webGLVersion) {
      if (webGLVersion === 0) {
          return false;
      }
      var gl = canvas_util_1.getWebGLContext(webGLVersion);
      if (webGLVersion === 1) {
          if (!hasExtension(gl, 'OES_texture_float')) {
              return false;
          }
      }
      else {
          if (!hasExtension(gl, 'EXT_color_buffer_float')) {
              return false;
          }
      }
      var isFrameBufferComplete = createFloatTextureAndBindToFramebuffer(gl, webGLVersion);
      return isFrameBufferComplete;
  }
  exports.isRenderToFloatTextureEnabled = isRenderToFloatTextureEnabled;
  function isDownloadFloatTextureEnabled(webGLVersion) {
      if (webGLVersion === 0) {
          return false;
      }
      var gl = canvas_util_1.getWebGLContext(webGLVersion);
      if (webGLVersion === 1) {
          if (!hasExtension(gl, 'OES_texture_float')) {
              return false;
          }
          if (!hasExtension(gl, 'WEBGL_color_buffer_float')) {
              return false;
          }
      }
      else {
          if (!hasExtension(gl, 'EXT_color_buffer_float')) {
              return false;
          }
      }
      var isFrameBufferComplete = createFloatTextureAndBindToFramebuffer(gl, webGLVersion);
      return isFrameBufferComplete;
  }
  exports.isDownloadFloatTextureEnabled = isDownloadFloatTextureEnabled;
  function isWebGLFenceEnabled(webGLVersion) {
      if (webGLVersion !== 2) {
          return false;
      }
      var gl = canvas_util_1.getWebGLContext(webGLVersion);
      // tslint:disable-next-line:no-any
      var isEnabled = gl.fenceSync != null;
      return isEnabled;
  }
  exports.isWebGLFenceEnabled = isWebGLFenceEnabled;
  function isChrome() {
      return typeof navigator !== 'undefined' && navigator != null &&
          navigator.userAgent != null && /Chrome/.test(navigator.userAgent) &&
          /Google Inc/.test(navigator.vendor);
  }
  exports.isChrome = isChrome;
  // Expects flags from URL in the format ?tfjsflags=FLAG1:1,FLAG2:true.
  var TENSORFLOWJS_FLAGS_PREFIX = 'tfjsflags';
  function getFeaturesFromURL() {
      var features = {};
      if (typeof window === 'undefined' || typeof window.location === 'undefined' ||
          typeof window.location.search === 'undefined') {
          return features;
      }
      var urlParams = getQueryParams(window.location.search);
      if (TENSORFLOWJS_FLAGS_PREFIX in urlParams) {
          var urlFlags_1 = {};
          var keyValues = urlParams[TENSORFLOWJS_FLAGS_PREFIX].split(',');
          keyValues.forEach(function (keyValue) {
              var _a = keyValue.split(':'), key = _a[0], value = _a[1];
              urlFlags_1[key] = value;
          });
          exports.URL_PROPERTIES.forEach(function (urlProperty) {
              if (urlProperty.name in urlFlags_1) {
                  console.log("Setting feature override from URL " + urlProperty.name + ": " +
                      ("" + urlFlags_1[urlProperty.name]));
                  if (urlProperty.type === Type.NUMBER) {
                      features[urlProperty.name] = +urlFlags_1[urlProperty.name];
                  }
                  else if (urlProperty.type === Type.BOOLEAN) {
                      features[urlProperty.name] = urlFlags_1[urlProperty.name] === 'true';
                  }
                  else if (urlProperty.type === Type.STRING) {
                      // tslint:disable-next-line:no-any
                      features[urlProperty.name] = urlFlags_1[urlProperty.name];
                  }
                  else {
                      console.warn("Unknown URL param: " + urlProperty.name + ".");
                  }
              }
          });
      }
      return features;
  }
  exports.getFeaturesFromURL = getFeaturesFromURL;
  function hasExtension(gl, extensionName) {
      var ext = gl.getExtension(extensionName);
      return ext != null;
  }
  function createFloatTextureAndBindToFramebuffer(gl, webGLVersion) {
      var frameBuffer = gl.createFramebuffer();
      var texture = gl.createTexture();
      gl.bindTexture(gl.TEXTURE_2D, texture);
      // tslint:disable-next-line:no-any
      var internalFormat = webGLVersion === 2 ? gl.RGBA32F : gl.RGBA;
      gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, 1, 1, 0, gl.RGBA, gl.FLOAT, null);
      gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
      gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
      var isFrameBufferComplete = gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE;
      gl.bindTexture(gl.TEXTURE_2D, null);
      gl.bindFramebuffer(gl.FRAMEBUFFER, null);
      gl.deleteTexture(texture);
      gl.deleteFramebuffer(frameBuffer);
      return isFrameBufferComplete;
  }
  function getQueryParams(queryString) {
      var params = {};
      queryString.replace(/[?&]([^=?&]+)(?:=([^&]*))?/g, function (s) {
          var t = [];
          for (var _i = 1; _i < arguments.length; _i++) {
              t[_i - 1] = arguments[_i];
          }
          decodeParam(params, t[0], t[1]);
          return t.join('=');
      });
      return params;
  }
  exports.getQueryParams = getQueryParams;
  function decodeParam(params, name, value) {
      params[decodeURIComponent(name)] = decodeURIComponent(value || '');
  }
  // Empirically determined constant used to decide the number of bytes on GPU
  // before we start paging. The MB are this constant * screen area * dpi / 1024.
  exports.BEFORE_PAGING_CONSTANT = 600;
  function getNumMBBeforePaging() {
      return (window.screen.height * window.screen.width *
          window.devicePixelRatio) *
          exports.BEFORE_PAGING_CONSTANT / 1024;
  }
  exports.getNumMBBeforePaging = getNumMBBeforePaging;
  //# sourceMappingURL=environment_util.js.map