Update from https://crrev.com/314320

TBR=jamesr@chromium.org

Review URL: https://codereview.chromium.org/895853003
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_android.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_android.cc
index 5b86b87..2389dc1 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_manager_android.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager_android.cc
@@ -5,8 +5,8 @@
 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
 
 #include "base/command_line.h"
-#include "base/debug/trace_event.h"
 #include "base/sys_info.h"
+#include "base/trace_event/trace_event.h"
 #include "gpu/command_buffer/service/async_pixel_transfer_manager_egl.h"
 #include "gpu/command_buffer/service/async_pixel_transfer_manager_idle.h"
 #include "gpu/command_buffer/service/async_pixel_transfer_manager_stub.h"
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc
index 4b87938..f0faded 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc
@@ -8,13 +8,13 @@
 #include <string>
 
 #include "base/bind.h"
-#include "base/debug/trace_event.h"
-#include "base/debug/trace_event_synthetic_delay.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/thread.h"
+#include "base/trace_event/trace_event.h"
+#include "base/trace_event/trace_event_synthetic_delay.h"
 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
 #include "ui/gl/gl_context.h"
 #include "ui/gl/gl_surface_egl.h"
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc
index de92c0c..2ed4f7d 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc
@@ -5,10 +5,10 @@
 #include "gpu/command_buffer/service/async_pixel_transfer_manager_idle.h"
 
 #include "base/bind.h"
-#include "base/debug/trace_event.h"
-#include "base/debug/trace_event_synthetic_delay.h"
 #include "base/lazy_instance.h"
 #include "base/memory/weak_ptr.h"
+#include "base/trace_event/trace_event.h"
+#include "base/trace_event/trace_event_synthetic_delay.h"
 #include "ui/gl/scoped_binders.h"
 
 namespace gpu {
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_linux.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_linux.cc
index b2be97d..e756a46 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_manager_linux.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager_linux.cc
@@ -5,7 +5,7 @@
 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
 
 #include "base/command_line.h"
-#include "base/debug/trace_event.h"
+#include "base/trace_event/trace_event.h"
 #include "gpu/command_buffer/service/async_pixel_transfer_manager_idle.h"
 #include "gpu/command_buffer/service/async_pixel_transfer_manager_share_group.h"
 #include "gpu/command_buffer/service/async_pixel_transfer_manager_stub.h"
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_mac.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_mac.cc
index 8c19b57..6f7c5d1 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_manager_mac.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager_mac.cc
@@ -4,7 +4,7 @@
 
 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
 
-#include "base/debug/trace_event.h"
+#include "base/trace_event/trace_event.h"
 #include "gpu/command_buffer/service/async_pixel_transfer_manager_idle.h"
 #include "gpu/command_buffer/service/async_pixel_transfer_manager_stub.h"
 #include "ui/gl/gl_implementation.h"
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc
index 4f85e33..16089f6 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc
@@ -7,8 +7,6 @@
 #include <list>
 
 #include "base/bind.h"
-#include "base/debug/trace_event.h"
-#include "base/debug/trace_event_synthetic_delay.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
@@ -18,6 +16,8 @@
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_checker.h"
+#include "base/trace_event/trace_event.h"
+#include "base/trace_event/trace_event_synthetic_delay.h"
 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_context.h"
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_win.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_win.cc
index 6955885..3bf32c0 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_manager_win.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager_win.cc
@@ -4,7 +4,7 @@
 
 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
 
-#include "base/debug/trace_event.h"
+#include "base/trace_event/trace_event.h"
 #include "gpu/command_buffer/service/async_pixel_transfer_manager_idle.h"
 #include "gpu/command_buffer/service/async_pixel_transfer_manager_stub.h"
 #include "ui/gl/gl_implementation.h"
diff --git a/gpu/command_buffer/service/buffer_manager.cc b/gpu/command_buffer/service/buffer_manager.cc
index 94a252c..1f64fd5 100644
--- a/gpu/command_buffer/service/buffer_manager.cc
+++ b/gpu/command_buffer/service/buffer_manager.cc
@@ -4,8 +4,8 @@
 
 #include "gpu/command_buffer/service/buffer_manager.h"
 #include <limits>
-#include "base/debug/trace_event.h"
 #include "base/logging.h"
+#include "base/trace_event/trace_event.h"
 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
 #include "gpu/command_buffer/service/context_state.h"
 #include "gpu/command_buffer/service/error_state.h"
diff --git a/gpu/command_buffer/service/cmd_parser.cc b/gpu/command_buffer/service/cmd_parser.cc
index ffcdfff..d7dfc59 100644
--- a/gpu/command_buffer/service/cmd_parser.cc
+++ b/gpu/command_buffer/service/cmd_parser.cc
@@ -7,7 +7,7 @@
 #include "gpu/command_buffer/service/cmd_parser.h"
 
 #include "base/logging.h"
-#include "base/debug/trace_event.h"
+#include "base/trace_event/trace_event.h"
 
 namespace gpu {
 
diff --git a/gpu/command_buffer/service/command_buffer_service.cc b/gpu/command_buffer/service/command_buffer_service.cc
index 1453a0a..21e2ae4 100644
--- a/gpu/command_buffer/service/command_buffer_service.cc
+++ b/gpu/command_buffer/service/command_buffer_service.cc
@@ -7,7 +7,7 @@
 #include <limits>
 
 #include "base/logging.h"
-#include "base/debug/trace_event.h"
+#include "base/trace_event/trace_event.h"
 #include "gpu/command_buffer/common/cmd_buffer_common.h"
 #include "gpu/command_buffer/common/command_buffer_shared.h"
 #include "gpu/command_buffer/service/transfer_buffer_manager.h"
diff --git a/gpu/command_buffer/service/feature_info_unittest.cc b/gpu/command_buffer/service/feature_info_unittest.cc
index e81dad1..8455be6 100644
--- a/gpu/command_buffer/service/feature_info_unittest.cc
+++ b/gpu/command_buffer/service/feature_info_unittest.cc
@@ -42,7 +42,7 @@
   }
 
   void SetupInitExpectations(const char* extensions) {
-    SetupInitExpectationsWithGLVersion(extensions, "", "");
+    SetupInitExpectationsWithGLVersion(extensions, "", "3.0");
   }
 
   void SetupInitExpectationsWithGLVersion(
diff --git a/gpu/command_buffer/service/framebuffer_manager_unittest.cc b/gpu/command_buffer/service/framebuffer_manager_unittest.cc
index 859726d..ddd3739 100644
--- a/gpu/command_buffer/service/framebuffer_manager_unittest.cc
+++ b/gpu/command_buffer/service/framebuffer_manager_unittest.cc
@@ -126,10 +126,12 @@
   }
 
  protected:
-  void SetUp() override { InitializeContext("", ""); }
+  void SetUp() override {
+    InitializeContext("2.0", "GL_EXT_framebuffer_object");
+  }
 
   void InitializeContext(const char* gl_version, const char* extensions) {
-    GpuServiceTest::SetUp();
+    GpuServiceTest::SetUpWithGLVersion(gl_version, extensions);
     TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion(gl_.get(),
         extensions, "", gl_version);
     feature_info_->Initialize();
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 13b10c5..f37c61a 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -17,13 +17,13 @@
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/command_line.h"
-#include "base/debug/trace_event.h"
-#include "base/debug/trace_event_synthetic_delay.h"
 #include "base/float_util.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/numerics/safe_math.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
+#include "base/trace_event/trace_event.h"
+#include "base/trace_event/trace_event_synthetic_delay.h"
 #include "build/build_config.h"
 #define GLES2_GPU_SERVICE 1
 #include "gpu/command_buffer/common/debug_marker_manager.h"
@@ -1178,6 +1178,11 @@
   void DoShaderSource(
       GLuint client_id, GLsizei count, const char** data, const GLint* length);
 
+  // Wrapper for glTransformFeedbackVaryings.
+  void DoTransformFeedbackVaryings(
+      GLuint client_program_id, GLsizei count, const char* const* varyings,
+      GLenum buffer_mode);
+
   // Clear any textures used by the current program.
   bool ClearUnclearedTextures();
 
@@ -7057,6 +7062,18 @@
   shader->set_source(str);
 }
 
+void GLES2DecoderImpl::DoTransformFeedbackVaryings(
+    GLuint client_program_id, GLsizei count, const char* const* varyings,
+    GLenum buffer_mode) {
+  Program* program = GetProgramInfoNotShader(
+      client_program_id, "glTransformFeedbackVaryings");
+  if (!program) {
+    return;
+  }
+  glTransformFeedbackVaryings(
+      program->service_id(), count, varyings, buffer_mode);
+}
+
 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
   TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
   Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
index a1947f4..720d54e 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
@@ -86,10 +86,6 @@
   GLuint buffer = c.buffer;
   GLintptr offset = static_cast<GLintptr>(c.offset);
   GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
-  if (size < 0) {
-    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glBindBufferRange", "size < 0");
-    return error::kNoError;
-  }
   if (!group_->GetBufferServiceId(buffer, &buffer)) {
     if (!group_->bind_generates_resource()) {
       LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBindBufferRange",
@@ -616,10 +612,6 @@
   GLintptr readoffset = static_cast<GLintptr>(c.readoffset);
   GLintptr writeoffset = static_cast<GLintptr>(c.writeoffset);
   GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
-  if (size < 0) {
-    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopyBufferSubData", "size < 0");
-    return error::kNoError;
-  }
   glCopyBufferSubData(readtarget, writetarget, readoffset, writeoffset, size);
   return error::kNoError;
 }
@@ -697,6 +689,32 @@
   return error::kNoError;
 }
 
+error::Error GLES2DecoderImpl::HandleCopyTexSubImage3D(
+    uint32_t immediate_data_size,
+    const void* cmd_data) {
+  if (!unsafe_es3_apis_enabled())
+    return error::kUnknownCommand;
+  const gles2::cmds::CopyTexSubImage3D& c =
+      *static_cast<const gles2::cmds::CopyTexSubImage3D*>(cmd_data);
+  (void)c;
+  error::Error error;
+  error = WillAccessBoundFramebufferForRead();
+  if (error != error::kNoError)
+    return error;
+  GLenum target = static_cast<GLenum>(c.target);
+  GLint level = static_cast<GLint>(c.level);
+  GLint xoffset = static_cast<GLint>(c.xoffset);
+  GLint yoffset = static_cast<GLint>(c.yoffset);
+  GLint zoffset = static_cast<GLint>(c.zoffset);
+  GLint x = static_cast<GLint>(c.x);
+  GLint y = static_cast<GLint>(c.y);
+  GLsizei width = static_cast<GLsizei>(c.width);
+  GLsizei height = static_cast<GLsizei>(c.height);
+  glCopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width,
+                      height);
+  return error::kNoError;
+}
+
 error::Error GLES2DecoderImpl::HandleCreateProgram(uint32_t immediate_data_size,
                                                    const void* cmd_data) {
   const gles2::cmds::CreateProgram& c =
@@ -1526,11 +1544,6 @@
   Result* result = GetSharedMemoryAs<Result*>(
       c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values));
   GLint* params = result ? result->GetData() : NULL;
