Pass GL context bind_generates_resources flag to GPU Service.

GPU Client has been respecting the bind_generates_resources attrib,
however the GPU Service has been forcing it to always 'true'.  This
means glBind semantic validation has been incorrect when
bind_generates_resources is 'false' on the Client.

This patch passes the bind_generates_resources attrib for
WebGraphicsContext3DCommandBufferImpl, and checks that all contexts
in the same ContextGroup use the same setting.

BUG=333063, 244968

Review URL: https://codereview.chromium.org/213743003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@261563 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index e635ae5..1754704e 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -590,6 +590,7 @@
       'GL_UNPACK_FLIP_Y_CHROMIUM',
       'GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM',
       'GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM',
+      'GL_BIND_GENERATES_RESOURCE_CHROMIUM',
       # we can add this because we emulate it if the driver does not support it.
       'GL_VERTEX_ARRAY_BINDING_OES',
       'GL_VIEWPORT',
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index 70c5bc7..4178332 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -67,8 +67,8 @@
       max_vertex_texture_image_units(0),
       max_vertex_uniform_vectors(0),
       num_compressed_texture_formats(0),
-      num_shader_binary_formats(0) {
-}
+      num_shader_binary_formats(0),
+      bind_generates_resource_chromium(0) {}
 
 GLES2Implementation::SingleThreadChecker::SingleThreadChecker(
     GLES2Implementation* gles2_implementation)
@@ -201,6 +201,16 @@
       reserved_ids_[0],
       reserved_ids_[1]));
 
+  // GL_BIND_GENERATES_RESOURCE_CHROMIUM state must be the same
+  // on Client & Service.
+  if (static_state_.int_state.bind_generates_resource_chromium !=
+      (share_group_->bind_generates_resource() ? 1 : 0)) {
+    SetGLError(GL_INVALID_OPERATION,
+               "Initialize",
+               "Service bind_generates_resource mismatch.");
+    return false;
+  }
+
   return true;
 }
 
@@ -219,6 +229,7 @@
     GL_MAX_VERTEX_UNIFORM_VECTORS,
     GL_NUM_COMPRESSED_TEXTURE_FORMATS,
     GL_NUM_SHADER_BINARY_FORMATS,
+    GL_BIND_GENERATES_RESOURCE_CHROMIUM,
   };
 
   GetMultipleIntegervState integerv_state(
diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h
index a7517e8..70fe197 100644
--- a/gpu/command_buffer/client/gles2_implementation.h
+++ b/gpu/command_buffer/client/gles2_implementation.h
@@ -148,6 +148,7 @@
       GLint max_vertex_uniform_vectors;
       GLint num_compressed_texture_formats;
       GLint num_shader_binary_formats;
+      GLint bind_generates_resource_chromium;
     };
     IntState int_state;
 
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc
index f57d07a..a280e4f 100644
--- a/gpu/command_buffer/client/gles2_implementation_unittest.cc
+++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc
@@ -392,11 +392,12 @@
    public:
     TestContext() : commands_(NULL), token_(0) {}
 
