/*
 * Copyright 2015 The Cobalt Authors. 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.
 */

#include "glimp/gles/context.h"

#include <algorithm>
#include <string>

#include "glimp/egl/error.h"
#include "glimp/egl/surface.h"
#include "glimp/gles/blend_state.h"
#include "glimp/gles/cull_face_state.h"
#include "glimp/gles/draw_mode.h"
#include "glimp/gles/index_data_type.h"
#include "glimp/gles/pixel_format.h"
#include "glimp/tracing/tracing.h"
#include "starboard/common/log.h"
#include "starboard/common/pointer_arithmetic.h"
#include "starboard/memory.h"
#include "starboard/once.h"

namespace glimp {
namespace gles {

namespace {

std::atomic_int s_context_id_counter_(0);
SbOnceControl s_tls_current_context_key_once_control = SB_ONCE_INITIALIZER;
SbThreadLocalKey s_tls_current_context_key = kSbThreadLocalKeyInvalid;

void InitializeThreadLocalKey() {
  s_tls_current_context_key = SbThreadCreateLocalKey(NULL);
}

SbThreadLocalKey GetThreadLocalKey() {
  SbOnce(&s_tls_current_context_key_once_control, &InitializeThreadLocalKey);
  return s_tls_current_context_key;
}

}  // namespace

Context::Context(std::unique_ptr<ContextImpl> context_impl,
                 Context* share_context)
    : impl_(std::move(context_impl)),
      context_id_(s_context_id_counter_++),
      current_thread_(kSbThreadInvalid),
      has_been_current_(false),
      active_texture_(GL_TEXTURE0),
      enabled_textures_dirty_(true),
      enabled_vertex_attribs_dirty_(true),
      pack_alignment_(4),
      unpack_alignment_(4),
      unpack_row_length_(0),
      error_(GL_NO_ERROR) {
  SbAtomicRelease_Store(&has_swapped_buffers_, 0);
  if (share_context != NULL) {
    resource_manager_ = share_context->resource_manager_;
  } else {
    resource_manager_ = new ResourceManager();
  }

  SetupExtensionsString();

  texture_units_.reset(
      new nb::scoped_refptr<Texture>[impl_->GetMaxFragmentTextureUnits()]);
}

Context* Context::GetTLSCurrentContext() {
  return reinterpret_cast<Context*>(SbThreadGetLocalValue(GetThreadLocalKey()));
}

bool Context::SetTLSCurrentContext(Context* context,
                                   egl::Surface* draw,
                                   egl::Surface* read) {
  SB_DCHECK(context);
  SB_DCHECK(draw);
  SB_DCHECK(read);

  if (context->current_thread() != kSbThreadInvalid &&
      context->current_thread() != SbThreadGetCurrent()) {
    SB_DLOG(WARNING) << "Another thread holds current the context that is to "
                        "be made current on this thread.";
    egl::SetError(EGL_BAD_ACCESS);
    return false;
  }

  // If this thread currently has another context current, release that one
  // before we continue.
  Context* existing_context = GetTLSCurrentContext();
  if (existing_context != context) {
    if (existing_context) {
      existing_context->ReleaseContext();
    }
    SbThreadSetLocalValue(GetThreadLocalKey(),
                          reinterpret_cast<void*>(context));
  }

  context->MakeCurrent(draw, read);
  return true;
}

void Context::ReleaseTLSCurrentContext() {
  Context* existing_context = GetTLSCurrentContext();
  if (existing_context) {
    existing_context->ReleaseContext();
    SbThreadSetLocalValue(GetThreadLocalKey(), NULL);
  }
}

GLenum Context::GetError() {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  GLenum error = error_;
  error_ = GL_NO_ERROR;
  return error;
}

const GLubyte* Context::GetString(GLenum name) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  switch (name) {
    case GL_EXTENSIONS:
      return reinterpret_cast<const GLubyte*>(extensions_string_.c_str());
    case GL_VERSION:
      return reinterpret_cast<const GLubyte*>("OpenGL ES 2.0 (glimp)");
    case GL_VENDOR:
      return reinterpret_cast<const GLubyte*>("Google Inc.");
    case GL_RENDERER:
      return reinterpret_cast<const GLubyte*>("glimp");
    case GL_SHADING_LANGUAGE_VERSION:
      return reinterpret_cast<const GLubyte*>("OpenGL ES GLSL ES 1.00");

    default: {
      SetError(GL_INVALID_ENUM);
      return NULL;
    }
  }
}

void Context::GetIntegerv(GLenum pname, GLint* params) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  switch (pname) {
    case GL_MAX_TEXTURE_SIZE:
      *params = impl_->GetMaxTextureSize();
      break;
    case GL_ACTIVE_TEXTURE:
      *params = static_cast<GLint>(active_texture_);
      break;
    case GL_MAX_RENDERBUFFER_SIZE:
      *params = impl_->GetMaxRenderbufferSize();
      break;
    case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
      // We don't currently support compressed textures.
      *params = 0;
      break;
    case GL_MAX_VERTEX_ATTRIBS:
      *params = impl_->GetMaxVertexAttribs();
      break;
    case GL_MAX_TEXTURE_IMAGE_UNITS:
      *params = impl_->GetMaxFragmentTextureUnits();
      break;
    case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
      *params = impl_->GetMaxFragmentUniformVectors();
      break;
    case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
      *params = impl_->GetMaxVertexTextureImageUnits();
      break;
    case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
      *params = impl_->GetMaxCombinedTextureImageUnits();
      break;
    case GL_UNPACK_ALIGNMENT:
      *params = unpack_alignment_;
      break;
    default: {
      SB_NOTIMPLEMENTED();
      SetError(GL_INVALID_ENUM);
    }
  }
}

void Context::GetShaderiv(GLuint shader, GLenum pname, GLint* params) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  nb::scoped_refptr<Shader> shader_object =
      resource_manager_->GetShader(shader);
  if (!shader_object) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  GLenum result = shader_object->GetShaderiv(pname, params);
  if (result != GL_NO_ERROR) {
    SetError(result);
  }
}

void Context::GetShaderInfoLog(GLuint shader,
                               GLsizei bufsize,
                               GLsizei* length,
                               GLchar* infolog) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (bufsize < 0) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  nb::scoped_refptr<Shader> shader_object =
      resource_manager_->GetShader(shader);
  if (!shader_object) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  shader_object->GetShaderInfoLog(bufsize, length, infolog);
}

void Context::GetProgramiv(GLuint program, GLenum pname, GLint* params) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  nb::scoped_refptr<Program> program_object =
      resource_manager_->GetProgram(program);
  if (!program_object) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  GLenum result = program_object->GetProgramiv(pname, params);
  if (result != GL_NO_ERROR) {
    SetError(result);
  }
}

void Context::GetProgramInfoLog(GLuint program,
                                GLsizei bufsize,
                                GLsizei* length,
                                GLchar* infolog) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (bufsize < 0) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  nb::scoped_refptr<Program> program_object =
      resource_manager_->GetProgram(program);
  if (!program_object) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  program_object->GetProgramInfoLog(bufsize, length, infolog);
}

void Context::PixelStorei(GLenum pname, GLint param) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  switch (pname) {
    case GL_PACK_ALIGNMENT:
    case GL_UNPACK_ALIGNMENT:
      if (param != 1 && param != 4 && param != 8) {
        SetError(GL_INVALID_VALUE);
        return;
      }
      break;

    default:
      if (param < 0) {
        SetError(GL_INVALID_VALUE);
        return;
      }
      break;
  }

  switch (pname) {
    case GL_PACK_ALIGNMENT:
      pack_alignment_ = param;
      break;
    case GL_UNPACK_ALIGNMENT:
      unpack_alignment_ = param;
      break;
    case GL_UNPACK_ROW_LENGTH:
      unpack_row_length_ = param;
      break;
    case GL_PACK_ROW_LENGTH:
    case GL_PACK_SKIP_ROWS:
    case GL_PACK_SKIP_PIXELS:
    case GL_UNPACK_IMAGE_HEIGHT:
    case GL_UNPACK_SKIP_ROWS:
    case GL_UNPACK_SKIP_PIXELS:
    case GL_UNPACK_SKIP_IMAGES:
      SB_NOTIMPLEMENTED();
    default:
      SetError(GL_INVALID_ENUM);
      break;
  }
}

void Context::Enable(GLenum cap) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  switch (cap) {
    case GL_BLEND:
      draw_state_.blend_state.enabled = true;
      draw_state_dirty_flags_.blend_state_dirty = true;
      break;
    case GL_SCISSOR_TEST:
      draw_state_.scissor.enabled = true;
      draw_state_dirty_flags_.scissor_dirty = true;
      break;
    case GL_CULL_FACE:
      draw_state_.cull_face_state.enabled = true;
      draw_state_.cull_face_state.mode = CullFaceState::kBack;
      draw_state_dirty_flags_.cull_face_dirty = true;
      break;
    case GL_DEPTH_TEST:
    case GL_DITHER:
    case GL_STENCIL_TEST:
    case GL_POLYGON_OFFSET_FILL:
    case GL_SAMPLE_ALPHA_TO_COVERAGE:
    case GL_SAMPLE_COVERAGE:
      SB_NOTIMPLEMENTED();
    default:
      SetError(GL_INVALID_ENUM);
  }
}

