Update from chromium https://crrev.com/304586

Review URL: https://codereview.chromium.org/732423002
diff --git a/gpu/command_buffer/tests/gl_clear_framebuffer_unittest.cc b/gpu/command_buffer/tests/gl_clear_framebuffer_unittest.cc
new file mode 100644
index 0000000..8a925c8
--- /dev/null
+++ b/gpu/command_buffer/tests/gl_clear_framebuffer_unittest.cc
@@ -0,0 +1,200 @@
+// Copyright 2014 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.
+
+#ifndef GL_GLEXT_PROTOTYPES
+#define GL_GLEXT_PROTOTYPES
+#endif
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <GLES2/gl2extchromium.h>
+
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/strings/string_number_conversions.h"
+#include "gpu/command_buffer/service/gpu_switches.h"
+#include "gpu/command_buffer/tests/gl_manager.h"
+#include "gpu/command_buffer/tests/gl_test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace gpu {
+
+// A collection of tests that exercise the glClear workaround.
+class GLClearFramebufferTest : public testing::TestWithParam<bool> {
+ public:
+  GLClearFramebufferTest() : color_handle_(0u), depth_handle_(0u) {}
+
+ protected:
+  void SetUp() override {
+    if (GetParam()) {
+      // Force the glClear() workaround so we can test it here.
+      CommandLine command_line(base::CommandLine::NO_PROGRAM);
+      command_line.AppendSwitchASCII(switches::kGpuDriverBugWorkarounds,
+                                     base::IntToString(gpu::GL_CLEAR_BROKEN));
+      gl_.InitializeWithCommandLine(GLManager::Options(), &command_line);
+      DCHECK(gl_.workarounds().gl_clear_broken);
+    } else {
+      gl_.Initialize(GLManager::Options());
+      DCHECK(!gl_.workarounds().gl_clear_broken);
+    }
+  }
+
+  void InitDraw();
+  void SetDrawColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
+  void SetDrawDepth(GLfloat depth);
+  void DrawQuad();
+
+  void TearDown() override {
+    GLTestHelper::CheckGLError("no errors", __LINE__);
+    gl_.Destroy();
+  }
+
+ private:
+  GLManager gl_;
+  GLuint color_handle_;
+  GLuint depth_handle_;
+};
+
+void GLClearFramebufferTest::InitDraw() {
+  static const char* v_shader_str =
+      "attribute vec4 a_Position;\n"
+      "uniform float u_depth;\n"
+      "void main()\n"
+      "{\n"
+      "   gl_Position = a_Position;\n"
+      "   gl_Position.z = u_depth;\n"
+      "}\n";
+  static const char* f_shader_str =
+      "precision mediump float;\n"
+      "uniform vec4 u_draw_color;\n"
+      "void main()\n"
+      "{\n"
+      "  gl_FragColor = u_draw_color;\n"
+      "}\n";
+
+  GLuint program = GLTestHelper::LoadProgram(v_shader_str, f_shader_str);
+  DCHECK(program);
+  glUseProgram(program);
+  GLuint position_loc = glGetAttribLocation(program, "a_Position");
+
+  GLTestHelper::SetupUnitQuad(position_loc);
+  color_handle_ = glGetUniformLocation(program, "u_draw_color");
+  DCHECK(color_handle_ != static_cast<GLuint>(-1));
+  depth_handle_ = glGetUniformLocation(program, "u_depth");
+  DCHECK(depth_handle_ != static_cast<GLuint>(-1));
+}
+
+void GLClearFramebufferTest::SetDrawColor(GLfloat r,
+                                          GLfloat g,
+                                          GLfloat b,
+                                          GLfloat a) {
+  glUniform4f(color_handle_, r, g, b, a);
+}
+
+void GLClearFramebufferTest::SetDrawDepth(GLfloat depth) {
+  glUniform1f(depth_handle_, depth);
+}
+
+void GLClearFramebufferTest::DrawQuad() {
+  glDrawArrays(GL_TRIANGLES, 0, 6);
+}
+
+INSTANTIATE_TEST_CASE_P(GLClearFramebufferTestWithParam,
+                        GLClearFramebufferTest,
+                        ::testing::Values(true, false));
+
+TEST_P(GLClearFramebufferTest, ClearColor) {
+  glClearColor(1.0f, 0.5f, 0.25f, 0.5f);
+  glClear(GL_COLOR_BUFFER_BIT);
+
+  // Verify.
+  const uint8 expected[] = {255, 128, 64, 128};
+  EXPECT_TRUE(
+      GLTestHelper::CheckPixels(0, 0, 1, 1, 1 /* tolerance */, expected));
+}
+
+TEST_P(GLClearFramebufferTest, ClearColorWithMask) {
+  glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
+  glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+  glClear(GL_COLOR_BUFFER_BIT);
+
+  // Verify.
+  const uint8 expected[] = {255, 0, 0, 0};
+  EXPECT_TRUE(
+      GLTestHelper::CheckPixels(0, 0, 1, 1, 0 /* tolerance */, expected));
+}
+
+// crbug.com/434094
+#if !defined(OS_MACOSX)
+TEST_P(GLClearFramebufferTest, ClearColorWithScissor) {
+  glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+  glClear(GL_COLOR_BUFFER_BIT);
+
+  // Verify.
+  const uint8 expected[] = {255, 255, 255, 255};
+  EXPECT_TRUE(
+      GLTestHelper::CheckPixels(0, 0, 1, 1, 0 /* tolerance */, expected));
+
+  glScissor(0, 0, 0, 0);
+  glEnable(GL_SCISSOR_TEST);
+  glClearColor(0, 0, 0, 0);
+  glClear(GL_COLOR_BUFFER_BIT);
+
+  // Verify - no changes.
+  EXPECT_TRUE(
+      GLTestHelper::CheckPixels(0, 0, 1, 1, 0 /* tolerance */, expected));
+}
+#endif
+
+TEST_P(GLClearFramebufferTest, ClearDepthStencil) {
+  const GLuint kStencilRef = 1 << 2;
+  InitDraw();
+  SetDrawColor(1.0f, 0.0f, 0.0f, 1.0f);
+  DrawQuad();
+  // Verify.
+  const uint8 kRed[] = {255, 0, 0, 255};
+  const uint8 kGreen[] = {0, 255, 0, 255};
+  EXPECT_TRUE(
+      GLTestHelper::CheckPixels(0, 0, 1, 1, 0 /* tolerance */, kRed));
+
+  glClearStencil(kStencilRef);
+  glClear(GL_STENCIL_BUFFER_BIT);
+  glEnable(GL_STENCIL_TEST);
+  glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+  glStencilFunc(GL_NOTEQUAL, kStencilRef, 0xFFFFFFFF);
+
+  SetDrawColor(0.0f, 1.0f, 0.0f, 1.0f);
+  DrawQuad();
+  // Verify - stencil should have failed, so still red.
+  EXPECT_TRUE(
+      GLTestHelper::CheckPixels(0, 0, 1, 1, 0 /* tolerance */, kRed));
+
+  glStencilFunc(GL_EQUAL, kStencilRef, 0xFFFFFFFF);
+  DrawQuad();
+  // Verify - stencil should have passed, so green.
+  EXPECT_TRUE(
+      GLTestHelper::CheckPixels(0, 0, 1, 1, 0 /* tolerance */, kGreen));
+
+  glEnable(GL_DEPTH_TEST);
+  glClearDepthf(0.0f);
+  glClear(GL_DEPTH_BUFFER_BIT);
+
+  SetDrawDepth(0.5f);
+  SetDrawColor(1.0f, 0.0f, 0.0f, 1.0f);
+  DrawQuad();
+  // Verify - depth test should have failed, so still green.
+  EXPECT_TRUE(
+      GLTestHelper::CheckPixels(0, 0, 1, 1, 0 /* tolerance */, kGreen));
+
+  glClearDepthf(0.9f);
+  glClear(GL_DEPTH_BUFFER_BIT);
+  DrawQuad();
+  // Verify - depth test should have passed, so red.
+  EXPECT_TRUE(
+      GLTestHelper::CheckPixels(0, 0, 1, 1, 0 /* tolerance */, kRed));
+}
+
+}  // namespace gpu
diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc
index ebd821c..c09901f 100644
--- a/gpu/command_buffer/tests/gl_manager.cc
+++ b/gpu/command_buffer/tests/gl_manager.cc
@@ -139,6 +139,10 @@
 }
 
 void GLManager::Initialize(const GLManager::Options& options) {
+  InitializeWithCommandLine(options, nullptr);
+}
+void GLManager::InitializeWithCommandLine(const GLManager::Options& options,
+                                          base::CommandLine* command_line) {
   const int32 kCommandBufferSize = 1024 * 1024;
   const size_t kStartTransferBufferSize = 4 * 1024 * 1024;
   const size_t kMinTransferBufferSize = 1 * 256 * 1024;
@@ -186,14 +190,19 @@
   attrib_helper.blue_size = 8;
   attrib_helper.alpha_size = 8;
   attrib_helper.depth_size = 16;
+  attrib_helper.stencil_size = 8;
   attrib_helper.Serialize(&attribs);
 
+  DCHECK(!command_line || !context_group);
   if (!context_group) {
+    scoped_refptr<gles2::FeatureInfo> feature_info;
+    if (command_line)
+      feature_info = new gles2::FeatureInfo(*command_line);
     context_group =
         new gles2::ContextGroup(mailbox_manager_.get(),
                                 NULL,
                                 new gpu::gles2::ShaderTranslatorCache,
-                                NULL,
+                                feature_info,
                                 options.bind_generates_resource);
   }
 
diff --git a/gpu/command_buffer/tests/gl_manager.h b/gpu/command_buffer/tests/gl_manager.h
index 03ed6a1..7a3eb2c 100644
--- a/gpu/command_buffer/tests/gl_manager.h
+++ b/gpu/command_buffer/tests/gl_manager.h
@@ -13,6 +13,10 @@
 #include "ui/gfx/gpu_memory_buffer.h"
 #include "ui/gfx/size.h"
 
+namespace base {
+class CommandLine;
+}
+
 namespace gfx {
 
 class GLContext;
@@ -66,6 +70,8 @@
       gfx::GpuMemoryBuffer::Format format);
 
   void Initialize(const Options& options);
+  void InitializeWithCommandLine(const Options& options,
+                                 base::CommandLine* command_line);
   void Destroy();
 
   void MakeCurrent();
diff --git a/gpu/command_buffer/tests/gl_query_unittest.cc b/gpu/command_buffer/tests/gl_query_unittest.cc
index 0104430..5ea7e8d 100644
--- a/gpu/command_buffer/tests/gl_query_unittest.cc
+++ b/gpu/command_buffer/tests/gl_query_unittest.cc
@@ -63,7 +63,7 @@
   glGetQueryObjectuivEXT(commands_issue_query, GL_QUERY_RESULT_EXT, &result);
   // Sanity check - the resulting delta is shorter than the time it took to
   // run this test.
-  EXPECT_LT(result, base::TimeDelta(after - before).InMicroseconds());
+  EXPECT_LE(result, base::TimeDelta(after - before).InMicroseconds());
 
   result = 0;
   available = 0;
@@ -152,6 +152,8 @@
     return;
   }
 
+  base::TimeTicks before = base::TimeTicks::HighResNow();
+
   GLuint query;
   glGenQueriesEXT(1, &query);
   glBeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, query);
@@ -161,7 +163,12 @@
   glFlush();
   GLuint result = 0;
   glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT, &result);
-  EXPECT_EQ(0u, result);
+
+  base::TimeTicks after = base::TimeTicks::HighResNow();
+  // Sanity check - the resulting delta is shorter than the time it took to
+  // run this test.
+  EXPECT_LE(result, base::TimeDelta(after - before).InMicroseconds());
+
   glDeleteQueriesEXT(1, &query);
   GLTestHelper::CheckGLError("no errors", __LINE__);
 }