-    void Initialize(ShareGroup* share_group,
+    bool Initialize(ShareGroup* share_group,
                     bool bind_generates_resource,
                     bool lose_context_when_out_of_memory) {
       command_buffer_.reset(new StrictMock<MockClientCommandBuffer>());
-      ASSERT_TRUE(command_buffer_->Initialize());
+      if (!command_buffer_->Initialize())
+        return false;
 
       transfer_buffer_.reset(
           new MockTransferBuffer(command_buffer_.get(),
@@ -426,6 +427,8 @@
       int_state.max_vertex_uniform_vectors = kMaxVertexUniformVectors;
       int_state.num_compressed_texture_formats = kNumCompressedTextureFormats;
       int_state.num_shader_binary_formats = kNumShaderBinaryFormats;
+      int_state.bind_generates_resource_chromium =
+          bind_generates_resource ? 1 : 0;
 
       // This just happens to work for now because IntState has 1 GLint per
       // state.
@@ -449,10 +452,12 @@
                                           bind_generates_resource,
                                           lose_context_when_out_of_memory,
                                           gpu_control_.get()));
-        ASSERT_TRUE(gl_->Initialize(kTransferBufferSize,
-                                    kTransferBufferSize,
-                                    kTransferBufferSize,
-                                    GLES2Implementation::kNoLimit));
+
+        if (!gl_->Initialize(kTransferBufferSize,
+                             kTransferBufferSize,
+                             kTransferBufferSize,
+                             GLES2Implementation::kNoLimit))
+          return false;
       }
 
       EXPECT_CALL(*command_buffer_, OnFlush()).Times(1).RetiresOnSaturation();
@@ -466,6 +471,7 @@
       EXPECT_TRUE(transfer_buffer_->InSync());
 
       ::testing::Mock::VerifyAndClearExpectations(command_buffer());
+      return true;
     }
 
     void TearDown() {
@@ -518,14 +524,28 @@
     return gl_->query_tracker_->GetQuery(id);
   }
 