void Context::Disable(GLenum cap) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  switch (cap) {
    case GL_BLEND:
      draw_state_.blend_state.enabled = false;
      draw_state_dirty_flags_.blend_state_dirty = true;
      break;
    case GL_SCISSOR_TEST:
      draw_state_.scissor.enabled = false;
      draw_state_dirty_flags_.scissor_dirty = true;
      break;
    case GL_CULL_FACE:
      draw_state_.cull_face_state.enabled = false;
      draw_state_dirty_flags_.cull_face_dirty = true;
      break;
    case GL_DEPTH_TEST:
    case GL_DITHER:
    case GL_STENCIL_TEST:
    case GL_POLYGON_OFFSET_FILL:
    case GL_SAMPLE_ALPHA_TO_COVERAGE:
    case GL_SAMPLE_COVERAGE:
      // Since these are not implemented yet, it is not an error to do nothing
      // when we ask for them to be disabled!
      break;
    default:
      SetError(GL_INVALID_ENUM);
  }
}

void Context::ColorMask(GLboolean red,
                        GLboolean green,
                        GLboolean blue,
                        GLboolean alpha) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  draw_state_.color_mask = gles::ColorMask(red, green, blue, alpha);
  draw_state_dirty_flags_.color_mask_dirty = true;
}

void Context::DepthMask(GLboolean flag) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (flag == GL_TRUE) {
    SB_NOTIMPLEMENTED() << "glimp currently does not support depth buffers.";
    SetError(GL_INVALID_OPERATION);
  }
}

void Context::Clear(GLbitfield mask) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  impl_->Clear(mask & GL_COLOR_BUFFER_BIT, mask & GL_DEPTH_BUFFER_BIT,
               mask & GL_STENCIL_BUFFER_BIT, draw_state_,
               &draw_state_dirty_flags_);
}

void Context::ClearColor(GLfloat red,
                         GLfloat green,
                         GLfloat blue,
                         GLfloat alpha) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  draw_state_.clear_color = gles::ClearColor(red, green, blue, alpha);
  draw_state_dirty_flags_.clear_color_dirty = true;
}

namespace {
BlendState::Factor BlendStateFactorFromGLenum(GLenum blend_factor) {
  switch (blend_factor) {
    case GL_ZERO:
      return BlendState::kFactorZero;
    case GL_ONE:
      return BlendState::kFactorOne;
    case GL_SRC_COLOR:
      return BlendState::kFactorSrcColor;
    case GL_ONE_MINUS_SRC_COLOR:
      return BlendState::kFactorOneMinusSrcColor;
    case GL_DST_COLOR:
      return BlendState::kFactorDstColor;
    case GL_ONE_MINUS_DST_COLOR:
      return BlendState::kFactorOneMinusDstColor;
    case GL_SRC_ALPHA:
      return BlendState::kFactorSrcAlpha;
    case GL_ONE_MINUS_SRC_ALPHA:
      return BlendState::kFactorOneMinusSrcAlpha;
    case GL_DST_ALPHA:
      return BlendState::kFactorDstAlpha;
    case GL_ONE_MINUS_DST_ALPHA:
      return BlendState::kFactorOneMinusDstAlpha;
    case GL_CONSTANT_COLOR:
      return BlendState::kFactorConstantColor;
    case GL_ONE_MINUS_CONSTANT_COLOR:
      return BlendState::kFactorOneMinusConstantColor;
    case GL_CONSTANT_ALPHA:
      return BlendState::kFactorConstantAlpha;
    case GL_ONE_MINUS_CONSTANT_ALPHA:
      return BlendState::kFactorOneMinusConstantAlpha;
    case GL_SRC_ALPHA_SATURATE:
      return BlendState::kFactorSrcAlphaSaturate;
    default:
      return BlendState::kFactorInvalid;
  }
}

BlendState::Equation BlendStateEquationFromGLenum(GLenum equation) {
  switch (equation) {
    case GL_FUNC_ADD:
      return BlendState::kEquationFuncAdd;
    case GL_FUNC_SUBTRACT:
      return BlendState::kEquationFuncSubtract;
    case GL_FUNC_REVERSE_SUBTRACT:
      return BlendState::kEquationFuncReverseSubtract;
    default:
      return BlendState::kEquationFuncInvalid;
  }
}
}  // namespace

void Context::BlendFunc(GLenum sfactor, GLenum dfactor) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  BlendState::Factor src_factor = BlendStateFactorFromGLenum(sfactor);
  BlendState::Factor dst_factor = BlendStateFactorFromGLenum(dfactor);
  if (src_factor == BlendState::kFactorInvalid ||
      dst_factor == BlendState::kFactorInvalid) {
    SetError(GL_INVALID_ENUM);
    return;
  }

  draw_state_.blend_state.src_factor = src_factor;
  draw_state_.blend_state.dst_factor = dst_factor;
  draw_state_dirty_flags_.blend_state_dirty = true;
}

void Context::BlendEquation(GLenum mode) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  BlendState::Equation equation = BlendStateEquationFromGLenum(mode);
  if (equation == BlendState::kEquationFuncInvalid) {
    SetError(GL_INVALID_ENUM);
    return;
  }

  draw_state_.blend_state.equation = equation;
  draw_state_dirty_flags_.blend_state_dirty = true;
}

namespace {
CullFaceState::Mode CullFaceModeFromEnum(GLenum mode) {
  switch (mode) {
    case GL_FRONT:
      return CullFaceState::kFront;
    case GL_BACK:
      return CullFaceState::kBack;
    case GL_FRONT_AND_BACK:
      return CullFaceState::kFrontAndBack;
    default:
      return CullFaceState::kModeInvalid;
  }
}
}  // namespace

void Context::CullFace(GLenum mode) {
  CullFaceState::Mode cull_face_mode = CullFaceModeFromEnum(mode);
  if (cull_face_mode == CullFaceState::kModeInvalid) {
    SetError(GL_INVALID_ENUM);
    return;
  }
  draw_state_.cull_face_state.mode = cull_face_mode;
  draw_state_dirty_flags_.cull_face_dirty = true;
}

GLuint Context::CreateProgram() {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  std::unique_ptr<ProgramImpl> program_impl = impl_->CreateProgram();
  SB_DCHECK(program_impl);

  nb::scoped_refptr<Program> program(new Program(std::move(program_impl)));

  return resource_manager_->RegisterProgram(program);
}

void Context::DeleteProgram(GLuint program) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  // As indicated by the specification for glDeleteProgram(),
  //   https://www.khronos.org/opengles/sdk/docs/man/xhtml/glDeleteProgram.xml
  // values of 0 will be silently ignored.
  if (program == 0) {
    return;
  }

  nb::scoped_refptr<Program> program_object =
      resource_manager_->DeregisterProgram(program);

  if (!program_object) {
    SetError(GL_INVALID_VALUE);
  }
}

void Context::AttachShader(GLuint program, GLuint shader) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  nb::scoped_refptr<Program> program_object =
      resource_manager_->GetProgram(program);
  if (!program_object) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  nb::scoped_refptr<Shader> shader_object =
      resource_manager_->GetShader(shader);
  if (!shader_object) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  if (!program_object->AttachShader(shader_object)) {
    // A shader of the given type was already attached.
    SetError(GL_INVALID_OPERATION);
  }
}

void Context::LinkProgram(GLuint program) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  nb::scoped_refptr<Program> program_object =
      resource_manager_->GetProgram(program);
  if (!program_object) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  program_object->Link();

  if (program_object.get() == draw_state_.used_program.get()) {
    MarkUsedProgramDirty();
  }
}

void Context::BindAttribLocation(GLuint program,
                                 GLuint index,
                                 const GLchar* name) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (index >= GL_MAX_VERTEX_ATTRIBS) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  if (name[0] == 'g' && name[1] == 'l' && name[2] == '_') {
    // |name| is not allowed to begin with the reserved prefix, "gl_".
    SetError(GL_INVALID_OPERATION);
    return;
  }
  nb::scoped_refptr<Program> program_object =
      resource_manager_->GetProgram(program);
  if (!program_object) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  program_object->BindAttribLocation(index, name);

  if (program_object.get() == draw_state_.used_program.get()) {
    draw_state_dirty_flags_.vertex_attributes_dirty = true;
  }
}

void Context::UseProgram(GLuint program) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (program == 0) {
    draw_state_.used_program = NULL;
    MarkUsedProgramDirty();
    return;
  }

  nb::scoped_refptr<Program> program_object =
      resource_manager_->GetProgram(program);
  if (!program_object) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  if (!program_object->linked()) {
    // Only linked programs can be used.
    SetError(GL_INVALID_OPERATION);
    return;
  }

  if (program_object.get() != draw_state_.used_program.get()) {
    draw_state_.used_program = program_object;
    MarkUsedProgramDirty();
  }
}

GLuint Context::CreateShader(GLenum type) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  std::unique_ptr<ShaderImpl> shader_impl;
  if (type == GL_VERTEX_SHADER) {
    shader_impl = impl_->CreateVertexShader();
  } else if (type == GL_FRAGMENT_SHADER) {
    shader_impl = impl_->CreateFragmentShader();
  } else {
    SetError(GL_INVALID_ENUM);
    return 0;
  }
  SB_DCHECK(shader_impl);

  nb::scoped_refptr<Shader> shader(new Shader(std::move(shader_impl), type));

  return resource_manager_->RegisterShader(shader);
}

void Context::DeleteShader(GLuint shader) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  // As indicated by the specification for glDeleteShader(),
  //   https://www.khronos.org/opengles/sdk/docs/man/xhtml/glDeleteShader.xml
  // values of 0 will be silently ignored.
  if (shader == 0) {
    return;
  }

  nb::scoped_refptr<Shader> shader_object =
      resource_manager_->DeregisterShader(shader);

  if (!shader_object) {
    SetError(GL_INVALID_VALUE);
  }
}