-  if (bufSize < 0) {
-    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glGetInternalformativ",
-                       "bufSize < 0");
-    return error::kNoError;
-  }
   if (params == NULL) {
     return error::kOutOfBounds;
   }
@@ -1978,16 +1991,6 @@
   if (attachments == NULL) {
     return error::kOutOfBounds;
   }
-  if (width < 0) {
-    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glInvalidateSubFramebuffer",
-                       "width < 0");
-    return error::kNoError;
-  }
-  if (height < 0) {
-    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glInvalidateSubFramebuffer",
-                       "height < 0");
-    return error::kNoError;
-  }
   glInvalidateSubFramebuffer(target, count, attachments, x, y, width, height);
   return error::kNoError;
 }
@@ -2799,26 +2802,68 @@
   GLsizei width = static_cast<GLsizei>(c.width);
   GLsizei height = static_cast<GLsizei>(c.height);
   GLsizei depth = static_cast<GLsizei>(c.depth);
-  if (levels < 0) {
-    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexStorage3D", "levels < 0");
-    return error::kNoError;
-  }
-  if (width < 0) {
-    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexStorage3D", "width < 0");
-    return error::kNoError;
-  }
-  if (height < 0) {
-    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexStorage3D", "height < 0");
-    return error::kNoError;
-  }
-  if (depth < 0) {
-    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexStorage3D", "depth < 0");
-    return error::kNoError;
-  }
   glTexStorage3D(target, levels, internalFormat, width, height, depth);
   return error::kNoError;
 }
 
+error::Error GLES2DecoderImpl::HandleTransformFeedbackVaryingsBucket(
+    uint32_t immediate_data_size,
+    const void* cmd_data) {
+  if (!unsafe_es3_apis_enabled())
+    return error::kUnknownCommand;
+  const gles2::cmds::TransformFeedbackVaryingsBucket& c =
+      *static_cast<const gles2::cmds::TransformFeedbackVaryingsBucket*>(
+          cmd_data);
+  (void)c;
+  GLuint program = static_cast<GLuint>(c.program);
+
+  const size_t kMinBucketSize = sizeof(GLint);
+  // Each string has at least |length| in the header and a NUL character.
+  const size_t kMinStringSize = sizeof(GLint) + 1;
+  Bucket* bucket = GetBucket(c.varyings_bucket_id);
+  if (!bucket) {
+    return error::kInvalidArguments;
+  }
+  const size_t bucket_size = bucket->size();
+  if (bucket_size < kMinBucketSize) {
+    return error::kInvalidArguments;
+  }
+  const char* bucket_data = bucket->GetDataAs<const char*>(0, bucket_size);
+  const GLint* header = reinterpret_cast<const GLint*>(bucket_data);
+  GLsizei count = static_cast<GLsizei>(header[0]);
+  if (count < 0) {
+    return error::kInvalidArguments;
+  }
+  const size_t max_count = (bucket_size - kMinBucketSize) / kMinStringSize;
+  if (max_count < static_cast<size_t>(count)) {
+    return error::kInvalidArguments;
+  }
+  const GLint* length = header + 1;
+  scoped_ptr<const char* []> strs;
+  if (count > 0)
+    strs.reset(new const char* [count]);
+  const char** varyings = strs.get();
+  base::CheckedNumeric<size_t> total_size = sizeof(GLint);
+  total_size *= count + 1;  // Header size.
+  if (!total_size.IsValid())
+    return error::kInvalidArguments;
+  for (GLsizei ii = 0; ii < count; ++ii) {
+    varyings[ii] = bucket_data + total_size.ValueOrDefault(0);
+    total_size += length[ii];
+    total_size += 1;  // NUL char at the end of each char array.
+    if (!total_size.IsValid() || total_size.ValueOrDefault(0) > bucket_size ||
+        varyings[ii][length[ii]] != 0) {
+      return error::kInvalidArguments;
+    }
+  }
+  if (total_size.ValueOrDefault(0) != bucket_size) {
+    return error::kInvalidArguments;
+  }
+  GLenum buffermode = static_cast<GLenum>(c.buffermode);
+  DoTransformFeedbackVaryings(program, count, varyings, buffermode);
+  return error::kNoError;
+}
+
 error::Error GLES2DecoderImpl::HandleUniform1f(uint32_t immediate_data_size,
                                                const void* cmd_data) {
   const gles2::cmds::Uniform1f& c =
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
index 8794e42..905a390 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
@@ -62,7 +62,6 @@
       switches::kGpuDriverBugWorkarounds,
       base::IntToString(gpu::CLEAR_ALPHA_IN_READPIXELS));
   InitState init;
-  init.gl_version = "3.0";
   init.bind_generates_resource = true;
   InitDecoderWithCommandLine(init, &command_line);
   SetupDefaultProgram();
@@ -268,7 +267,6 @@
 
 TEST_P(GLES2DecoderManualInitTest, BindGeneratesResourceFalse) {
   InitState init;
-  init.gl_version = "3.0";
   InitDecoder(init);
 
   BindTexture cmd1;
@@ -704,7 +702,6 @@
 TEST_P(GLES2DecoderManualInitTest, GpuMemoryManagerCHROMIUM) {
   InitState init;
   init.extensions = "GL_ARB_texture_rectangle";
-  init.gl_version = "3.0";
   init.bind_generates_resource = true;
   InitDecoder(init);
 
@@ -780,7 +777,6 @@
       new SizeOnlyMemoryTracker();
   set_memory_tracker(memory_tracker.get());
   InitState init;
-  init.gl_version = "3.0";
   init.bind_generates_resource = true;
   InitDecoder(init);
   // Expect that initial size - size is 0.
@@ -793,7 +789,6 @@
       new SizeOnlyMemoryTracker();
   set_memory_tracker(memory_tracker.get());
   InitState init;
-  init.gl_version = "3.0";
   init.bind_generates_resource = true;
   InitDecoder(init);
   DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
@@ -850,7 +845,6 @@
       new SizeOnlyMemoryTracker();
   set_memory_tracker(memory_tracker.get());
   InitState init;
-  init.gl_version = "3.0";
   init.bind_generates_resource = true;
   InitDecoder(init);
   DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
@@ -877,7 +871,6 @@
       new SizeOnlyMemoryTracker();
   set_memory_tracker(memory_tracker.get());
   InitState init;
-  init.gl_version = "3.0";
   init.has_alpha = true;
   init.request_alpha = true;
   init.bind_generates_resource = true;
@@ -914,7 +907,6 @@
       new SizeOnlyMemoryTracker();
   set_memory_tracker(memory_tracker.get());
   InitState init;
-  init.gl_version = "3.0";
   init.bind_generates_resource = true;
   InitDecoder(init);
   DoBindRenderbuffer(
@@ -950,7 +942,6 @@
       new SizeOnlyMemoryTracker();
   set_memory_tracker(memory_tracker.get());
   InitState init;
-  init.gl_version = "3.0";
   init.bind_generates_resource = true;
   InitDecoder(init);
   DoBindBuffer(GL_ARRAY_BUFFER, client_buffer_id_, kServiceBufferId);
@@ -989,7 +980,6 @@
   const GLint kBorder = 0;
   InitState init;
   init.extensions = "GL_EXT_texture_storage";
-  init.gl_version = "3.0";
   init.has_alpha = true;
   init.request_alpha = true;
   init.bind_generates_resource = true;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h
index 18a6105..2b6a38f 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h
@@ -551,6 +551,18 @@
   EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
 }
 
+TEST_P(GLES2DecoderTest1, CopyTexSubImage3DValidArgs) {
+  EXPECT_CALL(*gl_, CopyTexSubImage3D(GL_TEXTURE_3D, 2, 3, 4, 5, 6, 7, 8, 9));
+  SpecializedSetup<cmds::CopyTexSubImage3D, 0>(true);
+  cmds::CopyTexSubImage3D cmd;
+  cmd.Init(GL_TEXTURE_3D, 2, 3, 4, 5, 6, 7, 8, 9);
+  decoder_->set_unsafe_es3_apis_enabled(true);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+  EXPECT_EQ(GL_NO_ERROR, GetGLError());
+  decoder_->set_unsafe_es3_apis_enabled(false);
+  EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
+}
+
 TEST_P(GLES2DecoderTest1, CreateProgramValidArgs) {
   EXPECT_CALL(*gl_, CreateProgram()).WillOnce(Return(kNewServiceId));
   SpecializedSetup<cmds::CreateProgram, 0>(true);
@@ -1943,6 +1955,4 @@
 }
 // TODO(gman): GetUniformfv
 
-// TODO(gman): GetUniformiv
-
 #endif  // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_1_AUTOGEN_H_
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h
index a5831d6..2947723 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h
@@ -12,6 +12,8 @@
 #ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_
 #define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_
 
+// TODO(gman): GetUniformiv
+
 // TODO(gman): GetUniformLocation
 
 TEST_P(GLES2DecoderTest2, GetVertexAttribfvValidArgs) {
@@ -578,20 +580,15 @@
   const char kValidStrEnd = 0;
   const GLsizei kCount = static_cast<GLsizei>(arraysize(kSource));
   const GLsizei kTests[] = {
-      kCount, 0, std::numeric_limits<GLsizei>::max(), -1, kCount,
+      kCount + 1, 0, std::numeric_limits<GLsizei>::max(), -1,
   };
   decoder_->set_unsafe_es3_apis_enabled(true);
   for (size_t ii = 0; ii < arraysize(kTests); ++ii) {
     SetBucketAsCStrings(kBucketId, 1, kSource, kTests[ii], kValidStrEnd);
     cmds::ShaderSourceBucket cmd;
     cmd.Init(client_shader_id_, kBucketId);
-    if (kTests[ii] == kCount) {
-      EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
-    } else {
-      EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd));
-    }
+    EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd));
   }