-  void Initialize(bool bind_generates_resource,
-                  bool lose_context_when_out_of_memory) {
-    share_group_ = new ShareGroup(bind_generates_resource);
+  struct ContextInitOptions {
+    ContextInitOptions()
+        : bind_generates_resource_client(true),
+          bind_generates_resource_service(true),
+          lose_context_when_out_of_memory(false) {}
 
-    for (int i = 0; i < kNumTestContexts; i++)
-      test_contexts_[i].Initialize(share_group_.get(),
-                                   bind_generates_resource,
-                                   lose_context_when_out_of_memory);
+    bool bind_generates_resource_client;
+    bool bind_generates_resource_service;
+    bool lose_context_when_out_of_memory;
+  };
+
+  bool Initialize(const ContextInitOptions& init_options) {
+    bool success = true;
+    share_group_ = new ShareGroup(init_options.bind_generates_resource_service);
+
+    for (int i = 0; i < kNumTestContexts; i++) {
+      if (!test_contexts_[i].Initialize(
+              share_group_.get(),
+              init_options.bind_generates_resource_client,
+              init_options.lose_context_when_out_of_memory))
+        success = false;
+    }
 
     // Default to test context 0.
     gpu_control_ = test_contexts_[0].gpu_control_.get();
@@ -533,6 +553,7 @@
     transfer_buffer_ = test_contexts_[0].transfer_buffer_.get();
     gl_ = test_contexts_[0].gl_.get();
     commands_ = test_contexts_[0].commands_;
+    return success;
   }
 
   MockClientCommandBuffer* command_buffer() const {
@@ -592,9 +613,8 @@
 };
 
 void GLES2ImplementationTest::SetUp() {
-  bool bind_generates_resource = true;
-  bool lose_context_when_out_of_memory = false;
-  Initialize(bind_generates_resource, lose_context_when_out_of_memory);
+  ContextInitOptions init_options;
+  ASSERT_TRUE(Initialize(init_options));
 }
 
 void GLES2ImplementationTest::TearDown() {
@@ -697,9 +717,10 @@
 };
 
 void GLES2ImplementationStrictSharedTest::SetUp() {
-  bool bind_generates_resource = false;
-  bool lose_context_when_out_of_memory = false;
-  Initialize(bind_generates_resource, lose_context_when_out_of_memory);
+  ContextInitOptions init_options;
+  init_options.bind_generates_resource_client = false;
+  init_options.bind_generates_resource_service = false;
+  ASSERT_TRUE(Initialize(init_options));
 }
 
 // GCC requires these declarations, but MSVC requires they not be present
@@ -3117,9 +3138,9 @@
 }
 
 TEST_F(GLES2ImplementationManualInitTest, LoseContextOnOOM) {
-  bool bind_generates_resource = false;
-  bool lose_context_when_out_of_memory = true;
-  Initialize(bind_generates_resource, lose_context_when_out_of_memory);
+  ContextInitOptions init_options;
+  init_options.lose_context_when_out_of_memory = true;
+  ASSERT_TRUE(Initialize(init_options));
 
   struct Cmds {
     cmds::LoseContextCHROMIUM cmd;
@@ -3136,9 +3157,8 @@
 }
 
 TEST_F(GLES2ImplementationManualInitTest, NoLoseContextOnOOM) {
-  bool bind_generates_resource = false;
-  bool lose_context_when_out_of_memory = false;
-  Initialize(bind_generates_resource, lose_context_when_out_of_memory);
+  ContextInitOptions init_options;
+  ASSERT_TRUE(Initialize(init_options));
 
   struct Cmds {
     cmds::LoseContextCHROMIUM cmd;
@@ -3152,6 +3172,20 @@
   EXPECT_TRUE(NoCommandsWritten());
 }
 
+TEST_F(GLES2ImplementationManualInitTest, FailInitOnBGRMismatch1) {
+  ContextInitOptions init_options;
+  init_options.bind_generates_resource_client = false;
+  init_options.bind_generates_resource_service = true;
+  EXPECT_FALSE(Initialize(init_options));
+}
+
+TEST_F(GLES2ImplementationManualInitTest, FailInitOnBGRMismatch2) {
+  ContextInitOptions init_options;
+  init_options.bind_generates_resource_client = true;
+  init_options.bind_generates_resource_service = false;
+  EXPECT_FALSE(Initialize(init_options));
+}
+
 #include "gpu/command_buffer/client/gles2_implementation_unittest_autogen.h"
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.cc b/gpu/command_buffer/common/gles2_cmd_utils.cc
index 97bc081..8381586 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils.cc
+++ b/gpu/command_buffer/common/gles2_cmd_utils.cc
@@ -326,6 +326,10 @@
     case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
       return 1;
 
+    // Chromium internal bind_generates_resource query
+    case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
+      return 1;
+
     // bad enum
     default:
       return 0;
diff --git a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
index 3bce267..62f1c308 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
@@ -389,6 +389,7 @@
     {0x812D, "GL_CLAMP_TO_BORDER_NV", },
     {0x812F, "GL_CLAMP_TO_EDGE", },
     {0x86A3, "GL_COMPRESSED_TEXTURE_FORMATS", },
+    {0x9244, "GL_BIND_GENERATES_RESOURCE_CHROMIUM", },
     {0x86A2, "GL_NUM_COMPRESSED_TEXTURE_FORMATS", },
     {0x0CF3, "GL_UNPACK_SKIP_ROWS_EXT", },
     {0x0CF2, "GL_UNPACK_ROW_LENGTH_EXT", },
@@ -1002,6 +1003,8 @@
        "GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM"},
       {GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM,
        "GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM"},
+      {GL_BIND_GENERATES_RESOURCE_CHROMIUM,
+       "GL_BIND_GENERATES_RESOURCE_CHROMIUM"},
       {GL_VERTEX_ARRAY_BINDING_OES, "GL_VERTEX_ARRAY_BINDING_OES"},
       {GL_VIEWPORT, "GL_VIEWPORT"},
       {GL_BLEND_COLOR, "GL_BLEND_COLOR"},
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 64ff616..c70a999 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -4555,6 +4555,12 @@
         params[0] = unpack_unpremultiply_alpha_;
       }
       return true;
+    case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
+      *num_written = 1;
+      if (params) {
+        params[0] = group_->bind_generates_resource() ? 1 : 0;
+      }
+      return true;
     default:
       if (pname >= GL_DRAW_BUFFER0_ARB &&
           pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
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 6a9b2b30..ca49ced 100644
--- a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h
@@ -116,6 +116,7 @@
     GL_UNPACK_FLIP_Y_CHROMIUM,
     GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM,
     GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM,
+    GL_BIND_GENERATES_RESOURCE_CHROMIUM,
     GL_VERTEX_ARRAY_BINDING_OES,
     GL_VIEWPORT,
     GL_BLEND_COLOR,