void Context::ShaderSource(GLuint shader,
                           GLsizei count,
                           const GLchar* const* string,
                           const GLint* length) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (count < 0) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  nb::scoped_refptr<Shader> shader_object =
      resource_manager_->GetShader(shader);

  if (!shader_object) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  shader_object->ShaderSource(count, string, length);
}

void Context::CompileShader(GLuint shader) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  nb::scoped_refptr<Shader> shader_object =
      resource_manager_->GetShader(shader);

  if (!shader_object) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  shader_object->CompileShader();
}

void Context::GenBuffers(GLsizei n, GLuint* buffers) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (n < 0) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  for (GLsizei i = 0; i < n; ++i) {
    std::unique_ptr<BufferImpl> buffer_impl = impl_->CreateBuffer();
    SB_DCHECK(buffer_impl);

    nb::scoped_refptr<Buffer> buffer(new Buffer(std::move(buffer_impl)));

    buffers[i] = resource_manager_->RegisterBuffer(buffer);
  }
}

void Context::GenBuffersForVideoFrame(GLsizei n, GLuint* buffers) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (n < 0) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  for (GLsizei i = 0; i < n; ++i) {
    std::unique_ptr<BufferImpl> buffer_impl =
        impl_->CreateBufferForVideoFrame();
    SB_DCHECK(buffer_impl);

    buffers[i] = resource_manager_->RegisterBuffer(
        nb::make_scoped_refptr(new Buffer(std::move(buffer_impl))));
  }
}

void Context::FrontFace(GLenum mode) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if ((mode != GL_CW) && (mode != GL_CCW)) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  // The default face is GL_CCW, per documentation at:
  // https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glFrontFace.xml
  if (mode != GL_CCW) {
    SB_NOTIMPLEMENTED();
  }
}

void Context::DeleteBuffers(GLsizei n, const GLuint* buffers) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (n < 0) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  for (GLsizei i = 0; i < n; ++i) {
    if (buffers[i] == 0) {
      // Silently ignore 0 buffers.
      continue;
    }

    nb::scoped_refptr<Buffer> buffer_object =
        resource_manager_->DeregisterBuffer(buffers[i]);

    if (!buffer_object) {
      // The specification does not indicate that any error should be set
      // in the case that there was an error deleting a specific buffer.
      //   https://www.khronos.org/opengles/sdk/docs/man/xhtml/glDeleteBuffers.xml
      return;
    }

    if (buffer_object->is_mapped()) {
      // Buffer objects should be unmapped if they are deleted.
      //   https://www.khronos.org/opengles/sdk/docs/man3/html/glMapBufferRange.xhtml
      buffer_object->Unmap();
    }

    // If a bound buffer is deleted, set the bound buffer to NULL. The buffer
    // may be bound to any target, therefore we must scan them all.
    const GLenum buffer_targets[3] = {GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER,
                                      GL_PIXEL_UNPACK_BUFFER};
    for (int target_index = 0; target_index < SB_ARRAY_SIZE(buffer_targets);
         ++target_index) {
      GLenum target = buffer_targets[target_index];
      nb::scoped_refptr<Buffer>* bound_buffer = GetBoundBufferForTarget(target);
      SB_DCHECK(bound_buffer);
      if ((*bound_buffer).get() == buffer_object.get()) {
        *bound_buffer = NULL;
      }
    }
  }
}

namespace {
bool IsValidBufferTarget(GLenum target) {
  switch (target) {
    case GL_ARRAY_BUFFER:
    case GL_ELEMENT_ARRAY_BUFFER:
    case GL_PIXEL_UNPACK_BUFFER:
      return true;
      break;
    case GL_COPY_READ_BUFFER:
    case GL_COPY_WRITE_BUFFER:
    case GL_PIXEL_PACK_BUFFER:
    case GL_TRANSFORM_FEEDBACK_BUFFER:
    case GL_UNIFORM_BUFFER:
      SB_NOTIMPLEMENTED() << "Buffer target " << target
                          << " is not supported "
                             "in glimp.";
    default:
      return false;
  }
}
}  // namespace

void Context::BindBuffer(GLenum target, GLuint buffer) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (!IsValidBufferTarget(target)) {
    SetError(GL_INVALID_ENUM);
    return;
  }

  nb::scoped_refptr<Buffer>* bound_buffer = GetBoundBufferForTarget(target);
  SB_DCHECK(bound_buffer);
  nb::scoped_refptr<Buffer> buffer_object;
  if (buffer != 0) {
    buffer_object = resource_manager_->GetBuffer(buffer);
    if (!buffer_object) {
      // The buffer to be bound is invalid.
      SB_NOTIMPLEMENTED()
          << "Creating buffers with glBindBuffer () not supported";
      return;
    }
  }

  *bound_buffer = buffer_object;
}

void Context::BufferData(GLenum target,
                         GLsizeiptr size,
                         const GLvoid* data,
                         GLenum usage) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (size < 0) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  if (usage != GL_STREAM_DRAW && usage != GL_STATIC_DRAW &&
      usage != GL_DYNAMIC_DRAW) {
    SetError(GL_INVALID_ENUM);
    return;
  }

  if (!IsValidBufferTarget(target)) {
    SetError(GL_INVALID_ENUM);
    return;
  }

  nb::scoped_refptr<Buffer> bound_buffer = *GetBoundBufferForTarget(target);
  if (bound_buffer == 0) {
    SetError(GL_INVALID_OPERATION);
    return;
  }

  if (bound_buffer->is_mapped()) {
    // According to the specification, we must unmap the buffer if its data
    // store is recreated with glBufferData.
    //   https://www.khronos.org/opengles/sdk/docs/man3/html/glMapBufferRange.xhtml
    bound_buffer->Unmap();
  }

  if (!bound_buffer->Allocate(usage, size)) {
    SetError(GL_OUT_OF_MEMORY);
    return;
  }

  if (data) {
    if (!bound_buffer->SetData(0, size, data)) {
      SetError(GL_OUT_OF_MEMORY);
      return;
    }
  }
}

void Context::BufferSubData(GLenum target,
                            GLintptr offset,
                            GLsizeiptr size,
                            const GLvoid* data) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (size < 0 || offset < 0) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  if (!IsValidBufferTarget(target)) {
    SetError(GL_INVALID_ENUM);
    return;
  }

  nb::scoped_refptr<Buffer> bound_buffer = *GetBoundBufferForTarget(target);
  if (bound_buffer == 0) {
    SetError(GL_INVALID_OPERATION);
    return;
  }

  if (offset + size > bound_buffer->size_in_bytes()) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  if (bound_buffer->is_mapped()) {
    // According to the specification, we must unmap the buffer if its data
    // store is recreated with glBufferData.
    //   https://www.khronos.org/opengles/sdk/docs/man3/html/glMapBufferRange.xhtml
    bound_buffer->Unmap();
  }

  // Nothing in the specification says there should be an error if data
  // is NULL.
  if (data) {
    if (!bound_buffer->SetData(offset, size, data)) {
      SetError(GL_OUT_OF_MEMORY);
      return;
    }
  }
}

namespace {
// This function is based off of the logic described in the "Errors" section
// of the specification:
//   https://www.khronos.org/opengles/sdk/docs/man3/html/glMapBufferRange.xhtml
bool MapBufferRangeAccessFlagsAreValid(GLbitfield access) {
  if (access & ~(GL_MAP_READ_BIT | GL_MAP_WRITE_BIT |
                 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT |
                 GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_UNSYNCHRONIZED_BIT)) {
    return false;
  }

  if (!(access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT))) {
    return false;
  }

  if ((access & GL_MAP_READ_BIT) &&
      (access & (GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
                 GL_MAP_UNSYNCHRONIZED_BIT))) {
    return false;
  }

  if ((access & GL_MAP_FLUSH_EXPLICIT_BIT) && !(access & GL_MAP_WRITE_BIT)) {
    return false;
  }

  return true;
}
}  // namespace

void* Context::MapBufferRange(GLenum target,
                              GLintptr offset,
                              GLsizeiptr length,
                              GLbitfield access) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (!IsValidBufferTarget(target)) {
    SetError(GL_INVALID_ENUM);
    return NULL;
  }

  nb::scoped_refptr<Buffer> bound_buffer = *GetBoundBufferForTarget(target);
  if (bound_buffer == 0) {
    SetError(GL_INVALID_OPERATION);
    return NULL;
  }

  if (offset < 0 || length < 0 ||
      offset + length > bound_buffer->size_in_bytes()) {
    SetError(GL_INVALID_VALUE);
    return NULL;
  }

  if (bound_buffer->is_mapped()) {
    SetError(GL_INVALID_OPERATION);
    return NULL;
  }

  if (!MapBufferRangeAccessFlagsAreValid(access)) {
    SetError(GL_INVALID_OPERATION);
    return NULL;
  }

  SB_DCHECK(access & GL_MAP_INVALIDATE_BUFFER_BIT)
      << "glimp requires the GL_MAP_INVALIDATE_BUFFER_BIT flag to be set.";
  SB_DCHECK(access & GL_MAP_UNSYNCHRONIZED_BIT)
      << "glimp requires the GL_MAP_UNSYNCHRONIZED_BIT flag to be set.";
  SB_DCHECK(!(access & GL_MAP_FLUSH_EXPLICIT_BIT))
      << "glimp does not support the GL_MAP_FLUSH_EXPLICIT_BIT flag.";
  SB_DCHECK(length == bound_buffer->size_in_bytes())
      << "glimp only supports mapping the entire buffer.";

  void* mapped = bound_buffer->Map();
  if (!mapped) {
    SetError(GL_OUT_OF_MEMORY);
  }

  return mapped;
}