-  EXPECT_EQ(GL_NO_ERROR, GetGLError());
 }
 
 TEST_P(GLES2DecoderTest2, ShaderSourceBucketInvalidStringEnding) {
@@ -604,7 +601,6 @@
   cmd.Init(client_shader_id_, kBucketId);
   decoder_->set_unsafe_es3_apis_enabled(true);
   EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd));
-  EXPECT_EQ(GL_NO_ERROR, GetGLError());
 }
 
 TEST_P(GLES2DecoderTest2, StencilFuncValidArgs) {
@@ -872,6 +868,69 @@
 
 // TODO(gman): TexSubImage3D
 
+TEST_P(GLES2DecoderTest2, TransformFeedbackVaryingsBucketValidArgs) {
+  EXPECT_CALL(*gl_, TransformFeedbackVaryings(kServiceProgramId, 1, _,
+                                              GL_INTERLEAVED_ATTRIBS));
+  const uint32 kBucketId = 123;
+  const char kSource0[] = "hello";
+  const char* kSource[] = {kSource0};
+  const char kValidStrEnd = 0;
+  SetBucketAsCStrings(kBucketId, 1, kSource, 1, kValidStrEnd);
+  cmds::TransformFeedbackVaryingsBucket cmd;
+  cmd.Init(client_program_id_, kBucketId, GL_INTERLEAVED_ATTRIBS);
+  decoder_->set_unsafe_es3_apis_enabled(true);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+  decoder_->set_unsafe_es3_apis_enabled(false);
+  EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
+}
+
+TEST_P(GLES2DecoderTest2, TransformFeedbackVaryingsBucketInvalidArgs) {
+  const uint32 kBucketId = 123;
+  const char kSource0[] = "hello";
+  const char* kSource[] = {kSource0};
+  const char kValidStrEnd = 0;
+  decoder_->set_unsafe_es3_apis_enabled(true);
+  cmds::TransformFeedbackVaryingsBucket cmd;
+  // Test no bucket.
+  cmd.Init(client_program_id_, kBucketId, GL_INTERLEAVED_ATTRIBS);
+  EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+  // Test invalid client.
+  SetBucketAsCStrings(kBucketId, 1, kSource, 1, kValidStrEnd);
+  cmd.Init(kInvalidClientId, kBucketId, GL_INTERLEAVED_ATTRIBS);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+  EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+}
+
+TEST_P(GLES2DecoderTest2, TransformFeedbackVaryingsBucketInvalidHeader) {
+  const uint32 kBucketId = 123;
+  const char kSource0[] = "hello";
+  const char* kSource[] = {kSource0};
+  const char kValidStrEnd = 0;
+  const GLsizei kCount = static_cast<GLsizei>(arraysize(kSource));
+  const GLsizei kTests[] = {
+      kCount + 1, 0, std::numeric_limits<GLsizei>::max(), -1,
+  };
+  decoder_->set_unsafe_es3_apis_enabled(true);
+  for (size_t ii = 0; ii < arraysize(kTests); ++ii) {
+    SetBucketAsCStrings(kBucketId, 1, kSource, kTests[ii], kValidStrEnd);
+    cmds::TransformFeedbackVaryingsBucket cmd;
+    cmd.Init(client_program_id_, kBucketId, GL_INTERLEAVED_ATTRIBS);
+    EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd));
+  }
+}
+
+TEST_P(GLES2DecoderTest2, TransformFeedbackVaryingsBucketInvalidStringEnding) {
+  const uint32 kBucketId = 123;
+  const char kSource0[] = "hello";
+  const char* kSource[] = {kSource0};
+  const char kInvalidStrEnd = '*';
+  SetBucketAsCStrings(kBucketId, 1, kSource, 1, kInvalidStrEnd);
+  cmds::TransformFeedbackVaryingsBucket cmd;
+  cmd.Init(client_program_id_, kBucketId, GL_INTERLEAVED_ATTRIBS);
+  decoder_->set_unsafe_es3_apis_enabled(true);
+  EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd));
+}
+
 TEST_P(GLES2DecoderTest2, Uniform1fValidArgs) {
   EXPECT_CALL(*gl_, Uniform1fv(1, 1, _));
   SpecializedSetup<cmds::Uniform1f, 0>(true);
@@ -1467,23 +1526,4 @@
   decoder_->set_unsafe_es3_apis_enabled(false);
   EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
 }
-
-TEST_P(GLES2DecoderTest2, VertexAttribI4uivImmediateValidArgs) {
-  cmds::VertexAttribI4uivImmediate& cmd =
-      *GetImmediateAs<cmds::VertexAttribI4uivImmediate>();
-  SpecializedSetup<cmds::VertexAttribI4uivImmediate, 0>(true);
-  GLuint temp[4] = {
-      0,
-  };
-  cmd.Init(1, &temp[0]);
-  EXPECT_CALL(*gl_, VertexAttribI4uiv(1, reinterpret_cast<GLuint*>(
-                                             ImmediateDataAddress(&cmd))));
-  decoder_->set_unsafe_es3_apis_enabled(true);
-  EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp)));
-  EXPECT_EQ(GL_NO_ERROR, GetGLError());
-  decoder_->set_unsafe_es3_apis_enabled(false);
-  EXPECT_EQ(error::kUnknownCommand, ExecuteImmediateCmd(cmd, sizeof(temp)));
-}
-// TODO(gman): VertexAttribIPointer
-
 #endif  // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h
index 20c09f6..2eb4e58 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h
@@ -12,6 +12,24 @@
 #ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_3_AUTOGEN_H_
 #define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_3_AUTOGEN_H_
 
+TEST_P(GLES2DecoderTest3, VertexAttribI4uivImmediateValidArgs) {
+  cmds::VertexAttribI4uivImmediate& cmd =
+      *GetImmediateAs<cmds::VertexAttribI4uivImmediate>();
+  SpecializedSetup<cmds::VertexAttribI4uivImmediate, 0>(true);
+  GLuint temp[4] = {
+      0,
+  };
+  cmd.Init(1, &temp[0]);
+  EXPECT_CALL(*gl_, VertexAttribI4uiv(1, reinterpret_cast<GLuint*>(
+                                             ImmediateDataAddress(&cmd))));
+  decoder_->set_unsafe_es3_apis_enabled(true);
+  EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp)));
+  EXPECT_EQ(GL_NO_ERROR, GetGLError());
+  decoder_->set_unsafe_es3_apis_enabled(false);
+  EXPECT_EQ(error::kUnknownCommand, ExecuteImmediateCmd(cmd, sizeof(temp)));
+}
+// TODO(gman): VertexAttribIPointer
+
 // TODO(gman): VertexAttribPointer
 
 TEST_P(GLES2DecoderTest3, ViewportValidArgs) {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_async_pixel.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_async_pixel.cc
index d32870d..4e6346e 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_async_pixel.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_async_pixel.cc
@@ -57,7 +57,6 @@
 TEST_P(GLES2DecoderManualInitTest, AsyncPixelTransfers) {
   InitState init;
   init.extensions = "GL_CHROMIUM_async_pixel_transfers";
-  init.gl_version = "3.0";
   init.bind_generates_resource = true;
   InitDecoder(init);
 
@@ -319,7 +318,6 @@
 TEST_P(GLES2DecoderManualInitTest, AsyncPixelTransferManager) {
   InitState init;
   init.extensions = "GL_CHROMIUM_async_pixel_transfers";
-  init.gl_version = "3.0";
   init.bind_generates_resource = true;
   InitDecoder(init);
 
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_attribs.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_attribs.cc
index fd28f75..cd39253 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_attribs.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_attribs.cc
@@ -356,7 +356,6 @@
 
   void SetUp() override {
     InitState init;
-    init.gl_version = "3.0";
     init.bind_generates_resource = true;
     init.use_native_vao = false;
     InitDecoder(init);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
index 07d1eaf..807d488 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -57,6 +57,7 @@
       break;
     }
   }
+
   if (init->use_native_vao) {
     if (contains_vao_extension)
       return;
@@ -75,6 +76,10 @@
     // Make sure we don't set up an invalid InitState.
     CHECK(!contains_vao_extension);
   }
+
+  if (!init->extensions.empty())
+    init->extensions += " ";
+  init->extensions += "GL_EXT_framebuffer_object ";
 }
 
 }  // namespace Anonymous
@@ -118,7 +123,9 @@
 
 void GLES2DecoderTestBase::SetUp() {
   InitState init;
-  init.gl_version = "3.0";
+  // Autogenerated tests do not overwrite version or extension string,
+  // so we have to pick something that supports everything here.
+  init.gl_version = "4.4";
   init.has_alpha = true;
   init.has_depth = true;
   init.request_alpha = true;
@@ -136,7 +143,9 @@
 }
 
 GLES2DecoderTestBase::InitState::InitState()
-    : has_alpha(false),
+    : extensions("GL_EXT_framebuffer_object"),
+      gl_version("2.1"),
+      has_alpha(false),
       has_depth(false),
       has_stencil(false),
       request_alpha(false),
@@ -156,6 +165,9 @@
     const base::CommandLine* command_line) {
   InitState normalized_init = init;
   NormalizeInitState(&normalized_init);
+  // For easier substring/extension matching
+  DCHECK(normalized_init.extensions.empty() ||
+         *normalized_init.extensions.rbegin() == ' ');
   Framebuffer::ClearFramebufferCompleteComboMap();
 
   gfx::SetGLGetProcAddressProc(gfx::MockGLInterface::GetGLProcAddress);
@@ -166,9 +178,6 @@
 
   SetupMockGLBehaviors();
 
-  // Only create stream texture manager if extension is requested.
-  std::vector<std::string> list;
-  base::SplitString(normalized_init.extensions, ' ', &list);
   scoped_refptr<FeatureInfo> feature_info;
   if (command_line)
     feature_info = new FeatureInfo(*command_line);
@@ -423,15 +432,27 @@
     decoder_->set_unsafe_es3_apis_enabled(true);
     reset_unsafe_es3_apis_enabled = true;
   }
