<commit_before>part of orange;


class GraphicsDevice {
  html.CanvasElement _renderingCanvas;
  gl.RenderingContext ctx;
  int _lastMaxEnabledArray = -1;
  int _textureIndex = -1;
  int _newMaxEnabledArray = -1;
  DeviceCapabilities _caps;
  StandardMaterial defaultMaterial;
  bool _depthMask = false;
  Pass _previousPass;

  html.Rectangle<int> _cachedViewport;
  RenderTargetTexture _currentRenderTarget;
  List<RenderTargetTexture> _renderTargets = [];

  GraphicsDevice(this._renderingCanvas) {
    ctx = _renderingCanvas.getContext3d(preserveDrawingBuffer: true);
    //    ctx.enable(gl.DEPTH_TEST);
    //    ctx.depthMask(true);
    //    ctx.depthFunc(gl.LEQUAL);
    //    ctx.frontFace(gl.CCW);
    //    ctx.cullFace(gl.BACK);
    //    ctx.enable(gl.CULL_FACE);
    //    ctx.clearDepth(1.0);

    depthWrite = true;
    depthBuffer = true;
    ctx.depthFunc(gl.LEQUAL);
    viewport(0, 0, _renderingCanvas.width, _renderingCanvas.height);

    _caps = new DeviceCapabilities();
    _caps.maxTexturesImageUnits = ctx.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
    _caps.maxTextureSize = ctx.getParameter(gl.MAX_TEXTURE_SIZE);
    _caps.maxCubemapTextureSize = ctx.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE);
    _caps.maxRenderTextureSize = ctx.getParameter(gl.MAX_RENDERBUFFER_SIZE);