bool Context::UnmapBuffer(GLenum target) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (!IsValidBufferTarget(target)) {
    SetError(GL_INVALID_ENUM);
    return GL_FALSE;
  }

  nb::scoped_refptr<Buffer> bound_buffer = *GetBoundBufferForTarget(target);
  if (bound_buffer == 0) {
    SetError(GL_INVALID_OPERATION);
    return GL_FALSE;
  }

  if (bound_buffer->is_mapped()) {
    return bound_buffer->Unmap();
  } else {
    // The specification is unclear on what to do in the case where the buffer
    // was not mapped to begin with, so we return GL_FALSE in this case.
    //   https://www.khronos.org/opengles/sdk/docs/man3/html/glMapBufferRange.xhtml
    return GL_FALSE;
  }
}

void Context::LineWidth(GLfloat width) {
  if (width <= 0) {
    SetError(GL_INVALID_VALUE);
    return;
  }
  const GLfloat kDefaultLineWidth = 1.0f;
  if (fabs(width - kDefaultLineWidth) > 0.01f * kDefaultLineWidth) {
    SB_NOTIMPLEMENTED();
  }
}

void Context::MakeCurrent(egl::Surface* draw, egl::Surface* read) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  SB_DCHECK(current_thread_ == kSbThreadInvalid ||
            current_thread_ == SbThreadGetCurrent());

  current_thread_ = SbThreadGetCurrent();

  if (!has_been_current_) {
    // According to the documentation for eglMakeCurrent(),
    //   https://www.khronos.org/registry/egl/sdk/docs/man/html/eglMakeCurrent.xhtml
    // we should set the scissor and viewport to the draw surface the first
    // time this context is made current.
    Scissor(0, 0, draw->impl()->GetWidth(), draw->impl()->GetHeight());
    Viewport(0, 0, draw->impl()->GetWidth(), draw->impl()->GetHeight());

    // Setup the default framebuffers and bind them.
    SB_DCHECK(!default_draw_framebuffer_);
    SB_DCHECK(!default_read_framebuffer_);
    SB_DCHECK(!draw_state_.framebuffer);
    default_draw_framebuffer_ = new Framebuffer(draw);
    default_read_framebuffer_ = new Framebuffer(read);
    draw_state_.framebuffer = default_draw_framebuffer_;
    read_framebuffer_ = default_read_framebuffer_;

    has_been_current_ = true;
  }

  // Update our draw and read framebuffers, marking the framebuffer dirty
  // flag if the default framebuffer is the one that is currently bound.
  if (default_draw_framebuffer_->color_attachment_surface() != draw) {
    default_draw_framebuffer_->UpdateColorSurface(draw);
    if (draw_state_.framebuffer == default_draw_framebuffer_) {
      draw_state_dirty_flags_.framebuffer_dirty = true;
    }
  }
  if (default_read_framebuffer_->color_attachment_surface() != read) {
    default_read_framebuffer_->UpdateColorSurface(read);
  }
}

void Context::ReleaseContext() {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  SB_DCHECK(current_thread_ != kSbThreadInvalid);
  SB_DCHECK(current_thread_ == SbThreadGetCurrent());
  SB_DCHECK(has_been_current_);

  current_thread_ = kSbThreadInvalid;
}

nb::scoped_refptr<Buffer>* Context::GetBoundBufferForTarget(GLenum target) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  switch (target) {
    case GL_ARRAY_BUFFER:
      draw_state_dirty_flags_.array_buffer_dirty = true;
      return &draw_state_.array_buffer;
    case GL_ELEMENT_ARRAY_BUFFER:
      draw_state_dirty_flags_.element_array_buffer_dirty = true;
      return &draw_state_.element_array_buffer;
    case GL_PIXEL_UNPACK_BUFFER:
      return &bound_pixel_unpack_buffer_;
  }

  SB_NOTREACHED();
  return NULL;
}

nb::scoped_refptr<Texture>* Context::GetBoundTextureForTarget(GLenum target,
                                                              GLenum texture) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  switch (target) {
    case GL_TEXTURE_2D:
      return &(texture_units_[texture - GL_TEXTURE0]);
    case GL_TEXTURE_CUBE_MAP:
      SB_NOTREACHED() << "Currently unimplemented in glimp.";
      return NULL;
  }

  SB_NOTREACHED();
  return NULL;
}

void Context::SetupExtensionsString() {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  // Extract the list of extensions from the platform-specific implementation
  // and then turn them into a string.
  ContextImpl::ExtensionList impl_extensions = impl_->GetExtensions();

  extensions_string_ = "";
  for (int i = 0; i < impl_extensions.size(); ++i) {
    if (i > 0) {
      extensions_string_ += " ";
    }
    extensions_string_ += impl_extensions[i];
  }

  // Since extensions_string_ will eventually be returned as an array of
  // unsigned chars, make sure that none of the characters in it are negative.
  for (int i = 0; i < extensions_string_.size(); ++i) {
    SB_DCHECK(extensions_string_[i] > 0);
  }
}

void Context::GenTextures(GLsizei n, GLuint* textures) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (n < 0) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  for (GLsizei i = 0; i < n; ++i) {
    std::unique_ptr<TextureImpl> texture_impl = impl_->CreateTexture();
    SB_DCHECK(texture_impl);

    nb::scoped_refptr<Texture> texture(new Texture(std::move(texture_impl)));

    textures[i] = resource_manager_->RegisterTexture(texture);
  }
}

void Context::DeleteTextures(GLsizei n, const GLuint* textures) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (n < 0) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  for (GLsizei i = 0; i < n; ++i) {
    if (textures[i] == 0) {
      // Silently ignore 0 textures.
      continue;
    }
    nb::scoped_refptr<Texture> texture_object =
        resource_manager_->DeregisterTexture(textures[i]);

    if (!texture_object) {
      // The specification does not indicate that any error should be set
      // in the case that there was an error deleting a specific texture.
      //   https://www.khronos.org/opengles/sdk/1.1/docs/man/glDeleteTextures.xml
      return;
    }

    // If a bound texture is deleted, set the bound texture to NULL. The texture
    // may be bound to multiple texture units, including texture units that are
    // not active, therefore we must scan them all.
    for (int texture_index = 0;
         texture_index < impl_->GetMaxFragmentTextureUnits(); ++texture_index) {
      GLenum texture_unit = texture_index + GL_TEXTURE0;
      nb::scoped_refptr<Texture>* bound_texture =
          GetBoundTextureForTarget(GL_TEXTURE_2D, texture_unit);
      if ((*bound_texture).get() == texture_object.get()) {
        enabled_textures_dirty_ = true;
        *bound_texture = NULL;
      }
    }
  }
}

void Context::ActiveTexture(GLenum texture) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (texture < GL_TEXTURE0 ||
      texture >= GL_TEXTURE0 + impl_->GetMaxFragmentTextureUnits()) {
    SetError(GL_INVALID_ENUM);
    return;
  }

  active_texture_ = texture;
}

void Context::BindTexture(GLenum target, GLuint texture) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP) {
    SetError(GL_INVALID_ENUM);
    return;
  }

  nb::scoped_refptr<Texture>* bound_texture =
      GetBoundTextureForTarget(target, active_texture_);
  SB_DCHECK(bound_texture);
  nb::scoped_refptr<Texture> texture_object;
  if (texture != 0) {
    texture_object = resource_manager_->GetTexture(texture);
    if (!texture_object) {
      // The texture to be bound is invalid.
      SB_NOTIMPLEMENTED()
          << "Creating textures with glBindTexture() not supported";
      return;
    }
  }

  if ((*bound_texture).get() == texture_object.get()) {
    // The new texture being bound is the same as the already the bound
    // texture.
    return;
  }
  *bound_texture = texture_object;
  enabled_textures_dirty_ = true;
}

namespace {
Sampler::MinFilter MinFilterFromGLEnum(GLenum min_filter) {
  switch (min_filter) {
    case GL_NEAREST:
      return Sampler::kMinFilterNearest;
    case GL_LINEAR:
      return Sampler::kMinFilterLinear;
    case GL_NEAREST_MIPMAP_NEAREST:
      return Sampler::kMinFilterNearestMipMapNearest;
    case GL_NEAREST_MIPMAP_LINEAR:
      return Sampler::kMinFilterNearestMipMapLinear;
    case GL_LINEAR_MIPMAP_NEAREST:
      return Sampler::kMinFilterLinearMipMapNearest;
    case GL_LINEAR_MIPMAP_LINEAR:
      return Sampler::kMinFilterLinearMipMapLinear;
    default:
      return Sampler::kMinFilterInvalid;
  }
}

Sampler::MagFilter MagFilterFromGLEnum(GLenum mag_filter) {
  switch (mag_filter) {
    case GL_NEAREST:
      return Sampler::kMagFilterNearest;
    case GL_LINEAR:
      return Sampler::kMagFilterLinear;
    default:
      return Sampler::kMagFilterInvalid;
  }
}

Sampler::WrapMode WrapModeFromGLEnum(GLenum wrap_mode) {
  switch (wrap_mode) {
    case GL_CLAMP_TO_EDGE:
      return Sampler::kWrapModeClampToEdge;
    case GL_MIRRORED_REPEAT:
      return Sampler::kWrapModeMirroredRepeat;
    case GL_REPEAT:
      return Sampler::kWrapModeRepeat;
    default:
      return Sampler::kWrapModeInvalid;
  }
}

GLenum GLEnumFromMinFilter(Sampler::MinFilter min_filter) {
  switch (min_filter) {
    case Sampler::kMinFilterNearest:
      return GL_NEAREST;
    case Sampler::kMinFilterLinear:
      return GL_LINEAR;
    case Sampler::kMinFilterNearestMipMapNearest:
      return GL_NEAREST_MIPMAP_NEAREST;
    case Sampler::kMinFilterNearestMipMapLinear:
      return GL_NEAREST_MIPMAP_LINEAR;
    case Sampler::kMinFilterLinearMipMapNearest:
      return GL_LINEAR_MIPMAP_NEAREST;
    case Sampler::kMinFilterLinearMipMapLinear:
      return GL_LINEAR_MIPMAP_LINEAR;
    default: {
      SB_NOTREACHED();
      return GL_LINEAR;
    }
  }
}

GLenum GLEnumFromMagFilter(Sampler::MagFilter mag_filter) {
  switch (mag_filter) {
    case Sampler::kMagFilterNearest:
      return GL_NEAREST;
    case Sampler::kMagFilterLinear:
      return GL_LINEAR;
    default: {
      SB_NOTREACHED();
      return GL_LINEAR;
    }
  }
}

GLenum GLEnumFromWrapMode(Sampler::WrapMode wrap_mode) {
  switch (wrap_mode) {
    case Sampler::kWrapModeClampToEdge:
      return GL_CLAMP_TO_EDGE;
    case Sampler::kWrapModeMirroredRepeat:
      return GL_MIRRORED_REPEAT;
    case Sampler::kWrapModeRepeat:
      return GL_REPEAT;
    default: {
      SB_NOTREACHED();
      return GL_REPEAT;
    }
  }
}
}  // namespace

