// Copyright (C) 2015 The Android Open Source Project
//
// 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.

@Doc("https://www.khronos.org/opengles/sdk/docs/man/xhtml/glEnable.xml","OpenGL ES 2.0")
@Doc("https://www.khronos.org/opengles/sdk/docs/man3/html/glEnable.xhtml","OpenGL ES 3.0")
@Doc("https://www.khronos.org/opengles/sdk/docs/man31/html/glEnable.xhtml","OpenGL ES 3.1")
cmd void glDisable(GLenum capability) {
  minRequiredVersion(2, 0)
  switch (capability) {
    case GL_BLEND, GL_CULL_FACE, GL_DEPTH_TEST, GL_DITHER, GL_POLYGON_OFFSET_FILL,
        GL_SAMPLE_ALPHA_TO_COVERAGE, GL_SAMPLE_COVERAGE, GL_SCISSOR_TEST, GL_STENCIL_TEST: {
      // version 2.0
    }
    case GL_PRIMITIVE_RESTART_FIXED_INDEX, GL_RASTERIZER_DISCARD: {
      minRequiredVersion(3, 0)
    }
    case GL_SAMPLE_MASK: {
      minRequiredVersion(3, 1)
    }
    default: {
      glErrorInvalidEnum(capability)
    }
  }

  ctx := GetContext()
  ctx.Capabilities[capability] = false
}

@Doc("https://www.khronos.org/opengles/sdk/docs/man/xhtml/glEnable.xml","OpenGL ES 2.0")
@Doc("https://www.khronos.org/opengles/sdk/docs/man3/html/glEnable.xhtml","OpenGL ES 3.0")
@Doc("https://www.khronos.org/opengles/sdk/docs/man31/html/glEnable.xhtml","OpenGL ES 3.1")
cmd void glEnable(GLenum capability) {
  minRequiredVersion(2, 0)
  switch (capability) {
    case GL_BLEND, GL_CULL_FACE, GL_DEPTH_TEST, GL_DITHER, GL_POLYGON_OFFSET_FILL,
        GL_SAMPLE_ALPHA_TO_COVERAGE, GL_SAMPLE_COVERAGE, GL_SCISSOR_TEST, GL_STENCIL_TEST: {
      // version 2.0
    }
    case GL_PRIMITIVE_RESTART_FIXED_INDEX, GL_RASTERIZER_DISCARD: {
      minRequiredVersion(3, 0)
    }
    case GL_SAMPLE_MASK: {
      minRequiredVersion(3, 1)
    }
    default: {
      glErrorInvalidEnum(capability)
    }
  }

  ctx := GetContext()
  ctx.Capabilities[capability] = true
}

@Doc("https://www.khronos.org/opengles/sdk/docs/man/xhtml/glFinish.xml","OpenGL ES 2.0")
@Doc("https://www.khronos.org/opengles/sdk/docs/man3/html/glFinish.xhtml","OpenGL ES 3.0")
@Doc("https://www.khronos.org/opengles/sdk/docs/man31/html/glFinish.xhtml","OpenGL ES 3.1")
cmd void glFinish() {
  minRequiredVersion(2, 0)

}

@Doc("https://www.khronos.org/opengles/sdk/docs/man/xhtml/glFlush.xml","OpenGL ES 2.0")
@Doc("https://www.khronos.org/opengles/sdk/docs/man3/html/glFlush.xhtml","OpenGL ES 3.0")
@Doc("https://www.khronos.org/opengles/sdk/docs/man31/html/glFlush.xhtml","OpenGL ES 3.1")
cmd void glFlush() {
  minRequiredVersion(2, 0)

}

@Doc("https://www.khronos.org/opengles/sdk/docs/man3/html/glFlushMappedBufferRange.xhtml","OpenGL ES 3.0")
@Doc("https://www.khronos.org/opengles/sdk/docs/man31/html/glFlushMappedBufferRange.xhtml","OpenGL ES 3.1")
cmd void glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) {
  minRequiredVersion(3, 0)
  switch (target) {
    case GL_ARRAY_BUFFER, GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, GL_ELEMENT_ARRAY_BUFFER,
        GL_PIXEL_PACK_BUFFER, GL_PIXEL_UNPACK_BUFFER, GL_TRANSFORM_FEEDBACK_BUFFER,
        GL_UNIFORM_BUFFER: {
      // version 3.0
    }
    default: {
      glErrorInvalidEnum(target)
    }
  }
  // TODO
}

@Doc("https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGetError.xml","OpenGL ES 2.0")
@Doc("https://www.khronos.org/opengles/sdk/docs/man3/html/glGetError.xhtml","OpenGL ES 3.0")
@Doc("https://www.khronos.org/opengles/sdk/docs/man31/html/glGetError.xhtml","OpenGL ES 3.1")
cmd GLenum glGetError() {
  minRequiredVersion(2, 0)

  return ?
}

@Doc("https://www.khronos.org/opengles/sdk/docs/man/xhtml/glHint.xml","OpenGL ES 2.0")
@Doc("https://www.khronos.org/opengles/sdk/docs/man3/html/glHint.xhtml","OpenGL ES 3.0")
@Doc("https://www.khronos.org/opengles/sdk/docs/man31/html/glHint.xhtml","OpenGL ES 3.1")
cmd void glHint(GLenum target, GLenum mode) {
  minRequiredVersion(2, 0)
  switch (target) {
    case GL_GENERATE_MIPMAP_HINT: {
      // version 2.0
    }
    case GL_FRAGMENT_SHADER_DERIVATIVE_HINT: {
      minRequiredVersion(3, 0)
    }
    default: {
      glErrorInvalidEnum(target)
    }
  }
  switch (mode) {
    case GL_DONT_CARE, GL_FASTEST, GL_NICEST: {
      // version 2.0
    }
    default: {
      glErrorInvalidEnum(mode)
    }
  }

  ctx := GetContext()
  ctx.GenerateMipmapHint = mode
}