    // extensions
    _caps.standardDerivatives = (ctx.getExtension('OES_standard_derivatives') != null);
    _caps.s3tc = ctx.getExtension('WEBGL_compressed_texture_s3tc');
    _caps.textureFloat = (ctx.getExtension('OES_texture_float') != null);
    _caps.textureAnisotropicFilterExtension = ctx.getExtension('EXT_texture_filter_anisotropic');
    if (_caps.textureAnisotropicFilterExtension == null) _caps.textureAnisotropicFilterExtension = ctx.getExtension('WEBKIT_EXT_texture_filter_anisotropic');
    if (_caps.textureAnisotropicFilterExtension == null) _caps.textureAnisotropicFilterExtension = ctx.getExtension('MOZ_EXT_texture_filter_anisotropic');
    if (_caps.textureAnisotropicFilterExtension == null) _caps.maxAnisotropy = 0; else _caps.maxAnisotropy = ctx.getParameter(gl.ExtTextureFilterAnisotropic.MAX_TEXTURE_MAX_ANISOTROPY_EXT);
    _caps.instancedArrays = ctx.getExtension('ANGLE_instanced_arrays');
  }

  void clear(Color color, {bool backBuffer: false, bool depthStencil: false}) {
    ctx.clearColor(color.red, color.green, color.blue, color.alpha);
    if (_depthMask) ctx.clearDepth(1.0);
    var mode = 0;
    if (backBuffer) mode |= gl.COLOR_BUFFER_BIT;
    if (depthStencil && _depthMask) mode |= gl.DEPTH_BUFFER_BIT;
    ctx.clear(mode);
  }

  void set depthWrite(bool enable) {
    ctx.depthMask(enable);
    _depthMask = enable;
  }

  void set depthBuffer(bool enable) {
    if (enable) ctx.enable(gl.DEPTH_TEST); else ctx.disable(gl.DEPTH_TEST);
  }

  void viewport(int x, int y, int width, int height) {
    _cachedViewport = new html.Rectangle(x, y, width, height);
    ctx.viewport(x, y, width, height);
  }

  void bindFramebuffer(RenderTargetTexture texture) {
    _currentRenderTarget = texture;
    ctx.bindFramebuffer(gl.FRAMEBUFFER, texture.framebuffer);
    ctx.viewport(0, 0, texture.width, texture.height);
    wipeCaches();
  }

  void unbindFramebuffer() {
    _currentRenderTarget = null;
    ctx.bindFramebuffer(gl.FRAMEBUFFER, null);
  }

  void restoreDefaultFramebuffer() {
    ctx.bindFramebuffer(gl.FRAMEBUFFER, null);
    viewport(_cachedViewport.left, _cachedViewport.top, _cachedViewport.width, _cachedViewport.height);
    wipeCaches();
  }

  void wipeCaches() {
    // TODO
  }

  use(Pass pass) {
    if (_previousPass == null || _previousPass.shader.program != pass.shader.program) {
      pass.bind(ctx);
      _previousPass = pass;
    }
  }

  void render(Scene scene) {
    // shadows
    scene._lights.forEach((light) {
      if (light is DirectionalLight && light.enabled) {
        if (light.shadowRenderer == null) light.shadowRenderer = new ShadowRenderer(512, light, this);
        _renderTargets.add(light.shadowRenderer.shadowMap);
      }
    });

    _renderTargets.forEach((renderTarget) {
      renderTarget.render(scene, scene._opaqueMeshes);
    });

    if (_renderTargets.length > 0) restoreDefaultFramebuffer();
    clear(scene.backgroundColor, backBuffer: scene.autoClear || scene.forceWireframe, depthStencil: true);
    scene.nodes.forEach((node) {
      _renderNode(node);
    });

    // reset
    // TODO : should dispose the renderTargets ?
    _renderTargets.clear();
  }

  _renderNode(Node node) {
    _textureIndex = -1;
    _newMaxEnabledArray = -1;
    if (node is Mesh) {
      _drawMesh(node);
    }
    node.children.forEach((c) => _renderNode(c));
  }

  _drawMesh(Mesh mesh) {
    var material = mesh.material;
    if (mesh.faces != null && material != null && material.ready(mesh)) {
      var shader = material.technique.pass.shader;
      use(material.technique.pass);
      material.bind(mesh: mesh);
      if (mesh.geometry != null) {
        var geometry = mesh.geometry;
        shader.attributes.forEach((semantic, attrib) {
          if (geometry.buffers.containsKey(semantic)) {
            geometry.buffers[semantic].enable(ctx, attrib);
            if (attrib.location > _newMaxEnabledArray) {
              _newMaxEnabledArray = attrib.location;
            }
          }
        });
      }
      for (var i = (_newMaxEnabledArray + 1); i < _lastMaxEnabledArray; i++) {
        ctx.disableVertexAttribArray(i);
      }
      _lastMaxEnabledArray = _newMaxEnabledArray;

      mesh.faces.bind(ctx);
      if (material.wireframe) {
        ctx.drawArrays(gl.LINE_LOOP, 0, mesh.geometry.buffers[Semantics.position].count);
      } else {
        ctx.drawElements(gl.TRIANGLES, mesh.faces.count, mesh.faces.type, mesh.faces.offset);
      }
      material.unbind();
    }
  }

  // TODO should not pass the shader again.
  bindUniform(Shader shader, String symbol, value) {
    if (!shader.ready) return;
    if (shader.uniforms.containsKey(symbol) && value != null) {
      var property = shader.uniforms[symbol];
      switch (property.type) {
        case gl.BYTE:
        case gl.UNSIGNED_BYTE:
        case gl.SHORT:
        case gl.UNSIGNED_SHORT:
          ctx.uniform1i(property.location, value);
          break;
        case gl.FLOAT_MAT2:
          ctx.uniformMatrix2fv(property.location, false, value);
          break;
        case gl.FLOAT_MAT3:
          ctx.uniformMatrix3fv(property.location, false, value);
          break;
        case gl.FLOAT_MAT4:
          ctx.uniformMatrix4fv(property.location, false, value);
          break;
        case gl.FLOAT:<commit_msg>use primitive of mesh<commit_after>part of orange;


class GraphicsDevice {
  html.CanvasElement _renderingCanvas;
  gl.RenderingContext ctx;
  int _lastMaxEnabledArray = -1;
  int _textureIndex = -1;
  int _newMaxEnabledArray = -1;
  DeviceCapabilities _caps;
  StandardMaterial defaultMaterial;
  bool _depthMask = false;
  Pass _previousPass;

  html.Rectangle<int> _cachedViewport;
  RenderTargetTexture _currentRenderTarget;
  List<RenderTargetTexture> _renderTargets = [];

  GraphicsDevice(this._renderingCanvas) {
    ctx = _renderingCanvas.getContext3d(preserveDrawingBuffer: true);
    //    ctx.enable(gl.DEPTH_TEST);
    //    ctx.depthMask(true);
    //    ctx.depthFunc(gl.LEQUAL);
    //    ctx.frontFace(gl.CCW);
    //    ctx.cullFace(gl.BACK);
    //    ctx.enable(gl.CULL_FACE);
    //    ctx.clearDepth(1.0);

    depthWrite = true;
    depthBuffer = true;
    ctx.depthFunc(gl.LEQUAL);
    viewport(0, 0, _renderingCanvas.width, _renderingCanvas.height);

    _caps = new DeviceCapabilities();
    _caps.maxTexturesImageUnits = ctx.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
    _caps.maxTextureSize = ctx.getParameter(gl.MAX_TEXTURE_SIZE);
    _caps.maxCubemapTextureSize = ctx.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE);
    _caps.maxRenderTextureSize = ctx.getParameter(gl.MAX_RENDERBUFFER_SIZE);

    // extensions
    _caps.standardDerivatives = (ctx.getExtension('OES_standard_derivatives') != null);
    _caps.s3tc = ctx.getExtension('WEBGL_compressed_texture_s3tc');
    _caps.textureFloat = (ctx.getExtension('OES_texture_float') != null);
    _caps.textureAnisotropicFilterExtension = ctx.getExtension('EXT_texture_filter_anisotropic');
    if (_caps.textureAnisotropicFilterExtension == null) _caps.textureAnisotropicFilterExtension = ctx.getExtension('WEBKIT_EXT_texture_filter_anisotropic');
    if (_caps.textureAnisotropicFilterExtension == null) _caps.textureAnisotropicFilterExtension = ctx.getExtension('MOZ_EXT_texture_filter_anisotropic');
    if (_caps.textureAnisotropicFilterExtension == null) _caps.maxAnisotropy = 0; else _caps.maxAnisotropy = ctx.getParameter(gl.ExtTextureFilterAnisotropic.MAX_TEXTURE_MAX_ANISOTROPY_EXT);
    _caps.instancedArrays = ctx.getExtension('ANGLE_instanced_arrays');
  }

  void clear(Color color, {bool backBuffer: false, bool depthStencil: false}) {
    ctx.clearColor(color.red, color.green, color.blue, color.alpha);
    if (_depthMask) ctx.clearDepth(1.0);
    var mode = 0;
    if (backBuffer) mode |= gl.COLOR_BUFFER_BIT;
    if (depthStencil && _depthMask) mode |= gl.DEPTH_BUFFER_BIT;
    ctx.clear(mode);
  }

  void set depthWrite(bool enable) {
    ctx.depthMask(enable);
    _depthMask = enable;
  }

  void set depthBuffer(bool enable) {
    if (enable) ctx.enable(gl.DEPTH_TEST); else ctx.disable(gl.DEPTH_TEST);
  }

  void viewport(int x, int y, int width, int height) {
    _cachedViewport = new html.Rectangle(x, y, width, height);
    ctx.viewport(x, y, width, height);
  }

  void bindFramebuffer(RenderTargetTexture texture) {
    _currentRenderTarget = texture;
    ctx.bindFramebuffer(gl.FRAMEBUFFER, texture.framebuffer);
    ctx.viewport(0, 0, texture.width, texture.height);
    wipeCaches();
  }

  void unbindFramebuffer() {
    _currentRenderTarget = null;
    ctx.bindFramebuffer(gl.FRAMEBUFFER, null);
  }

  void restoreDefaultFramebuffer() {
    ctx.bindFramebuffer(gl.FRAMEBUFFER, null);
    viewport(_cachedViewport.left, _cachedViewport.top, _cachedViewport.width, _cachedViewport.height);
    wipeCaches();
  }

  void wipeCaches() {
    // TODO
  }

  use(Pass pass) {
    if (_previousPass == null || _previousPass.shader.program != pass.shader.program) {
      pass.bind(ctx);
      _previousPass = pass;
    }
  }

  void render(Scene scene) {
    // shadows
    scene._lights.forEach((light) {
      if (light is DirectionalLight && light.enabled) {
        if (light.shadowRenderer == null) light.shadowRenderer = new ShadowRenderer(512, light, this);
        _renderTargets.add(light.shadowRenderer.shadowMap);
      }
    });

    _renderTargets.forEach((renderTarget) {
      renderTarget.render(scene, scene._opaqueMeshes);
    });

    if (_renderTargets.length > 0) restoreDefaultFramebuffer();
    clear(scene.backgroundColor, backBuffer: scene.autoClear || scene.forceWireframe, depthStencil: true);
    scene.nodes.forEach((node) {
      _renderNode(node);
    });

    // reset
    // TODO : should dispose the renderTargets ?
    _renderTargets.clear();
  }

  _renderNode(Node node) {
    _textureIndex = -1;
    _newMaxEnabledArray = -1;
    if (node is Mesh) {
      _drawMesh(node);
    }
    node.children.forEach((c) => _renderNode(c));
  }

  _drawMesh(Mesh mesh) {
    var material = mesh.material;
    if (mesh.faces != null && material != null && material.ready(mesh)) {
      var shader = material.technique.pass.shader;
      use(material.technique.pass);
      material.bind(mesh: mesh);
      if (mesh.geometry != null) {
        var geometry = mesh.geometry;
        shader.attributes.forEach((semantic, attrib) {
          if (geometry.buffers.containsKey(semantic)) {
            geometry.buffers[semantic].enable(ctx, attrib);
            if (attrib.location > _newMaxEnabledArray) {
              _newMaxEnabledArray = attrib.location;
            }
          }
        });
      }
      for (var i = (_newMaxEnabledArray + 1); i < _lastMaxEnabledArray; i++) {
        ctx.disableVertexAttribArray(i);
      }
      _lastMaxEnabledArray = _newMaxEnabledArray;

      mesh.faces.bind(ctx);
      if (material.wireframe) {
        ctx.drawArrays(gl.LINE_LOOP, 0, mesh.geometry.buffers[Semantics.position].count);
      } else {
        ctx.drawElements(mesh.primitive, mesh.faces.count, mesh.faces.type, mesh.faces.offset);
      }
      material.unbind();
    }
  }

  // TODO should not pass the shader again.
  bindUniform(Shader shader, String symbol, value) {
    if (!shader.ready) return;
    if (shader.uniforms.containsKey(symbol) && value != null) {
      var property = shader.uniforms[symbol];
      switch (property.type) {
        case gl.BYTE:
        case gl.UNSIGNED_BYTE:
        case gl.SHORT:
        case gl.UNSIGNED_SHORT:
          ctx.uniform1i(property.location, value);
          break;
        case gl.FLOAT_MAT2:
          ctx.uniformMatrix2fv(property.location, false, value);
          break;
        case gl.FLOAT_MAT3:
          ctx.uniformMatrix3fv(property.location, false, value);
          break;
        case gl.FLOAT_MAT4:
          ctx.uniformMatrix4fv(property.location, false, value);
          break;
        case gl.FLOAT:
{'fraction_non_alphanumeric': 0.1162403511427274, 'fraction_numerical': 0.004691993340396549, 'mean_word_length': 3.3299475753604195, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5974446', 'n_tokens_mistral': 4286, 'n_tokens_neox': 4159, 'n_words': 732}