void Context::GetTexParameteriv(GLenum target, GLenum pname, GLint* params) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  Sampler* active_sampler = (*GetBoundTextureForTarget(target, active_texture_))
                                ->sampler_parameters();
  switch (pname) {
    case GL_TEXTURE_MAG_FILTER: {
      *params = GLEnumFromMagFilter(active_sampler->mag_filter);
    } break;
    case GL_TEXTURE_MIN_FILTER: {
      *params = GLEnumFromMinFilter(active_sampler->min_filter);
    } break;
    case GL_TEXTURE_WRAP_S: {
      *params = GLEnumFromWrapMode(active_sampler->wrap_s);
    } break;
    case GL_TEXTURE_WRAP_T: {
      *params = GLEnumFromWrapMode(active_sampler->wrap_t);
    } break;

    default: {
      SetError(GL_INVALID_ENUM);
      return;
    }
  }
}

void Context::TexParameteri(GLenum target, GLenum pname, GLint param) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  Sampler* active_sampler = (*GetBoundTextureForTarget(target, active_texture_))
                                ->sampler_parameters();

  switch (pname) {
    case GL_TEXTURE_MAG_FILTER: {
      Sampler::MagFilter mag_filter = MagFilterFromGLEnum(param);
      if (mag_filter == Sampler::kMagFilterInvalid) {
        SetError(GL_INVALID_ENUM);
        return;
      }
      active_sampler->mag_filter = mag_filter;
    } break;
    case GL_TEXTURE_MIN_FILTER: {
      Sampler::MinFilter min_filter = MinFilterFromGLEnum(param);
      if (min_filter == Sampler::kMinFilterInvalid) {
        SetError(GL_INVALID_ENUM);
        return;
      }
      active_sampler->min_filter = min_filter;
    } break;
    case GL_TEXTURE_WRAP_S:
    case GL_TEXTURE_WRAP_T: {
      Sampler::WrapMode wrap_mode = WrapModeFromGLEnum(param);
      if (wrap_mode == Sampler::kWrapModeInvalid) {
        SetError(GL_INVALID_ENUM);
        return;
      }

      if (pname == GL_TEXTURE_WRAP_S) {
        active_sampler->wrap_s = wrap_mode;
      } else {
        SB_DCHECK(pname == GL_TEXTURE_WRAP_T);
        active_sampler->wrap_t = wrap_mode;
      }
    } break;

    default: {
      SetError(GL_INVALID_ENUM);
      return;
    }
  }

  enabled_textures_dirty_ = true;
}

namespace {

bool TextureFormatIsValid(GLenum format) {
  switch (format) {
    case GL_ALPHA:
    case GL_RGB:
    case GL_RGBA:
    case GL_LUMINANCE:
    case GL_LUMINANCE_ALPHA:
    case GL_RED_INTEGER:
      return true;
    default:
      return false;
  }
}

bool TextureTypeIsValid(GLenum type) {
  switch (type) {
    case GL_UNSIGNED_BYTE:
    case GL_UNSIGNED_SHORT:
    case GL_UNSIGNED_SHORT_5_6_5:
    case GL_UNSIGNED_SHORT_4_4_4_4:
    case GL_UNSIGNED_SHORT_5_5_5_1:
      return true;
    default:
      return false;
  }
}

// Converts a GL type and format to a glimp PixelFormat.  Information about
// the different possible values for type and format can be found here:
//   https://www.khronos.org/opengles/sdk/docs/man/xhtml/glTexImage2D.xml
// Note that glimp may not support all possible formats described above.
PixelFormat PixelFormatFromGLTypeAndFormat(GLenum format, GLenum type) {
  if (type == GL_UNSIGNED_BYTE) {
    switch (format) {
      case GL_RGBA:
        return kPixelFormatRGBA8;
      case GL_ALPHA:
        return kPixelFormatA8;
      case GL_LUMINANCE_ALPHA:
        return kPixelFormatBA8;
    }
  } else if (type == GL_UNSIGNED_SHORT && format == GL_RED_INTEGER) {
    return kPixelFormatA16;
  }
  return kPixelFormatInvalid;
}

}  // namespace

void Context::TexImage2D(GLenum target,
                         GLint level,
                         GLint internalformat,
                         GLsizei width,
                         GLsizei height,
                         GLint border,
                         GLenum format,
                         GLenum type,
                         const GLvoid* pixels) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (target != GL_TEXTURE_2D) {
    SB_NOTREACHED() << "Only target=GL_TEXTURE_2D is supported in glimp.";
    SetError(GL_INVALID_ENUM);
    return;
  }

  if (width < 0 || height < 0 || level < 0 || border != 0) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  int max_texture_size = impl_->GetMaxTextureSize();
  if (width > max_texture_size || height > max_texture_size) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  if (format != internalformat) {
    SetError(GL_INVALID_OPERATION);
    return;
  }

  if (!TextureFormatIsValid(format)) {
    SetError(GL_INVALID_ENUM);
    return;
  }

  if (!TextureTypeIsValid(type)) {
    SetError(GL_INVALID_ENUM);
    return;
  }

  // Fold format and type together to determine a single glimp PixelFormat
  // value for the incoming data.
  PixelFormat pixel_format = PixelFormatFromGLTypeAndFormat(format, type);
  SB_DCHECK(pixel_format != kPixelFormatInvalid)
      << "Pixel format not supported by glimp.";

  nb::scoped_refptr<Texture> texture_object =
      *GetBoundTextureForTarget(target, active_texture_);
  if (!texture_object) {
    // According to the specification, no error is generated if no texture
    // is bound.
    //   https://www.khronos.org/opengles/sdk/docs/man/xhtml/glTexImage2D.xml
    return;
  }

  // The incoming pixel data should be aligned as the client has specified
  // that it will be.
  SB_DCHECK(starboard::common::IsAligned(
      pixels, static_cast<size_t>(unpack_alignment_)));

  // Determine pitch taking into account glPixelStorei() settings.
  int pitch_in_bytes = GetPitchForTextureData(width, pixel_format);

  texture_object->Initialize(level, pixel_format, width, height);

  if (bound_pixel_unpack_buffer_) {
    if (bound_pixel_unpack_buffer_->is_mapped() ||
        height * pitch_in_bytes > bound_pixel_unpack_buffer_->size_in_bytes()) {
      SetError(GL_INVALID_OPERATION);
      return;
    }

    texture_object->UpdateDataFromBuffer(
        level, 0, 0, width, height, pitch_in_bytes, bound_pixel_unpack_buffer_,
        starboard::common::AsInteger(pixels));
  } else if (pixels) {
    if (!texture_object->UpdateData(level, 0, 0, width, height, pitch_in_bytes,
                                    pixels)) {
      SetError(GL_OUT_OF_MEMORY);
    }
  }
}

void Context::TexSubImage2D(GLenum target,
                            GLint level,
                            GLint xoffset,
                            GLint yoffset,
                            GLsizei width,
                            GLsizei height,
                            GLenum format,
                            GLenum type,
                            const GLvoid* pixels) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (target != GL_TEXTURE_2D) {
    SB_NOTREACHED() << "Only target=GL_TEXTURE_2D is supported in glimp.";
    SetError(GL_INVALID_ENUM);
    return;
  }

  if (width < 0 || height < 0 || level < 0 || xoffset < 0 || yoffset < 0) {
    SetError(GL_INVALID_VALUE);
  }

  if (!TextureFormatIsValid(format)) {
    SetError(GL_INVALID_ENUM);
    return;
  }

  if (!TextureTypeIsValid(type)) {
    SetError(GL_INVALID_ENUM);
    return;
  }

  PixelFormat pixel_format = PixelFormatFromGLTypeAndFormat(format, type);
  SB_DCHECK(pixel_format != kPixelFormatInvalid)
      << "Pixel format not supported by glimp.";

  nb::scoped_refptr<Texture> texture_object =
      *GetBoundTextureForTarget(target, active_texture_);
  if (!texture_object) {
    // According to the specification, no error is generated if no texture
    // is bound.
    //   https://www.khronos.org/opengles/sdk/docs/man/xhtml/glTexSubImage2D.xml
    return;
  }

  if (!texture_object->texture_allocated() ||
      pixel_format != texture_object->pixel_format()) {
    SetError(GL_INVALID_OPERATION);
    return;
  }

  if (xoffset + width > texture_object->width() ||
      yoffset + height > texture_object->height()) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  // The incoming pixel data should be aligned as the client has specified
  // that it will be.
  SB_DCHECK(starboard::common::IsAligned(
      pixels, static_cast<size_t>(unpack_alignment_)));

  // Determine pitch taking into account glPixelStorei() settings.
  int pitch_in_bytes = GetPitchForTextureData(width, pixel_format);

  if (bound_pixel_unpack_buffer_) {
    if (bound_pixel_unpack_buffer_->is_mapped() ||
        height * pitch_in_bytes > bound_pixel_unpack_buffer_->size_in_bytes()) {
      SetError(GL_INVALID_OPERATION);
      return;
    }

    texture_object->UpdateDataFromBuffer(
        level, xoffset, yoffset, width, height, pitch_in_bytes,
        bound_pixel_unpack_buffer_, starboard::common::AsInteger(pixels));
  } else {
    if (!texture_object->UpdateData(level, xoffset, yoffset, width, height,
                                    pitch_in_bytes, pixels)) {
      SetError(GL_OUT_OF_MEMORY);
    }
  }
}

