Implement immutable texture base/max level clamping

It seems some drivers fail to handle that gracefully, so let's always clamp
to be on the safe side.

BUG=877874
TEST=test case in the bug, gpu_unittests
R=kbr@chromium.org

Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel
Change-Id: I6d93cb9389ea70525df4604112223604577582a2
Reviewed-on: https://chromium-review.googlesource.com/1194994
Reviewed-by: Kenneth Russell <kbr@chromium.org>
Commit-Queue: Zhenyao Mo <zmo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#587264}
bool BackTexture::AllocateStorage(
    const gfx::Size& size, GLenum format, bool zero) {
  DCHECK_NE(id(), 0u);
  ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
                                     decoder_->state_.GetErrorState());
  ScopedTextureBinder binder(&decoder_->state_, id(), Target());
  uint32_t image_size = 0;
  GLES2Util::ComputeImageDataSizes(size.width(), size.height(), 1, format,
                                   GL_UNSIGNED_BYTE, 8, &image_size, nullptr,
                                   nullptr);

  bool success = false;
  size_ = size;
  if (decoder_->should_use_native_gmb_for_backbuffer_) {
    DestroyNativeGpuMemoryBuffer(true);
    success = AllocateNativeGpuMemoryBuffer(size, format, zero);
  } else {
    {
      std::unique_ptr<char[]> zero_data;
      if (zero) {
        zero_data.reset(new char[image_size]);
        memset(zero_data.get(), 0, image_size);
      }

      api()->glTexImage2DFn(Target(),
                            0,  // mip level
                            format, size.width(), size.height(),
                            0,  // border
                            format, GL_UNSIGNED_BYTE, zero_data.get());
    }

    decoder_->texture_manager()->SetLevelInfo(
        texture_ref_.get(), Target(),
        0,  // level
        GL_RGBA, size.width(), size.height(),
        1,  // depth
        0,  // border
        GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(size));
    success = api()->glGetErrorFn() == GL_NO_ERROR;
  }

  if (success) {
    memory_tracker_.TrackMemFree(bytes_allocated_);
    bytes_allocated_ = image_size;
    memory_tracker_.TrackMemAlloc(bytes_allocated_);
  }
  return success;
}

bool BackTexture::AllocateStorage(
    const gfx::Size& size, GLenum format, bool zero) {
  DCHECK_NE(id(), 0u);
  ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
                                     decoder_->state_.GetErrorState());
  ScopedTextureBinder binder(&decoder_->state_, id(), Target());
  uint32_t image_size = 0;
  GLES2Util::ComputeImageDataSizes(size.width(), size.height(), 1, format,
                                   GL_UNSIGNED_BYTE, 8, &image_size, nullptr,
                                   nullptr);

  bool success = false;
  size_ = size;
  if (decoder_->should_use_native_gmb_for_backbuffer_) {
    DestroyNativeGpuMemoryBuffer(true);
    success = AllocateNativeGpuMemoryBuffer(size, format, zero);
  } else {
    {
      std::unique_ptr<char[]> zero_data;
      if (zero) {
        zero_data.reset(new char[image_size]);
        memset(zero_data.get(), 0, image_size);
      }

      api()->glTexImage2DFn(Target(),
                            0,  // mip level
                            format, size.width(), size.height(),
                            0,  // border
                            format, GL_UNSIGNED_BYTE, zero_data.get());
    }

    decoder_->texture_manager()->SetLevelInfo(
        texture_ref_.get(), Target(),
        0,  // level
        GL_RGBA, size.width(), size.height(),
        1,  // depth
        0,  // border
        GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(size));
    success = api()->glGetErrorFn() == GL_NO_ERROR;
  }

  if (success) {
    memory_tracker_.TrackMemFree(bytes_allocated_);
    bytes_allocated_ = image_size;
    memory_tracker_.TrackMemAlloc(bytes_allocated_);
  }
  return success;
}