-  EXPECT_CALL(*gl_, GenSamplers(_, _))
-      .WillOnce(SetArgumentPointee<1>(kServiceSamplerId))
-      .RetiresOnSaturation();
-  GenHelper<cmds::GenSamplersImmediate>(client_sampler_id_);
-  EXPECT_CALL(*gl_, GenTransformFeedbacks(_, _))
-      .WillOnce(SetArgumentPointee<1>(kServiceTransformFeedbackId))
-      .RetiresOnSaturation();
-  GenHelper<cmds::GenTransformFeedbacksImmediate>(client_transformfeedback_id_);
-  DoFenceSync(client_sync_id_, kServiceSyncId);
+
+  const gfx::GLVersionInfo* version = context_->GetVersionInfo();
+  if (version->IsAtLeastGL(3, 3) || version->IsAtLeastGLES(3, 0)) {
+    EXPECT_CALL(*gl_, GenSamplers(_, _))
+        .WillOnce(SetArgumentPointee<1>(kServiceSamplerId))
+        .RetiresOnSaturation();
+    GenHelper<cmds::GenSamplersImmediate>(client_sampler_id_);
+  }
+  if (version->IsAtLeastGL(4, 0) || version->IsAtLeastGLES(3, 0)) {
+    EXPECT_CALL(*gl_, GenTransformFeedbacks(_, _))
+        .WillOnce(SetArgumentPointee<1>(kServiceTransformFeedbackId))
+        .RetiresOnSaturation();
+    GenHelper<cmds::GenTransformFeedbacksImmediate>(
+        client_transformfeedback_id_);
+  }
+
+  if (init.extensions.find("GL_ARB_sync ") != std::string::npos ||
+      version->IsAtLeastGL(3, 2) || version->IsAtLeastGLES(3, 0)) {
+    DoFenceSync(client_sync_id_, kServiceSyncId);
+  }
+
   if (reset_unsafe_es3_apis_enabled) {
     decoder_->set_unsafe_es3_apis_enabled(false);
   }
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_state.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_state.cc
index 74149ef..3578b5b 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_state.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_state.cc
@@ -99,7 +99,6 @@
 
 TEST_P(GLES2DecoderRestoreStateTest, NullPreviousStateBGR) {
   InitState init;
-  init.gl_version = "3.0";
   init.bind_generates_resource = true;
   InitDecoder(init);
   SetupTexture();
@@ -128,7 +127,6 @@
 
 TEST_P(GLES2DecoderRestoreStateTest, NullPreviousState) {
   InitState init;
-  init.gl_version = "3.0";
   InitDecoder(init);
   SetupTexture();
 
@@ -153,7 +151,6 @@
 
 TEST_P(GLES2DecoderRestoreStateTest, WithPreviousStateBGR) {
   InitState init;
-  init.gl_version = "3.0";
   init.bind_generates_resource = true;
   InitDecoder(init);
   SetupTexture();
@@ -178,7 +175,6 @@
 
 TEST_P(GLES2DecoderRestoreStateTest, WithPreviousState) {
   InitState init;
-  init.gl_version = "3.0";
   InitDecoder(init);
   SetupTexture();
 
@@ -202,7 +198,6 @@
 
 TEST_P(GLES2DecoderRestoreStateTest, ActiveUnit1) {
   InitState init;
-  init.gl_version = "3.0";
   InitDecoder(init);
 
   // Bind a non-default texture to GL_TEXTURE1 unit.
@@ -233,7 +228,6 @@
 
 TEST_P(GLES2DecoderRestoreStateTest, NonDefaultUnit0BGR) {
   InitState init;
-  init.gl_version = "3.0";
   init.bind_generates_resource = true;
   InitDecoder(init);
 
@@ -272,7 +266,6 @@
 
 TEST_P(GLES2DecoderRestoreStateTest, NonDefaultUnit1BGR) {
   InitState init;
-  init.gl_version = "3.0";
   init.bind_generates_resource = true;
   InitDecoder(init);
 
@@ -305,7 +298,6 @@
 
 TEST_P(GLES2DecoderRestoreStateTest, DefaultUnit0) {
   InitState init;
-  init.gl_version = "3.0";
   InitDecoder(init);
 
   // Bind a non-default texture to GL_TEXTURE1 unit.
@@ -342,7 +334,6 @@
 
 TEST_P(GLES2DecoderRestoreStateTest, DefaultUnit1) {
   InitState init;
-  init.gl_version = "3.0";
   InitDecoder(init);
 
   // Bind a non-default texture to GL_TEXTURE0 unit.
@@ -391,7 +382,6 @@
                      {0, false, false}};
 
   InitState init;
-  init.gl_version = "2.1";
   InitDecoder(init);
 
   for (int i = 0; test[i].gl_enum; i++) {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc
index baff353..957b53b 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc
@@ -391,7 +391,6 @@
 
 TEST_P(GLES2DecoderManualInitTest, DepthEnableWithDepth) {
   InitState init;
-  init.gl_version = "3.0";
   init.has_depth = true;
   init.request_depth = true;
   init.bind_generates_resource = true;
@@ -444,7 +443,6 @@
 
 TEST_P(GLES2DecoderManualInitTest, DepthEnableWithoutRequestedDepth) {
   InitState init;
-  init.gl_version = "3.0";
   init.has_depth = true;
   init.bind_generates_resource = true;
   InitDecoder(init);
@@ -496,7 +494,6 @@
 
 TEST_P(GLES2DecoderManualInitTest, StencilEnableWithStencil) {
   InitState init;
-  init.gl_version = "3.0";
   init.has_stencil = true;
   init.request_stencil = true;
   init.bind_generates_resource = true;
@@ -550,7 +547,6 @@
 
 TEST_P(GLES2DecoderManualInitTest, StencilEnableWithoutRequestedStencil) {
   InitState init;
-  init.gl_version = "3.0";
   init.has_stencil = true;
   init.bind_generates_resource = true;
   InitDecoder(init);
@@ -602,7 +598,6 @@
 
 TEST_P(GLES2DecoderManualInitTest, CachedColorMask) {
   InitState init;
-  init.gl_version = "3.0";
   init.has_alpha = true;
   init.has_depth = true;
   init.has_stencil = true;
@@ -630,7 +625,6 @@
 
 TEST_P(GLES2DecoderManualInitTest, CachedDepthMask) {
   InitState init;
-  init.gl_version = "3.0";
   init.has_alpha = true;
   init.has_depth = true;
   init.has_stencil = true;
@@ -657,7 +651,6 @@
 
 TEST_P(GLES2DecoderManualInitTest, CachedStencilMask) {
   InitState init;
-  init.gl_version = "3.0";
   init.has_alpha = true;
   init.has_depth = true;
   init.has_stencil = true;
@@ -746,7 +739,6 @@
 // Test that we lose context.
 TEST_P(GLES2DecoderManualInitTest, LoseContextWhenOOM) {
   InitState init;
-  init.gl_version = "3.0";
   init.has_alpha = true;
   init.has_depth = true;
   init.request_alpha = true;
@@ -863,7 +855,6 @@
       switches::kGpuDriverBugWorkarounds,
       base::IntToString(gpu::INIT_VERTEX_ATTRIBUTES));
   InitState init;
-  init.gl_version = "3.0";
   init.has_alpha = true;
   init.has_depth = true;
   init.request_alpha = true;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc
index d230be7..21526b1 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc
@@ -927,7 +927,6 @@
 
 TEST_P(GLES2DecoderManualInitTest, ActualAlphaMatchesRequestedAlpha) {
   InitState init;
-  init.gl_version = "3.0";
   init.has_alpha = true;
   init.request_alpha = true;
   init.bind_generates_resource = true;
@@ -954,7 +953,6 @@
 
 TEST_P(GLES2DecoderManualInitTest, ActualAlphaDoesNotMatchRequestedAlpha) {
   InitState init;
-  init.gl_version = "3.0";
   init.has_alpha = true;
   init.bind_generates_resource = true;
   InitDecoder(init);
@@ -980,7 +978,6 @@
 
 TEST_P(GLES2DecoderManualInitTest, ActualDepthMatchesRequestedDepth) {
   InitState init;
-  init.gl_version = "3.0";
   init.has_depth = true;
   init.request_depth = true;
   init.bind_generates_resource = true;
@@ -1007,7 +1004,6 @@
 
 TEST_P(GLES2DecoderManualInitTest, ActualDepthDoesNotMatchRequestedDepth) {
   InitState init;
-  init.gl_version = "3.0";
   init.has_depth = true;
   init.bind_generates_resource = true;
   InitDecoder(init);
@@ -1033,7 +1029,6 @@
 
 TEST_P(GLES2DecoderManualInitTest, ActualStencilMatchesRequestedStencil) {
   InitState init;
-  init.gl_version = "3.0";
   init.has_stencil = true;
   init.request_stencil = true;
   init.bind_generates_resource = true;
@@ -1060,7 +1055,6 @@
 
 TEST_P(GLES2DecoderManualInitTest, ActualStencilDoesNotMatchRequestedStencil) {
   InitState init;
-  init.gl_version = "3.0";
   init.has_stencil = true;
   init.bind_generates_resource = true;
   InitDecoder(init);
@@ -1404,7 +1398,6 @@
        RenderbufferStorageMultisampleCHROMIUMGLError) {
   InitState init;
   init.extensions = "GL_EXT_framebuffer_multisample";
-  init.gl_version = "2.1";
   init.bind_generates_resource = true;
   InitDecoder(init);
   DoBindRenderbuffer(
@@ -1429,7 +1422,6 @@
        RenderbufferStorageMultisampleCHROMIUMBadArgs) {
   InitState init;
   init.extensions = "GL_EXT_framebuffer_multisample";
-  init.gl_version = "2.1";
   init.bind_generates_resource = true;
   InitDecoder(init);
   DoBindRenderbuffer(
@@ -1464,7 +1456,6 @@
 TEST_P(GLES2DecoderManualInitTest, RenderbufferStorageMultisampleCHROMIUM) {
   InitState init;
   init.extensions = "GL_EXT_framebuffer_multisample";
-  init.gl_version = "2.1";
   InitDecoder(init);
   DoBindRenderbuffer(
       GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId);
@@ -1482,7 +1473,6 @@
        RenderbufferStorageMultisampleCHROMIUMRebindRenderbuffer) {
   InitState init;
   init.extensions = "GL_EXT_framebuffer_multisample";
-  init.gl_version = "2.1";
   InitDecoder(init);
   DoBindRenderbuffer(
       GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId);
@@ -1501,7 +1491,6 @@
        RenderbufferStorageMultisampleEXTNotSupported) {
   InitState init;
   init.extensions = "GL_EXT_framebuffer_multisample";
-  init.gl_version = "2.1";
   init.bind_generates_resource = true;
   InitDecoder(init);
   DoBindRenderbuffer(
@@ -1786,7 +1775,6 @@
        UnClearedAttachmentsGetClearedOnReadPixelsAndDrawBufferGetsRestored) {
   InitState init;
   init.extensions = "GL_EXT_framebuffer_multisample";
-  init.gl_version = "2.1";
   init.bind_generates_resource = true;
   InitDecoder(init);
   const GLuint kFBOClientTextureId = 4100;
@@ -2277,7 +2265,6 @@
 TEST_P(GLES2DecoderManualInitTest, ReadFormatExtension) {
   InitState init;
   init.extensions = "GL_OES_read_format";
-  init.gl_version = "2.1";
   init.bind_generates_resource = true;
   InitDecoder(init);
 
@@ -2336,7 +2323,6 @@
 
 TEST_P(GLES2DecoderManualInitTest, NoReadFormatExtension) {
   InitState init;
-  init.gl_version = "2.1";
   init.bind_generates_resource = true;
   InitDecoder(init);
 
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc
index bcfeb1b..5eda0a9 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc
@@ -1032,7 +1032,6 @@
       switches::kGpuDriverBugWorkarounds,
       base::IntToString(gpu::CLEAR_UNIFORMS_BEFORE_FIRST_PROGRAM_USE));
   InitState init;
-  init.gl_version = "3.0";
   init.has_alpha = true;
   init.request_alpha = true;
   init.bind_generates_resource = true;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc
index f0cadf1..05b44af 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc
@@ -131,7 +131,6 @@
       switches::kGpuDriverBugWorkarounds,
       base::IntToString(gpu::SET_TEXTURE_FILTER_BEFORE_GENERATING_MIPMAP));
   InitState init;
-  init.gl_version = "3.0";
   init.bind_generates_resource = true;
   InitDecoderWithCommandLine(init, &command_line);
 
@@ -641,7 +640,6 @@
 TEST_P(GLES2DecoderManualInitTest, CompressedTexImage2DBucketBadBucket) {
   InitState init;
   init.extensions = "GL_EXT_texture_compression_s3tc";
-  init.gl_version = "3.0";
   init.bind_generates_resource = true;
   InitDecoder(init);
 
@@ -679,7 +677,6 @@
 TEST_P(GLES2DecoderManualInitTest, CompressedTexImage2DS3TC) {
   InitState init;
   init.extensions = "GL_EXT_texture_compression_s3tc";
-  init.gl_version = "3.0";
   init.bind_generates_resource = true;
   InitDecoder(init);
   const uint32 kBucketId = 123;
@@ -1090,7 +1087,6 @@
 
 TEST_P(GLES2DecoderManualInitTest, DefaultTextureZero) {
   InitState init;
-  init.gl_version = "3.0";
   InitDecoder(init);
 
   BindTexture cmd1;
@@ -1108,7 +1104,6 @@
 
 TEST_P(GLES2DecoderManualInitTest, DefaultTextureBGR) {
   InitState init;
-  init.gl_version = "3.0";
   init.bind_generates_resource = true;
   InitDecoder(init);
 
@@ -1131,7 +1126,6 @@
 // Test that default texture 0 is immutable.
 TEST_P(GLES2DecoderManualInitTest, NoDefaultTexParameterf) {
   InitState init;
-  init.gl_version = "3.0";
   InitDecoder(init);
 
   {
@@ -1163,7 +1157,6 @@
 
 TEST_P(GLES2DecoderManualInitTest, NoDefaultTexParameteri) {
   InitState init;
-  init.gl_version = "3.0";
   InitDecoder(init);
 
   {
@@ -1195,7 +1188,6 @@
 
 TEST_P(GLES2DecoderManualInitTest, NoDefaultTexParameterfv) {
   InitState init;
-  init.gl_version = "3.0";
   InitDecoder(init);
 
   {
@@ -1235,7 +1227,6 @@
 
 TEST_P(GLES2DecoderManualInitTest, NoDefaultTexParameteriv) {
   InitState init;
-  init.gl_version = "3.0";
   InitDecoder(init);
 
   {
@@ -1275,7 +1266,6 @@
 
 TEST_P(GLES2DecoderManualInitTest, NoDefaultTexImage2D) {
   InitState init;
-  init.gl_version = "3.0";
   InitDecoder(init);
 
   BindTexture cmd1;
@@ -1300,7 +1290,6 @@
 
 TEST_P(GLES2DecoderManualInitTest, NoDefaultTexSubImage2D) {
   InitState init;
-  init.gl_version = "3.0";
   InitDecoder(init);
 
   BindTexture cmd1;
@@ -1328,7 +1317,6 @@
 TEST_P(GLES2DecoderManualInitTest, ARBTextureRectangleBindTexture) {
   InitState init;
   init.extensions = "GL_ARB_texture_rectangle";
-  init.gl_version = "3.0";
   init.bind_generates_resource = true;
   InitDecoder(init);
   EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_RECTANGLE_ARB, kNewServiceId));
@@ -1346,7 +1334,6 @@
 TEST_P(GLES2DecoderManualInitTest, ARBTextureRectangleGetBinding) {
   InitState init;
   init.extensions = "GL_ARB_texture_rectangle";
-  init.gl_version = "3.0";
   init.bind_generates_resource = true;
   InitDecoder(init);
   DoBindTexture(
@@ -1377,7 +1364,6 @@
 TEST_P(GLES2DecoderManualInitTest, ARBTextureRectangleTextureDefaults) {
   InitState init;
   init.extensions = "GL_ARB_texture_rectangle";
-  init.gl_version = "3.0";
   init.bind_generates_resource = true;
   InitDecoder(init);
   DoBindTexture(
@@ -1394,7 +1380,6 @@
 TEST_P(GLES2DecoderManualInitTest, ARBTextureRectangleTextureParam) {
   InitState init;
   init.extensions = "GL_ARB_texture_rectangle";
-  init.gl_version = "3.0";
   init.bind_generates_resource = true;
   InitDecoder(init);
 
@@ -1443,7 +1428,6 @@
 TEST_P(GLES2DecoderManualInitTest, ARBTextureRectangleTextureParamInvalid) {
   InitState init;
   init.extensions = "GL_ARB_texture_rectangle";
-  init.gl_version = "3.0";
   init.bind_generates_resource = true;
   InitDecoder(init);
 
@@ -1476,7 +1460,6 @@
 TEST_P(GLES2DecoderManualInitTest, ARBTextureRectangleTexImage2DError) {
   InitState init;
   init.extensions = "GL_ARB_texture_rectangle";
-  init.gl_version = "3.0";
   init.bind_generates_resource = true;
   InitDecoder(init);
 
@@ -1632,7 +1615,6 @@
       switches::kGpuDriverBugWorkarounds,
       base::IntToString(gpu::TEXSUBIMAGE2D_FASTER_THAN_TEXIMAGE2D));
   InitState init;
-  init.gl_version = "3.0";
   init.bind_generates_resource = true;
   InitDecoderWithCommandLine(init, &command_line);
   DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
@@ -1834,7 +1816,6 @@
 TEST_P(GLES2DecoderManualInitTest, CompressedImage2DMarksTextureAsCleared) {
   InitState init;
   init.extensions = "GL_EXT_texture_compression_s3tc";
-  init.gl_version = "3.0";
   init.bind_generates_resource = true;
   InitDecoder(init);
 
@@ -2663,7 +2644,6 @@
 TEST_P(GLES2DecoderManualInitTest, TexImage2DFloatConvertsFormatDesktop) {
   InitState init;
   init.extensions = "GL_ARB_texture_float";
-  init.gl_version = "2.1";
   InitDecoder(init);
   DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
   DoTexImage2D(
@@ -2742,7 +2722,6 @@
   void CheckFormats(const char* extension, const GLenum* formats, int count) {
     InitState init;
     init.extensions = extension;
-    init.gl_version = "3.0";
     init.bind_generates_resource = true;
     InitDecoder(init);
 
@@ -2814,7 +2793,6 @@
 
 TEST_P(GLES2DecoderManualInitTest, GetNoCompressedTextureFormats) {
   InitState init;
-  init.gl_version = "3.0";
   init.bind_generates_resource = true;
   InitDecoder(init);
 
diff --git a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
index e163642..6c9d377 100644
--- a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
@@ -14,6 +14,7 @@
 ValueValidator<GLenum> attachment;
 ValueValidator<GLenum> backbuffer_attachment;
 ValueValidator<GLenum> blit_filter;
+ValueValidator<GLenum> buffer_mode;
 ValueValidator<GLenum> buffer_parameter;
 ValueValidator<GLenum> buffer_target;
 ValueValidator<GLenum> buffer_usage;
diff --git a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h
index febce20..1f1211b 100644
--- a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h
@@ -28,6 +28,11 @@
     GL_LINEAR,
 };
 
+static const GLenum valid_buffer_mode_table[] = {
+    GL_INTERLEAVED_ATTRIBS,
+    GL_SEPARATE_ATTRIBS,
+};
+
 static const GLenum valid_buffer_parameter_table[] = {
     GL_BUFFER_SIZE,
     GL_BUFFER_USAGE,
@@ -585,6 +590,7 @@
       backbuffer_attachment(valid_backbuffer_attachment_table,
                             arraysize(valid_backbuffer_attachment_table)),
       blit_filter(valid_blit_filter_table, arraysize(valid_blit_filter_table)),
+      buffer_mode(valid_buffer_mode_table, arraysize(valid_buffer_mode_table)),
       buffer_parameter(valid_buffer_parameter_table,
                        arraysize(valid_buffer_parameter_table)),
       buffer_target(valid_buffer_target_table,
diff --git a/gpu/command_buffer/service/gpu_scheduler.cc b/gpu/command_buffer/service/gpu_scheduler.cc
index 93cf89f..8570fcd 100644
--- a/gpu/command_buffer/service/gpu_scheduler.cc
+++ b/gpu/command_buffer/service/gpu_scheduler.cc
@@ -7,9 +7,9 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/compiler_specific.h"
-#include "base/debug/trace_event.h"
 #include "base/message_loop/message_loop.h"
 #include "base/time/time.h"
+#include "base/trace_event/trace_event.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_fence.h"
 #include "ui/gl/gl_switches.h"
diff --git a/gpu/command_buffer/service/gpu_service_test.cc b/gpu/command_buffer/service/gpu_service_test.cc
index a7c9db1..89740b9 100644
--- a/gpu/command_buffer/service/gpu_service_test.cc
+++ b/gpu/command_buffer/service/gpu_service_test.cc
@@ -38,7 +38,7 @@
 }
 
 void GpuServiceTest::SetUp() {
-  SetUpWithGLVersion("2.0", NULL);
+  SetUpWithGLVersion("2.0", "GL_EXT_framebuffer_object");
 }
 
 void GpuServiceTest::TearDown() {
diff --git a/gpu/command_buffer/service/gpu_state_tracer.cc b/gpu/command_buffer/service/gpu_state_tracer.cc
index 51b0eba..47938cc 100644
--- a/gpu/command_buffer/service/gpu_state_tracer.cc
+++ b/gpu/command_buffer/service/gpu_state_tracer.cc
@@ -5,7 +5,7 @@
 #include "gpu/command_buffer/service/gpu_state_tracer.h"
 
 #include "base/base64.h"
-#include "base/debug/trace_event.h"
+#include "base/trace_event/trace_event.h"
 #include "context_state.h"
 #include "ui/gfx/codec/png_codec.h"
 #include "ui/gl/gl_bindings.h"
diff --git a/gpu/command_buffer/service/gpu_tracer.cc b/gpu/command_buffer/service/gpu_tracer.cc
index 84656c3..72b29dd 100644
--- a/gpu/command_buffer/service/gpu_tracer.cc
+++ b/gpu/command_buffer/service/gpu_tracer.cc
@@ -7,9 +7,9 @@
 #include <deque>
 
 #include "base/bind.h"
-#include "base/debug/trace_event.h"
 #include "base/strings/string_util.h"
 #include "base/time/time.h"
+#include "base/trace_event/trace_event.h"
 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
 #include "gpu/command_buffer/service/context_group.h"
 #include "ui/gl/gl_version_info.h"
diff --git a/gpu/command_buffer/service/gpu_tracer_unittest.cc b/gpu/command_buffer/service/gpu_tracer_unittest.cc
index 3737018..1b10fc6 100644
--- a/gpu/command_buffer/service/gpu_tracer_unittest.cc
+++ b/gpu/command_buffer/service/gpu_tracer_unittest.cc
@@ -225,7 +225,17 @@
 
  protected:
   void SetUp() override {
-    GpuServiceTest::SetUp();
+    const char* gl_version = "3.2";
+    const char* extensions = nullptr;
+    if (GetTracerType() == kTracerTypeDisjointTimer) {
+      gl_version = "opengl es 3.0";
+      extensions = "GL_EXT_disjoint_timer_query";
+    } else if (GetTracerType() == kTracerTypeARBTimer) {
+      // TODO(sievers): The tracer should not depend on ARB_occlusion_query.
+      // Try merge Query APIs (core, ARB, EXT) into a single binding each.
+      extensions = "GL_ARB_timer_query GL_ARB_occlusion_query";
+    }
+    GpuServiceTest::SetUpWithGLVersion(gl_version, extensions);
     gl_fake_queries_.Reset();
     gl_surface_ = new gfx::GLSurfaceStub();
     gl_context_ = new gfx::GLContextStub();
diff --git a/gpu/command_buffer/service/mailbox_manager_unittest.cc b/gpu/command_buffer/service/mailbox_manager_unittest.cc
index 231193f..388e1da 100644
--- a/gpu/command_buffer/service/mailbox_manager_unittest.cc
+++ b/gpu/command_buffer/service/mailbox_manager_unittest.cc
@@ -72,6 +72,13 @@
                           cleared);
   }
 
+  void SetLevelCleared(Texture* texture,
+                       GLenum target,
+                       GLint level,
+                       bool cleared) {
+    texture->SetLevelCleared(target, level, cleared);
+  }
+
   GLenum SetParameter(Texture* texture, GLenum pname, GLint param) {
     return texture->SetParameteri(feature_info_.get(), pname, param);
   }
@@ -543,6 +550,51 @@
   EXPECT_EQ(NULL, manager2_->ConsumeTexture(name));
 }
 
+TEST_F(MailboxManagerSyncTest, ClearedStateSynced) {
+  const GLuint kNewTextureId = 1234;
+
+  Texture* texture = DefineTexture();
+  EXPECT_TRUE(texture->SafeToRenderFrom());
+
+  Mailbox name = Mailbox::Generate();
+
+  manager_->ProduceTexture(name, texture);
+  EXPECT_EQ(texture, manager_->ConsumeTexture(name));
+
+  // Synchronize
+  manager_->PushTextureUpdates(0);
+  manager2_->PullTextureUpdates(0);
+
+  EXPECT_CALL(*gl_, GenTextures(1, _))
+      .WillOnce(SetArgPointee<1>(kNewTextureId));
+  SetupUpdateTexParamExpectations(
+      kNewTextureId, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT);
+  Texture* new_texture = manager2_->ConsumeTexture(name);
+  EXPECT_FALSE(new_texture == NULL);
+  EXPECT_NE(texture, new_texture);
+  EXPECT_EQ(kNewTextureId, new_texture->service_id());
+  EXPECT_TRUE(texture->SafeToRenderFrom());
+
+  // Change cleared to false.
+  SetLevelCleared(texture, texture->target(), 0, false);
+  EXPECT_FALSE(texture->SafeToRenderFrom());
+
+  // Synchronize
+  manager_->PushTextureUpdates(0);
+  SetupUpdateTexParamExpectations(
+      kNewTextureId, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT);
+  manager2_->PullTextureUpdates(0);
+
+  // Cleared state should be synced.
+  EXPECT_FALSE(new_texture->SafeToRenderFrom());
+
+  DestroyTexture(texture);
+  DestroyTexture(new_texture);
+
+  EXPECT_EQ(NULL, manager_->ConsumeTexture(name));
+  EXPECT_EQ(NULL, manager2_->ConsumeTexture(name));
+}
+
 // Putting the same texture into multiple mailboxes should result in sharing
 // only a single texture also within a synchronized manager instance.
 TEST_F(MailboxManagerSyncTest, SharedThroughMultipleMailboxes) {
diff --git a/gpu/command_buffer/service/memory_program_cache_unittest.cc b/gpu/command_buffer/service/memory_program_cache_unittest.cc
index 9134c78..7c39028 100644
--- a/gpu/command_buffer/service/memory_program_cache_unittest.cc
+++ b/gpu/command_buffer/service/memory_program_cache_unittest.cc
@@ -86,7 +86,7 @@
 
  protected:
   void SetUp() override {
-    GpuServiceTest::SetUp();
+    GpuServiceTest::SetUpWithGLVersion("3.0", "GL_ARB_get_program_binary");
 
     vertex_shader_ = shader_manager_.CreateShader(kVertexShaderClientId,
                                                   kVertexShaderServiceId,
diff --git a/gpu/command_buffer/service/memory_tracking.h b/gpu/command_buffer/service/memory_tracking.h
index 1514325..a7447e4 100644
--- a/gpu/command_buffer/service/memory_tracking.h
+++ b/gpu/command_buffer/service/memory_tracking.h
@@ -7,9 +7,9 @@
 
 #include <string>
 #include "base/basictypes.h"
-#include "base/debug/trace_event.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
+#include "base/trace_event/trace_event.h"
 
 namespace gpu {
 namespace gles2 {
diff --git a/gpu/command_buffer/service/program_manager.cc b/gpu/command_buffer/service/program_manager.cc
index d776350..d866504 100644
--- a/gpu/command_buffer/service/program_manager.cc
+++ b/gpu/command_buffer/service/program_manager.cc
@@ -107,6 +107,11 @@
   return hit->second.isInvariant;
 }
 
+uint32 ComputeOffset(const void* start, const void* position) {
+  return static_cast<const uint8*>(position) -
+         static_cast<const uint8*>(start);
+}
+
 }  // anonymous namespace.
 
 Program::UniformInfo::UniformInfo()
@@ -1201,11 +1206,6 @@
       combined_map.size());
 }
 
-static uint32 ComputeOffset(const void* start, const void* position) {
-  return static_cast<const uint8*>(position) -
-         static_cast<const uint8*>(start);
-}
-
 void Program::GetProgramInfo(
     ProgramManager* manager, CommonDecoder::Bucket* bucket) const {
   // NOTE: It seems to me the math in here does not need check for overflow
@@ -1290,6 +1290,141 @@
   DCHECK_EQ(ComputeOffset(header, strings), size);
 }
 
+bool Program::GetUniformBlocks(CommonDecoder::Bucket* bucket) const {
+  // The data is packed into the bucket in the following order
+  //   1) header
+  //   2) N entries of block data (except for name and indices)
+  //   3) name1, indices1, name2, indices2, ..., nameN, indicesN
+  //
+  // We query all the data directly through GL calls, assuming they are
+  // cheap through MANGLE.
+
+  DCHECK(bucket);
+  GLuint program = service_id();
+
+  uint32_t header_size = sizeof(UniformBlocksHeader);
+
+  uint32_t num_uniform_blocks = 0;
+  GLint param = GL_FALSE;
+  // We assume program is a valid program service id.
+  glGetProgramiv(program, GL_LINK_STATUS, &param);
+  if (param == GL_TRUE) {
+    param = 0;
+    glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &param);
+    num_uniform_blocks = static_cast<uint32_t>(param);
+  }
+  if (num_uniform_blocks == 0) {
+    // Although spec allows an implementation to return uniform block info
+    // even if a link fails, for consistency, we disallow that.
+    bucket->SetSize(header_size);
+    UniformBlocksHeader* header =
+        bucket->GetDataAs<UniformBlocksHeader*>(0, header_size);
+    header->num_uniform_blocks = 0;
+    return true;
+  }
+
+  std::vector<UniformBlockInfo> blocks(num_uniform_blocks);
+  base::CheckedNumeric<uint32_t> size = sizeof(UniformBlockInfo);
+  size *= num_uniform_blocks;
+  uint32_t entry_size = size.ValueOrDefault(0);
+  size += header_size;
+  std::vector<std::string> names(num_uniform_blocks);
+  GLint max_name_length = 0;
+  glGetProgramiv(
+      program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_name_length);
+  std::vector<GLchar> buffer(max_name_length);
+  GLsizei length;
+  for (uint32_t ii = 0; ii < num_uniform_blocks; ++ii) {
+    param = 0;
+    glGetActiveUniformBlockiv(program, ii, GL_UNIFORM_BLOCK_BINDING, &param);
+    blocks[ii].binding = static_cast<uint32_t>(param);
+
+    param = 0;
+    glGetActiveUniformBlockiv(program, ii, GL_UNIFORM_BLOCK_DATA_SIZE, &param);
+    blocks[ii].data_size = static_cast<uint32_t>(param);
+
+    blocks[ii].name_offset = size.ValueOrDefault(0);
+    param = 0;
+    glGetActiveUniformBlockiv(
+        program, ii, GL_UNIFORM_BLOCK_NAME_LENGTH, &param);
+    DCHECK_GE(max_name_length, param);
+    memset(&buffer[0], 0, param);
+    length = 0;
+    glGetActiveUniformBlockName(
+        program, ii, static_cast<GLsizei>(param), &length, &buffer[0]);
+    DCHECK_EQ(param, length + 1);
+    names[ii] = std::string(&buffer[0], length);
+    // TODO(zmo): optimize the name mapping lookup.
+    const std::string* original_name = GetOriginalNameFromHashedName(names[ii]);
+    if (original_name)
+      names[ii] = *original_name;
+    blocks[ii].name_length = names[ii].size() + 1;
+    size += blocks[ii].name_length;
+
+    param = 0;
+    glGetActiveUniformBlockiv(
+        program, ii, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &param);
+    blocks[ii].active_uniforms = static_cast<uint32_t>(param);
+    blocks[ii].active_uniform_offset = size.ValueOrDefault(0);
+    base::CheckedNumeric<uint32_t> indices_size = blocks[ii].active_uniforms;
+    indices_size *= sizeof(uint32_t);
+    if (!indices_size.IsValid())
+      return false;
+    size += indices_size.ValueOrDefault(0);
+
+    param = 0;
+    glGetActiveUniformBlockiv(
+        program, ii, GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER, &param);
+    blocks[ii].referenced_by_vertex_shader = static_cast<uint32_t>(param);
+
+    param = 0;
+    glGetActiveUniformBlockiv(
+        program, ii, GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER, &param);
+    blocks[ii].referenced_by_fragment_shader = static_cast<uint32_t>(param);
+  }
+  if (!size.IsValid())
+    return false;
+  uint32_t total_size = size.ValueOrDefault(0);
+  DCHECK_LE(header_size + entry_size, total_size);
+  uint32_t data_size = total_size - header_size - entry_size;
+
+  bucket->SetSize(total_size);
+  UniformBlocksHeader* header =
+      bucket->GetDataAs<UniformBlocksHeader*>(0, total_size);
+  UniformBlockInfo* entries = bucket->GetDataAs<UniformBlockInfo*>(
+      header_size, entry_size);
+  char* data = bucket->GetDataAs<char*>(header_size + entry_size, data_size);
+  DCHECK(header);
+  DCHECK(entries);
+  DCHECK(data);
+
+  // Copy over data for the header and entries.
+  header->num_uniform_blocks = num_uniform_blocks;
+  memcpy(entries, &blocks[0], entry_size);
+
+  std::vector<GLint> params;
+  for (uint32_t ii = 0; ii < num_uniform_blocks; ++ii) {
+    // Get active uniform name.
+    memcpy(data, names[ii].c_str(), blocks[ii].name_length);
+    data += blocks[ii].name_length;
+
+    // Get active uniform indices.
+    if (params.size() < blocks[ii].active_uniforms)
+      params.resize(blocks[ii].active_uniforms);
+    uint32_t num_bytes = blocks[ii].active_uniforms * sizeof(GLint);
+    memset(&params[0], 0, num_bytes);
+    glGetActiveUniformBlockiv(
+        program, ii, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, &params[0]);
+    uint32_t* indices = reinterpret_cast<uint32_t*>(data);
+    for (uint32_t uu = 0; uu < blocks[ii].active_uniforms; ++uu) {
+      indices[uu] = static_cast<uint32_t>(params[uu]);
+    }
+    data += num_bytes;
+  }
+  DCHECK_EQ(ComputeOffset(header, data), total_size);
+  return true;
+}
+
 Program::~Program() {
   if (manager_) {
     if (manager_->have_context_) {
diff --git a/gpu/command_buffer/service/program_manager.h b/gpu/command_buffer/service/program_manager.h
index 2f5deae..6f7e3a9 100644
--- a/gpu/command_buffer/service/program_manager.h
+++ b/gpu/command_buffer/service/program_manager.h
@@ -149,6 +149,10 @@
   void GetProgramInfo(
       ProgramManager* manager, CommonDecoder::Bucket* bucket) const;
 
+  // Gets all the UniformBlock info.
+  // Return false on overflow.
+  bool GetUniformBlocks(CommonDecoder::Bucket* bucket) const;
+
   // Sets the sampler values for a uniform.
   // This is safe to call for any location. If the location is not
   // a sampler uniform nothing will happen.
diff --git a/gpu/command_buffer/service/program_manager_unittest.cc b/gpu/command_buffer/service/program_manager_unittest.cc
index 4acd220..7d9ea9d 100644
--- a/gpu/command_buffer/service/program_manager_unittest.cc
+++ b/gpu/command_buffer/service/program_manager_unittest.cc
@@ -28,7 +28,7 @@
 using ::testing::Return;
 using ::testing::ReturnRef;
 using ::testing::SetArrayArgument;
-using ::testing::SetArgumentPointee;
+using ::testing::SetArgPointee;
 using ::testing::StrEq;
 
 namespace gpu {
@@ -38,6 +38,12 @@
 const uint32 kMaxVaryingVectors = 8;
 
 void ShaderCacheCb(const std::string& key, const std::string& shader) {}
+
+uint32 ComputeOffset(const void* start, const void* position) {
+  return static_cast<const uint8*>(position) -
+         static_cast<const uint8*>(start);
+}
+
 }  // namespace anonymous
 
 class ProgramManagerTest : public GpuServiceTest {
@@ -214,7 +220,8 @@
   } VarInfo;
 
   void SetUp() override {
-    GpuServiceTest::SetUp();
+    // Need to be at leat 3.1 for UniformBlock related GL APIs.
+    GpuServiceTest::SetUpWithGLVersion("3.1", NULL);
 
     SetupDefaultShaderExpectations();
 
@@ -1073,6 +1080,153 @@
             static_cast<uint32>(input - inputs));
 }
 
+TEST_F(ProgramManagerWithShaderTest, ProgramInfoGetUniformBlocksNone) {
+  CommonDecoder::Bucket bucket;
+  const Program* program = manager_.GetProgram(kClientProgramId);
+  ASSERT_TRUE(program != NULL);
+  // The program's previous link failed.
+  EXPECT_CALL(*(gl_.get()),
+              GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+      .WillOnce(SetArgPointee<2>(GL_FALSE))
+      .RetiresOnSaturation();
+  EXPECT_TRUE(program->GetUniformBlocks(&bucket));
+  EXPECT_EQ(sizeof(UniformBlocksHeader), bucket.size());
+  UniformBlocksHeader* header =
+      bucket.GetDataAs<UniformBlocksHeader*>(0, sizeof(UniformBlocksHeader));
+  EXPECT_TRUE(header != NULL);
+  EXPECT_EQ(0u, header->num_uniform_blocks);
+  // Zero uniform blocks.
+  EXPECT_CALL(*(gl_.get()),
+              GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+      .WillOnce(SetArgPointee<2>(GL_TRUE))
+      .RetiresOnSaturation();
+  EXPECT_CALL(*(gl_.get()),
+              GetProgramiv(kServiceProgramId, GL_ACTIVE_UNIFORM_BLOCKS, _))
+      .WillOnce(SetArgPointee<2>(0))
+      .RetiresOnSaturation();
+  EXPECT_TRUE(program->GetUniformBlocks(&bucket));
+  EXPECT_EQ(sizeof(UniformBlocksHeader), bucket.size());
+  header =
+      bucket.GetDataAs<UniformBlocksHeader*>(0, sizeof(UniformBlocksHeader));
+  EXPECT_TRUE(header != NULL);
+  EXPECT_EQ(0u, header->num_uniform_blocks);
+}
+
+TEST_F(ProgramManagerWithShaderTest, ProgramInfoGetUniformBlocksValid) {
+  CommonDecoder::Bucket bucket;
+  const Program* program = manager_.GetProgram(kClientProgramId);
+  ASSERT_TRUE(program != NULL);
+  struct Data {
+    UniformBlocksHeader header;
+    UniformBlockInfo entry[2];
+    char name0[4];
+    uint32_t indices0[2];
+    char name1[8];
+    uint32_t indices1[1];
+  };
+  Data data;
+  // The names needs to be of size 4*k-1 to avoid padding in the struct Data.
+  // This is a testing only problem.
+  const char* kName[] = { "cow", "chicken" };
+  const uint32_t kIndices0[] = { 1, 2 };
+  const uint32_t kIndices1[] = { 3 };
+  const uint32_t* kIndices[] = { kIndices0, kIndices1 };
+  data.header.num_uniform_blocks = 2;
+  data.entry[0].binding = 0;
+  data.entry[0].data_size = 8;
+  data.entry[0].name_offset = ComputeOffset(&data, data.name0);
+  data.entry[0].name_length = arraysize(data.name0);
+  data.entry[0].active_uniforms = arraysize(data.indices0);
+  data.entry[0].active_uniform_offset = ComputeOffset(&data, data.indices0);
+  data.entry[0].referenced_by_vertex_shader = static_cast<uint32_t>(true);
+  data.entry[0].referenced_by_fragment_shader = static_cast<uint32_t>(false);
+  data.entry[1].binding = 1;
+  data.entry[1].data_size = 4;
+  data.entry[1].name_offset = ComputeOffset(&data, data.name1);
+  data.entry[1].name_length = arraysize(data.name1);
+  data.entry[1].active_uniforms = arraysize(data.indices1);
+  data.entry[1].active_uniform_offset = ComputeOffset(&data, data.indices1);
+  data.entry[1].referenced_by_vertex_shader = static_cast<uint32_t>(false);
+  data.entry[1].referenced_by_fragment_shader = static_cast<uint32_t>(true);
+  memcpy(data.name0, kName[0], arraysize(data.name0));
+  data.indices0[0] = kIndices[0][0];
+  data.indices0[1] = kIndices[0][1];
+  memcpy(data.name1, kName[1], arraysize(data.name1));
+  data.indices1[0] = kIndices[1][0];
+
+  EXPECT_CALL(*(gl_.get()),
+              GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+      .WillOnce(SetArgPointee<2>(GL_TRUE))
+      .RetiresOnSaturation();
+  EXPECT_CALL(*(gl_.get()),
+              GetProgramiv(kServiceProgramId, GL_ACTIVE_UNIFORM_BLOCKS, _))
+      .WillOnce(SetArgPointee<2>(data.header.num_uniform_blocks))
+      .RetiresOnSaturation();
+  EXPECT_CALL(*(gl_.get()),
+              GetProgramiv(kServiceProgramId,
+                           GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, _))
+      .WillOnce(SetArgPointee<2>(
+          1 + std::max(strlen(kName[0]), strlen(kName[1]))))
+      .RetiresOnSaturation();
+  for (uint32_t ii = 0; ii < data.header.num_uniform_blocks; ++ii) {
+    EXPECT_CALL(*(gl_.get()),
+                GetActiveUniformBlockiv(
+                    kServiceProgramId, ii, GL_UNIFORM_BLOCK_BINDING, _))
+        .WillOnce(SetArgPointee<3>(data.entry[ii].binding))
+        .RetiresOnSaturation();
+    EXPECT_CALL(*(gl_.get()),
+                GetActiveUniformBlockiv(
+                    kServiceProgramId, ii, GL_UNIFORM_BLOCK_DATA_SIZE, _))
+        .WillOnce(SetArgPointee<3>(data.entry[ii].data_size))
+        .RetiresOnSaturation();
+    EXPECT_CALL(*(gl_.get()),
+                GetActiveUniformBlockiv(
+                    kServiceProgramId, ii, GL_UNIFORM_BLOCK_NAME_LENGTH, _))
+        .WillOnce(SetArgPointee<3>(data.entry[ii].name_length))
+        .RetiresOnSaturation();
+    EXPECT_CALL(*(gl_.get()),
+                GetActiveUniformBlockName(
+                    kServiceProgramId, ii, data.entry[ii].name_length, _, _))
+          .WillOnce(DoAll(
+              SetArgPointee<3>(strlen(kName[ii])),
+              SetArrayArgument<4>(
+                  kName[ii], kName[ii] + data.entry[ii].name_length)))
+          .RetiresOnSaturation();
+    EXPECT_CALL(*(gl_.get()),
+                GetActiveUniformBlockiv(
+                    kServiceProgramId, ii, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, _))
+        .WillOnce(SetArgPointee<3>(data.entry[ii].active_uniforms))
+        .RetiresOnSaturation();
+    EXPECT_CALL(*(gl_.get()),
+                GetActiveUniformBlockiv(
+                    kServiceProgramId, ii,
+                    GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER, _))
+        .WillOnce(SetArgPointee<3>(data.entry[ii].referenced_by_vertex_shader))
+        .RetiresOnSaturation();
+    EXPECT_CALL(*(gl_.get()),
+                GetActiveUniformBlockiv(
+                    kServiceProgramId, ii,
+                    GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER, _))
+        .WillOnce(SetArgPointee<3>(
+            data.entry[ii].referenced_by_fragment_shader))
+        .RetiresOnSaturation();
+  }
+  for (uint32_t ii = 0; ii < data.header.num_uniform_blocks; ++ii) {
+    EXPECT_CALL(*(gl_.get()),
+                GetActiveUniformBlockiv(
+                    kServiceProgramId, ii,
+                    GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, _))
+        .WillOnce(SetArrayArgument<3>(
+            kIndices[ii], kIndices[ii] + data.entry[ii].active_uniforms))
+        .RetiresOnSaturation();
+  }
+  program->GetUniformBlocks(&bucket);
+  EXPECT_EQ(sizeof(Data), bucket.size());
+  Data* bucket_data = bucket.GetDataAs<Data*>(0, sizeof(Data));
+  EXPECT_TRUE(bucket_data != NULL);
+  EXPECT_EQ(0, memcmp(&data, bucket_data, sizeof(Data)));
+}
+
 // Some drivers optimize out unused uniform array elements, so their
 // location would be -1.
 TEST_F(ProgramManagerWithShaderTest, UnusedUniformArrayElements) {
@@ -1717,7 +1871,7 @@
                 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(1);
     EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(1);
     EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _))
-        .WillOnce(SetArgumentPointee<2>(GL_TRUE));
+        .WillOnce(SetArgPointee<2>(GL_TRUE));
   }
 
   void SetExpectationsForNoCompile(const Shader* shader) {
@@ -1737,9 +1891,9 @@
                 ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(1);
     EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(1);
     EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _))
-        .WillOnce(SetArgumentPointee<2>(GL_FALSE));
+        .WillOnce(SetArgPointee<2>(GL_FALSE));
     EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_INFO_LOG_LENGTH, _))
-        .WillOnce(SetArgumentPointee<2>(0));
+        .WillOnce(SetArgPointee<2>(0));
     EXPECT_CALL(*gl_.get(), GetShaderInfoLog(shader_id, 0, _, _))
         .Times(1);
   }
diff --git a/gpu/command_buffer/service/query_manager_unittest.cc b/gpu/command_buffer/service/query_manager_unittest.cc
index 7c8e93c..9c3dd10 100644
--- a/gpu/command_buffer/service/query_manager_unittest.cc
+++ b/gpu/command_buffer/service/query_manager_unittest.cc
@@ -38,7 +38,7 @@
 
  protected:
   void SetUp() override {
-    GpuServiceTest::SetUp();
+    GpuServiceTest::SetUpWithGLVersion("2.1", "GL_ARB_occlusion_query");
     engine_.reset(new MockCommandBufferEngine());
     decoder_.reset(new MockGLES2Decoder());
     decoder_->set_engine(engine_.get());
diff --git a/gpu/command_buffer/service/renderbuffer_manager.cc b/gpu/command_buffer/service/renderbuffer_manager.cc
index ff8ae7b..4b4337e 100644
--- a/gpu/command_buffer/service/renderbuffer_manager.cc
+++ b/gpu/command_buffer/service/renderbuffer_manager.cc
@@ -3,9 +3,10 @@
 // found in the LICENSE file.
 
 #include "gpu/command_buffer/service/renderbuffer_manager.h"
-#include "base/debug/trace_event.h"
+
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
+#include "base/trace_event/trace_event.h"
 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
 #include "gpu/command_buffer/service/memory_tracking.h"
diff --git a/gpu/command_buffer/service/shader_translator.cc b/gpu/command_buffer/service/shader_translator.cc
index 74b183b..878490c 100644
--- a/gpu/command_buffer/service/shader_translator.cc
+++ b/gpu/command_buffer/service/shader_translator.cc
@@ -10,10 +10,10 @@
 
 #include "base/at_exit.h"
 #include "base/command_line.h"
-#include "base/debug/trace_event.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/trace_event/trace_event.h"
 #include "gpu/command_buffer/service/gpu_switches.h"
 
 namespace gpu {
diff --git a/gpu/command_buffer/service/texture_definition.cc b/gpu/command_buffer/service/texture_definition.cc
index edd4271..7af662c 100644
--- a/gpu/command_buffer/service/texture_definition.cc
+++ b/gpu/command_buffer/service/texture_definition.cc
@@ -413,7 +413,8 @@
   if (texture->min_filter_ != min_filter_ ||
       texture->mag_filter_ != mag_filter_ ||
       texture->wrap_s_ != wrap_s_ ||
-      texture->wrap_t_ != wrap_t_) {
+      texture->wrap_t_ != wrap_t_ ||
+      texture->SafeToRenderFrom() != SafeToRenderFrom()) {
     return false;
   }
 
@@ -424,5 +425,16 @@
   return true;
 }
 
+bool TextureDefinition::SafeToRenderFrom() const {
+  for (const std::vector<LevelInfo>& face_info : level_infos_) {
+    for (const LevelInfo& level_info : face_info) {
+      if (!level_info.cleared) {
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
 }  // namespace gles2
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/texture_definition.h b/gpu/command_buffer/service/texture_definition.h
index ff891fc..95f0fa2 100644
--- a/gpu/command_buffer/service/texture_definition.h
+++ b/gpu/command_buffer/service/texture_definition.h
@@ -58,6 +58,8 @@
   scoped_refptr<NativeImageBuffer> image() const { return image_buffer_; }
 
  private:
+  bool SafeToRenderFrom() const;
+
   struct LevelInfo {
     LevelInfo(GLenum target,
               GLenum internal_format,
diff --git a/gpu/command_buffer/service/transfer_buffer_manager.cc b/gpu/command_buffer/service/transfer_buffer_manager.cc
index 4404a9e..e9c83e0 100644
--- a/gpu/command_buffer/service/transfer_buffer_manager.cc
+++ b/gpu/command_buffer/service/transfer_buffer_manager.cc
@@ -8,8 +8,8 @@
 
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/debug/trace_event.h"
 #include "base/process/process_handle.h"
+#include "base/trace_event/trace_event.h"
 #include "gpu/command_buffer/common/cmd_buffer_common.h"
 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
 
diff --git a/gpu/command_buffer/service/vertex_array_manager.cc b/gpu/command_buffer/service/vertex_array_manager.cc
index 1560c04..0809eda 100644
--- a/gpu/command_buffer/service/vertex_array_manager.cc
+++ b/gpu/command_buffer/service/vertex_array_manager.cc
@@ -3,8 +3,9 @@
 // found in the LICENSE file.
 
 #include "gpu/command_buffer/service/vertex_array_manager.h"
-#include "base/debug/trace_event.h"
+
 #include "base/logging.h"
+#include "base/trace_event/trace_event.h"
 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
 #include "gpu/command_buffer/service/buffer_manager.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
diff --git a/gpu/command_buffer/service/vertex_array_manager_unittest.cc b/gpu/command_buffer/service/vertex_array_manager_unittest.cc
index 24592b6..0d3d1d0 100644
--- a/gpu/command_buffer/service/vertex_array_manager_unittest.cc
+++ b/gpu/command_buffer/service/vertex_array_manager_unittest.cc
@@ -29,7 +29,7 @@
 
  protected:
   void SetUp() override {
-    GpuServiceTest::SetUp();
+    GpuServiceTest::SetUpWithGLVersion("2.1", "GL_ARB_vertex_array_object");
     manager_.reset(new VertexArrayManager());
   }