void Context::CopyTexSubImage2D(GLenum target,
                                GLint level,
                                GLint xoffset,
                                GLint yoffset,
                                GLint x,
                                GLint y,
                                GLsizei width,
                                GLsizei height) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (target != GL_TEXTURE_2D) {
    SB_NOTREACHED() << "Only target=GL_TEXTURE_2D is supported in glimp.";
    SetError(GL_INVALID_ENUM);
    return;
  }

  if (width < 0 || height < 0 || level < 0 || xoffset < 0 || yoffset < 0) {
    SetError(GL_INVALID_VALUE);
  }

  nb::scoped_refptr<Texture> texture_object =
      *GetBoundTextureForTarget(target, active_texture_);
  if (!texture_object) {
    // According to the specification, no error is generated if no texture
    // is bound.
    //   https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCopyTexSubImage2D.xml
    return;
  }

  if (!texture_object->texture_allocated()) {
    SetError(GL_INVALID_OPERATION);
    return;
  }

  if (xoffset + width > texture_object->width() ||
      yoffset + height > texture_object->height()) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  if (read_framebuffer_->CheckFramebufferStatus() != GL_FRAMEBUFFER_COMPLETE) {
    SetError(GL_INVALID_FRAMEBUFFER_OPERATION);
    return;
  }

  // The pixels in the rectangle are processed exactly as if glReadPixels had
  // been called with format set to GL_RGBA, but the process stops just after
  // conversion of RGBA values. Subsequent processing is identical to that
  // described for glTexSubImage2D.
  uint8_t pixels[read_framebuffer_->GetWidth() *
                 read_framebuffer_->GetHeight() *
                 BytesPerPixel(kPixelFormatRGBA8)];
  ReadPixels(0, 0, read_framebuffer_->GetWidth(),
             read_framebuffer_->GetHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
             &pixels);

  // If any of the pixels within the specified rectangle are outside the
  // framebuffer associated with the current rendering context, then the values
  // obtained for those pixels are undefined. Make sure that we only access
  // pixels within a valid range.
  x = std::max(0, x);
  y = std::max(0, y);
  width = std::min(read_framebuffer_->GetWidth() - x, width);
  height = std::min(read_framebuffer_->GetHeight() - y, height);
  int pitch_in_bytes =
      read_framebuffer_->GetWidth() * BytesPerPixel(kPixelFormatRGBA8);
  if (!texture_object->UpdateData(
          level, xoffset, yoffset, width, height, pitch_in_bytes,
          &pixels[y * pitch_in_bytes + x * BytesPerPixel(kPixelFormatRGBA8)])) {
    SetError(GL_OUT_OF_MEMORY);
  }
}

void Context::GenFramebuffers(GLsizei n, GLuint* framebuffers) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (n < 0) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  for (GLsizei i = 0; i < n; ++i) {
    nb::scoped_refptr<Framebuffer> framebuffer(new Framebuffer());

    framebuffers[i] = resource_manager_->RegisterFramebuffer(framebuffer);
  }
}

void Context::DeleteFramebuffers(GLsizei n, const GLuint* framebuffers) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (n < 0) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  for (GLsizei i = 0; i < n; ++i) {
    if (framebuffers[i] == 0) {
      // Silently ignore 0 framebuffers.
      continue;
    }

    nb::scoped_refptr<Framebuffer> framebuffer_object =
        resource_manager_->DeregisterFramebuffer(framebuffers[i]);

    if (!framebuffer_object) {
      // The specification does not indicate that any error should be set
      // in the case that there was an error deleting a specific framebuffer.
      //   https://www.khronos.org/opengles/sdk/docs/man/xhtml/glDeleteFramebuffers.xml
      return;
    }

    // If a bound framebuffer is deleted, set the bound framebuffer back to
    // the default framebuffer.
    if (framebuffer_object == draw_state_.framebuffer) {
      SetBoundDrawFramebufferToDefault();
    }
    if (framebuffer_object == read_framebuffer_) {
      SetBoundReadFramebufferToDefault();
    }
  }
}

void Context::BindFramebuffer(GLenum target, GLuint framebuffer) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (target != GL_FRAMEBUFFER) {
    SetError(GL_INVALID_ENUM);
    return;
  }

  if (framebuffer == 0) {
    SetBoundDrawFramebufferToDefault();
    SetBoundReadFramebufferToDefault();
    return;
  }

  nb::scoped_refptr<Framebuffer> framebuffer_object =
      resource_manager_->GetFramebuffer(framebuffer);

  if (!framebuffer_object) {
    // According to the specification, no error is generated if the buffer is
    // invalid.
    //   https://www.khronos.org/opengles/sdk/docs/man/xhtml/glBindFramebuffer.xml
    SB_DLOG(WARNING) << "Could not glBindFramebuffer() to invalid framebuffer.";
    return;
  }

  draw_state_.framebuffer = framebuffer_object;
  draw_state_dirty_flags_.framebuffer_dirty = true;

  read_framebuffer_ = framebuffer_object;
}

void Context::FramebufferTexture2D(GLenum target,
                                   GLenum attachment,
                                   GLenum textarget,
                                   GLuint texture,
                                   GLint level) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (target != GL_FRAMEBUFFER) {
    SetError(GL_INVALID_ENUM);
    return;
  }

  if (IsDefaultDrawFramebufferBound() || IsDefaultReadFramebufferBound()) {
    SetError(GL_INVALID_OPERATION);
    return;
  }

  if (textarget != GL_TEXTURE_2D) {
    SB_NOTREACHED() << "Only textarget=GL_TEXTURE_2D is supported in glimp.";
    SetError(GL_INVALID_ENUM);
    return;
  }

  if (attachment != GL_COLOR_ATTACHMENT0) {
    SB_NOTREACHED()
        << "Only attachment=GL_COLOR_ATTACHMENT0 is supported in glimp.";
    SetError(GL_INVALID_ENUM);
    return;
  }

  nb::scoped_refptr<Texture> texture_object;
  if (texture != 0) {
    texture_object = resource_manager_->GetTexture(texture);
    if (!texture_object) {
      SetError(GL_INVALID_OPERATION);
      return;
    }
  }

  draw_state_.framebuffer->AttachTexture2D(texture_object, level);
}

GLenum Context::CheckFramebufferStatus(GLenum target) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (target != GL_FRAMEBUFFER) {
    SetError(GL_INVALID_ENUM);
    return 0;
  }

  return draw_state_.framebuffer->CheckFramebufferStatus();
}

void Context::FramebufferRenderbuffer(GLenum target,
                                      GLenum attachment,
                                      GLenum renderbuffertarget,
                                      GLuint renderbuffer) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (target != GL_FRAMEBUFFER || renderbuffertarget != GL_RENDERBUFFER) {
    SetError(GL_INVALID_ENUM);
    return;
  }

  SB_DCHECK(attachment != GL_COLOR_ATTACHMENT0)
      << "glimp does not support attaching color renderbuffers to "
         "framebuffers.";

  if (IsDefaultDrawFramebufferBound()) {
    SetError(GL_INVALID_OPERATION);
    return;
  }

  nb::scoped_refptr<Renderbuffer> renderbuffer_object = nullptr;

  // Resolve the actual render buffer object to bind if we are not binding
  // render buffer 0, in which case we leave the value to set as NULL.
  if (renderbuffer != 0) {
    renderbuffer_object = resource_manager_->GetRenderbuffer(renderbuffer);

    if (!renderbuffer_object) {
      SetError(GL_INVALID_OPERATION);
      return;
    }
  }

  switch (attachment) {
    case GL_DEPTH_ATTACHMENT:
      draw_state_.framebuffer->SetDepthAttachment(renderbuffer_object);
      break;
    case GL_STENCIL_ATTACHMENT:
      draw_state_.framebuffer->SetStencilAttachment(renderbuffer_object);
      break;
    default:
      SetError(GL_INVALID_ENUM);
  }
}

void Context::GenRenderbuffers(GLsizei n, GLuint* renderbuffers) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (n < 0) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  for (GLsizei i = 0; i < n; ++i) {
    nb::scoped_refptr<Renderbuffer> renderbuffer(new Renderbuffer());

    renderbuffers[i] = resource_manager_->RegisterRenderbuffer(renderbuffer);
  }
}

