'use strict';

require('../core/settings.js');
require('../color.js');
require('../constants.js');
require('../extensions.js');
require('../math/const.js');
require('../math/groupD8.js');
require('../math/Transform.js');
require('../runner.js');
require('../ticker/settings.js');
require('../ticker/const.js');
require('../ticker/Ticker.js');
require('../ticker/TickerPlugin.js');
require('../utils/settings.js');
require('../utils/is_mobile/index.js');
require('../utils/color/premultiply.js');
require('../utils/media/BoundingBox.js');
require('../core/autoDetectRenderer.js');
require('../core/background/BackgroundSystem.js');
var Buffer = require('../core/geometry/Buffer.js');
var Geometry = require('../core/geometry/Geometry.js');
require('../core/batch/BatchRenderer.js');
var Program = require('../core/shader/Program.js');
var Shader = require('../core/shader/Shader.js');
require('../core/batch/BatchSystem.js');
require('../core/context/ContextSystem.js');
require('../core/filters/Filter.js');
require('../core/filters/FilterSystem.js');
require('../core/textures/BaseTexture.js');
require('../core/framebuffer/FramebufferSystem.js');
require('../core/framebuffer/MultisampleSystem.js');
require('../core/geometry/BufferSystem.js');
require('../core/geometry/GeometrySystem.js');
require('../core/mask/MaskSystem.js');
require('../core/mask/ScissorSystem.js');
require('../core/mask/StencilSystem.js');
require('../core/plugin/PluginSystem.js');
require('../core/projection/ProjectionSystem.js');
require('../core/render/ObjectRendererSystem.js');
require('../core/Renderer.js');
require('../core/renderTexture/GenerateTextureSystem.js');
require('../core/renderTexture/RenderTexturePool.js');
require('../core/renderTexture/RenderTextureSystem.js');
require('../core/shader/ShaderSystem.js');
require('../core/startup/StartupSystem.js');
require('../core/state/StateSystem.js');
require('../core/textures/TextureGCSystem.js');
require('../core/textures/TextureSystem.js');
require('../core/transformFeedback/TransformFeedbackSystem.js');
require('../core/view/ViewSystem.js');
require('../core/textures/resources/index.js');

const fragment = `#version 300 es
precision highp float;

out vec4 outColor;

void main() {
    outColor = vec4(0.0, 0.0, 0.0, 1.0);
}
`;
function genVertex(elemSize, elemCount) {
  let code = `#version 300 es
precision highp float;
precision highp int;
`;
  for (let i = 1; i <= elemCount; i++) {
    code += `in vec${elemSize} a_silly${i};
`;
  }
  for (let i = 1; i <= elemCount; i++) {
    code += `out vec${elemSize} v_silly${i};
`;
  }
  code += `void main() {`;
  for (let i = 1; i <= elemCount; i++) {
    code += `v_silly${i} = a_silly${i};
`;
  }
  code += `
    gl_PointSize = 0.0;
    gl_Position = vec4(-2.0, -2.0, 0.0, 1.0);
}
`;
  return code;
}
function genAttribs(geom, buf, elemSize, elemCount) {
  for (let i = 1; i <= elemCount; i++) {
    geom.addAttribute(`a_silly${i}`, buf, elemSize);
  }
}
function genVaryings(elemCount) {
  const res = [];
  for (let i = 1; i <= elemCount; i++) {
    res.push(`v_silly${i}`);
  }
  return res;
}
class TFBufferCopier {
  constructor(strideFloats = 16) {
    this.elemCount = 0;
    this.elemSize = 0;
    this.program = null;
    this.shader = null;
    this.tf = {};
    this.strideFloats = strideFloats;
    this.strideBytes = 4 * strideFloats;
    this.initProgram();
    this.initGeom();
  }
  initProgram() {
    const { strideFloats } = this;
    let elemSize = 4;
    while (elemSize > 1 && strideFloats % elemSize > 0) {
      elemSize--;
    }
    this.elemSize = elemSize;
    this.elemCount = strideFloats / this.elemSize;
    const vertex = genVertex(this.elemSize, this.elemCount);
    const tfNames = genVaryings(this.elemCount);
    this.program = new Program.Program({ vertex, fragment, name: "silly tf" }, {
      transformFeedbackVaryings: {
        names: tfNames,
        bufferMode: "interleaved"
      }
    });
    this.shader = new Shader.Shader(this.program);
  }
  initGeom() {
    this.tempBuffer = new Buffer.Buffer(new Float32Array());
    this.geom = new Geometry.Geometry();
    genAttribs(this.geom, this.tempBuffer, this.elemSize, this.elemCount);
  }
  doCopy(renderer, src, target, strideBytes, copies, copyCount = copies.length) {
    if (strideBytes % this.strideBytes !== 0) {
      return;
    }
    const gl = renderer.gl;
    const CONTEXT_UID = renderer.CONTEXT_UID;
    let tf = this.tf[CONTEXT_UID];
    if (!tf) {
      tf = this.tf[CONTEXT_UID] = gl.createTransformFeedback();
    }
    if (!target._glBuffers[CONTEXT_UID]) {
      renderer.buffer.bind(target);
      renderer.buffer.update(target);
    }
    this.geom.swapBuffer(0, src);
    renderer.shader.bind(this.shader);
    renderer.geometry.bind(this.geom);
    gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
    for (let i = 0; i < copyCount; i++) {
      const op = copies[i];
      gl.bindBufferRange(gl.TRANSFORM_FEEDBACK_BUFFER, 0, target._glBuffers[CONTEXT_UID].buffer, op.dst * strideBytes, op.count * strideBytes);
      gl.beginTransformFeedback(gl.POINTS);
      gl.drawArrays(gl.POINTS, op.src * strideBytes / this.strideBytes, op.count * strideBytes / this.strideBytes);
      gl.endTransformFeedback();
    }
    gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
    renderer.geometry.unbind();
    this.geom.swapBuffer(0, this.tempBuffer);
  }
}

exports.TFBufferCopier = TFBufferCopier;
//# sourceMappingURL=TFBufferCopier.js.map
