// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gpu/command_buffer/service/context_state.h"

#include <stddef.h>

#include <cmath>

#include "gpu/command_buffer/common/gles2_cmd_utils.h"
#include "gpu/command_buffer/service/buffer_manager.h"
#include "gpu/command_buffer/service/framebuffer_manager.h"
#include "gpu/command_buffer/service/program_manager.h"
#include "gpu/command_buffer/service/renderbuffer_manager.h"
#include "gpu/command_buffer/service/transform_feedback_manager.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_version_info.h"

namespace gpu {
namespace gles2 {

namespace {

GLuint Get2dServiceId(const TextureUnit& unit) {
  return unit.bound_texture_2d.get() ? unit.bound_texture_2d->service_id() : 0;
}

GLuint Get2dArrayServiceId(const TextureUnit& unit) {
  return unit.bound_texture_2d_array.get()
             ? unit.bound_texture_2d_array->service_id()
             : 0;
}

GLuint Get3dServiceId(const TextureUnit& unit) {
  return unit.bound_texture_3d.get() ? unit.bound_texture_3d->service_id() : 0;
}

GLuint GetCubeServiceId(const TextureUnit& unit) {
  return unit.bound_texture_cube_map.get()
             ? unit.bound_texture_cube_map->service_id()
             : 0;
}

GLuint GetOesServiceId(const TextureUnit& unit) {
  return unit.bound_texture_external_oes.get()
             ? unit.bound_texture_external_oes->service_id()
             : 0;
}

GLuint GetArbServiceId(const TextureUnit& unit) {
  return unit.bound_texture_rectangle_arb.get()
             ? unit.bound_texture_rectangle_arb->service_id()
             : 0;
}

GLuint GetServiceId(const TextureUnit& unit, GLuint target) {
  switch (target) {
    case GL_TEXTURE_2D:
      return Get2dServiceId(unit);
    case GL_TEXTURE_CUBE_MAP:
      return GetCubeServiceId(unit);
    case GL_TEXTURE_RECTANGLE_ARB:
      return GetArbServiceId(unit);
    case GL_TEXTURE_EXTERNAL_OES:
      return GetOesServiceId(unit);
    default:
      NOTREACHED();
      return 0;
  }
}

bool TargetIsSupported(const FeatureInfo* feature_info, GLuint target) {
  switch (target) {
    case GL_TEXTURE_2D:
      return true;
    case GL_TEXTURE_CUBE_MAP:
      return true;
    case GL_TEXTURE_RECTANGLE_ARB:
      return feature_info->feature_flags().arb_texture_rectangle;
    case GL_TEXTURE_EXTERNAL_OES:
      return feature_info->feature_flags().oes_egl_image_external ||
             feature_info->feature_flags().nv_egl_stream_consumer_external;
    default:
      NOTREACHED();
      return false;
  }
}

GLuint GetBufferId(const Buffer* buffer) {
  if (buffer)
    return buffer->service_id();
  return 0;
}

}  // anonymous namespace.

TextureUnit::TextureUnit() : bind_target(GL_TEXTURE_2D) {}

TextureUnit::TextureUnit(const TextureUnit& other) = default;

TextureUnit::~TextureUnit() = default;

bool Vec4::Equal(const Vec4& other) const {
  if (type_ != other.type_)
    return false;
  switch (type_) {
    case SHADER_VARIABLE_FLOAT:
      for (size_t ii = 0; ii < 4; ++ii) {
        if (v_[ii].float_value != other.v_[ii].float_value)
          return false;
      }
      break;
    case SHADER_VARIABLE_INT:
      for (size_t ii = 0; ii < 4; ++ii) {
        if (v_[ii].int_value != other.v_[ii].int_value)
          return false;
      }
      break;
    case SHADER_VARIABLE_UINT:
      for (size_t ii = 0; ii < 4; ++ii) {
        if (v_[ii].uint_value != other.v_[ii].uint_value)
          return false;
      }
      break;
    default:
      NOTREACHED();
      break;
  }
  return true;
}

template <>
void Vec4::GetValues<GLfloat>(GLfloat* values) const {
  DCHECK(values);
  switch (type_) {
    case SHADER_VARIABLE_FLOAT:
      for (size_t ii = 0; ii < 4; ++ii)
        values[ii] = v_[ii].float_value;
      break;
    case SHADER_VARIABLE_INT:
      for (size_t ii = 0; ii < 4; ++ii)
        values[ii] = static_cast<GLfloat>(v_[ii].int_value);
      break;
    case SHADER_VARIABLE_UINT:
      for (size_t ii = 0; ii < 4; ++ii)
        values[ii] = static_cast<GLfloat>(v_[ii].uint_value);
      break;
    default:
      NOTREACHED();
      break;
  }
}

template <>
void Vec4::GetValues<GLint>(GLint* values) const {
  DCHECK(values);
  switch (type_) {
    case SHADER_VARIABLE_FLOAT:
      for (size_t ii = 0; ii < 4; ++ii)
        values[ii] = static_cast<GLint>(v_[ii].float_value);
      break;
    case SHADER_VARIABLE_INT:
      for (size_t ii = 0; ii < 4; ++ii)
        values[ii] = v_[ii].int_value;
      break;
    case SHADER_VARIABLE_UINT:
      for (size_t ii = 0; ii < 4; ++ii)
        values[ii] = static_cast<GLint>(v_[ii].uint_value);
      break;
    default:
      NOTREACHED();
      break;
  }
}

template <>
void Vec4::GetValues<GLuint>(GLuint* values) const {
  DCHECK(values);
  switch (type_) {
    case SHADER_VARIABLE_FLOAT:
      for (size_t ii = 0; ii < 4; ++ii)
        values[ii] = static_cast<GLuint>(v_[ii].float_value);
      break;
    case SHADER_VARIABLE_INT:
      for (size_t ii = 0; ii < 4; ++ii)
        values[ii] = static_cast<GLuint>(v_[ii].int_value);
      break;
    case SHADER_VARIABLE_UINT:
      for (size_t ii = 0; ii < 4; ++ii)
        values[ii] = v_[ii].uint_value;
      break;
    default:
      NOTREACHED();
      break;
  }
}

template <>
void Vec4::SetValues<GLfloat>(const GLfloat* values) {
  DCHECK(values);
  for (size_t ii = 0; ii < 4; ++ii)
    v_[ii].float_value = values[ii];
  type_ = SHADER_VARIABLE_FLOAT;
}

template <>
void Vec4::SetValues<GLint>(const GLint* values) {
  DCHECK(values);
  for (size_t ii = 0; ii < 4; ++ii)
    v_[ii].int_value = values[ii];
  type_ = SHADER_VARIABLE_INT;
}

template <>
void Vec4::SetValues<GLuint>(const GLuint* values) {
  DCHECK(values);
  for (size_t ii = 0; ii < 4; ++ii)
    v_[ii].uint_value = values[ii];
  type_ = SHADER_VARIABLE_UINT;
}

ContextState::ContextState(FeatureInfo* feature_info,
                           bool track_texture_and_sampler_units)
    : track_texture_and_sampler_units(track_texture_and_sampler_units),
      feature_info_(feature_info) {
  Initialize();
}

ContextState::~ContextState() = default;

void ContextState::SetLineWidthBounds(GLfloat min, GLfloat max) {
  line_width_min_ = min;
  line_width_max_ = max;
}

void ContextState::RestoreTextureUnitBindings(
    GLuint unit,
    const ContextState* prev_state) const {
  DCHECK(unit < texture_units.size() ||
         (unit == 0 && !track_texture_and_sampler_units));

  GLuint service_id_2d = 0u;
  GLuint service_id_2d_array = 0u;
  GLuint service_id_3d = 0u;
  GLuint service_id_cube = 0u;
  GLuint service_id_oes = 0u;
  GLuint service_id_arb = 0u;

  if (track_texture_and_sampler_units) {
    const TextureUnit& texture_unit = texture_units[unit];
    service_id_2d = Get2dServiceId(texture_unit);
    service_id_2d_array = Get2dArrayServiceId(texture_unit);
    service_id_3d = Get3dServiceId(texture_unit);
    service_id_cube = GetCubeServiceId(texture_unit);
    service_id_oes = GetOesServiceId(texture_unit);
    service_id_arb = GetArbServiceId(texture_unit);
  }

  bool bind_texture_2d = true;
  bool bind_texture_cube = true;
  bool bind_texture_oes =
      feature_info_->feature_flags().oes_egl_image_external ||
      feature_info_->feature_flags().nv_egl_stream_consumer_external;
  bool bind_texture_arb = feature_info_->feature_flags().arb_texture_rectangle;
  // TEXTURE_2D_ARRAY and TEXTURE_3D are only applicable from ES3 version.
  // So set it to FALSE by default.
  bool bind_texture_2d_array = false;
  bool bind_texture_3d = false;
  // set the variables to true only if the application is ES3 or newer
  if (feature_info_->IsES3Capable()) {
    bind_texture_2d_array = true;
    bind_texture_3d = true;
  }

  if (prev_state) {
    if (prev_state->track_texture_and_sampler_units) {
      const TextureUnit& prev_unit = prev_state->texture_units[unit];
      bind_texture_2d = service_id_2d != Get2dServiceId(prev_unit);
      bind_texture_2d_array =
          bind_texture_2d_array &&
          service_id_2d_array != Get2dArrayServiceId(prev_unit);
      bind_texture_3d =
          bind_texture_3d && service_id_3d != Get3dServiceId(prev_unit);
      bind_texture_cube = service_id_cube != GetCubeServiceId(prev_unit);
      bind_texture_oes =
          bind_texture_oes && service_id_oes != GetOesServiceId(prev_unit);
      bind_texture_arb =
          bind_texture_arb && service_id_arb != GetArbServiceId(prev_unit);
    } else if (prev_state->texture_units_in_ground_state) {
      bind_texture_2d = service_id_2d;
      bind_texture_2d_array = bind_texture_2d_array && service_id_2d_array;
      bind_texture_3d = bind_texture_3d && service_id_3d;
      bind_texture_cube = service_id_cube;
      bind_texture_oes = bind_texture_oes && service_id_oes;
      bind_texture_arb = bind_texture_arb && service_id_arb;
    } else {
      // We need bind all restore target binding, if texture units is not in
      // ground state.
    }
  }

  // Early-out if nothing has changed from the previous state.
  if (!bind_texture_2d && !bind_texture_2d_array && !bind_texture_3d &&
      !bind_texture_cube && !bind_texture_oes && !bind_texture_arb) {
    return;
  }

  api()->glActiveTextureFn(GL_TEXTURE0 + unit);
  if (bind_texture_2d) {
    api()->glBindTextureFn(GL_TEXTURE_2D, service_id_2d);
  }
  if (bind_texture_cube) {
    api()->glBindTextureFn(GL_TEXTURE_CUBE_MAP, service_id_cube);
  }
  if (bind_texture_oes) {
    api()->glBindTextureFn(GL_TEXTURE_EXTERNAL_OES, service_id_oes);
  }
  if (bind_texture_arb) {
    api()->glBindTextureFn(GL_TEXTURE_RECTANGLE_ARB, service_id_arb);
  }
  if (bind_texture_2d_array) {
    api()->glBindTextureFn(GL_TEXTURE_2D_ARRAY, service_id_2d_array);
  }
  if (bind_texture_3d) {
    api()->glBindTextureFn(GL_TEXTURE_3D, service_id_3d);
  }
}  // namespace gles2

void ContextState::RestoreSamplerBinding(GLuint unit,
                                         const ContextState* prev_state) const {
  if (!feature_info_->IsES3Capable())
    return;
  const scoped_refptr<Sampler>& cur_sampler = sampler_units[unit];
  GLuint cur_id = cur_sampler ? cur_sampler->service_id() : 0;
  GLuint prev_id = 0;
  if (prev_state && prev_state->track_texture_and_sampler_units) {
    const scoped_refptr<Sampler>& prev_sampler =
        prev_state->sampler_units[unit];
    prev_id = prev_sampler ? prev_sampler->service_id() : 0;
  }
  if (!prev_state || !prev_state->sampler_units_in_ground_state ||
      cur_id != prev_id) {
    api()->glBindSamplerFn(unit, cur_id);
  }
}

void ContextState::PushTextureUnpackState() const {
  api()->glPixelStoreiFn(GL_UNPACK_ALIGNMENT, 1);

  if (bound_pixel_unpack_buffer.get()) {
    api()->glBindBufferFn(GL_PIXEL_UNPACK_BUFFER, 0);
    api()->glPixelStoreiFn(GL_UNPACK_ROW_LENGTH, 0);
    api()->glPixelStoreiFn(GL_UNPACK_IMAGE_HEIGHT, 0);
    DCHECK_EQ(0, unpack_skip_pixels);
    DCHECK_EQ(0, unpack_skip_rows);
    DCHECK_EQ(0, unpack_skip_images);
  }
}

void ContextState::RestoreUnpackState() const {
  api()->glPixelStoreiFn(GL_UNPACK_ALIGNMENT, unpack_alignment);
  if (bound_pixel_unpack_buffer.get()) {
    api()->glBindBufferFn(GL_PIXEL_UNPACK_BUFFER,
                          GetBufferId(bound_pixel_unpack_buffer.get()));
    api()->glPixelStoreiFn(GL_UNPACK_ROW_LENGTH, unpack_row_length);
    api()->glPixelStoreiFn(GL_UNPACK_IMAGE_HEIGHT, unpack_image_height);
  }
}

void ContextState::DoLineWidth(GLfloat width) const {
  api()->glLineWidthFn(
      std::min(std::max(width, line_width_min_), line_width_max_));
}

void ContextState::RestoreBufferBindings() const {
  if (vertex_attrib_manager.get()) {
    Buffer* element_array_buffer =
        vertex_attrib_manager->element_array_buffer();
    api()->glBindBufferFn(GL_ELEMENT_ARRAY_BUFFER,
                          GetBufferId(element_array_buffer));
  }
  api()->glBindBufferFn(GL_ARRAY_BUFFER, GetBufferId(bound_array_buffer.get()));
  if (feature_info_->IsES3Capable()) {
    api()->glBindBufferFn(GL_COPY_READ_BUFFER,
                          GetBufferId(bound_copy_read_buffer.get()));
    api()->glBindBufferFn(GL_COPY_WRITE_BUFFER,
                          GetBufferId(bound_copy_write_buffer.get()));
    api()->glBindBufferFn(GL_PIXEL_PACK_BUFFER,
                          GetBufferId(bound_pixel_pack_buffer.get()));
    UpdatePackParameters();
    api()->glBindBufferFn(GL_PIXEL_UNPACK_BUFFER,
                          GetBufferId(bound_pixel_unpack_buffer.get()));
    UpdateUnpackParameters();
    api()->glBindBufferFn(GL_TRANSFORM_FEEDBACK_BUFFER,
                          GetBufferId(bound_transform_feedback_buffer.get()));
    api()->glBindBufferFn(GL_UNIFORM_BUFFER,
                          GetBufferId(bound_uniform_buffer.get()));
  }
}

void ContextState::RestoreRenderbufferBindings() {
  // Require Renderbuffer rebind.
  bound_renderbuffer_valid = false;
}

void ContextState::RestoreProgramSettings(
    const ContextState* prev_state,
    bool restore_transform_feedback_bindings) const {
  bool flag =
      (restore_transform_feedback_bindings && feature_info_->IsES3Capable());
  if (flag && prev_state) {
    if (prev_state->bound_transform_feedback.get() &&
        prev_state->bound_transform_feedback->active() &&
        !prev_state->bound_transform_feedback->paused()) {
      api()->glPauseTransformFeedbackFn();
    }
  }
  api()->glUseProgramFn(current_program.get() ? current_program->service_id()
                                              : 0);
  if (flag) {
    if (bound_transform_feedback.get()) {
      bound_transform_feedback->DoBindTransformFeedback(
          GL_TRANSFORM_FEEDBACK, bound_transform_feedback.get(),
          bound_transform_feedback_buffer.get());
    } else {
      api()->glBindTransformFeedbackFn(GL_TRANSFORM_FEEDBACK, 0);
    }
  }
}

void ContextState::RestoreIndexedUniformBufferBindings(
    const ContextState* prev_state) {
  if (!feature_info_->IsES3Capable())
    return;
  indexed_uniform_buffer_bindings->RestoreBindings(
      prev_state ? prev_state->indexed_uniform_buffer_bindings.get() : nullptr);
}

void ContextState::RestoreActiveTexture() const {
  api()->glActiveTextureFn(GL_TEXTURE0 + active_texture_unit);
}

void ContextState::RestoreAllTextureUnitAndSamplerBindings(
    const ContextState* prev_state) const {
  if (!track_texture_and_sampler_units) {
    if (prev_state) {
      if (!prev_state->track_texture_and_sampler_units) {
        texture_units_in_ground_state =
            prev_state->texture_units_in_ground_state;
        sampler_units_in_ground_state =
            prev_state->sampler_units_in_ground_state;
        return;
      }

      texture_units_in_ground_state = true;
      for (size_t i = 1; i < prev_state->texture_units.size(); ++i) {
        if (prev_state->texture_units[i].AnyTargetBound()) {
          texture_units_in_ground_state = false;
          break;
        }
      }

      // If the current gl texture units are not in ground state, then we do
      // need reset texture unit 0.
      if (texture_units_in_ground_state)
        RestoreTextureUnitBindings(0, prev_state);

      sampler_units_in_ground_state = true;
      for (auto& sampler : prev_state->sampler_units) {
        if (sampler) {
          sampler_units_in_ground_state = false;
          break;
        }
      }
    } else {
      texture_units_in_ground_state = false;
      sampler_units_in_ground_state = false;
    }
  } else {
    // Restore Texture state.
    for (size_t i = 0; i < texture_units.size(); ++i) {
      RestoreTextureUnitBindings(i, prev_state);
      RestoreSamplerBinding(i, prev_state);
    }
    RestoreActiveTexture();
  }
}

void ContextState::RestoreActiveTextureUnitBinding(unsigned int target) const {
  DCHECK(active_texture_unit < texture_units.size() ||
         (active_texture_unit == 0 && !track_texture_and_sampler_units));
  GLuint service_id = 0;
  if (track_texture_and_sampler_units) {
    const TextureUnit& texture_unit = texture_units[active_texture_unit];
    service_id = GetServiceId(texture_unit, target);
  }
  if (TargetIsSupported(feature_info_, target))
    api()->glBindTextureFn(target, service_id);
}

void ContextState::RestoreVertexAttribValues() const {
  for (size_t attrib = 0; attrib < vertex_attrib_manager->num_attribs();
       ++attrib) {
    switch (attrib_values[attrib].type()) {
      case SHADER_VARIABLE_FLOAT: {
        GLfloat v[4];
        attrib_values[attrib].GetValues(v);
        api()->glVertexAttrib4fvFn(attrib, v);
      } break;
      case SHADER_VARIABLE_INT: {
        GLint v[4];
        attrib_values[attrib].GetValues(v);
        api()->glVertexAttribI4ivFn(attrib, v);
      } break;
      case SHADER_VARIABLE_UINT: {
        GLuint v[4];
        attrib_values[attrib].GetValues(v);
        api()->glVertexAttribI4uivFn(attrib, v);
      } break;
      default:
        NOTREACHED();
        break;
    }
  }
}

void ContextState::RestoreVertexAttribArrays(
    const scoped_refptr<VertexAttribManager> attrib_manager) const {
  // This is expected to be called only for VAO with service_id 0,
  // either to restore the default VAO or a virtual VAO with service_id 0.
  GLuint vao_service_id = attrib_manager->service_id();
  DCHECK(vao_service_id == 0);

  // Bind VAO if supported.
  if (feature_info_->feature_flags().native_vertex_array_object)
    api()->glBindVertexArrayOESFn(vao_service_id);

  // Restore vertex attrib arrays.
  for (size_t attrib_index = 0; attrib_index < attrib_manager->num_attribs();
       ++attrib_index) {
    const VertexAttrib* attrib = attrib_manager->GetVertexAttrib(attrib_index);

    // Restore vertex array.
    Buffer* buffer = attrib->buffer();
    GLuint buffer_service_id = buffer ? buffer->service_id() : 0;
    api()->glBindBufferFn(GL_ARRAY_BUFFER, buffer_service_id);
    const void* ptr = reinterpret_cast<const void*>(attrib->offset());
    api()->glVertexAttribPointerFn(attrib_index, attrib->size(), attrib->type(),
                                   attrib->normalized(), attrib->gl_stride(),
                                   ptr);

    // Restore attrib divisor if supported.
    if (feature_info_->feature_flags().angle_instanced_arrays)
      api()->glVertexAttribDivisorANGLEFn(attrib_index, attrib->divisor());

    if (attrib->enabled_in_driver()) {
      api()->glEnableVertexAttribArrayFn(attrib_index);
    } else {
      api()->glDisableVertexAttribArrayFn(attrib_index);
    }
  }
}

void ContextState::RestoreVertexAttribs(const ContextState* prev_state) const {
  // Restore Vertex Attrib Arrays
  DCHECK(vertex_attrib_manager.get());
  // Restore VAOs.
  if (feature_info_->feature_flags().native_vertex_array_object) {
    // If default VAO is still using shared id 0 instead of unique ids
    // per-context, default VAO state must be restored.
    GLuint default_vao_service_id = default_vertex_attrib_manager->service_id();
    if (default_vao_service_id == 0)
      RestoreVertexAttribArrays(default_vertex_attrib_manager);

    // Restore the current VAO binding, unless it's the same as the
    // default above.
    GLuint curr_vao_service_id = vertex_attrib_manager->service_id();
    if (curr_vao_service_id != 0)
      api()->glBindVertexArrayOESFn(curr_vao_service_id);
  } else {
    if (prev_state &&
        prev_state->feature_info_->feature_flags().native_vertex_array_object &&
        feature_info_->workarounds()
            .use_client_side_arrays_for_stream_buffers) {
      // In order to use client side arrays, the driver's default VAO has to be
      // bound.
      api()->glBindVertexArrayOESFn(0);
    }
    // If native VAO isn't supported, emulated VAOs are used.
    // Restore to the currently bound VAO.
    RestoreVertexAttribArrays(vertex_attrib_manager);
  }

  // glVertexAttrib4fv aren't part of VAO state and must be restored.
  RestoreVertexAttribValues();
}

void ContextState::RestoreGlobalState(const ContextState* prev_state) const {
  InitCapabilities(prev_state);
  InitState(prev_state);
}

void ContextState::RestoreState(const ContextState* prev_state) {
  RestoreAllTextureUnitAndSamplerBindings(prev_state);
  // For RasterDecoder, |vertex_attrib_manager| will be nullptr, and we don't
  // need restore vertex attribs for them.
  if (vertex_attrib_manager)
    RestoreVertexAttribs(prev_state);
  // RestoreIndexedUniformBufferBindings must be called before
  // RestoreBufferBindings. This is because setting the indexed uniform buffer
  // bindings via glBindBuffer{Base,Range} also sets the general uniform buffer
  // bindings (glBindBuffer), but not vice versa.
  // For RasterDecoder, |indexed_uniform_buffer_bindings| will be nullptr, and
  // we don't need restore indexed uniform buffer for them.
  if (indexed_uniform_buffer_bindings)
    RestoreIndexedUniformBufferBindings(prev_state);
  RestoreBufferBindings();
  RestoreRenderbufferBindings();
  RestoreProgramSettings(prev_state, true);
  RestoreGlobalState(prev_state);

  // FRAMEBUFFER_SRGB will be restored lazily at render time.
  framebuffer_srgb_valid_ = false;
}

void ContextState::EnableDisable(GLenum pname, bool enable) const {
  if (pname == GL_PRIMITIVE_RESTART_FIXED_INDEX &&
      feature_info_->feature_flags().emulate_primitive_restart_fixed_index) {
    // GLES2DecoderImpl::DoDrawElements can handle this situation
    return;
  }
  if (enable) {
    api()->glEnableFn(pname);
  } else {
    api()->glDisableFn(pname);
  }
}

void ContextState::UpdatePackParameters() const {
  if (!feature_info_->IsES3Capable())
    return;
  if (bound_pixel_pack_buffer.get()) {
    api()->glPixelStoreiFn(GL_PACK_ROW_LENGTH, pack_row_length);
  } else {
    api()->glPixelStoreiFn(GL_PACK_ROW_LENGTH, 0);
  }
}

void ContextState::SetMaxWindowRectangles(size_t max) {
  window_rectangles_ = std::vector<GLint>(max * 4, 0);
}

size_t ContextState::GetMaxWindowRectangles() const {
  size_t size = window_rectangles_.size();
  DCHECK_EQ(0ull, size % 4);
  return size / 4;
}

void ContextState::SetWindowRectangles(GLenum mode,
                                       size_t count,
                                       const volatile GLint* box) {
  window_rectangles_mode = mode;
  num_window_rectangles = count;
  DCHECK_LE(count, GetMaxWindowRectangles());
  if (count) {
    std::copy(box, &box[count * 4], window_rectangles_.begin());
  }
}

void ContextState::UpdateWindowRectangles() const {
  if (!feature_info_->feature_flags().ext_window_rectangles) {
    return;
  }

  if (current_draw_framebuffer_client_id == 0) {
    // Window rectangles must not take effect for client_id 0 (backbuffer).
    api()->glWindowRectanglesEXTFn(GL_EXCLUSIVE_EXT, 0, nullptr);
  } else {
    DCHECK_LE(static_cast<size_t>(num_window_rectangles),
              GetMaxWindowRectangles());
    const GLint* data =
        num_window_rectangles ? window_rectangles_.data() : nullptr;
    api()->glWindowRectanglesEXTFn(window_rectangles_mode,
                                   num_window_rectangles, data);
  }
}

void ContextState::UpdateWindowRectanglesForBoundDrawFramebufferClientID(
    GLuint client_id) {
  bool old_id_nonzero = current_draw_framebuffer_client_id != 0;
  bool new_id_nonzero = client_id != 0;
  current_draw_framebuffer_client_id = client_id;
  // If switching from FBO to backbuffer, or vice versa, update driver state.
  if (old_id_nonzero ^ new_id_nonzero) {
    UpdateWindowRectangles();
  }
}

void ContextState::UpdateUnpackParameters() const {
  if (!feature_info_->IsES3Capable())
    return;
  if (bound_pixel_unpack_buffer.get()) {
    api()->glPixelStoreiFn(GL_UNPACK_ROW_LENGTH, unpack_row_length);
    api()->glPixelStoreiFn(GL_UNPACK_IMAGE_HEIGHT, unpack_image_height);
  } else {
    api()->glPixelStoreiFn(GL_UNPACK_ROW_LENGTH, 0);
    api()->glPixelStoreiFn(GL_UNPACK_IMAGE_HEIGHT, 0);
  }
}

void ContextState::SetBoundBuffer(GLenum target, Buffer* buffer) {
  bool do_refcounting = feature_info_->IsWebGL2OrES3Context();
  switch (target) {
    case GL_ARRAY_BUFFER:
      if (do_refcounting && bound_array_buffer)
        bound_array_buffer->OnUnbind(target, false);
      bound_array_buffer = buffer;
      if (do_refcounting && buffer)
        buffer->OnBind(target, false);
      break;
    case GL_ELEMENT_ARRAY_BUFFER:
      vertex_attrib_manager->SetElementArrayBuffer(buffer);
      break;
    case GL_COPY_READ_BUFFER:
      if (do_refcounting && bound_copy_read_buffer)
        bound_copy_read_buffer->OnUnbind(target, false);
      bound_copy_read_buffer = buffer;
      if (do_refcounting && buffer)
        buffer->OnBind(target, false);
      break;
    case GL_COPY_WRITE_BUFFER:
      if (do_refcounting && bound_copy_write_buffer)
        bound_copy_write_buffer->OnUnbind(target, false);
      bound_copy_write_buffer = buffer;
      if (do_refcounting && buffer)
        buffer->OnBind(target, false);
      break;
    case GL_PIXEL_PACK_BUFFER:
      if (do_refcounting && bound_pixel_pack_buffer)
        bound_pixel_pack_buffer->OnUnbind(target, false);
      bound_pixel_pack_buffer = buffer;
      if (do_refcounting && buffer)
        buffer->OnBind(target, false);
      UpdatePackParameters();
      break;
    case GL_PIXEL_UNPACK_BUFFER:
      if (do_refcounting && bound_pixel_unpack_buffer)
        bound_pixel_unpack_buffer->OnUnbind(target, false);
      bound_pixel_unpack_buffer = buffer;
      if (do_refcounting && buffer)
        buffer->OnBind(target, false);
      UpdateUnpackParameters();
      break;
    case GL_TRANSFORM_FEEDBACK_BUFFER:
      if (do_refcounting && bound_transform_feedback_buffer)
        bound_transform_feedback_buffer->OnUnbind(target, false);
      bound_transform_feedback_buffer = buffer;
      if (do_refcounting && buffer)
        buffer->OnBind(target, false);
      break;
    case GL_UNIFORM_BUFFER:
      if (do_refcounting && bound_uniform_buffer)
        bound_uniform_buffer->OnUnbind(target, false);
      bound_uniform_buffer = buffer;
      if (do_refcounting && buffer)
        buffer->OnBind(target, false);
      break;
    default:
      NOTREACHED();
      break;
  }
}

void ContextState::RemoveBoundBuffer(Buffer* buffer) {
  DCHECK(buffer);
  bool do_refcounting = feature_info_->IsWebGL2OrES3Context();
  if (bound_array_buffer.get() == buffer) {
    bound_array_buffer = nullptr;
    if (do_refcounting)
      buffer->OnUnbind(GL_ARRAY_BUFFER, false);
    if (!context_lost_)
      api()->glBindBufferFn(GL_ARRAY_BUFFER, 0);
  }
  // Needs to be called after bound_array_buffer handled.
  vertex_attrib_manager->Unbind(buffer, bound_array_buffer.get());
  if (bound_copy_read_buffer.get() == buffer) {
    bound_copy_read_buffer = nullptr;
    if (do_refcounting)
      buffer->OnUnbind(GL_COPY_READ_BUFFER, false);
    if (!context_lost_)
      api()->glBindBufferFn(GL_COPY_READ_BUFFER, 0);
  }
  if (bound_copy_write_buffer.get() == buffer) {
    bound_copy_write_buffer = nullptr;
    if (do_refcounting)
      buffer->OnUnbind(GL_COPY_WRITE_BUFFER, false);
    if (!context_lost_)
      api()->glBindBufferFn(GL_COPY_WRITE_BUFFER, 0);
  }
  if (bound_pixel_pack_buffer.get() == buffer) {
    bound_pixel_pack_buffer = nullptr;
    if (do_refcounting)
      buffer->OnUnbind(GL_PIXEL_PACK_BUFFER, false);
    if (!context_lost_)
      api()->glBindBufferFn(GL_PIXEL_PACK_BUFFER, 0);
    UpdatePackParameters();
  }
  if (bound_pixel_unpack_buffer.get() == buffer) {
    bound_pixel_unpack_buffer = nullptr;
    if (do_refcounting)
      buffer->OnUnbind(GL_PIXEL_UNPACK_BUFFER, false);
    if (!context_lost_)
      api()->glBindBufferFn(GL_PIXEL_UNPACK_BUFFER, 0);
    UpdateUnpackParameters();
  }
  if (bound_transform_feedback_buffer.get() == buffer) {
    bound_transform_feedback_buffer = nullptr;
    if (do_refcounting)
      buffer->OnUnbind(GL_TRANSFORM_FEEDBACK_BUFFER, false);
    if (!context_lost_)
      api()->glBindBufferFn(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
  }
  // Needs to be called after bound_transform_feedback_buffer handled.
  if (bound_transform_feedback.get()) {
    bound_transform_feedback->RemoveBoundBuffer(
        GL_TRANSFORM_FEEDBACK_BUFFER, buffer,
        bound_transform_feedback_buffer.get(), !context_lost_);
  }
  if (bound_uniform_buffer.get() == buffer) {
    bound_uniform_buffer = nullptr;
    if (do_refcounting)
      buffer->OnUnbind(GL_UNIFORM_BUFFER, false);
    if (!context_lost_)
      api()->glBindBufferFn(GL_UNIFORM_BUFFER, 0);
  }
  // Needs to be called after bound_uniform_buffer handled.
  if (indexed_uniform_buffer_bindings) {
    indexed_uniform_buffer_bindings->RemoveBoundBuffer(
        GL_UNIFORM_BUFFER, buffer, bound_uniform_buffer.get(), !context_lost_);
  }
}

void ContextState::UnbindTexture(TextureRef* texture) {
  GLuint active_unit = active_texture_unit;
  for (size_t jj = 0; jj < texture_units.size(); ++jj) {
    TextureUnit& unit = texture_units[jj];
    if (unit.bound_texture_2d.get() == texture) {
      unit.bound_texture_2d = nullptr;
      if (active_unit != jj) {
        api()->glActiveTextureFn(GL_TEXTURE0 + jj);
        active_unit = jj;
      }
      api()->glBindTextureFn(GL_TEXTURE_2D, 0);
    } else if (unit.bound_texture_cube_map.get() == texture) {
      unit.bound_texture_cube_map = nullptr;
      if (active_unit != jj) {
        api()->glActiveTextureFn(GL_TEXTURE0 + jj);
        active_unit = jj;
      }
      api()->glBindTextureFn(GL_TEXTURE_CUBE_MAP, 0);
    } else if (unit.bound_texture_external_oes.get() == texture) {
      unit.bound_texture_external_oes = nullptr;
      if (active_unit != jj) {
        api()->glActiveTextureFn(GL_TEXTURE0 + jj);
        active_unit = jj;
      }
      api()->glBindTextureFn(GL_TEXTURE_EXTERNAL_OES, 0);
    } else if (unit.bound_texture_rectangle_arb.get() == texture) {
      unit.bound_texture_rectangle_arb = nullptr;
      if (active_unit != jj) {
        api()->glActiveTextureFn(GL_TEXTURE0 + jj);
        active_unit = jj;
      }
      api()->glBindTextureFn(GL_TEXTURE_RECTANGLE_ARB, 0);
    } else if (unit.bound_texture_3d.get() == texture) {
      unit.bound_texture_3d = nullptr;
      if (active_unit != jj) {
        api()->glActiveTextureFn(GL_TEXTURE0 + jj);
        active_unit = jj;
      }
      api()->glBindTextureFn(GL_TEXTURE_3D, 0);
    } else if (unit.bound_texture_2d_array.get() == texture) {
      unit.bound_texture_2d_array = nullptr;
      if (active_unit != jj) {
        api()->glActiveTextureFn(GL_TEXTURE0 + jj);
        active_unit = jj;
      }
      api()->glBindTextureFn(GL_TEXTURE_2D_ARRAY, 0);
    }
  }

  if (active_unit != active_texture_unit) {
    api()->glActiveTextureFn(GL_TEXTURE0 + active_texture_unit);
  }
}

void ContextState::UnbindSampler(Sampler* sampler) {
  for (size_t jj = 0; jj < sampler_units.size(); ++jj) {
    if (sampler_units[jj].get() == sampler) {
      sampler_units[jj] = nullptr;
      api()->glBindSamplerFn(jj, 0);
    }
  }
}

PixelStoreParams ContextState::GetPackParams() {
  DCHECK_EQ(0, pack_skip_pixels);
  DCHECK_EQ(0, pack_skip_rows);
  PixelStoreParams params;
  params.alignment = pack_alignment;
  params.row_length = pack_row_length;
  return params;
}

PixelStoreParams ContextState::GetUnpackParams(Dimension dimension) {
  DCHECK_EQ(0, unpack_skip_pixels);
  DCHECK_EQ(0, unpack_skip_rows);
  DCHECK_EQ(0, unpack_skip_images);
  PixelStoreParams params;
  params.alignment = unpack_alignment;
  params.row_length = unpack_row_length;
  if (dimension == k3D) {
    params.image_height = unpack_image_height;
  }
  return params;
}

void ContextState::EnableDisableFramebufferSRGB(bool enable) {
  if (framebuffer_srgb_valid_ && framebuffer_srgb_ == enable)
    return;
  EnableDisable(GL_FRAMEBUFFER_SRGB, enable);
  framebuffer_srgb_ = enable;
  framebuffer_srgb_valid_ = true;
}

void ContextState::InitStateManual(const ContextState*) const {
  // Here we always reset the states whether it's different from previous ones.
  // We have very limited states here; also, once we switch to MANGLE, MANGLE
  // will opmitize this.
  UpdatePackParameters();
  UpdateUnpackParameters();
  UpdateWindowRectangles();
}

// Include the auto-generated part of this file. We split this because it means
// we can easily edit the non-auto generated parts right here in this file
// instead of having to edit some template or the code generator.
#include "gpu/command_buffer/service/context_state_impl_autogen.h"

}  // namespace gles2
}  // namespace gpu