void Context::DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (n < 0) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  for (GLsizei i = 0; i < n; ++i) {
    if (renderbuffers[i] == 0) {
      // Silently ignore 0 renderbuffers.
      continue;
    }

    nb::scoped_refptr<Renderbuffer> renderbuffer_object =
        resource_manager_->DeregisterRenderbuffer(renderbuffers[i]);

    if (!renderbuffer_object) {
      // The specification does not indicate that any error should be set
      // in the case that there was an error deleting a specific renderbuffer.
      //   https://www.khronos.org/opengles/sdk/docs/man/xhtml/glDeleteRenderbuffers.xml
      return;
    }

    // If we're deleting the currently bound renderbuffer, set the currently
    // bound render buffer to NULL.
    if (renderbuffer_object == bound_renderbuffer_) {
      bound_renderbuffer_ = NULL;
    }
  }
}

void Context::BindRenderbuffer(GLenum target, GLuint renderbuffer) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (target != GL_RENDERBUFFER) {
    SetError(GL_INVALID_ENUM);
    return;
  }

  if (renderbuffer == 0) {
    bound_renderbuffer_ = NULL;
    return;
  }

  nb::scoped_refptr<Renderbuffer> renderbuffer_object =
      resource_manager_->GetRenderbuffer(renderbuffer);

  if (!renderbuffer_object) {
    // According to the specification, no error is generated if the buffer is
    // invalid.
    //   https://www.khronos.org/opengles/sdk/docs/man/xhtml/glBindRenderbuffer.xml
    SB_DLOG(WARNING)
        << "Could not glBindRenderbuffer() to invalid renderbuffer.";
    return;
  }

  bound_renderbuffer_ = renderbuffer_object;
}

namespace {
// Valid formats as listed here:
//   https://www.khronos.org/opengles/sdk/docs/man/xhtml/glRenderbufferStorage.xml
bool RenderbufferStorageFormatIsValid(GLenum internalformat) {
  switch (internalformat) {
    case GL_RGBA4:
    case GL_RGB565:
    case GL_RGB5_A1:
    case GL_DEPTH_COMPONENT16:
    case GL_STENCIL_INDEX8:
      return true;
    default:
      return false;
  }
}
}  // namespace

void Context::RenderbufferStorage(GLenum target,
                                  GLenum internalformat,
                                  GLsizei width,
                                  GLsizei height) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (target != GL_RENDERBUFFER) {
    SetError(GL_INVALID_ENUM);
    return;
  }

  if (!RenderbufferStorageFormatIsValid(internalformat)) {
    SetError(GL_INVALID_ENUM);
    return;
  }

  if (width < 0 || height < 0) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  if (bound_renderbuffer_ == 0) {
    SetError(GL_INVALID_OPERATION);
    return;
  }

  bound_renderbuffer_->Initialize(internalformat, width, height);
}

void Context::StencilMask(GLuint mask) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (mask != 0xFFFFFFFF) {
    // If we are not setting stencil mask to its initial value then indicate
    // that our implementation is lacking.
    SB_NOTIMPLEMENTED();
  }
}

void Context::ClearStencil(GLint s) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (s != 0) {
    // If we are not setting stencil clear to its initial value then indicate
    // that our implementation is lacking.
    SB_NOTIMPLEMENTED();
  }
}

void Context::Viewport(GLint x, GLint y, GLsizei width, GLsizei height) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  draw_state_.viewport.rect = nb::Rect<int>(x, y, width, height);
  draw_state_dirty_flags_.viewport_dirty = true;
}

void Context::Scissor(GLint x, GLint y, GLsizei width, GLsizei height) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (x < 0) {
    SB_DLOG(WARNING) << "glScissor() x coordinate is set to negative.";
  }
  if (y < 0) {
    SB_DLOG(WARNING) << "glScissor() y coordinate is set to negative.";
  }
  draw_state_.scissor.rect = nb::Rect<int>(x, y, width, height);
  draw_state_dirty_flags_.scissor_dirty = true;
}

namespace {
// Converts from the GLenum passed into glVertexAttribPointer() to the enum
// defined in VertexAttribute.
static VertexAttributeType VertexAttributeTypeFromGLEnum(GLenum type) {
  switch (type) {
    case GL_BYTE:
      return kVertexAttributeTypeByte;
    case GL_UNSIGNED_BYTE:
      return kVertexAttributeTypeUnsignedByte;
    case GL_SHORT:
      return kVertexAttributeTypeShort;
    case GL_UNSIGNED_SHORT:
      return kVertexAttributeTypeUnsignedShort;
    case GL_FIXED:
      return kVertexAttributeTypeFixed;
    case GL_FLOAT:
      return kVertexAttributeTypeFloat;
    case GL_HALF_FLOAT:
      return kVertexAttributeTypeHalfFloat;
    default:
      return kVertexAttributeTypeInvalid;
  }
}
}  // namespace

void Context::VertexAttribPointer(GLuint indx,
                                  GLint size,
                                  GLenum type,
                                  GLboolean normalized,
                                  GLsizei stride,
                                  const GLvoid* ptr) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (indx >= GL_MAX_VERTEX_ATTRIBS) {
    SetError(GL_INVALID_VALUE);
    return;
  }
  if (size < 1 || size > 4) {
    SetError(GL_INVALID_VALUE);
    return;
  }
  if (stride < 0) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  VertexAttributeType vertex_attribute_type =
      VertexAttributeTypeFromGLEnum(type);
  if (vertex_attribute_type == kVertexAttributeTypeInvalid) {
    SetError(GL_INVALID_ENUM);
    return;
  }

  vertex_attrib_map_[indx] =
      VertexAttributeArray(size, vertex_attribute_type, normalized, stride,
                           static_cast<int>(reinterpret_cast<uintptr_t>(ptr)));
  if (enabled_vertex_attribs_.find(indx) != enabled_vertex_attribs_.end()) {
    enabled_vertex_attribs_dirty_ = true;
  }
}

void Context::EnableVertexAttribArray(GLuint index) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (index >= GL_MAX_VERTEX_ATTRIBS) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  enabled_vertex_attribs_.insert(index);
  enabled_vertex_attribs_dirty_ = true;
}

void Context::DisableVertexAttribArray(GLuint index) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (index >= GL_MAX_VERTEX_ATTRIBS) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  enabled_vertex_attribs_.erase(index);
  enabled_vertex_attribs_dirty_ = true;
}

void Context::VertexAttribfv(GLuint indx,
                             int elem_size,
                             const GLfloat* values) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  SB_DCHECK(elem_size > 0);
  SB_DCHECK(elem_size <= 4);

  VertexAttributeConstant* value = &const_vertex_attrib_map_[indx];
  memset(value, 0, sizeof(*value));
  for (int i = 0; i < elem_size; ++i) {
    value->data[i] = values[i];
  }
  value->size = elem_size;
  value->type = kVertexAttributeTypeFloat;

  enabled_vertex_attribs_dirty_ = true;
}

GLint Context::GetUniformLocation(GLuint program, const GLchar* name) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (name[0] == 'g' && name[1] == 'l' && name[2] == '_') {
    // |name| is not allowed to begin with the reserved prefix, "gl_".
    return -1;
  }

  nb::scoped_refptr<Program> program_object =
      resource_manager_->GetProgram(program);
  if (!program_object) {
    SetError(GL_INVALID_VALUE);
    return -1;
  }

  if (!program_object->linked()) {
    SetError(GL_INVALID_OPERATION);
    return -1;
  }

  return program_object->GetUniformLocation(name);
}

void Context::Uniformiv(GLint location,
                        GLsizei count,
                        GLsizei elem_size,
                        const GLint* v) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  SB_DCHECK(elem_size >= 1 && elem_size <= 4);

  if (count < 0) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  if (!draw_state_.used_program) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  GLenum result =
      draw_state_.used_program->Uniformiv(location, count, elem_size, v);
  if (result == GL_NO_ERROR) {
    draw_state_dirty_flags_.uniforms_dirty.Mark(location);
  } else {
    SetError(result);
  }
}

void Context::Uniformfv(GLint location,
                        GLsizei count,
                        GLsizei elem_size,
                        const GLfloat* v) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  SB_DCHECK(elem_size >= 1 && elem_size <= 4);

  if (count < 0) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  if (!draw_state_.used_program) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  GLenum result =
      draw_state_.used_program->Uniformfv(location, count, elem_size, v);
  if (result == GL_NO_ERROR) {
    draw_state_dirty_flags_.uniforms_dirty.Mark(location);
  } else {
    SetError(result);
  }
}

void Context::UniformMatrixfv(GLint location,
                              GLsizei count,
                              GLboolean transpose,
                              GLsizei dim_size,
                              const GLfloat* value) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  SB_DCHECK(dim_size >= 2 && dim_size <= 4);

  if (transpose != GL_FALSE) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  if (!draw_state_.used_program) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  GLenum result = draw_state_.used_program->UniformMatrixfv(location, count,
                                                            dim_size, value);
  if (result == GL_NO_ERROR) {
    draw_state_dirty_flags_.uniforms_dirty.Mark(location);
  } else {
    SetError(result);
  }
}

namespace {
DrawMode DrawModeFromGLEnum(GLenum mode) {
  switch (mode) {
    case GL_POINTS:
      return kDrawModePoints;
    case GL_LINE_STRIP:
      return kDrawModeLineStrip;
    case GL_LINE_LOOP:
      return kDrawModeLineLoop;
    case GL_LINES:
      return kDrawModeLines;
    case GL_TRIANGLE_STRIP:
      return kDrawModeTriangleStrip;
    case GL_TRIANGLE_FAN:
      return kDrawModeTriangleFan;
    case GL_TRIANGLES:
      return kDrawModeTriangles;
    default:
      return kDrawModeInvalid;
  }
}
}  // namespace

