content: /*
   * Copyright 2013 Hannes Janetzek
   * Copyright 2016 devemux86
   * Copyright 2018-2019 Gustl22
   *
   * This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
   *
   * This program is free software: you can redistribute it and/or modify it under the
   * terms of the GNU Lesser General Public License as published by the Free Software
   * Foundation, either version 3 of the License, or (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful, but WITHOUT ANY
   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
   * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public License along with
   * this program. If not, see <http://www.gnu.org/licenses/>.
   */
  package org.oscim.renderer;
  
  import org.oscim.backend.GL;
  import org.oscim.backend.GLAdapter;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  import static org.oscim.backend.GLAdapter.gl;
  
  public class GLState {
      static final Logger log = LoggerFactory.getLogger(GLState.class);
  
      public static final int DISABLED = -1;
      public static final int UNBIND = 0;
  
      private static final boolean[] vertexArray = {false, false};
      private static boolean blend = false;
      private static boolean depth = false;
      private static boolean stencil = false;
      private static int shader;
      private static float[] clearColor;
      private static int glVertexBuffer;
      private static int glIndexBuffer;
  
      private static int currentFramebufferId;
      private static int currentTexId;
  
      private static int viewportWidth;
      private static int viewportHeight;
  
      static void init() {
          vertexArray[0] = false;
          vertexArray[1] = false;
          blend = false;
          depth = false;
          stencil = false;
          shader = DISABLED;
          currentTexId = DISABLED;
          glVertexBuffer = DISABLED;
          glIndexBuffer = DISABLED;
          clearColor = null;
  
          gl.disable(GL.STENCIL_TEST);
          gl.disable(GL.DEPTH_TEST);
          gl.disable(GL.BLEND);
      }
  
      public static boolean useProgram(int shaderProgram) {
          if (shaderProgram < 0) {
              shader = DISABLED;
          } else if (shaderProgram != shader) {
              gl.useProgram(shaderProgram);
              shader = shaderProgram;
              return true;
          }
          return false;
      }
  
      public static void blend(boolean enable) {
          if (blend == enable)
              return;
  
          if (enable)
              gl.enable(GL.BLEND);
          else
              gl.disable(GL.BLEND);
          blend = enable;
      }
  
      public static void testDepth(boolean enable) {
          if (depth != enable) {
  
              if (enable)
                  gl.enable(GL.DEPTH_TEST);
              else
                  gl.disable(GL.DEPTH_TEST);
  
              depth = enable;
          }
      }
  
      public static void test(boolean depthTest, boolean stencilTest) {
          if (depth != depthTest) {
  
              if (depthTest)
                  gl.enable(GL.DEPTH_TEST);
              else
                  gl.disable(GL.DEPTH_TEST);
  
              depth = depthTest;
          }
  
          if (stencil != stencilTest) {
  
              if (stencilTest)
                  gl.enable(GL.STENCIL_TEST);
              else
                  gl.disable(GL.STENCIL_TEST);
  
              stencil = stencilTest;
          }
      }
  
      /**
       * Enable or disable vertex arrays.
       * Valid values are
       * -1: {@link #DISABLED},
       * 0: enable first,
       * 1: enable second.
       */
      public static void enableVertexArrays(int va1, int va2) {
          if (va1 > 1 || va2 > 1)
              log.debug("FIXME: enableVertexArrays...");
  
          if ((va1 == 0 || va2 == 0)) {
              if (!vertexArray[0]) {
                  gl.enableVertexAttribArray(0);
                  vertexArray[0] = true;
              }
          } else {
              if (vertexArray[0]) {
                  gl.disableVertexAttribArray(0);
                  vertexArray[0] = false;
              }
          }
  
          if ((va1 == 1 || va2 == 1)) {
              if (!vertexArray[1]) {
                  gl.enableVertexAttribArray(1);
                  vertexArray[1] = true;
              }
          } else {
              if (vertexArray[1]) {
                  gl.disableVertexAttribArray(1);
                  vertexArray[1] = false;
              }
          }
      }
  
      public static void bindFramebuffer(int id) {
          gl.bindFramebuffer(GL.FRAMEBUFFER, id);
          currentFramebufferId = id;
      }
  
      public static int getFramebuffer() {
          return currentFramebufferId;
      }
  
      public static void bindTex2D(int id) {
          if (id < 0) {
              gl.bindTexture(GL.TEXTURE_2D, 0);
              currentTexId = 0;
          } else if (currentTexId != id) {
              gl.bindTexture(GL.TEXTURE_2D, id);
              currentTexId = id;
          }
      }
  
      public static int getTexture() {
          return currentTexId;
      }
  
      public static void setClearColor(float[] color) {
          // Workaround for artifacts at canvas resize on desktop
          if (!GLAdapter.GDX_DESKTOP_QUIRKS) {
              if (clearColor != null &&
                      color[0] == clearColor[0] &&
                      color[1] == clearColor[1] &&
                      color[2] == clearColor[2] &&
                      color[3] == clearColor[3])
                  return;
          }
  
          clearColor = color;
          gl.clearColor(color[0], color[1], color[2], color[3]);
      }
  
      public static void bindBuffer(int target, int id) {
          //log.debug(">> buffer {} {}", target == GL20.ARRAY_BUFFER, id);
  
          if (target == GL.ARRAY_BUFFER) {
              if (glVertexBuffer == id)
                  return;
              glVertexBuffer = id;
          } else if (target == GL.ELEMENT_ARRAY_BUFFER) {
              if (glIndexBuffer == id)
                  return;
              glIndexBuffer = id;
          } else {
              log.debug("invalid target {}", target);
              return;
          }
          //log.debug("bind buffer {} {}", target == GL20.ARRAY_BUFFER, id);
  
          if (id >= 0)
              gl.bindBuffer(target, id);
      }
  
      public static void bindElementBuffer(int id) {
  
          if (glIndexBuffer == id)
              return;
          glIndexBuffer = id;
  
          if (id >= 0)
              gl.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, id);
  
      }
  
      public static void bindVertexBuffer(int id) {
  
          if (glVertexBuffer == id)
              return;
          glVertexBuffer = id;
  
          if (id >= 0)
              gl.bindBuffer(GL.ARRAY_BUFFER, id);
  
      }
  
      public static void viewport(int width, int height) {
          gl.viewport(0, 0, width, height);
          viewportWidth = width;
          viewportHeight = height;
      }
  
      public static int getViewportWidth() {
          return viewportWidth;
      }
  
      public static int getViewportHeight() {
          return viewportHeight;
      }
  }
  