/*
 * Copyright 2015 Google Inc. 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 "nb/pointer_arithmetic.h"
#include "starboard/common/log.h"
#include "starboard/memory.h"
#include "starboard/once.h"

namespace glimp {
namespace gles {

namespace {

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(nb::scoped_ptr<ContextImpl> context_impl,
                 Context* share_context)
    : impl_(context_impl.Pass()),
      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) {
  SbAtomicNoBarrier_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__);
  nb::scoped_ptr<ProgramImpl> program_impl = impl_->CreateProgram();
  SB_DCHECK(program_impl);

  nb::scoped_refptr<Program> program(new Program(program_impl.Pass()));

  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__);
  nb::scoped_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(shader_impl.Pass(), 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) {
    nb::scoped_ptr<BufferImpl> buffer_impl = impl_->CreateBuffer();
    SB_DCHECK(buffer_impl);

    nb::scoped_refptr<Buffer> buffer(new Buffer(buffer_impl.Pass()));

    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) {
    nb::scoped_ptr<BufferImpl> buffer_impl = impl_->CreateBufferForVideoFrame();
    SB_DCHECK(buffer_impl);

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

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 requres 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) {
    nb::scoped_ptr<TextureImpl> texture_impl = impl_->CreateTexture();
    SB_DCHECK(texture_impl);

    nb::scoped_refptr<Texture> texture(new Texture(texture_impl.Pass()));

    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(nb::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_,
        nb::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(nb::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_, nb::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 = NULL;

  // 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];
  SbMemorySet(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()) {
      SbAtomicNoBarrier_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 nb::AlignUp(s * n * len, a) / s;
  }
}

SbAtomic32 Context::has_swapped_buffers_ = 0;

}  // namespace gles
}  // namespace glimp