void Context::DrawArrays(GLenum mode, GLint first, GLsizei count) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (count < 0) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  if (draw_state_.framebuffer->CheckFramebufferStatus() !=
      GL_FRAMEBUFFER_COMPLETE) {
    SetError(GL_INVALID_FRAMEBUFFER_OPERATION);
    return;
  }

  DrawMode draw_mode = DrawModeFromGLEnum(mode);
  if (draw_mode == kDrawModeInvalid) {
    SetError(GL_INVALID_ENUM);
    return;
  }

  SB_DCHECK(draw_state_.array_buffer)
      << "glimp only supports vertices from vertex buffers.";

  CompressDrawStateForDrawCall();

  impl_->DrawArrays(draw_mode, first, count, draw_state_,
                    &draw_state_dirty_flags_);
}

namespace {
IndexDataType IndexDataTypeFromGLenum(GLenum type) {
  switch (type) {
    case GL_UNSIGNED_BYTE:
      return kIndexDataTypeUnsignedByte;
    case GL_UNSIGNED_SHORT:
      return kIndexDataTypeUnsignedShort;
    default:
      return kIndexDataTypeInvalid;
  }
}
}  // namespace

void Context::DrawElements(GLenum mode,
                           GLsizei count,
                           GLenum type,
                           const GLvoid* indices) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (count < 0) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  if (draw_state_.framebuffer->CheckFramebufferStatus() !=
      GL_FRAMEBUFFER_COMPLETE) {
    SetError(GL_INVALID_FRAMEBUFFER_OPERATION);
    return;
  }

  DrawMode draw_mode = DrawModeFromGLEnum(mode);
  if (draw_mode == kDrawModeInvalid) {
    SetError(GL_INVALID_ENUM);
    return;
  }

  IndexDataType index_data_type = IndexDataTypeFromGLenum(type);
  if (type == kIndexDataTypeInvalid) {
    SetError(GL_INVALID_ENUM);
    return;
  }

  SB_DCHECK(draw_state_.array_buffer)
      << "glimp only supports vertices from vertex buffers.";
  SB_DCHECK(draw_state_.element_array_buffer)
      << "glimp only supports indices from element vertex buffers.";

  CompressDrawStateForDrawCall();

  impl_->DrawElements(draw_mode, count, index_data_type,
                      reinterpret_cast<intptr_t>(indices), draw_state_,
                      &draw_state_dirty_flags_);
}

namespace {
bool ValidReadPixelsFormat(GLenum format) {
  switch (format) {
    case GL_RGBA:
    case GL_RGBA_INTEGER:
    case GL_RED_INTEGER:
      return true;
      break;
    default:
      return false;
      break;
  }
}

bool ValidReadPixelsType(GLenum type) {
  switch (type) {
    case GL_UNSIGNED_BYTE:
    case GL_UNSIGNED_INT:
    case GL_UNSIGNED_SHORT:
    case GL_INT:
    case GL_FLOAT:
      return true;
      break;
    default:
      return false;
      break;
  }
}
}  // namespace

void Context::ReadPixels(GLint x,
                         GLint y,
                         GLsizei width,
                         GLsizei height,
                         GLenum format,
                         GLenum type,
                         GLvoid* pixels) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (!ValidReadPixelsFormat(format) || !ValidReadPixelsType(type)) {
    SetError(GL_INVALID_ENUM);
    return;
  }

  SB_DCHECK(format == GL_RGBA) << "glimp only supports format=GL_RGBA.";
  SB_DCHECK(type == GL_UNSIGNED_BYTE)
      << "glimp only supports type=GL_UNSIGNED_BYTE.";

  SB_DCHECK(read_framebuffer_->color_attachment_texture())
      << "glimp only supports glReadPixels() calls on non-default "
         "framebuffers.";

  if (x < 0 || y < 0 || width < 0 || height < 0 ||
      x + width > read_framebuffer_->GetWidth() ||
      y + height > read_framebuffer_->GetHeight()) {
    SetError(GL_INVALID_VALUE);
    return;
  }

  // Ensure that all GPU activity (in particular, texture writes) complete
  // before we attempt to read pixel data from the texture.
  Finish();

  read_framebuffer_->color_attachment_texture()->ReadPixelsAsRGBA8(
      x, y, width, height, width * BytesPerPixel(kPixelFormatRGBA8), pixels);
}

void Context::Flush() {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  impl_->Flush();
}

void Context::Finish() {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  impl_->Finish();
}

void Context::SwapBuffers() {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  egl::Surface* surface = default_draw_framebuffer_->color_attachment_surface();
  // If surface is a pixel buffer or a pixmap, eglSwapBuffers has no effect, and
  // no error is generated.
  //   https://www.khronos.org/registry/egl/sdk/docs/man/html/eglSwapBuffers.xhtml
  if (surface->impl()->IsWindowSurface()) {
    Flush();
    impl_->SwapBuffers(surface);
    if (!has_swapped_buffers()) {
      SbAtomicBarrier_Increment(&has_swapped_buffers_, 1);
    }
  }
}

bool Context::BindTextureToEGLSurface(egl::Surface* surface) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  SB_DCHECK(surface->GetTextureTarget() == EGL_TEXTURE_2D);

  const nb::scoped_refptr<Texture>& current_texture =
      *GetBoundTextureForTarget(GL_TEXTURE_2D, active_texture_);

  if (!current_texture) {
    SB_DLOG(WARNING) << "No texture is currently bound during call to "
                        "eglBindTexImage().";
    return false;
  }

  SB_DCHECK(bound_egl_surfaces_.find(surface) == bound_egl_surfaces_.end());

  bool success = current_texture->BindToEGLSurface(surface);
  if (success) {
    bound_egl_surfaces_[surface] = current_texture;
  }

  return success;
}

bool Context::ReleaseTextureFromEGLSurface(egl::Surface* surface) {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  std::map<egl::Surface*, nb::scoped_refptr<Texture> >::iterator found =
      bound_egl_surfaces_.find(surface);
  if (found == bound_egl_surfaces_.end()) {
    SB_LOG(WARNING) << "Releasing EGLSurface was never bound to a texture in "
                       "this context.";
    return false;
  }

  bool success = found->second->ReleaseFromEGLSurface(surface);
  if (success) {
    bound_egl_surfaces_.erase(found);
  }
  return success;
}

void Context::UpdateVertexAttribsInDrawState() {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  // Setup the dense list of enabled vertex attributes.
  draw_state_.vertex_attributes.clear();
  for (std::set<unsigned int>::const_iterator iter =
           enabled_vertex_attribs_.begin();
       iter != enabled_vertex_attribs_.end(); ++iter) {
    draw_state_.vertex_attributes.push_back(
        std::make_pair(*iter, &vertex_attrib_map_[*iter]));
  }

  draw_state_.constant_vertex_attributes.clear();
  for (std::map<unsigned int, VertexAttributeConstant>::iterator iter =
           const_vertex_attrib_map_.begin();
       iter != const_vertex_attrib_map_.end(); ++iter) {
    // Add constant vertex attributes only if they do not have a vertex
    // attribute array enabled for them.
    if (enabled_vertex_attribs_.find(iter->first) ==
        enabled_vertex_attribs_.end()) {
      draw_state_.constant_vertex_attributes.push_back(
          std::make_pair(iter->first, &iter->second));
    }
  }

  draw_state_dirty_flags_.vertex_attributes_dirty = true;
  enabled_vertex_attribs_dirty_ = false;
}

void Context::UpdateSamplersInDrawState() {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  // Setup the list of enabled samplers.
  draw_state_.textures.clear();
  int max_active_textures = impl_->GetMaxFragmentTextureUnits();
  for (int i = 0; i < max_active_textures; ++i) {
    if (texture_units_[i]) {
      draw_state_.textures.push_back(std::make_pair(
          static_cast<unsigned int>(i), texture_units_[i].get()));
    }
  }

  draw_state_dirty_flags_.textures_dirty = true;
  enabled_textures_dirty_ = false;
}

void Context::CompressDrawStateForDrawCall() {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (enabled_vertex_attribs_dirty_) {
    UpdateVertexAttribsInDrawState();
    SB_DCHECK(enabled_vertex_attribs_dirty_ == false);
  }

  if (enabled_textures_dirty_) {
    UpdateSamplersInDrawState();
    SB_DCHECK(enabled_textures_dirty_ == false);
  }
}

void Context::MarkUsedProgramDirty() {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  draw_state_dirty_flags_.MarkUsedProgram();
}

void Context::SetBoundDrawFramebufferToDefault() {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (draw_state_.framebuffer != default_draw_framebuffer_) {
    draw_state_.framebuffer = default_draw_framebuffer_;
    draw_state_dirty_flags_.framebuffer_dirty = true;
  }
}

void Context::SetBoundReadFramebufferToDefault() {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  if (read_framebuffer_ != default_read_framebuffer_) {
    read_framebuffer_ = default_read_framebuffer_;
  }
}

bool Context::IsDefaultDrawFramebufferBound() const {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  return draw_state_.framebuffer == default_draw_framebuffer_;
}

bool Context::IsDefaultReadFramebufferBound() const {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  return read_framebuffer_ == default_read_framebuffer_;
}

int Context::GetPitchForTextureData(int width, PixelFormat pixel_format) const {
  GLIMP_TRACE_EVENT0(__FUNCTION__);
  // The equations for determining the pitch are described here:
  //   https://www.khronos.org/opengles/sdk/docs/man3/html/glPixelStorei.xhtml
  int n = BytesPerPixel(pixel_format);
  int s = 1;
  int len = unpack_row_length_ > 0 ? unpack_row_length_ : width;
  int a = unpack_alignment_;

  if (s >= a) {
    return n * len;
  } else {
    return starboard::common::AlignUp(s * n * len, a) / s;
  }
}

SbAtomic32 Context::has_swapped_buffers_ = 0;

}  // namespace gles
}  // namespace glimp
