summaryrefslogtreecommitdiffstats
path: root/gpu/command_buffer/service
diff options
context:
space:
mode:
authorapatrick@google.com <apatrick@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-24 19:34:24 +0000
committerapatrick@google.com <apatrick@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-24 19:34:24 +0000
commit97632e2039e3ec0b9342f5e7c074bf631c738a9f (patch)
tree71e51bad650961671a0aa96b433403fc5a8ff544 /gpu/command_buffer/service
parentd4edbe5e406c5773d66d65214b963ed474b34cf4 (diff)
downloadchromium_src-97632e2039e3ec0b9342f5e7c074bf631c738a9f.zip
chromium_src-97632e2039e3ec0b9342f5e7c074bf631c738a9f.tar.gz
chromium_src-97632e2039e3ec0b9342f5e7c074bf631c738a9f.tar.bz2
Branched gpu process and command buffer code into Chrome tree. Fixed up paths and other minor changes to make it work in the Chrome tree. Will remove copy from O3D tree shortly. Only works in Windows currently.
TEST=none BUG=none Review URL: http://codereview.chromium.org/436017 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@32952 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu/command_buffer/service')
-rw-r--r--gpu/command_buffer/service/cmd_buffer_engine.h70
-rw-r--r--gpu/command_buffer/service/cmd_parser.cc110
-rw-r--r--gpu/command_buffer/service/cmd_parser.h115
-rw-r--r--gpu/command_buffer/service/cmd_parser_test.cc316
-rw-r--r--gpu/command_buffer/service/command_buffer_service.cc159
-rw-r--r--gpu/command_buffer/service/command_buffer_service.h93
-rw-r--r--gpu/command_buffer/service/command_buffer_service_unittest.cc185
-rw-r--r--gpu/command_buffer/service/common_decoder.cc122
-rw-r--r--gpu/command_buffer/service/common_decoder.h107
-rw-r--r--gpu/command_buffer/service/gl_utils.h58
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc950
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.h74
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_autogen.h2610
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_validate.h1255
-rw-r--r--gpu/command_buffer/service/gpu_processor.cc84
-rw-r--r--gpu/command_buffer/service/gpu_processor.h99
-rw-r--r--gpu/command_buffer/service/gpu_processor_mock.h40
-rw-r--r--gpu/command_buffer/service/gpu_processor_unittest.cc285
-rw-r--r--gpu/command_buffer/service/gpu_processor_win.cc80
-rw-r--r--gpu/command_buffer/service/mocks.h108
-rw-r--r--gpu/command_buffer/service/precompile.cc33
-rw-r--r--gpu/command_buffer/service/precompile.h50
-rw-r--r--gpu/command_buffer/service/resource.cc101
-rw-r--r--gpu/command_buffer/service/resource.h268
-rw-r--r--gpu/command_buffer/service/resource_test.cc127
-rw-r--r--gpu/command_buffer/service/x_utils.cc92
-rw-r--r--gpu/command_buffer/service/x_utils.h76
27 files changed, 7667 insertions, 0 deletions
diff --git a/gpu/command_buffer/service/cmd_buffer_engine.h b/gpu/command_buffer/service/cmd_buffer_engine.h
new file mode 100644
index 0000000..74ad649
--- /dev/null
+++ b/gpu/command_buffer/service/cmd_buffer_engine.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file defines the CommandBufferEngine class, providing the main loop for
+// the service, exposing the RPC API, managing the command parser.
+
+#ifndef GPU_COMMAND_BUFFER_SERVICE_CROSS_CMD_BUFFER_ENGINE_H_
+#define GPU_COMMAND_BUFFER_SERVICE_CROSS_CMD_BUFFER_ENGINE_H_
+
+#include "base/basictypes.h"
+
+namespace command_buffer {
+
+class CommandBufferEngine {
+ public:
+ CommandBufferEngine() {
+ }
+
+ virtual ~CommandBufferEngine() {
+ }
+
+ // Gets the base address of a registered shared memory buffer.
+ // Parameters:
+ // shm_id: the identifier for the shared memory buffer.
+ virtual void *GetSharedMemoryAddress(int32 shm_id) = 0;
+
+ // Gets the size of a registered shared memory buffer.
+ // Parameters:
+ // shm_id: the identifier for the shared memory buffer.
+ virtual size_t GetSharedMemorySize(int32 shm_id) = 0;
+
+ // Sets the token value.
+ virtual void set_token(int32 token) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CommandBufferEngine);
+};
+
+} // namespace command_buffer
+
+#endif // GPU_COMMAND_BUFFER_SERVICE_CROSS_CMD_BUFFER_ENGINE_H_
diff --git a/gpu/command_buffer/service/cmd_parser.cc b/gpu/command_buffer/service/cmd_parser.cc
new file mode 100644
index 0000000..019e7b2
--- /dev/null
+++ b/gpu/command_buffer/service/cmd_parser.cc
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the implementation of the command parser.
+
+#include "gpu/command_buffer/service/precompile.h"
+#include "gpu/command_buffer/service/cmd_parser.h"
+
+namespace command_buffer {
+
+CommandParser::CommandParser(void *shm_address,
+ size_t shm_size,
+ ptrdiff_t offset,
+ size_t size,
+ CommandBufferOffset start_get,
+ AsyncAPIInterface *handler)
+ : get_(start_get),
+ put_(start_get),
+ handler_(handler) {
+ // check proper alignments.
+ DCHECK_EQ(0, (reinterpret_cast<intptr_t>(shm_address)) % 4);
+ DCHECK_EQ(0, offset % 4);
+ DCHECK_EQ(0u, size % 4);
+ // check that the command buffer fits into the memory buffer.
+ DCHECK_GE(shm_size, offset + size);
+ char * buffer_begin = static_cast<char *>(shm_address) + offset;
+ buffer_ = reinterpret_cast<CommandBufferEntry *>(buffer_begin);
+ entry_count_ = size / 4;
+}
+
+// Process one command, reading the header from the command buffer, and
+// forwarding the command index and the arguments to the handler.
+// Note that:
+// - validation needs to happen on a copy of the data (to avoid race
+// conditions). This function only validates the header, leaving the arguments
+// validation to the handler, so it can pass a reference to them.
+// - get_ is modified *after* the command has been executed.
+parse_error::ParseError CommandParser::ProcessCommand() {
+ CommandBufferOffset get = get_;
+ if (get == put_) return parse_error::kParseNoError;
+
+ CommandHeader header = buffer_[get].value_header;
+ if (header.size == 0) {
+ DLOG(INFO) << "Error: zero sized command in command buffer";
+ return parse_error::kParseInvalidSize;
+ }
+
+ if (header.size + get > entry_count_) {
+ DLOG(INFO) << "Error: get offset out of bounds";
+ return parse_error::kParseOutOfBounds;
+ }
+
+ parse_error::ParseError result = handler_->DoCommand(
+ header.command, header.size - 1, buffer_ + get);
+ // TODO(gman): If you want to log errors this is the best place to catch them.
+ // It seems like we need an official way to turn on a debug mode and
+ // get these errors.
+ if (result != parse_error::kParseNoError) {
+ ReportError(header.command, result);
+ }
+ get_ = (get + header.size) % entry_count_;
+ return result;
+}
+
+void CommandParser::ReportError(unsigned int command_id,
+ parse_error::ParseError result) {
+ DLOG(INFO) << "Error: " << result << " for Command "
+ << handler_->GetCommandName(command_id);
+}
+
+// Processes all the commands, while the buffer is not empty. Stop if an error
+// is encountered.
+parse_error::ParseError CommandParser::ProcessAllCommands() {
+ while (!IsEmpty()) {
+ parse_error::ParseError error = ProcessCommand();
+ if (error) return error;
+ }
+ return parse_error::kParseNoError;
+}
+
+} // namespace command_buffer
diff --git a/gpu/command_buffer/service/cmd_parser.h b/gpu/command_buffer/service/cmd_parser.h
new file mode 100644
index 0000000..2209cf8
--- /dev/null
+++ b/gpu/command_buffer/service/cmd_parser.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the command parser class.
+
+#ifndef GPU_COMMAND_BUFFER_SERVICE_CROSS_CMD_PARSER_H_
+#define GPU_COMMAND_BUFFER_SERVICE_CROSS_CMD_PARSER_H_
+
+#include "gpu/command_buffer/common/constants.h"
+#include "gpu/command_buffer/common/cmd_buffer_common.h"
+
+namespace command_buffer {
+
+class AsyncAPIInterface;
+
+// Command parser class. This class parses commands from a shared memory
+// buffer, to implement some asynchronous RPC mechanism.
+class CommandParser {
+ public:
+ CommandParser(void *shm_address,
+ size_t shm_size,
+ ptrdiff_t offset,
+ size_t size,
+ CommandBufferOffset start_get,
+ AsyncAPIInterface *handler);
+
+ // Gets the "get" pointer. The get pointer is an index into the command
+ // buffer considered as an array of CommandBufferEntry.
+ CommandBufferOffset get() const { return get_; }
+
+ // Sets the "put" pointer. The put pointer is an index into the command
+ // buffer considered as an array of CommandBufferEntry.
+ void set_put(CommandBufferOffset put) { put_ = put; }
+
+ // Gets the "put" pointer. The put pointer is an index into the command
+ // buffer considered as an array of CommandBufferEntry.
+ CommandBufferOffset put() const { return put_; }
+
+ // Checks whether there are commands to process.
+ bool IsEmpty() const { return put_ == get_; }
+
+ // Processes one command, updating the get pointer. This will return an error
+ // if there are no commands in the buffer.
+ parse_error::ParseError ProcessCommand();
+
+ // Processes all commands until get == put.
+ parse_error::ParseError ProcessAllCommands();
+
+ // Reports an error.
+ void ReportError(unsigned int command_id, parse_error::ParseError result);
+
+ private:
+ CommandBufferOffset get_;
+ CommandBufferOffset put_;
+ CommandBufferEntry *buffer_;
+ size_t entry_count_;
+ AsyncAPIInterface *handler_;
+};
+
+// This class defines the interface for an asynchronous API handler, that
+// is responsible for de-multiplexing commands and their arguments.
+class AsyncAPIInterface {
+ public:
+ AsyncAPIInterface() {}
+ virtual ~AsyncAPIInterface() {}
+
+ // Executes a command.
+ // Parameters:
+ // command: the command index.
+ // arg_count: the number of CommandBufferEntry arguments.
+ // cmd_data: the command data.
+ // Returns:
+ // parse_error::NO_ERROR if no error was found, one of
+ // parse_error::ParseError otherwise.
+ virtual parse_error::ParseError DoCommand(
+ unsigned int command,
+ unsigned int arg_count,
+ const void* cmd_data) = 0;
+
+ // Returns a name for a command. Useful for logging / debuging.
+ virtual const char* GetCommandName(unsigned int command_id) const = 0;
+};
+
+} // namespace command_buffer
+
+#endif // GPU_COMMAND_BUFFER_SERVICE_CROSS_CMD_PARSER_H_
diff --git a/gpu/command_buffer/service/cmd_parser_test.cc b/gpu/command_buffer/service/cmd_parser_test.cc
new file mode 100644
index 0000000..347eef2
--- /dev/null
+++ b/gpu/command_buffer/service/cmd_parser_test.cc
@@ -0,0 +1,316 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// Tests for the command parser.
+
+#include "gpu/command_buffer/service/precompile.h"
+
+#include "base/scoped_ptr.h"
+#include "gpu/command_buffer/service/cmd_parser.h"
+#include "gpu/command_buffer/service/mocks.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace command_buffer {
+
+using testing::Return;
+using testing::Mock;
+using testing::Truly;
+using testing::Sequence;
+using testing::_;
+
+// Test fixture for CommandParser test - Creates a mock AsyncAPIInterface, and
+// a fixed size memory buffer. Also provides a simple API to create a
+// CommandParser.
+class CommandParserTest : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ api_mock_.reset(new AsyncAPIMock);
+ buffer_entry_count_ = 20;
+ buffer_.reset(new CommandBufferEntry[buffer_entry_count_]);
+ }
+ virtual void TearDown() {}
+
+ // Adds a DoCommand expectation in the mock.
+ void AddDoCommandExpect(parse_error::ParseError _return,
+ unsigned int command,
+ unsigned int arg_count,
+ CommandBufferEntry *args) {
+ EXPECT_CALL(*api_mock(), DoCommand(command, arg_count,
+ Truly(AsyncAPIMock::IsArgs(arg_count, args))))
+ .InSequence(sequence_)
+ .WillOnce(Return(_return));
+ }
+
+ // Creates a parser, with a buffer of the specified size (in entries).
+ CommandParser *MakeParser(unsigned int entry_count) {
+ size_t shm_size = buffer_entry_count_ *
+ sizeof(CommandBufferEntry); // NOLINT
+ size_t command_buffer_size = entry_count *
+ sizeof(CommandBufferEntry); // NOLINT
+ DCHECK_LE(command_buffer_size, shm_size);
+ return new CommandParser(buffer(),
+ shm_size,
+ 0,
+ command_buffer_size,
+ 0,
+ api_mock());
+ }
+
+ unsigned int buffer_entry_count() { return 20; }
+ AsyncAPIMock *api_mock() { return api_mock_.get(); }
+ CommandBufferEntry *buffer() { return buffer_.get(); }
+ private:
+ unsigned int buffer_entry_count_;
+ scoped_ptr<AsyncAPIMock> api_mock_;
+ scoped_array<CommandBufferEntry> buffer_;
+ Sequence sequence_;
+};
+
+// Tests initialization conditions.
+TEST_F(CommandParserTest, TestInit) {
+ scoped_ptr<CommandParser> parser(MakeParser(10));
+ EXPECT_EQ(0u, parser->get());
+ EXPECT_EQ(0u, parser->put());
+ EXPECT_TRUE(parser->IsEmpty());
+}
+
+// Tests simple commands.
+TEST_F(CommandParserTest, TestSimple) {
+ scoped_ptr<CommandParser> parser(MakeParser(10));
+ CommandBufferOffset put = parser->put();
+ CommandHeader header;
+
+ // add a single command, no args
+ header.size = 1;
+ header.command = 123;
+ buffer()[put++].value_header = header;
+
+ parser->set_put(put);
+ EXPECT_EQ(put, parser->put());
+
+ AddDoCommandExpect(parse_error::kParseNoError, 123, 0, NULL);
+ EXPECT_EQ(parse_error::kParseNoError, parser->ProcessCommand());
+ EXPECT_EQ(put, parser->get());
+ Mock::VerifyAndClearExpectations(api_mock());
+
+ // add a single command, 2 args
+ header.size = 3;
+ header.command = 456;
+ buffer()[put++].value_header = header;
+ buffer()[put++].value_int32 = 2134;
+ buffer()[put++].value_float = 1.f;
+
+ parser->set_put(put);
+ EXPECT_EQ(put, parser->put());
+
+ CommandBufferEntry param_array[2];
+ param_array[0].value_int32 = 2134;
+ param_array[1].value_float = 1.f;
+ AddDoCommandExpect(parse_error::kParseNoError, 456, 2, param_array);
+ EXPECT_EQ(parse_error::kParseNoError, parser->ProcessCommand());
+ EXPECT_EQ(put, parser->get());
+ Mock::VerifyAndClearExpectations(api_mock());
+}
+
+// Tests having multiple commands in the buffer.
+TEST_F(CommandParserTest, TestMultipleCommands) {
+ scoped_ptr<CommandParser> parser(MakeParser(10));
+ CommandBufferOffset put = parser->put();
+ CommandHeader header;
+
+ // add 2 commands, test with single ProcessCommand()
+ header.size = 2;
+ header.command = 789;
+ buffer()[put++].value_header = header;
+ buffer()[put++].value_int32 = 5151;
+
+ CommandBufferOffset put_cmd2 = put;
+ header.size = 2;
+ header.command = 2121;
+ buffer()[put++].value_header = header;
+ buffer()[put++].value_int32 = 3434;
+
+ parser->set_put(put);
+ EXPECT_EQ(put, parser->put());
+
+ CommandBufferEntry param_array[2];
+ param_array[0].value_int32 = 5151;
+ AddDoCommandExpect(parse_error::kParseNoError, 789, 1, param_array);
+ param_array[1].value_int32 = 3434;
+ AddDoCommandExpect(parse_error::kParseNoError, 2121, 1,
+ param_array+1);
+
+ EXPECT_EQ(parse_error::kParseNoError, parser->ProcessCommand());
+ EXPECT_EQ(put_cmd2, parser->get());
+ EXPECT_EQ(parse_error::kParseNoError, parser->ProcessCommand());
+ EXPECT_EQ(put, parser->get());
+ Mock::VerifyAndClearExpectations(api_mock());
+
+ // add 2 commands again, test with ProcessAllCommands()
+ header.size = 2;
+ header.command = 4545;
+ buffer()[put++].value_header = header;
+ buffer()[put++].value_int32 = 5656;
+
+ header.size = 2;
+ header.command = 6767;
+ buffer()[put++].value_header = header;
+ buffer()[put++].value_int32 = 7878;
+
+ parser->set_put(put);
+ EXPECT_EQ(put, parser->put());
+
+ param_array[0].value_int32 = 5656;
+ AddDoCommandExpect(parse_error::kParseNoError, 4545, 1, param_array);
+ param_array[1].value_int32 = 7878;
+ AddDoCommandExpect(parse_error::kParseNoError, 6767, 1,
+ param_array+1);
+
+ EXPECT_EQ(parse_error::kParseNoError, parser->ProcessAllCommands());
+ EXPECT_EQ(put, parser->get());
+ Mock::VerifyAndClearExpectations(api_mock());
+}
+
+// Tests that the parser will wrap correctly at the end of the buffer.
+TEST_F(CommandParserTest, TestWrap) {
+ scoped_ptr<CommandParser> parser(MakeParser(5));
+ CommandBufferOffset put = parser->put();
+ CommandHeader header;
+
+ // add 3 commands with no args (1 word each)
+ for (unsigned int i = 0; i < 3; ++i) {
+ header.size = 1;
+ header.command = i;
+ buffer()[put++].value_header = header;
+ AddDoCommandExpect(parse_error::kParseNoError, i, 0, NULL);
+ }
+ parser->set_put(put);
+ EXPECT_EQ(put, parser->put());
+ EXPECT_EQ(parse_error::kParseNoError, parser->ProcessAllCommands());
+ EXPECT_EQ(put, parser->get());
+ Mock::VerifyAndClearExpectations(api_mock());
+
+ // add 1 command with 1 arg (2 words). That should put us at the end of the
+ // buffer.
+ header.size = 2;
+ header.command = 3;
+ buffer()[put++].value_header = header;
+ buffer()[put++].value_int32 = 5;
+ CommandBufferEntry param;
+ param.value_int32 = 5;
+ AddDoCommandExpect(parse_error::kParseNoError, 3, 1, &param);
+
+ DCHECK_EQ(5u, put);
+ put = 0;
+ parser->set_put(put);
+ EXPECT_EQ(put, parser->put());
+ EXPECT_EQ(parse_error::kParseNoError, parser->ProcessAllCommands());
+ EXPECT_EQ(put, parser->get());
+ Mock::VerifyAndClearExpectations(api_mock());
+
+ // add 1 command with 1 arg (2 words).
+ header.size = 2;
+ header.command = 4;
+ buffer()[put++].value_header = header;
+ buffer()[put++].value_int32 = 6;
+ param.value_int32 = 6;
+ AddDoCommandExpect(parse_error::kParseNoError, 4, 1, &param);
+ parser->set_put(put);
+ EXPECT_EQ(put, parser->put());
+ EXPECT_EQ(parse_error::kParseNoError, parser->ProcessAllCommands());
+ EXPECT_EQ(put, parser->get());
+ Mock::VerifyAndClearExpectations(api_mock());
+}
+
+// Tests error conditions.
+TEST_F(CommandParserTest, TestError) {
+ scoped_ptr<CommandParser> parser(MakeParser(5));
+ CommandBufferOffset put = parser->put();
+ CommandHeader header;
+
+ // Generate a command with size 0.
+ header.size = 0;
+ header.command = 3;
+ buffer()[put++].value_header = header;
+
+ parser->set_put(put);
+ EXPECT_EQ(put, parser->put());
+ EXPECT_EQ(parse_error::kParseInvalidSize,
+ parser->ProcessAllCommands());
+ // check that no DoCommand call was made.
+ Mock::VerifyAndClearExpectations(api_mock());
+
+ parser.reset(MakeParser(5));
+ put = parser->put();
+
+ // Generate a command with size 6, extends beyond the end of the buffer.
+ header.size = 6;
+ header.command = 3;
+ buffer()[put++].value_header = header;
+
+ parser->set_put(put);
+ EXPECT_EQ(put, parser->put());
+ EXPECT_EQ(parse_error::kParseOutOfBounds,
+ parser->ProcessAllCommands());
+ // check that no DoCommand call was made.
+ Mock::VerifyAndClearExpectations(api_mock());
+
+ parser.reset(MakeParser(5));
+ put = parser->put();
+
+ // Generates 2 commands.
+ header.size = 1;
+ header.command = 3;
+ buffer()[put++].value_header = header;
+ CommandBufferOffset put_post_fail = put;
+ header.size = 1;
+ header.command = 4;
+ buffer()[put++].value_header = header;
+
+ parser->set_put(put);
+ EXPECT_EQ(put, parser->put());
+ // have the first command fail to parse.
+ AddDoCommandExpect(parse_error::kParseUnknownCommand, 3, 0, NULL);
+ EXPECT_EQ(parse_error::kParseUnknownCommand,
+ parser->ProcessAllCommands());
+ // check that only one command was executed, and that get reflects that
+ // correctly.
+ EXPECT_EQ(put_post_fail, parser->get());
+ Mock::VerifyAndClearExpectations(api_mock());
+ // make the second one succeed, and check that the parser recovered fine.
+ AddDoCommandExpect(parse_error::kParseNoError, 4, 0, NULL);
+ EXPECT_EQ(parse_error::kParseNoError, parser->ProcessAllCommands());
+ EXPECT_EQ(put, parser->get());
+ Mock::VerifyAndClearExpectations(api_mock());
+}
+
+} // namespace command_buffer
diff --git a/gpu/command_buffer/service/command_buffer_service.cc b/gpu/command_buffer/service/command_buffer_service.cc
new file mode 100644
index 0000000..1ab2a9b
--- /dev/null
+++ b/gpu/command_buffer/service/command_buffer_service.cc
@@ -0,0 +1,159 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/command_buffer/service/command_buffer_service.h"
+
+using ::base::SharedMemory;
+
+namespace command_buffer {
+
+CommandBufferService::CommandBufferService()
+ : size_(0),
+ get_offset_(0),
+ put_offset_(0),
+ token_(0),
+ parse_error_(0),
+ error_status_(false) {
+ // Element zero is always NULL.
+ registered_objects_.push_back(linked_ptr<SharedMemory>());
+}
+
+CommandBufferService::~CommandBufferService() {
+}
+
+bool CommandBufferService::Initialize(::base::SharedMemory* ring_buffer) {
+ DCHECK(ring_buffer);
+
+ // Fail if already initialized.
+ if (ring_buffer_.get())
+ return false;
+
+ size_t size_in_bytes = ring_buffer->max_size();
+ size_ = size_in_bytes / sizeof(int32);
+ ring_buffer_.reset(ring_buffer);
+
+ return true;
+}
+
+SharedMemory* CommandBufferService::GetRingBuffer() {
+ return ring_buffer_.get();
+}
+
+int32 CommandBufferService::GetSize() {
+ return size_;
+}
+
+int32 CommandBufferService::SyncOffsets(int32 put_offset) {
+ if (put_offset < 0 || put_offset >= size_)
+ return -1;
+
+ put_offset_ = put_offset;
+
+ if (put_offset_change_callback_.get()) {
+ put_offset_change_callback_->Run();
+ }
+
+ return get_offset_;
+}
+
+int32 CommandBufferService::GetGetOffset() {
+ return get_offset_;
+}
+
+void CommandBufferService::SetGetOffset(int32 get_offset) {
+ DCHECK(get_offset >= 0 && get_offset < size_);
+ get_offset_ = get_offset;
+}
+
+int32 CommandBufferService::GetPutOffset() {
+ return put_offset_;
+}
+
+void CommandBufferService::SetPutOffsetChangeCallback(
+ Callback0::Type* callback) {
+ put_offset_change_callback_.reset(callback);
+}
+
+int32 CommandBufferService::CreateTransferBuffer(size_t size) {
+ linked_ptr<SharedMemory> buffer(new SharedMemory);
+ if (!buffer->Create(std::wstring(), false, false, size))
+ return -1;
+
+ if (unused_registered_object_elements_.empty()) {
+ // Check we haven't exceeded the range that fits in a 32-bit integer.
+ int32 handle = static_cast<int32>(registered_objects_.size());
+ if (handle != registered_objects_.size())
+ return -1;
+
+ registered_objects_.push_back(buffer);
+ return handle;
+ }
+
+ int32 handle = *unused_registered_object_elements_.begin();
+ unused_registered_object_elements_.erase(
+ unused_registered_object_elements_.begin());
+ DCHECK(!registered_objects_[handle].get());
+ registered_objects_[handle] = buffer;
+ return handle;
+}
+
+void CommandBufferService::DestroyTransferBuffer(int32 handle) {
+ if (handle <= 0)
+ return;
+
+ if (static_cast<size_t>(handle) >= registered_objects_.size())
+ return;
+
+ registered_objects_[handle].reset();
+ unused_registered_object_elements_.insert(handle);
+
+ // Remove all null objects from the end of the vector. This allows the vector
+ // to shrink when, for example, all objects are unregistered. Note that this
+ // loop never removes element zero, which is always NULL.
+ while (registered_objects_.size() > 1 && !registered_objects_.back().get()) {
+ registered_objects_.pop_back();
+ unused_registered_object_elements_.erase(
+ static_cast<int32>(registered_objects_.size()));
+ }
+}
+
+::base::SharedMemory* CommandBufferService::GetTransferBuffer(int32 handle) {
+ if (handle < 0)
+ return NULL;
+
+ if (static_cast<size_t>(handle) >= registered_objects_.size())
+ return NULL;
+
+ return registered_objects_[handle].get();
+}
+
+int32 CommandBufferService::GetToken() {
+ return token_;
+}
+
+void CommandBufferService::SetToken(int32 token) {
+ token_ = token;
+}
+
+int32 CommandBufferService::ResetParseError() {
+ int32 last_error = parse_error_;
+ parse_error_ = 0;
+ return last_error;
+}
+
+void CommandBufferService::SetParseError(int32 parse_error) {
+ if (parse_error_ == 0) {
+ parse_error_ = parse_error;
+ }
+}
+
+bool CommandBufferService::GetErrorStatus() {
+ return error_status_;
+}
+
+void CommandBufferService::RaiseErrorStatus() {
+ error_status_ = true;
+}
+
+} // namespace command_buffer
diff --git a/gpu/command_buffer/service/command_buffer_service.h b/gpu/command_buffer/service/command_buffer_service.h
new file mode 100644
index 0000000..d6da953
--- /dev/null
+++ b/gpu/command_buffer/service/command_buffer_service.h
@@ -0,0 +1,93 @@
+// Copyright (c) 2006-2008 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 GPU_COMMAND_BUFFER_SERVICE_COMMAND_BUFFER_H_
+#define GPU_COMMAND_BUFFER_SERVICE_COMMAND_BUFFER_H_
+
+#include <set>
+#include <vector>
+
+#include "base/linked_ptr.h"
+#include "base/scoped_ptr.h"
+#include "base/shared_memory.h"
+#include "base/task.h"
+#include "gpu/command_buffer/common/command_buffer.h"
+#include "gpu/np_utils/default_np_object.h"
+#include "gpu/np_utils/np_dispatcher.h"
+
+namespace command_buffer {
+
+// An NPObject that implements a shared memory command buffer and a synchronous
+// API to manage the put and get pointers.
+class CommandBufferService : public CommandBuffer {
+ public:
+ CommandBufferService();
+ virtual ~CommandBufferService();
+
+ // Overrides CommandBuffer.
+ virtual bool Initialize(::base::SharedMemory* ring_buffer);
+
+ // Overrides CommandBuffer.
+ virtual ::base::SharedMemory* GetRingBuffer();
+
+ virtual int32 GetSize();
+
+ // Overrides CommandBuffer.
+ virtual int32 SyncOffsets(int32 put_offset);
+
+ // Overrides CommandBuffer.
+ virtual int32 GetGetOffset();
+
+ // Overrides CommandBuffer.
+ virtual void SetGetOffset(int32 get_offset);
+
+ // Overrides CommandBuffer.
+ virtual int32 GetPutOffset();
+
+ // Overrides CommandBuffer.
+ virtual void SetPutOffsetChangeCallback(Callback0::Type* callback);
+
+ // Overrides CommandBuffer.
+ virtual int32 CreateTransferBuffer(size_t size);
+
+ // Overrides CommandBuffer.
+ virtual void DestroyTransferBuffer(int32 id);
+
+ // Overrides CommandBuffer.
+ virtual ::base::SharedMemory* GetTransferBuffer(int32 handle);
+
+ // Overrides CommandBuffer.
+ virtual int32 GetToken();
+
+ // Overrides CommandBuffer.
+ virtual void SetToken(int32 token);
+
+ // Overrides CommandBuffer.
+ virtual int32 ResetParseError();
+
+ // Overrides CommandBuffer.
+ virtual void SetParseError(int32 parse_error);
+
+ // Overrides CommandBuffer.
+ virtual bool GetErrorStatus();
+
+ // Overrides CommandBuffer.
+ virtual void RaiseErrorStatus();
+
+ private:
+ scoped_ptr< ::base::SharedMemory> ring_buffer_;
+ int32 size_;
+ int32 get_offset_;
+ int32 put_offset_;
+ scoped_ptr<Callback0::Type> put_offset_change_callback_;
+ std::vector<linked_ptr< ::base::SharedMemory> > registered_objects_;
+ std::set<int32> unused_registered_object_elements_;
+ int32 token_;
+ int32 parse_error_;
+ bool error_status_;
+};
+
+} // namespace command_buffer
+
+#endif // GPU_COMMAND_BUFFER_SERVICE_COMMAND_BUFFER_H_
diff --git a/gpu/command_buffer/service/command_buffer_service_unittest.cc b/gpu/command_buffer/service/command_buffer_service_unittest.cc
new file mode 100644
index 0000000..2f9c1fb
--- /dev/null
+++ b/gpu/command_buffer/service/command_buffer_service_unittest.cc
@@ -0,0 +1,185 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/thread.h"
+#include "gpu/command_buffer/service/command_buffer_service.h"
+#include "gpu/np_utils/np_browser_mock.h"
+#include "gpu/np_utils/dynamic_np_object.h"
+#include "gpu/np_utils/np_object_mock.h"
+#include "gpu/np_utils/np_object_pointer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+using base::SharedMemory;
+using np_utils::NPCreateObject;
+using np_utils::NPObjectPointer;
+using testing::_;
+using testing::DoAll;
+using testing::Return;
+using testing::SetArgumentPointee;
+using testing::StrictMock;
+
+namespace command_buffer {
+
+class CommandBufferServiceTest : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ command_buffer_.reset(new CommandBufferService);
+ }
+
+ np_utils::MockNPBrowser mock_browser_;
+ scoped_ptr<CommandBufferService> command_buffer_;
+};
+
+TEST_F(CommandBufferServiceTest, NullRingBufferByDefault) {
+ EXPECT_TRUE(NULL == command_buffer_->GetRingBuffer());
+}
+
+TEST_F(CommandBufferServiceTest, InitializesCommandBuffer) {
+ SharedMemory* ring_buffer = new SharedMemory;
+ EXPECT_TRUE(ring_buffer->Create(std::wstring(), false, false, 1024));
+ EXPECT_TRUE(command_buffer_->Initialize(ring_buffer));
+ EXPECT_TRUE(ring_buffer == command_buffer_->GetRingBuffer());
+ EXPECT_EQ(256, command_buffer_->GetSize());
+}
+
+TEST_F(CommandBufferServiceTest, InitializeFailsSecondTime) {
+ SharedMemory* ring_buffer = new SharedMemory;
+ EXPECT_TRUE(command_buffer_->Initialize(ring_buffer));
+ EXPECT_FALSE(command_buffer_->Initialize(ring_buffer));
+}
+
+TEST_F(CommandBufferServiceTest, GetAndPutOffsetsDefaultToZero) {
+ EXPECT_EQ(0, command_buffer_->GetGetOffset());
+ EXPECT_EQ(0, command_buffer_->GetPutOffset());
+}
+
+class MockCallback : public CallbackRunner<Tuple0> {
+ public:
+ MOCK_METHOD1(RunWithParams, void(const Tuple0&));
+};
+
+TEST_F(CommandBufferServiceTest, CanSyncGetAndPutOffset) {
+ SharedMemory* ring_buffer = new SharedMemory;
+ ring_buffer->Create(std::wstring(), false, false, 1024);
+
+ EXPECT_TRUE(command_buffer_->Initialize(ring_buffer));
+
+ StrictMock<MockCallback>* put_offset_change_callback =
+ new StrictMock<MockCallback>;
+ command_buffer_->SetPutOffsetChangeCallback(put_offset_change_callback);
+
+ EXPECT_CALL(*put_offset_change_callback, RunWithParams(_));
+ EXPECT_EQ(0, command_buffer_->SyncOffsets(2));
+ EXPECT_EQ(2, command_buffer_->GetPutOffset());
+
+ EXPECT_CALL(*put_offset_change_callback, RunWithParams(_));
+ EXPECT_EQ(0, command_buffer_->SyncOffsets(4));
+ EXPECT_EQ(4, command_buffer_->GetPutOffset());
+
+ command_buffer_->SetGetOffset(2);
+ EXPECT_EQ(2, command_buffer_->GetGetOffset());
+ EXPECT_CALL(*put_offset_change_callback, RunWithParams(_));
+ EXPECT_EQ(2, command_buffer_->SyncOffsets(6));
+
+ EXPECT_EQ(-1, command_buffer_->SyncOffsets(-1));
+ EXPECT_EQ(-1, command_buffer_->SyncOffsets(1024));
+}
+
+TEST_F(CommandBufferServiceTest, ZeroHandleMapsToNull) {
+ EXPECT_TRUE(NULL == command_buffer_->GetTransferBuffer(0));
+}
+
+TEST_F(CommandBufferServiceTest, NegativeHandleMapsToNull) {
+ EXPECT_TRUE(NULL == command_buffer_->GetTransferBuffer(-1));
+}
+
+TEST_F(CommandBufferServiceTest, OutOfRangeHandleMapsToNull) {
+ EXPECT_TRUE(NULL == command_buffer_->GetTransferBuffer(1));
+}
+
+TEST_F(CommandBufferServiceTest, CanCreateTransferBuffers) {
+ int32 handle = command_buffer_->CreateTransferBuffer(1024);
+ EXPECT_EQ(1, handle);
+ SharedMemory* buffer = command_buffer_->GetTransferBuffer(handle);
+ ASSERT_TRUE(NULL != buffer);
+ EXPECT_EQ(1024, buffer->max_size());
+}
+
+TEST_F(CommandBufferServiceTest, CreateTransferBufferReturnsDistinctHandles) {
+ EXPECT_EQ(1, command_buffer_->CreateTransferBuffer(1024));
+}
+
+TEST_F(CommandBufferServiceTest,
+ CreateTransferBufferReusesUnregisteredHandles) {
+ EXPECT_EQ(1, command_buffer_->CreateTransferBuffer(1024));
+ EXPECT_EQ(2, command_buffer_->CreateTransferBuffer(1024));
+ command_buffer_->DestroyTransferBuffer(1);
+ EXPECT_EQ(1, command_buffer_->CreateTransferBuffer(1024));
+ EXPECT_EQ(3, command_buffer_->CreateTransferBuffer(1024));
+}
+
+TEST_F(CommandBufferServiceTest, CannotUnregisterHandleZero) {
+ command_buffer_->DestroyTransferBuffer(0);
+ EXPECT_TRUE(NULL == command_buffer_->GetTransferBuffer(0));
+ EXPECT_EQ(1, command_buffer_->CreateTransferBuffer(1024));
+}
+
+TEST_F(CommandBufferServiceTest, CannotUnregisterNegativeHandles) {
+ command_buffer_->DestroyTransferBuffer(-1);
+ EXPECT_EQ(1, command_buffer_->CreateTransferBuffer(1024));
+}
+
+TEST_F(CommandBufferServiceTest, CannotUnregisterUnregisteredHandles) {
+ command_buffer_->DestroyTransferBuffer(1);
+ EXPECT_EQ(1, command_buffer_->CreateTransferBuffer(1024));
+}
+
+// Testing this case specifically because there is an optimization that takes
+// a different code path in this case.
+TEST_F(CommandBufferServiceTest, UnregistersLastRegisteredHandle) {
+ EXPECT_EQ(1, command_buffer_->CreateTransferBuffer(1024));
+ command_buffer_->DestroyTransferBuffer(1);
+ EXPECT_EQ(1, command_buffer_->CreateTransferBuffer(1024));
+}
+
+// Testing this case specifically because there is an optimization that takes
+// a different code path in this case.
+TEST_F(CommandBufferServiceTest, UnregistersTwoLastRegisteredHandles) {
+ EXPECT_EQ(1, command_buffer_->CreateTransferBuffer(1024));
+ EXPECT_EQ(2, command_buffer_->CreateTransferBuffer(1024));
+ command_buffer_->DestroyTransferBuffer(2);
+ command_buffer_->DestroyTransferBuffer(1);
+ EXPECT_EQ(1, command_buffer_->CreateTransferBuffer(1024));
+}
+
+TEST_F(CommandBufferServiceTest, DefaultTokenIsZero) {
+ EXPECT_EQ(0, command_buffer_->GetToken());
+}
+
+TEST_F(CommandBufferServiceTest, CanSetToken) {
+ command_buffer_->SetToken(7);
+ EXPECT_EQ(7, command_buffer_->GetToken());
+}
+
+TEST_F(CommandBufferServiceTest, DefaultParseErrorIsNoError) {
+ EXPECT_EQ(0, command_buffer_->ResetParseError());
+}
+
+TEST_F(CommandBufferServiceTest, CanSetAndResetParseError) {
+ command_buffer_->SetParseError(1);
+ EXPECT_EQ(1, command_buffer_->ResetParseError());
+ EXPECT_EQ(0, command_buffer_->ResetParseError());
+}
+
+TEST_F(CommandBufferServiceTest, DefaultErrorStatusIsFalse) {
+ EXPECT_FALSE(command_buffer_->GetErrorStatus());
+}
+
+TEST_F(CommandBufferServiceTest, CanRaiseErrorStatus) {
+ command_buffer_->RaiseErrorStatus();
+ EXPECT_TRUE(command_buffer_->GetErrorStatus());
+}
+
+} // namespace command_buffer
diff --git a/gpu/command_buffer/service/common_decoder.cc b/gpu/command_buffer/service/common_decoder.cc
new file mode 100644
index 0000000..22bf445
--- /dev/null
+++ b/gpu/command_buffer/service/common_decoder.cc
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gpu/command_buffer/service/precompile.h"
+#include "gpu/command_buffer/service/common_decoder.h"
+#include "gpu/command_buffer/service/cmd_buffer_engine.h"
+
+namespace command_buffer {
+
+void* CommonDecoder::GetAddressAndCheckSize(unsigned int shm_id,
+ unsigned int offset,
+ unsigned int size) {
+ void* shm_addr = engine_->GetSharedMemoryAddress(shm_id);
+ if (!shm_addr) return NULL;
+ size_t shm_size = engine_->GetSharedMemorySize(shm_id);
+ unsigned int end = offset + size;
+ if (end > shm_size || end < offset) {
+ return NULL;
+ }
+ return static_cast<int8 *>(shm_addr) + offset;
+}
+
+const char* CommonDecoder::GetCommonCommandName(
+ cmd::CommandId command_id) const {
+ return cmd::GetCommandName(command_id);
+}
+
+namespace {
+
+// A struct to hold info about each command.
+struct CommandInfo {
+ int arg_flags; // How to handle the arguments for this command
+ int arg_count; // How many arguments are expected for this command.
+};
+
+// A table of CommandInfo for all the commands.
+const CommandInfo g_command_info[] = {
+ #define COMMON_COMMAND_BUFFER_CMD_OP(name) { \
+ cmd::name::kArgFlags, \
+ sizeof(cmd::name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
+
+ COMMON_COMMAND_BUFFER_CMDS(COMMON_COMMAND_BUFFER_CMD_OP)
+
+ #undef COMMON_COMMAND_BUFFER_CMD_OP
+};
+
+} // anonymous namespace.
+
+// Decode command with its arguments, and call the corresponding method.
+// Note: args is a pointer to the command buffer. As such, it could be changed
+// by a (malicious) client at any time, so if validation has to happen, it
+// should operate on a copy of them.
+parse_error::ParseError CommonDecoder::DoCommonCommand(
+ unsigned int command,
+ unsigned int arg_count,
+ const void* cmd_data) {
+ if (command < arraysize(g_command_info)) {
+ const CommandInfo& info = g_command_info[command];
+ unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
+ if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
+ (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
+ switch (command) {
+ #define COMMON_COMMAND_BUFFER_CMD_OP(name) \
+ case cmd::name::kCmdId: \
+ return Handle ## name( \
+ arg_count, \
+ *static_cast<const cmd::name*>(cmd_data)); \
+
+ COMMON_COMMAND_BUFFER_CMDS(COMMON_COMMAND_BUFFER_CMD_OP)
+
+ #undef COMMON_COMMAND_BUFFER_CMD_OP
+ }
+ } else {
+ return parse_error::kParseInvalidArguments;
+ }
+ }
+ return DoCommonCommand(command, arg_count, cmd_data);
+ return parse_error::kParseUnknownCommand;
+}
+
+parse_error::ParseError CommonDecoder::HandleNoop(
+ uint32 arg_count,
+ const cmd::Noop& args) {
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError CommonDecoder::HandleSetToken(
+ uint32 arg_count,
+ const cmd::SetToken& args) {
+ engine_->set_token(args.token);
+ return parse_error::kParseNoError;
+}
+
+} // namespace command_buffer
diff --git a/gpu/command_buffer/service/common_decoder.h b/gpu/command_buffer/service/common_decoder.h
new file mode 100644
index 0000000..25d1dbe
--- /dev/null
+++ b/gpu/command_buffer/service/common_decoder.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GPU_COMMAND_BUFFER_SERVICE_CROSS_COMMON_DECODER_H_
+#define GPU_COMMAND_BUFFER_SERVICE_CROSS_COMMON_DECODER_H_
+
+#include "gpu/command_buffer/service/cmd_parser.h"
+
+namespace command_buffer {
+
+class CommandBufferEngine;
+
+// This class is a helper base class for implementing the common parts of the
+// o3d/gl2 command buffer decoder.
+class CommonDecoder : public AsyncAPIInterface {
+ public:
+ typedef parse_error::ParseError ParseError;
+
+ CommonDecoder() : engine_(NULL) {
+ }
+ virtual ~CommonDecoder() {
+ }
+
+ // Sets the engine, to get shared memory buffers from, and to set the token
+ // to.
+ void set_engine(CommandBufferEngine* engine) {
+ engine_ = engine;
+ }
+
+ protected:
+ // Executes a common command.
+ // Parameters:
+ // command: the command index.
+ // arg_count: the number of CommandBufferEntry arguments.
+ // cmd_data: the command data.
+ // Returns:
+ // parse_error::NO_ERROR if no error was found, one of
+ // parse_error::ParseError otherwise.
+ parse_error::ParseError DoCommonCommand(
+ unsigned int command,
+ unsigned int arg_count,
+ const void* cmd_data);
+
+ // Gets the address of shared memory data, given a shared memory ID and an
+ // offset. Also checks that the size is consistent with the shared memory
+ // size.
+ // Parameters:
+ // shm_id: the id of the shared memory buffer.
+ // offset: the offset of the data in the shared memory buffer.
+ // size: the size of the data.
+ // Returns:
+ // NULL if shm_id isn't a valid shared memory buffer ID or if the size
+ // check fails. Return a pointer to the data otherwise.
+ void* GetAddressAndCheckSize(unsigned int shm_id,
+ unsigned int offset,
+ unsigned int size);
+
+ // Gets an name for a common command.
+ const char* GetCommonCommandName(cmd::CommandId command_id) const;
+
+ private:
+ // Generate a member function prototype for each command in an automated and
+ // typesafe way.
+ #define COMMON_COMMAND_BUFFER_CMD_OP(name) \
+ parse_error::ParseError Handle ## name( \
+ unsigned int arg_count, \
+ const cmd::name& args); \
+
+ COMMON_COMMAND_BUFFER_CMDS(COMMON_COMMAND_BUFFER_CMD_OP)
+
+ #undef COMMON_COMMAND_BUFFER_CMD_OP
+
+ CommandBufferEngine* engine_;
+};
+
+} // namespace command_buffer
+
+#endif // GPU_COMMAND_BUFFER_SERVICE_CROSS_COMMON_DECODER_H_
+
diff --git a/gpu/command_buffer/service/gl_utils.h b/gpu/command_buffer/service/gl_utils.h
new file mode 100644
index 0000000..b9c10f5
--- /dev/null
+++ b/gpu/command_buffer/service/gl_utils.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file includes all the necessary GL headers and implements some useful
+// utilities.
+
+#ifndef GPU_COMMAND_BUFFER_SERVICE_GL_UTILS_H_
+#define GPU_COMMAND_BUFFER_SERVICE_GL_UTILS_H_
+
+#include <GL/glew.h>
+#if defined(OS_WIN)
+#include <GL/wglew.h>
+#endif
+#include <build/build_config.h>
+
+#define GL_GLEXT_PROTOTYPES
+
+// Define this for extra GL error debugging (slower).
+// #define GL_ERROR_DEBUGGING
+#ifdef GL_ERROR_DEBUGGING
+#define CHECK_GL_ERROR() do { \
+ GLenum gl_error = glGetError(); \
+ LOG_IF(ERROR, gl_error != GL_NO_ERROR) << "GL Error :" << gl_error; \
+ } while (0)
+#else // GL_ERROR_DEBUGGING
+#define CHECK_GL_ERROR() void(0)
+#endif // GL_ERROR_DEBUGGING
+
+#endif // GPU_COMMAND_BUFFER_SERVICE_GL_UTILS_H_
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
new file mode 100644
index 0000000..159c5c5
--- /dev/null
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -0,0 +1,950 @@
+// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <vector>
+#include <string>
+#include <map>
+#include <build/build_config.h>
+#include "base/scoped_ptr.h"
+#define GLES2_GPU_SERVICE 1
+#include "gpu/command_buffer/common/gles2_cmd_format.h"
+#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/service/cmd_buffer_engine.h"
+#include "gpu/command_buffer/service/gl_utils.h"
+#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
+
+namespace command_buffer {
+namespace gles2 {
+
+namespace {
+
+// Returns the address of the first byte after a struct.
+template <typename T>
+const void* AddressAfterStruct(const T& pod) {
+ return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
+}
+
+// Returns the address of the frst byte after the struct.
+template <typename RETURN_TYPE, typename COMMAND_TYPE>
+RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod) {
+ return static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod)));
+}
+
+// Returns the size in bytes of the data of an Immediate command, a command with
+// its data inline in the command buffer.
+template <typename T>
+unsigned int ImmediateDataSize(uint32 arg_count) {
+ return static_cast<unsigned int>(
+ (arg_count + 1 - ComputeNumEntries(sizeof(T))) *
+ sizeof(CommandBufferEntry)); // NOLINT
+}
+
+// Checks if there is enough immediate data.
+template<typename T>
+bool CheckImmediateDataSize(
+ unsigned int arg_count,
+ GLuint count,
+ size_t size,
+ unsigned int elements_per_unit) {
+ return ImmediateDataSize<T>(arg_count) == count * size * elements_per_unit;
+}
+
+// A struct to hold info about each command.
+struct CommandInfo {
+ int arg_flags; // How to handle the arguments for this command
+ int arg_count; // How many arguments are expected for this command.
+};
+
+// A table of CommandInfo for all the commands.
+const CommandInfo g_command_info[] = {
+ #define GLES2_CMD_OP(name) { \
+ name::kArgFlags, \
+ sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
+
+ GLES2_COMMAND_LIST(GLES2_CMD_OP)
+
+ #undef GLES2_CMD_OP
+};
+
+// These commands convert from c calls to local os calls.
+void GLGenBuffersHelper(GLsizei n, GLuint* ids) {
+ glGenBuffersARB(n, ids);
+}
+
+void GLGenFramebuffersHelper(GLsizei n, GLuint* ids) {
+ glGenFramebuffersEXT(n, ids);
+}
+
+void GLGenRenderbuffersHelper(GLsizei n, GLuint* ids) {
+ glGenRenderbuffersEXT(n, ids);
+}
+
+void GLGenTexturesHelper(GLsizei n, GLuint* ids) {
+ glGenTextures(n, ids);
+}
+
+void GLDeleteBuffersHelper(GLsizei n, GLuint* ids) {
+ glDeleteBuffersARB(n, ids);
+}
+
+void GLDeleteFramebuffersHelper(GLsizei n, GLuint* ids) {
+ glDeleteFramebuffersEXT(n, ids);
+}
+
+void GLDeleteRenderbuffersHelper(GLsizei n, GLuint* ids) {
+ glDeleteRenderbuffersEXT(n, ids);
+}
+
+void GLDeleteTexturesHelper(GLsizei n, GLuint* ids) {
+ glDeleteTextures(n, ids);
+}
+
+namespace GLErrorBit {
+enum GLErrorBit {
+ kNoError = 0,
+ kInvalidEnum,
+ kInvalidValue,
+ kInvalidOperation,
+ kOutOfMemory,
+ kInvalidFrameBufferOperation,
+};
+}
+
+uint32 GLErrorToErrorBit(GLenum error) {
+ switch(error) {
+ case GL_INVALID_ENUM:
+ return GLErrorBit::kInvalidEnum;
+ case GL_INVALID_VALUE:
+ return GLErrorBit::kInvalidValue;
+ case GL_INVALID_OPERATION:
+ return GLErrorBit::kInvalidOperation;
+ case GL_OUT_OF_MEMORY:
+ return GLErrorBit::kOutOfMemory;
+ case GL_INVALID_FRAMEBUFFER_OPERATION:
+ return GLErrorBit::kInvalidFrameBufferOperation;
+ default:
+ DCHECK(false);
+ return GLErrorBit::kNoError;
+ }
+}
+
+GLenum GLErrorBitToGLError(uint32 error_bit) {
+ switch(error_bit) {
+ case GLErrorBit::kInvalidEnum:
+ return GL_INVALID_ENUM;
+ case GLErrorBit::kInvalidValue:
+ return GL_INVALID_VALUE;
+ case GLErrorBit::kInvalidOperation:
+ return GL_INVALID_OPERATION;
+ case GLErrorBit::kOutOfMemory:
+ return GL_OUT_OF_MEMORY;
+ case GLErrorBit::kInvalidFrameBufferOperation:
+ return GL_INVALID_FRAMEBUFFER_OPERATION;
+ default:
+ DCHECK(false);
+ return GL_NO_ERROR;
+ }
+}
+
+} // anonymous namespace.
+
+GLES2Decoder::GLES2Decoder()
+#ifdef OS_LINUX
+ : window_(NULL) {
+#endif
+#ifdef OS_WIN
+ : hwnd_(NULL) {
+#endif
+}
+
+// This class maps one set of ids to another.
+class IdMap {
+ public:
+ // Maps a client_id to a service_id. Return false if the client_id or
+ // service_id are already mapped to something else.
+ bool AddMapping(GLuint client_id, GLuint service_id);
+
+ // Unmaps a pair of ids. Returns false if the pair were not previously mapped.
+ bool RemoveMapping(GLuint client_id, GLuint service_id);
+
+ // Gets the corresponding service_id for the given client_id.
+ // Returns false if there is no corresponding service_id.
+ bool GetServiceId(GLuint client_id, GLuint* service_id);
+
+ // Gets the corresponding client_id for the given service_id.
+ // Returns false if there is no corresponding client_id.
+ bool GetClientId(GLuint service_id, GLuint* client_id);
+
+ private:
+ // TODO(gman): Replace with faster implementation.
+ typedef std::map<GLuint, GLuint> MapType;
+ MapType id_map_;
+};
+
+bool IdMap::AddMapping(GLuint client_id, GLuint service_id) {
+ std::pair<MapType::iterator, bool> result = id_map_.insert(
+ std::make_pair(client_id, service_id));
+ return result.second;
+}
+
+bool IdMap::RemoveMapping(GLuint client_id, GLuint service_id) {
+ MapType::iterator iter = id_map_.find(client_id);
+ if (iter != id_map_.end() && iter->second == service_id) {
+ id_map_.erase(iter);
+ return true;
+ }
+ return false;
+}
+
+bool IdMap::GetServiceId(GLuint client_id, GLuint* service_id) {
+ DCHECK(service_id);
+ MapType::iterator iter = id_map_.find(client_id);
+ if (iter != id_map_.end()) {
+ *service_id = iter->second;
+ return true;
+ }
+ return false;
+}
+
+bool IdMap::GetClientId(GLuint service_id, GLuint* client_id) {
+ DCHECK(client_id);
+ MapType::iterator end(id_map_.end());
+ for (MapType::iterator iter(id_map_.begin());
+ iter != end;
+ ++iter) {
+ if (iter->second == service_id) {
+ *client_id = iter->first;
+ return true;
+ }
+ }
+ return false;
+}
+
+// This class implements GLES2Decoder so we don't have to expose all the GLES2
+// cmd stuff to outside this class.
+class GLES2DecoderImpl : public GLES2Decoder {
+ public:
+ GLES2DecoderImpl();
+
+ // Overridden from AsyncAPIInterface.
+ virtual ParseError DoCommand(unsigned int command,
+ unsigned int arg_count,
+ const void* args);
+
+ // Overridden from AsyncAPIInterface.
+ virtual const char* GetCommandName(unsigned int command_id) const;
+
+ // Overridden from GLES2Decoder.
+ virtual bool Initialize();
+
+ // Overridden from GLES2Decoder.
+ virtual void Destroy();
+
+ private:
+ bool InitPlatformSpecific();
+ bool InitGlew();
+
+ // Typed version of GetAddressAndCheckSize.
+ template <typename T>
+ T GetSharedMemoryAs(unsigned int shm_id, unsigned int offset,
+ unsigned int size) {
+ return static_cast<T>(GetAddressAndCheckSize(shm_id, offset, size));
+ }
+
+ // Template to help call glGenXXX functions.
+ template <void gl_gen_function(GLsizei, GLuint*)>
+ bool GenGLObjects(GLsizei n, const GLuint* client_ids) {
+ // TODO(gman): Verify client ids are unused.
+ scoped_array<GLuint>temp(new GLuint[n]);
+ gl_gen_function(n, temp.get());
+ // TODO(gman): check for success before copying results.
+ for (GLsizei ii = 0; ii < n; ++ii) {
+ if (!id_map_.AddMapping(client_ids[ii], temp[ii])) {
+ // TODO(gman): fail.
+ }
+ }
+ return true;
+ }
+
+ // Template to help call glDeleteXXX functions.
+ template <void gl_delete_function(GLsizei, GLuint*)>
+ bool DeleteGLObjects(GLsizei n, const GLuint* client_ids) {
+ scoped_array<GLuint>temp(new GLuint[n]);
+ // TODO(gman): check for success before copying results.
+ for (GLsizei ii = 0; ii < n; ++ii) {
+ if (id_map_.GetServiceId(client_ids[ii], &temp[ii])) {
+ id_map_.RemoveMapping(client_ids[ii], temp[ii]);
+ } else {
+ temp[ii] = 0;
+ }
+ }
+ gl_delete_function(n, temp.get());
+ return true;
+ }
+
+ // Wrapper for glCreateProgram
+ void CreateProgramHelper(GLuint client_id);
+
+ // Wrapper for glCreateShader
+ void CreateShaderHelper(GLenum type, GLuint client_id);
+
+ // Wrapper for glBindBuffer since we need to track the current targets.
+ void DoBindBuffer(GLenum target, GLuint buffer);
+
+ // Wrapper for glDeleteProgram.
+ void DoDeleteProgram(GLuint program);
+
+ // Wrapper for glDeleteShader.
+ void DoDeleteShader(GLuint shader);
+
+ // Swaps the buffers (copies/renders to the current window).
+ void DoSwapBuffers();
+
+ // Gets the GLError through our wrapper.
+ GLenum GetGLError();
+
+ // Sets our wrapper for the GLError.
+ void SetGLError(GLenum error);
+
+ // Generate a member function prototype for each command in an automated and
+ // typesafe way.
+ #define GLES2_CMD_OP(name) \
+ ParseError Handle ## name( \
+ unsigned int arg_count, \
+ const gles2::name& args); \
+
+ GLES2_COMMAND_LIST(GLES2_CMD_OP)
+
+ #undef GLES2_CMD_OP
+
+ // Current GL error bits.
+ uint32 error_bits_;
+
+ // Map of client ids to GL ids.
+ IdMap id_map_;
+
+ // Util to help with GL.
+ GLES2Util util_;
+
+ // pack alignment as last set by glPixelStorei
+ GLint pack_alignment_;
+
+ // unpack alignment as last set by glPixelStorei
+ GLint unpack_alignment_;
+
+ // The currently bound array buffer. If this is 0 it is illegal to call
+ // glVertexAttribPointer.
+ GLuint bound_array_buffer_;
+
+ // The currently bound element array buffer. If this is 0 it is illegal
+ // to call glDrawElements.
+ GLuint bound_element_array_buffer_;
+
+#if defined(OS_WIN)
+ HDC device_context_;
+ HGLRC gl_context_;
+#endif
+
+ bool anti_aliased_;
+
+ DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
+};
+
+GLES2Decoder* GLES2Decoder::Create() {
+ return new GLES2DecoderImpl();
+}
+
+GLES2DecoderImpl::GLES2DecoderImpl()
+ : GLES2Decoder(),
+ error_bits_(0),
+ util_(0), // TODO(gman): Set to actual num compress texture formats.
+ pack_alignment_(4),
+ unpack_alignment_(4),
+ bound_array_buffer_(0),
+ bound_element_array_buffer_(0),
+#ifdef OS_WIN
+ device_context_(NULL),
+ gl_context_(NULL),
+#endif
+ anti_aliased_(false) {
+}
+
+bool GLES2DecoderImpl::Initialize() {
+ if (!InitPlatformSpecific())
+ return false;
+ if (!InitGlew())
+ return false;
+ CHECK_GL_ERROR();
+
+ //glBindFramebuffer(0, 0);
+ return true;
+}
+
+#if defined(OS_WIN)
+namespace {
+
+const PIXELFORMATDESCRIPTOR kPixelFormatDescriptor = {
+ sizeof(kPixelFormatDescriptor), // Size of structure.
+ 1, // Default version.
+ PFD_DRAW_TO_WINDOW | // Window drawing support.
+ PFD_SUPPORT_OPENGL | // OpenGL support.
+ PFD_DOUBLEBUFFER, // Double buffering support (not stereo).
+ PFD_TYPE_RGBA, // RGBA color mode (not indexed).
+ 24, // 24 bit color mode.
+ 0, 0, 0, 0, 0, 0, // Don't set RGB bits & shifts.
+ 8, 0, // 8 bit alpha
+ 0, // No accumulation buffer.
+ 0, 0, 0, 0, // Ignore accumulation bits.
+ 24, // 24 bit z-buffer size.
+ 8, // 8-bit stencil buffer.
+ 0, // No aux buffer.
+ PFD_MAIN_PLANE, // Main drawing plane (not overlay).
+ 0, // Reserved.
+ 0, 0, 0, // Layer masks ignored.
+};
+
+LRESULT CALLBACK IntermediateWindowProc(HWND window,
+ UINT message,
+ WPARAM w_param,
+ LPARAM l_param) {
+ return ::DefWindowProc(window, message, w_param, l_param);
+}
+
+// Helper routine that returns the highest quality pixel format supported on
+// the current platform. Returns true upon success.
+bool GetWindowsPixelFormat(HWND window,
+ bool anti_aliased,
+ int* pixel_format) {
+ // We must initialize a GL context before we can determine the multi-sampling
+ // supported on the current hardware, so we create an intermediate window
+ // and context here.
+ HINSTANCE module_handle;
+ if (!::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT |
+ GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
+ reinterpret_cast<wchar_t*>(IntermediateWindowProc),
+ &module_handle)) {
+ return false;
+ }
+
+ WNDCLASS intermediate_class;
+ intermediate_class.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
+ intermediate_class.lpfnWndProc = IntermediateWindowProc;
+ intermediate_class.cbClsExtra = 0;
+ intermediate_class.cbWndExtra = 0;
+ intermediate_class.hInstance = module_handle;
+ intermediate_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+ intermediate_class.hCursor = LoadCursor(NULL, IDC_ARROW);
+ intermediate_class.hbrBackground = NULL;
+ intermediate_class.lpszMenuName = NULL;
+ intermediate_class.lpszClassName = L"Intermediate GL Window";
+
+ ATOM class_registration = ::RegisterClass(&intermediate_class);
+ if (!class_registration) {
+ return false;
+ }
+
+ HWND intermediate_window = ::CreateWindow(
+ reinterpret_cast<wchar_t*>(class_registration),
+ L"",
+ WS_OVERLAPPEDWINDOW,
+ 0, 0,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+
+ if (!intermediate_window) {
+ ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
+ module_handle);
+ return false;
+ }
+
+ HDC intermediate_dc = ::GetDC(intermediate_window);
+ int format_index = ::ChoosePixelFormat(intermediate_dc,
+ &kPixelFormatDescriptor);
+ if (format_index == 0) {
+ DLOG(ERROR) << "Unable to get the pixel format for GL context.";
+ ::ReleaseDC(intermediate_window, intermediate_dc);
+ ::DestroyWindow(intermediate_window);
+ ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
+ module_handle);
+ return false;
+ }
+ if (!::SetPixelFormat(intermediate_dc, format_index,
+ &kPixelFormatDescriptor)) {
+ DLOG(ERROR) << "Unable to set the pixel format for GL context.";
+ ::ReleaseDC(intermediate_window, intermediate_dc);
+ ::DestroyWindow(intermediate_window);
+ ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
+ module_handle);
+ return false;
+ }
+
+ // Store the pixel format without multisampling.
+ *pixel_format = format_index;
+ HGLRC gl_context = ::wglCreateContext(intermediate_dc);
+ if (::wglMakeCurrent(intermediate_dc, gl_context)) {
+ // GL context was successfully created and applied to the window's DC.
+ // Startup GLEW, the GL extensions wrangler.
+ GLenum glew_error = ::glewInit();
+ if (glew_error == GLEW_OK) {
+ DLOG(INFO) << "Initialized GLEW " << ::glewGetString(GLEW_VERSION);
+ } else {
+ DLOG(ERROR) << "Unable to initialise GLEW : "
+ << ::glewGetErrorString(glew_error);
+ ::wglMakeCurrent(intermediate_dc, NULL);
+ ::wglDeleteContext(gl_context);
+ ::ReleaseDC(intermediate_window, intermediate_dc);
+ ::DestroyWindow(intermediate_window);
+ ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
+ module_handle);
+ return false;
+ }
+
+ // If the multi-sample extensions are present, query the api to determine
+ // the pixel format.
+ if (anti_aliased && WGLEW_ARB_pixel_format && WGLEW_ARB_multisample) {
+ int pixel_attributes[] = {
+ WGL_SAMPLES_ARB, 4,
+ WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
+ WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
+ WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
+ WGL_COLOR_BITS_ARB, 24,
+ WGL_ALPHA_BITS_ARB, 8,
+ WGL_DEPTH_BITS_ARB, 24,
+ WGL_STENCIL_BITS_ARB, 8,
+ WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
+ WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
+ 0, 0};
+
+ float pixel_attributes_f[] = {0, 0};
+ int msaa_pixel_format;
+ unsigned int num_formats;
+
+ // Query for the highest sampling rate supported, starting at 4x.
+ static const int kSampleCount[] = {4, 2};
+ static const int kNumSamples = 2;
+ for (int sample = 0; sample < kNumSamples; ++sample) {
+ pixel_attributes[1] = kSampleCount[sample];
+ if (GL_TRUE == ::wglChoosePixelFormatARB(intermediate_dc,
+ pixel_attributes,
+ pixel_attributes_f,
+ 1,
+ &msaa_pixel_format,
+ &num_formats)) {
+ *pixel_format = msaa_pixel_format;
+ break;
+ }
+ }
+ }
+ }
+
+ ::wglMakeCurrent(intermediate_dc, NULL);
+ ::wglDeleteContext(gl_context);
+ ::ReleaseDC(intermediate_window, intermediate_dc);
+ ::DestroyWindow(intermediate_window);
+ ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
+ module_handle);
+ return true;
+}
+
+} // anonymous namespace
+#endif
+
+bool GLES2DecoderImpl::InitPlatformSpecific() {
+#if defined(OS_WIN)
+ device_context_ = ::GetDC(hwnd());
+
+ int pixel_format;
+
+ if (!GetWindowsPixelFormat(hwnd(),
+ anti_aliased_,
+ &pixel_format)) {
+ DLOG(ERROR) << "Unable to determine optimal pixel format for GL context.";
+ return false;
+ }
+
+ if (!::SetPixelFormat(device_context_, pixel_format,
+ &kPixelFormatDescriptor)) {
+ DLOG(ERROR) << "Unable to set the pixel format for GL context.";
+ return false;
+ }
+
+ gl_context_ = ::wglCreateContext(device_context_);
+ if (!gl_context_) {
+ DLOG(ERROR) << "Failed to create GL context.";
+ return false;
+ }
+
+ if (!::wglMakeCurrent(device_context_, gl_context_)) {
+ DLOG(ERROR) << "Unable to make gl context current.";
+ return false;
+ }
+#elif defined(OS_LINUX)
+ DCHECK(window());
+ if (!window()->Initialize())
+ return false;
+ if (!window()->MakeCurrent())
+ return false;
+#endif
+
+ return true;
+}
+
+bool GLES2DecoderImpl::InitGlew() {
+ DLOG(INFO) << "Initializing GL and GLEW for GLES2Decoder.";
+
+ GLenum glew_error = glewInit();
+ if (glew_error != GLEW_OK) {
+ DLOG(ERROR) << "Unable to initialise GLEW : "
+ << ::glewGetErrorString(glew_error);
+ return false;
+ }
+
+ // Check to see that we can use the OpenGL vertex attribute APIs
+ // TODO(petersont): Return false if this check fails, but because some
+ // Intel hardware does not support OpenGL 2.0, yet does support all of the
+ // extensions we require, we only log an error. A future CL should change
+ // this check to ensure that all of the extension strings we require are
+ // present.
+ if (!GLEW_VERSION_2_0) {
+ DLOG(ERROR) << "GL drivers do not have OpenGL 2.0 functionality.";
+ }
+
+ bool extensions_found = true;
+ if (!GLEW_ARB_vertex_buffer_object) {
+ // NOTE: Linux NVidia drivers claim to support OpenGL 2.0 when using
+ // indirect rendering (e.g. remote X), but it is actually lying. The
+ // ARB_vertex_buffer_object functions silently no-op (!) when using
+ // indirect rendering, leading to crashes. Fortunately, in that case, the
+ // driver claims to not support ARB_vertex_buffer_object, so fail in that
+ // case.
+ DLOG(ERROR) << "GL drivers do not support vertex buffer objects.";
+ extensions_found = false;
+ }
+ if (!GLEW_EXT_framebuffer_object) {
+ DLOG(ERROR) << "GL drivers do not support framebuffer objects.";
+ extensions_found = false;
+ }
+ // Check for necessary extensions
+ if (!GLEW_VERSION_2_0 && !GLEW_EXT_stencil_two_side) {
+ DLOG(ERROR) << "Two sided stencil extension missing.";
+ extensions_found = false;
+ }
+ if (!GLEW_VERSION_1_4 && !GLEW_EXT_blend_func_separate) {
+ DLOG(ERROR) <<"Separate blend func extension missing.";
+ extensions_found = false;
+ }
+ if (!GLEW_VERSION_2_0 && !GLEW_EXT_blend_equation_separate) {
+ DLOG(ERROR) << "Separate blend function extension missing.";
+ extensions_found = false;
+ }
+ if (!extensions_found)
+ return false;
+
+ return true;
+}
+
+void GLES2DecoderImpl::Destroy() {
+#ifdef OS_LINUX
+ DCHECK(window());
+ window()->Destroy();
+#endif
+}
+
+const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
+ if (command_id > kStartPoint && command_id < kNumCommands) {
+ return gles2::GetCommandName(static_cast<CommandId>(command_id));
+ }
+ return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
+}
+
+// Decode command with its arguments, and call the corresponding GL function.
+// Note: args is a pointer to the command buffer. As such, it could be changed
+// by a (malicious) client at any time, so if validation has to happen, it
+// should operate on a copy of them.
+parse_error::ParseError GLES2DecoderImpl::DoCommand(
+ unsigned int command,
+ unsigned int arg_count,
+ const void* cmd_data) {
+ unsigned int command_index = command - kStartPoint - 1;
+ if (command_index < arraysize(g_command_info)) {
+ const CommandInfo& info = g_command_info[command_index];
+ unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
+ if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
+ (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
+ switch (command) {
+ #define GLES2_CMD_OP(name) \
+ case name::kCmdId: \
+ return Handle ## name( \
+ arg_count, \
+ *static_cast<const name*>(cmd_data)); \
+
+ GLES2_COMMAND_LIST(GLES2_CMD_OP)
+
+ #undef GLES2_CMD_OP
+ }
+ } else {
+ return parse_error::kParseInvalidArguments;
+ }
+ }
+ return DoCommonCommand(command, arg_count, cmd_data);
+}
+
+} // namespace gles2
+} // namespace command_buffer
+
+// This is included so the compiler will make these inline.
+#include "gpu/command_buffer/service/gles2_cmd_decoder_validate.h"
+
+namespace command_buffer {
+namespace gles2 {
+
+void GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
+ // TODO(gman): verify client_id is unused.
+ GLuint service_id = glCreateProgram();
+ if (service_id) {
+ id_map_.AddMapping(client_id, service_id);
+ }
+}
+
+void GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
+ // TODO(gman): verify client_id is unused.
+ GLuint service_id = glCreateShader(type);
+ if (service_id) {
+ id_map_.AddMapping(client_id, service_id);
+ }
+}
+
+void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint buffer) {
+ switch (target) {
+ case GL_ARRAY_BUFFER:
+ bound_array_buffer_ = buffer;
+ break;
+ case GL_ELEMENT_ARRAY_BUFFER:
+ bound_element_array_buffer_ = buffer;
+ break;
+ default:
+ break;
+ }
+ glBindBuffer(target, buffer);
+}
+
+void GLES2DecoderImpl::DoDeleteProgram(GLuint program) {
+ GLuint service_id;
+ if (id_map_.GetServiceId(program, &service_id)) {
+ glDeleteProgram(service_id);
+ id_map_.RemoveMapping(program, service_id);
+ }
+}
+
+void GLES2DecoderImpl::DoDeleteShader(GLuint shader) {
+ GLuint service_id;
+ if (id_map_.GetServiceId(shader, &service_id)) {
+ glDeleteProgram(service_id);
+ id_map_.RemoveMapping(shader, service_id);
+ }
+}
+
+// NOTE: If you need to know the results of SwapBuffers (like losing
+// the context) then add a new command. Do NOT make SwapBuffers synchronous.
+void GLES2DecoderImpl::DoSwapBuffers() {
+#ifdef OS_WIN
+ ::SwapBuffers(device_context_);
+#endif
+
+#ifdef OS_LINUX
+ DCHECK(window());
+ window()->SwapBuffers();
+#endif
+}
+
+GLenum GLES2DecoderImpl::GetGLError() {
+ // Check the GL error first, then our wrapped error.
+ GLenum error = glGetError();
+ if (error == GL_NO_ERROR && error_bits_ != 0) {
+ uint32 mask = 1;
+ while (mask) {
+ if ((error_bits_ & mask) != 0) {
+ error = GLErrorBitToGLError(mask);
+ break;
+ }
+ }
+ }
+
+ if (error != GL_NO_ERROR) {
+ // There was an error, clear the corresponding wrapped error.
+ error_bits_ &= ~GLErrorToErrorBit(error);
+ }
+ return error;
+}
+
+void GLES2DecoderImpl::SetGLError(GLenum error) {
+ error_bits_ |= GLErrorToErrorBit(error);
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDrawElements(
+ unsigned int arg_count, const gles2::DrawElements& c) {
+ if (bound_element_array_buffer_ != 0) {
+ GLenum mode = c.mode;
+ GLsizei count = c.count;
+ GLenum type = c.type;
+ const GLvoid* indices = reinterpret_cast<const GLvoid*>(c.index_offset);
+ glDrawElements(mode, count, type, indices);
+ } else {
+ SetGLError(GL_INVALID_VALUE);
+ }
+ return parse_error::kParseNoError;
+}
+
+namespace {
+
+// Calls glShaderSource for the various versions of the ShaderSource command.
+// Assumes that data / data_size points to a piece of memory that is in range
+// of whatever context it came from (shared memory, immediate memory, bucket
+// memory.)
+parse_error::ParseError ShaderSourceHelper(
+ GLuint shader, GLsizei count, const char* data, uint32 data_size) {
+ std::vector<std::string> strings(count);
+ scoped_array<const char*> string_pointers(new const char* [count]);
+
+ const uint32* ends = reinterpret_cast<const uint32*>(data);
+ uint32 start_offset = count * sizeof(*ends);
+ if (start_offset > data_size) {
+ return parse_error::kParseOutOfBounds;
+ }
+ for (GLsizei ii = 0; ii < count; ++ii) {
+ uint32 end_offset = ends[ii];
+ if (end_offset > data_size || end_offset < start_offset) {
+ return parse_error::kParseOutOfBounds;
+ }
+ strings[ii] = std::string(data + start_offset, end_offset - start_offset);
+ string_pointers[ii] = strings[ii].c_str();
+ }
+
+ glShaderSource(shader, count, string_pointers.get(), NULL);
+ return parse_error::kParseNoError;
+}
+
+} // anonymous namespace.
+
+parse_error::ParseError GLES2DecoderImpl::HandleShaderSource(
+ unsigned int arg_count, const gles2::ShaderSource& c) {
+ GLuint shader = c.shader;
+ GLsizei count = c.count;
+ uint32 data_size = c.data_size;
+ const char** data = GetSharedMemoryAs<const char**>(
+ c.data_shm_id, c.data_shm_offset, data_size);
+ parse_error::ParseError result =
+ ValidateShaderSource(this, arg_count, shader, count, data, NULL);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ return ShaderSourceHelper(
+ shader, count, reinterpret_cast<const char*>(data), data_size);
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleShaderSourceImmediate(
+ unsigned int arg_count, const gles2::ShaderSourceImmediate& c) {
+ GLuint shader = c.shader;
+ GLsizei count = c.count;
+ uint32 data_size = c.data_size;
+ // TODO(gman): need to check that data_size is in range for arg_count.
+ const char** data = GetImmediateDataAs<const char**>(c);
+ parse_error::ParseError result =
+ ValidateShaderSourceImmediate(
+ this, arg_count, shader, count, data, NULL);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ return ShaderSourceHelper(
+ shader, count, reinterpret_cast<const char*>(data), data_size);
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleVertexAttribPointer(
+ unsigned int arg_count, const gles2::VertexAttribPointer& c) {
+ if (bound_array_buffer_ != 0) {
+ GLuint indx = c.indx;
+ GLint size = c.size;
+ GLenum type = c.type;
+ GLboolean normalized = c.normalized;
+ GLsizei stride = c.stride;
+ GLuint offset = c.offset;
+ const void* ptr = reinterpret_cast<const void*>(c.offset);
+ parse_error::ParseError result =
+ ValidateVertexAttribPointer(
+ this, arg_count, indx, size, type, normalized, stride, ptr);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
+ } else {
+ SetGLError(GL_INVALID_VALUE);
+ }
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleReadPixels(
+ unsigned int arg_count, const gles2::ReadPixels& c) {
+ // TODO(gman): Implement.
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandlePixelStorei(
+ unsigned int arg_count, const gles2::PixelStorei& c) {
+ // TODO(gman): Implement.
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetVertexAttribPointerv(
+ unsigned int arg_count, const gles2::GetVertexAttribPointerv& c) {
+ // TODO(gman): Implement.
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetUniformiv(
+ unsigned int arg_count, const gles2::GetUniformiv& c) {
+ // TODO(gman): Implement.
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetUniformfv(
+ unsigned int arg_count, const gles2::GetUniformfv& c) {
+ // TODO(gman): Implement.
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
+ unsigned int arg_count, const gles2::GetShaderPrecisionFormat& c) {
+ // TODO(gman): Implement.
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetAttachedShaders(
+ unsigned int arg_count, const gles2::GetAttachedShaders& c) {
+ // TODO(gman): Implement.
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetActiveUniform(
+ unsigned int arg_count, const gles2::GetActiveUniform& c) {
+ // TODO(gman): Implement.
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetActiveAttrib(
+ unsigned int arg_count, const gles2::GetActiveAttrib& c) {
+ // TODO(gman): Implement.
+ return parse_error::kParseNoError;
+}
+
+// Include the auto-generated part of this file. We split this because it means
+// we can easily edit the non-auto generated parts right here in this file
+// instead of having to edit some template or the code generator.
+#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
+
+} // namespace gles2
+} // namespace command_buffer
+
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h
new file mode 100644
index 0000000..10387c6
--- /dev/null
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.h
@@ -0,0 +1,74 @@
+// Copyright (c) 2006-2009 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.
+
+// This file contains the GLES2Decoder class.
+
+#ifndef O3D_COMMAND_BUFFER_SERVICE_CROSS_GLES2_CMD_DECODER_H
+#define O3D_COMMAND_BUFFER_SERVICE_CROSS_GLES2_CMD_DECODER_H
+
+#include <build/build_config.h>
+#ifdef OS_WIN
+#include <windows.h>
+#endif
+#include "gpu/command_buffer/service/common_decoder.h"
+
+namespace command_buffer {
+namespace gles2 {
+
+// This class implements the AsyncAPIInterface interface, decoding GLES2
+// commands and calling GL.
+class GLES2Decoder : public CommonDecoder {
+ public:
+ typedef parse_error::ParseError ParseError;
+
+ // Creates a decoder.
+ static GLES2Decoder* Create();
+
+ virtual ~GLES2Decoder() {
+ }
+
+#if defined(OS_LINUX)
+ void set_window_wrapper(XWindowWrapper *window) {
+ window_ = window;
+ }
+ XWindowWrapper* window() const {
+ return window_;
+ }
+#elif defined(OS_WIN)
+ void set_hwnd(HWND hwnd) {
+ hwnd_ = hwnd;
+ }
+
+ HWND hwnd() const {
+ return hwnd_;
+ }
+#endif
+
+ // Initializes the graphics context.
+ // Returns:
+ // true if successful.
+ virtual bool Initialize() = 0;
+
+ // Destroys the graphics context.
+ virtual void Destroy() = 0;
+
+ protected:
+ GLES2Decoder();
+
+ private:
+#if defined(OS_LINUX)
+ XWindowWrapper *window_;
+#elif defined(OS_WIN)
+ // Handle to the GL device.
+ HWND hwnd_;
+#endif
+
+ DISALLOW_COPY_AND_ASSIGN(GLES2Decoder);
+};
+
+} // namespace gles2
+} // namespace command_buffer
+
+#endif // O3D_COMMAND_BUFFER_SERVICE_CROSS_GLES2_CMD_DECODER_H
+
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
new file mode 100644
index 0000000..1a247fd
--- /dev/null
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
@@ -0,0 +1,2610 @@
+// This file is auto-generated. DO NOT EDIT!
+
+// It is included by gles2_cmd_decoder.cc
+
+parse_error::ParseError GLES2DecoderImpl::HandleActiveTexture(
+ unsigned int arg_count, const gles2::ActiveTexture& c) {
+ GLenum texture = static_cast<GLenum>(c.texture);
+ parse_error::ParseError result =
+ ValidateActiveTexture(this, arg_count, texture);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glActiveTexture(texture);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleAttachShader(
+ unsigned int arg_count, const gles2::AttachShader& c) {
+ GLuint program;
+ if (!id_map_.GetServiceId(c.program, &program)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ GLuint shader;
+ if (!id_map_.GetServiceId(c.shader, &shader)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ parse_error::ParseError result =
+ ValidateAttachShader(this, arg_count, program, shader);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glAttachShader(program, shader);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBindAttribLocation(
+ unsigned int arg_count, const gles2::BindAttribLocation& c) {
+ GLuint program;
+ if (!id_map_.GetServiceId(c.program, &program)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ GLuint index = static_cast<GLuint>(c.index);
+ uint32 name_size = c.data_size;
+ const char* name = GetSharedMemoryAs<const char*>(
+ c.name_shm_id, c.name_shm_offset, name_size);
+ parse_error::ParseError result =
+ ValidateBindAttribLocation(this, arg_count, program, index, name);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ String name_str(name, name_size);
+ glBindAttribLocation(program, index, name_str.c_str());
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBindAttribLocationImmediate(
+ unsigned int arg_count, const gles2::BindAttribLocationImmediate& c) {
+ GLuint program;
+ if (!id_map_.GetServiceId(c.program, &program)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ GLuint index = static_cast<GLuint>(c.index);
+ uint32 name_size = c.data_size;
+ const char* name = GetImmediateDataAs<const char*>(c);
+ // TODO(gman): Make sure validate checks arg_count
+ // covers data_size.
+ parse_error::ParseError result =
+ ValidateBindAttribLocationImmediate(
+ this, arg_count, program, index, name);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ String name_str(name, name_size);
+ glBindAttribLocation(program, index, name_str.c_str());
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBindBuffer(
+ unsigned int arg_count, const gles2::BindBuffer& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ GLuint buffer;
+ if (!id_map_.GetServiceId(c.buffer, &buffer)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ parse_error::ParseError result =
+ ValidateBindBuffer(this, arg_count, target, buffer);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ DoBindBuffer(target, buffer);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBindFramebuffer(
+ unsigned int arg_count, const gles2::BindFramebuffer& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ GLuint framebuffer;
+ if (!id_map_.GetServiceId(c.framebuffer, &framebuffer)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ parse_error::ParseError result =
+ ValidateBindFramebuffer(this, arg_count, target, framebuffer);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glBindFramebufferEXT(target, framebuffer);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBindRenderbuffer(
+ unsigned int arg_count, const gles2::BindRenderbuffer& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ GLuint renderbuffer;
+ if (!id_map_.GetServiceId(c.renderbuffer, &renderbuffer)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ parse_error::ParseError result =
+ ValidateBindRenderbuffer(this, arg_count, target, renderbuffer);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glBindRenderbufferEXT(target, renderbuffer);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBindTexture(
+ unsigned int arg_count, const gles2::BindTexture& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ GLuint texture;
+ if (!id_map_.GetServiceId(c.texture, &texture)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ parse_error::ParseError result =
+ ValidateBindTexture(this, arg_count, target, texture);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glBindTexture(target, texture);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBlendColor(
+ unsigned int arg_count, const gles2::BlendColor& c) {
+ GLclampf red = static_cast<GLclampf>(c.red);
+ GLclampf green = static_cast<GLclampf>(c.green);
+ GLclampf blue = static_cast<GLclampf>(c.blue);
+ GLclampf alpha = static_cast<GLclampf>(c.alpha);
+ parse_error::ParseError result =
+ ValidateBlendColor(this, arg_count, red, green, blue, alpha);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glBlendColor(red, green, blue, alpha);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBlendEquation(
+ unsigned int arg_count, const gles2::BlendEquation& c) {
+ GLenum mode = static_cast<GLenum>(c.mode);
+ parse_error::ParseError result =
+ ValidateBlendEquation(this, arg_count, mode);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glBlendEquation(mode);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBlendEquationSeparate(
+ unsigned int arg_count, const gles2::BlendEquationSeparate& c) {
+ GLenum modeRGB = static_cast<GLenum>(c.modeRGB);
+ GLenum modeAlpha = static_cast<GLenum>(c.modeAlpha);
+ parse_error::ParseError result =
+ ValidateBlendEquationSeparate(this, arg_count, modeRGB, modeAlpha);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glBlendEquationSeparate(modeRGB, modeAlpha);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBlendFunc(
+ unsigned int arg_count, const gles2::BlendFunc& c) {
+ GLenum sfactor = static_cast<GLenum>(c.sfactor);
+ GLenum dfactor = static_cast<GLenum>(c.dfactor);
+ parse_error::ParseError result =
+ ValidateBlendFunc(this, arg_count, sfactor, dfactor);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glBlendFunc(sfactor, dfactor);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBlendFuncSeparate(
+ unsigned int arg_count, const gles2::BlendFuncSeparate& c) {
+ GLenum srcRGB = static_cast<GLenum>(c.srcRGB);
+ GLenum dstRGB = static_cast<GLenum>(c.dstRGB);
+ GLenum srcAlpha = static_cast<GLenum>(c.srcAlpha);
+ GLenum dstAlpha = static_cast<GLenum>(c.dstAlpha);
+ parse_error::ParseError result =
+ ValidateBlendFuncSeparate(
+ this, arg_count, srcRGB, dstRGB, srcAlpha, dstAlpha);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBufferData(
+ unsigned int arg_count, const gles2::BufferData& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
+ uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
+ uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
+ GLenum usage = static_cast<GLenum>(c.usage);
+ uint32 data_size = size;
+ const void* data = GetSharedMemoryAs<const void*>(
+ data_shm_id, data_shm_offset, data_size);
+ parse_error::ParseError result =
+ ValidateBufferData(this, arg_count, target, size, data, usage);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glBufferData(target, size, data, usage);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBufferDataImmediate(
+ unsigned int arg_count, const gles2::BufferDataImmediate& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
+ const void* data = GetImmediateDataAs<const void*>(c);
+ GLenum usage = static_cast<GLenum>(c.usage);
+ // Immediate version.
+ parse_error::ParseError result =
+ ValidateBufferDataImmediate(this, arg_count, target, size, data, usage);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glBufferData(target, size, data, usage);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBufferSubData(
+ unsigned int arg_count, const gles2::BufferSubData& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ GLintptr offset = static_cast<GLintptr>(c.offset);
+ GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
+ uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
+ uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
+ uint32 data_size = size;
+ const void* data = GetSharedMemoryAs<const void*>(
+ data_shm_id, data_shm_offset, data_size);
+ parse_error::ParseError result =
+ ValidateBufferSubData(this, arg_count, target, offset, size, data);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glBufferSubData(target, offset, size, data);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleBufferSubDataImmediate(
+ unsigned int arg_count, const gles2::BufferSubDataImmediate& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ GLintptr offset = static_cast<GLintptr>(c.offset);
+ GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
+ const void* data = GetImmediateDataAs<const void*>(c);
+ // Immediate version.
+ parse_error::ParseError result =
+ ValidateBufferSubDataImmediate(
+ this, arg_count, target, offset, size, data);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glBufferSubData(target, offset, size, data);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleCheckFramebufferStatus(
+ unsigned int arg_count, const gles2::CheckFramebufferStatus& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ parse_error::ParseError result =
+ ValidateCheckFramebufferStatus(this, arg_count, target);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glCheckFramebufferStatusEXT(target);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleClear(
+ unsigned int arg_count, const gles2::Clear& c) {
+ GLbitfield mask = static_cast<GLbitfield>(c.mask);
+ parse_error::ParseError result =
+ ValidateClear(this, arg_count, mask);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glClear(mask);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleClearColor(
+ unsigned int arg_count, const gles2::ClearColor& c) {
+ GLclampf red = static_cast<GLclampf>(c.red);
+ GLclampf green = static_cast<GLclampf>(c.green);
+ GLclampf blue = static_cast<GLclampf>(c.blue);
+ GLclampf alpha = static_cast<GLclampf>(c.alpha);
+ parse_error::ParseError result =
+ ValidateClearColor(this, arg_count, red, green, blue, alpha);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glClearColor(red, green, blue, alpha);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleClearDepthf(
+ unsigned int arg_count, const gles2::ClearDepthf& c) {
+ GLclampf depth = static_cast<GLclampf>(c.depth);
+ parse_error::ParseError result =
+ ValidateClearDepthf(this, arg_count, depth);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glClearDepth(depth);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleClearStencil(
+ unsigned int arg_count, const gles2::ClearStencil& c) {
+ GLint s = static_cast<GLint>(c.s);
+ parse_error::ParseError result =
+ ValidateClearStencil(this, arg_count, s);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glClearStencil(s);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleColorMask(
+ unsigned int arg_count, const gles2::ColorMask& c) {
+ GLboolean red = static_cast<GLboolean>(c.red);
+ GLboolean green = static_cast<GLboolean>(c.green);
+ GLboolean blue = static_cast<GLboolean>(c.blue);
+ GLboolean alpha = static_cast<GLboolean>(c.alpha);
+ parse_error::ParseError result =
+ ValidateColorMask(this, arg_count, red, green, blue, alpha);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glColorMask(red, green, blue, alpha);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleCompileShader(
+ unsigned int arg_count, const gles2::CompileShader& c) {
+ GLuint shader;
+ if (!id_map_.GetServiceId(c.shader, &shader)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ parse_error::ParseError result =
+ ValidateCompileShader(this, arg_count, shader);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glCompileShader(shader);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleCompressedTexImage2D(
+ unsigned int arg_count, const gles2::CompressedTexImage2D& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ GLint level = static_cast<GLint>(c.level);
+ GLenum internalformat = static_cast<GLenum>(c.internalformat);
+ GLsizei width = static_cast<GLsizei>(c.width);
+ GLsizei height = static_cast<GLsizei>(c.height);
+ GLint border = static_cast<GLint>(c.border);
+ GLsizei imageSize = static_cast<GLsizei>(c.imageSize);
+ uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
+ uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
+ uint32 data_size = imageSize;
+ const void* data = GetSharedMemoryAs<const void*>(
+ data_shm_id, data_shm_offset, data_size);
+ parse_error::ParseError result =
+ ValidateCompressedTexImage2D(
+ this, arg_count, target, level, internalformat, width, height, border,
+ imageSize, data);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glCompressedTexImage2D(
+ target, level, internalformat, width, height, border, imageSize, data);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
+ unsigned int arg_count, const gles2::CompressedTexImage2DImmediate& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ GLint level = static_cast<GLint>(c.level);
+ GLenum internalformat = static_cast<GLenum>(c.internalformat);
+ GLsizei width = static_cast<GLsizei>(c.width);
+ GLsizei height = static_cast<GLsizei>(c.height);
+ GLint border = static_cast<GLint>(c.border);
+ GLsizei imageSize = static_cast<GLsizei>(c.imageSize);
+ const void* data = GetImmediateDataAs<const void*>(c);
+ // Immediate version.
+ parse_error::ParseError result =
+ ValidateCompressedTexImage2DImmediate(
+ this, arg_count, target, level, internalformat, width, height, border,
+ imageSize, data);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glCompressedTexImage2D(
+ target, level, internalformat, width, height, border, imageSize, data);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleCompressedTexSubImage2D(
+ unsigned int arg_count, const gles2::CompressedTexSubImage2D& c) {
+ 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);
+ GLsizei width = static_cast<GLsizei>(c.width);
+ GLsizei height = static_cast<GLsizei>(c.height);
+ GLenum format = static_cast<GLenum>(c.format);
+ GLsizei imageSize = static_cast<GLsizei>(c.imageSize);
+ uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
+ uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
+ uint32 data_size = imageSize;
+ const void* data = GetSharedMemoryAs<const void*>(
+ data_shm_id, data_shm_offset, data_size);
+ parse_error::ParseError result =
+ ValidateCompressedTexSubImage2D(
+ this, arg_count, target, level, xoffset, yoffset, width, height,
+ format, imageSize, data);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glCompressedTexSubImage2D(
+ target, level, xoffset, yoffset, width, height, format, imageSize, data);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleCompressedTexSubImage2DImmediate(
+
+ unsigned int arg_count, const gles2::CompressedTexSubImage2DImmediate& c) {
+ 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);
+ GLsizei width = static_cast<GLsizei>(c.width);
+ GLsizei height = static_cast<GLsizei>(c.height);
+ GLenum format = static_cast<GLenum>(c.format);
+ GLsizei imageSize = static_cast<GLsizei>(c.imageSize);
+ const void* data = GetImmediateDataAs<const void*>(c);
+ // Immediate version.
+ parse_error::ParseError result =
+ ValidateCompressedTexSubImage2DImmediate(
+ this, arg_count, target, level, xoffset, yoffset, width, height,
+ format, imageSize, data);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glCompressedTexSubImage2D(
+ target, level, xoffset, yoffset, width, height, format, imageSize, data);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleCopyTexImage2D(
+ unsigned int arg_count, const gles2::CopyTexImage2D& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ GLint level = static_cast<GLint>(c.level);
+ GLenum internalformat = static_cast<GLenum>(c.internalformat);
+ 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);
+ GLint border = static_cast<GLint>(c.border);
+ parse_error::ParseError result =
+ ValidateCopyTexImage2D(
+ this, arg_count, target, level, internalformat, x, y, width, height,
+ border);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glCopyTexImage2D(target, level, internalformat, x, y, width, height, border);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleCopyTexSubImage2D(
+ unsigned int arg_count, const gles2::CopyTexSubImage2D& c) {
+ 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 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);
+ parse_error::ParseError result =
+ ValidateCopyTexSubImage2D(
+ this, arg_count, target, level, xoffset, yoffset, x, y, width,
+ height);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleCreateProgram(
+ unsigned int arg_count, const gles2::CreateProgram& c) {
+ uint32 client_id = c.client_id;
+ parse_error::ParseError result =
+ ValidateCreateProgram(this, arg_count);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ CreateProgramHelper(client_id);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleCreateShader(
+ unsigned int arg_count, const gles2::CreateShader& c) {
+ GLenum type = static_cast<GLenum>(c.type);
+ uint32 client_id = c.client_id;
+ parse_error::ParseError result =
+ ValidateCreateShader(this, arg_count, type);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ CreateShaderHelper(type, client_id);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleCullFace(
+ unsigned int arg_count, const gles2::CullFace& c) {
+ GLenum mode = static_cast<GLenum>(c.mode);
+ parse_error::ParseError result =
+ ValidateCullFace(this, arg_count, mode);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glCullFace(mode);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDeleteBuffers(
+ unsigned int arg_count, const gles2::DeleteBuffers& c) {
+ GLsizei n = static_cast<GLsizei>(c.n);
+ const GLuint* buffers = GetSharedMemoryAs<const GLuint*>(
+ c.buffers_shm_id, c.buffers_shm_offset, 0 /* TODO(gman): size */);
+ parse_error::ParseError result =
+ ValidateDeleteBuffers(this, arg_count, n, buffers);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ DeleteGLObjects<GLDeleteBuffersHelper>(n, buffers);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDeleteBuffersImmediate(
+ unsigned int arg_count, const gles2::DeleteBuffersImmediate& c) {
+ GLsizei n = static_cast<GLsizei>(c.n);
+ const GLuint* buffers = GetImmediateDataAs<const GLuint*>(c);
+ parse_error::ParseError result =
+ ValidateDeleteBuffersImmediate(this, arg_count, n, buffers);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ DeleteGLObjects<GLDeleteBuffersHelper>(n, buffers);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDeleteFramebuffers(
+ unsigned int arg_count, const gles2::DeleteFramebuffers& c) {
+ GLsizei n = static_cast<GLsizei>(c.n);
+ const GLuint* framebuffers = GetSharedMemoryAs<const GLuint*>(
+ c.framebuffers_shm_id, c.framebuffers_shm_offset, 0 /* TODO(
+ gman): size */);
+ parse_error::ParseError result =
+ ValidateDeleteFramebuffers(this, arg_count, n, framebuffers);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ DeleteGLObjects<GLDeleteFramebuffersHelper>(n, framebuffers);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDeleteFramebuffersImmediate(
+ unsigned int arg_count, const gles2::DeleteFramebuffersImmediate& c) {
+ GLsizei n = static_cast<GLsizei>(c.n);
+ const GLuint* framebuffers = GetImmediateDataAs<const GLuint*>(c);
+ parse_error::ParseError result =
+ ValidateDeleteFramebuffersImmediate(this, arg_count, n, framebuffers);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ DeleteGLObjects<GLDeleteFramebuffersHelper>(n, framebuffers);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDeleteProgram(
+ unsigned int arg_count, const gles2::DeleteProgram& c) {
+ GLuint program;
+ if (!id_map_.GetServiceId(c.program, &program)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ parse_error::ParseError result =
+ ValidateDeleteProgram(this, arg_count, program);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ DoDeleteProgram(program);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDeleteRenderbuffers(
+ unsigned int arg_count, const gles2::DeleteRenderbuffers& c) {
+ GLsizei n = static_cast<GLsizei>(c.n);
+ const GLuint* renderbuffers = GetSharedMemoryAs<const GLuint*>(
+ c.renderbuffers_shm_id, c.renderbuffers_shm_offset, 0 /* TODO(
+ gman): size */);
+ parse_error::ParseError result =
+ ValidateDeleteRenderbuffers(this, arg_count, n, renderbuffers);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ DeleteGLObjects<GLDeleteRenderbuffersHelper>(n, renderbuffers);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDeleteRenderbuffersImmediate(
+ unsigned int arg_count, const gles2::DeleteRenderbuffersImmediate& c) {
+ GLsizei n = static_cast<GLsizei>(c.n);
+ const GLuint* renderbuffers = GetImmediateDataAs<const GLuint*>(c);
+ parse_error::ParseError result =
+ ValidateDeleteRenderbuffersImmediate(this, arg_count, n, renderbuffers);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ DeleteGLObjects<GLDeleteRenderbuffersHelper>(n, renderbuffers);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDeleteShader(
+ unsigned int arg_count, const gles2::DeleteShader& c) {
+ GLuint shader;
+ if (!id_map_.GetServiceId(c.shader, &shader)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ parse_error::ParseError result =
+ ValidateDeleteShader(this, arg_count, shader);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ DoDeleteShader(shader);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDeleteTextures(
+ unsigned int arg_count, const gles2::DeleteTextures& c) {
+ GLsizei n = static_cast<GLsizei>(c.n);
+ const GLuint* textures = GetSharedMemoryAs<const GLuint*>(
+ c.textures_shm_id, c.textures_shm_offset, 0 /* TODO(gman): size */);
+ parse_error::ParseError result =
+ ValidateDeleteTextures(this, arg_count, n, textures);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ DeleteGLObjects<GLDeleteTexturesHelper>(n, textures);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDeleteTexturesImmediate(
+ unsigned int arg_count, const gles2::DeleteTexturesImmediate& c) {
+ GLsizei n = static_cast<GLsizei>(c.n);
+ const GLuint* textures = GetImmediateDataAs<const GLuint*>(c);
+ parse_error::ParseError result =
+ ValidateDeleteTexturesImmediate(this, arg_count, n, textures);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ DeleteGLObjects<GLDeleteTexturesHelper>(n, textures);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDepthFunc(
+ unsigned int arg_count, const gles2::DepthFunc& c) {
+ GLenum func = static_cast<GLenum>(c.func);
+ parse_error::ParseError result =
+ ValidateDepthFunc(this, arg_count, func);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glDepthFunc(func);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDepthMask(
+ unsigned int arg_count, const gles2::DepthMask& c) {
+ GLboolean flag = static_cast<GLboolean>(c.flag);
+ parse_error::ParseError result =
+ ValidateDepthMask(this, arg_count, flag);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glDepthMask(flag);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDepthRangef(
+ unsigned int arg_count, const gles2::DepthRangef& c) {
+ GLclampf zNear = static_cast<GLclampf>(c.zNear);
+ GLclampf zFar = static_cast<GLclampf>(c.zFar);
+ parse_error::ParseError result =
+ ValidateDepthRangef(this, arg_count, zNear, zFar);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glDepthRange(zNear, zFar);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDetachShader(
+ unsigned int arg_count, const gles2::DetachShader& c) {
+ GLuint program;
+ if (!id_map_.GetServiceId(c.program, &program)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ GLuint shader;
+ if (!id_map_.GetServiceId(c.shader, &shader)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ parse_error::ParseError result =
+ ValidateDetachShader(this, arg_count, program, shader);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glDetachShader(program, shader);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDisable(
+ unsigned int arg_count, const gles2::Disable& c) {
+ GLenum cap = static_cast<GLenum>(c.cap);
+ parse_error::ParseError result =
+ ValidateDisable(this, arg_count, cap);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glDisable(cap);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDisableVertexAttribArray(
+ unsigned int arg_count, const gles2::DisableVertexAttribArray& c) {
+ GLuint index = static_cast<GLuint>(c.index);
+ parse_error::ParseError result =
+ ValidateDisableVertexAttribArray(this, arg_count, index);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glDisableVertexAttribArray(index);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleDrawArrays(
+ unsigned int arg_count, const gles2::DrawArrays& c) {
+ GLenum mode = static_cast<GLenum>(c.mode);
+ GLint first = static_cast<GLint>(c.first);
+ GLsizei count = static_cast<GLsizei>(c.count);
+ parse_error::ParseError result =
+ ValidateDrawArrays(this, arg_count, mode, first, count);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glDrawArrays(mode, first, count);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleEnable(
+ unsigned int arg_count, const gles2::Enable& c) {
+ GLenum cap = static_cast<GLenum>(c.cap);
+ parse_error::ParseError result =
+ ValidateEnable(this, arg_count, cap);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glEnable(cap);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleEnableVertexAttribArray(
+ unsigned int arg_count, const gles2::EnableVertexAttribArray& c) {
+ GLuint index = static_cast<GLuint>(c.index);
+ parse_error::ParseError result =
+ ValidateEnableVertexAttribArray(this, arg_count, index);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glEnableVertexAttribArray(index);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleFinish(
+ unsigned int arg_count, const gles2::Finish& c) {
+ parse_error::ParseError result =
+ ValidateFinish(this, arg_count);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glFinish();
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleFlush(
+ unsigned int arg_count, const gles2::Flush& c) {
+ parse_error::ParseError result =
+ ValidateFlush(this, arg_count);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glFlush();
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleFramebufferRenderbuffer(
+ unsigned int arg_count, const gles2::FramebufferRenderbuffer& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ GLenum attachment = static_cast<GLenum>(c.attachment);
+ GLenum renderbuffertarget = static_cast<GLenum>(c.renderbuffertarget);
+ GLuint renderbuffer;
+ if (!id_map_.GetServiceId(c.renderbuffer, &renderbuffer)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ parse_error::ParseError result =
+ ValidateFramebufferRenderbuffer(
+ this, arg_count, target, attachment, renderbuffertarget,
+ renderbuffer);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glFramebufferRenderbufferEXT(
+ target, attachment, renderbuffertarget, renderbuffer);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleFramebufferTexture2D(
+ unsigned int arg_count, const gles2::FramebufferTexture2D& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ GLenum attachment = static_cast<GLenum>(c.attachment);
+ GLenum textarget = static_cast<GLenum>(c.textarget);
+ GLuint texture;
+ if (!id_map_.GetServiceId(c.texture, &texture)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ GLint level = static_cast<GLint>(c.level);
+ parse_error::ParseError result =
+ ValidateFramebufferTexture2D(
+ this, arg_count, target, attachment, textarget, texture, level);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glFramebufferTexture2DEXT(target, attachment, textarget, texture, level);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleFrontFace(
+ unsigned int arg_count, const gles2::FrontFace& c) {
+ GLenum mode = static_cast<GLenum>(c.mode);
+ parse_error::ParseError result =
+ ValidateFrontFace(this, arg_count, mode);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glFrontFace(mode);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGenBuffers(
+ unsigned int arg_count, const gles2::GenBuffers& c) {
+ GLsizei n = static_cast<GLsizei>(c.n);
+ GLuint* buffers = GetSharedMemoryAs<GLuint*>(
+ c.buffers_shm_id, c.buffers_shm_offset, 0 /* TODO(gman): size */);
+ parse_error::ParseError result =
+ ValidateGenBuffers(this, arg_count, n, buffers);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ GenGLObjects<GLGenBuffersHelper>(n, buffers);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGenBuffersImmediate(
+ unsigned int arg_count, const gles2::GenBuffersImmediate& c) {
+ GLsizei n = static_cast<GLsizei>(c.n);
+ GLuint* buffers = GetImmediateDataAs<GLuint*>(c);
+ parse_error::ParseError result =
+ ValidateGenBuffersImmediate(this, arg_count, n, buffers);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ GenGLObjects<GLGenBuffersHelper>(n, buffers);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGenerateMipmap(
+ unsigned int arg_count, const gles2::GenerateMipmap& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ parse_error::ParseError result =
+ ValidateGenerateMipmap(this, arg_count, target);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glGenerateMipmapEXT(target);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGenFramebuffers(
+ unsigned int arg_count, const gles2::GenFramebuffers& c) {
+ GLsizei n = static_cast<GLsizei>(c.n);
+ GLuint* framebuffers = GetSharedMemoryAs<GLuint*>(
+ c.framebuffers_shm_id, c.framebuffers_shm_offset, 0 /* TODO(
+ gman): size */);
+ parse_error::ParseError result =
+ ValidateGenFramebuffers(this, arg_count, n, framebuffers);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ GenGLObjects<GLGenFramebuffersHelper>(n, framebuffers);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGenFramebuffersImmediate(
+ unsigned int arg_count, const gles2::GenFramebuffersImmediate& c) {
+ GLsizei n = static_cast<GLsizei>(c.n);
+ GLuint* framebuffers = GetImmediateDataAs<GLuint*>(c);
+ parse_error::ParseError result =
+ ValidateGenFramebuffersImmediate(this, arg_count, n, framebuffers);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ GenGLObjects<GLGenFramebuffersHelper>(n, framebuffers);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGenRenderbuffers(
+ unsigned int arg_count, const gles2::GenRenderbuffers& c) {
+ GLsizei n = static_cast<GLsizei>(c.n);
+ GLuint* renderbuffers = GetSharedMemoryAs<GLuint*>(
+ c.renderbuffers_shm_id, c.renderbuffers_shm_offset, 0 /* TODO(
+ gman): size */);
+ parse_error::ParseError result =
+ ValidateGenRenderbuffers(this, arg_count, n, renderbuffers);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ GenGLObjects<GLGenRenderbuffersHelper>(n, renderbuffers);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGenRenderbuffersImmediate(
+ unsigned int arg_count, const gles2::GenRenderbuffersImmediate& c) {
+ GLsizei n = static_cast<GLsizei>(c.n);
+ GLuint* renderbuffers = GetImmediateDataAs<GLuint*>(c);
+ parse_error::ParseError result =
+ ValidateGenRenderbuffersImmediate(this, arg_count, n, renderbuffers);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ GenGLObjects<GLGenRenderbuffersHelper>(n, renderbuffers);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGenTextures(
+ unsigned int arg_count, const gles2::GenTextures& c) {
+ GLsizei n = static_cast<GLsizei>(c.n);
+ GLuint* textures = GetSharedMemoryAs<GLuint*>(
+ c.textures_shm_id, c.textures_shm_offset, 0 /* TODO(gman): size */);
+ parse_error::ParseError result =
+ ValidateGenTextures(this, arg_count, n, textures);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ GenGLObjects<GLGenTexturesHelper>(n, textures);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGenTexturesImmediate(
+ unsigned int arg_count, const gles2::GenTexturesImmediate& c) {
+ GLsizei n = static_cast<GLsizei>(c.n);
+ GLuint* textures = GetImmediateDataAs<GLuint*>(c);
+ parse_error::ParseError result =
+ ValidateGenTexturesImmediate(this, arg_count, n, textures);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ GenGLObjects<GLGenTexturesHelper>(n, textures);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetAttribLocation(
+ unsigned int arg_count, const gles2::GetAttribLocation& c) {
+ GLuint program;
+ if (!id_map_.GetServiceId(c.program, &program)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ uint32 name_size = c.data_size;
+ const char* name = GetSharedMemoryAs<const char*>(
+ c.name_shm_id, c.name_shm_offset, name_size);
+ parse_error::ParseError result =
+ ValidateGetAttribLocation(this, arg_count, program, name);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ String name_str(name, name_size);
+ GLint location = glGetAttribLocation(program, name_str.c_str());
+ DCHECK(false); // TODO: return result.
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetAttribLocationImmediate(
+ unsigned int arg_count, const gles2::GetAttribLocationImmediate& c) {
+ GLuint program;
+ if (!id_map_.GetServiceId(c.program, &program)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ uint32 name_size = c.data_size;
+ const char* name = GetImmediateDataAs<const char*>(c);
+ // TODO(gman): Make sure validate checks arg_count
+ // covers data_size.
+ parse_error::ParseError result =
+ ValidateGetAttribLocationImmediate(this, arg_count, program, name);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ String name_str(name, name_size);
+ GLint location = glGetAttribLocation(program, name_str.c_str());
+ DCHECK(false); // TODO: return result.
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetBooleanv(
+ unsigned int arg_count, const gles2::GetBooleanv& c) {
+ GLenum pname = static_cast<GLenum>(c.pname);
+ GLboolean* params;
+ GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+ uint32 params_size = num_values * sizeof(*params);
+ params = GetSharedMemoryAs<GLboolean*>(
+ c.params_shm_id, c.params_shm_offset, params_size);
+ parse_error::ParseError result =
+ ValidateGetBooleanv(this, arg_count, pname, params);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glGetBooleanv(pname, params);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetBufferParameteriv(
+ unsigned int arg_count, const gles2::GetBufferParameteriv& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ GLenum pname = static_cast<GLenum>(c.pname);
+ GLint* params;
+ GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+ uint32 params_size = num_values * sizeof(*params);
+ params = GetSharedMemoryAs<GLint*>(
+ c.params_shm_id, c.params_shm_offset, params_size);
+ parse_error::ParseError result =
+ ValidateGetBufferParameteriv(this, arg_count, target, pname, params);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glGetBufferParameteriv(target, pname, params);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetError(
+ unsigned int arg_count, const gles2::GetError& c) {
+ GLenum* result_dst = GetSharedMemoryAs<GLenum*>(
+ c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
+ parse_error::ParseError result =
+ ValidateGetError(this, arg_count);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ *result_dst = glGetError();
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetFloatv(
+ unsigned int arg_count, const gles2::GetFloatv& c) {
+ GLenum pname = static_cast<GLenum>(c.pname);
+ GLfloat* params;
+ GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+ uint32 params_size = num_values * sizeof(*params);
+ params = GetSharedMemoryAs<GLfloat*>(
+ c.params_shm_id, c.params_shm_offset, params_size);
+ parse_error::ParseError result =
+ ValidateGetFloatv(this, arg_count, pname, params);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glGetFloatv(pname, params);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetFramebufferAttachmentParameteriv(
+
+ unsigned int arg_count,
+ const gles2::GetFramebufferAttachmentParameteriv& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ GLenum attachment = static_cast<GLenum>(c.attachment);
+ GLenum pname = static_cast<GLenum>(c.pname);
+ GLint* params;
+ GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+ uint32 params_size = num_values * sizeof(*params);
+ params = GetSharedMemoryAs<GLint*>(
+ c.params_shm_id, c.params_shm_offset, params_size);
+ parse_error::ParseError result =
+ ValidateGetFramebufferAttachmentParameteriv(
+ this, arg_count, target, attachment, pname, params);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetIntegerv(
+ unsigned int arg_count, const gles2::GetIntegerv& c) {
+ GLenum pname = static_cast<GLenum>(c.pname);
+ GLint* params;
+ GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+ uint32 params_size = num_values * sizeof(*params);
+ params = GetSharedMemoryAs<GLint*>(
+ c.params_shm_id, c.params_shm_offset, params_size);
+ parse_error::ParseError result =
+ ValidateGetIntegerv(this, arg_count, pname, params);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glGetIntegerv(pname, params);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetProgramiv(
+ unsigned int arg_count, const gles2::GetProgramiv& c) {
+ GLuint program;
+ if (!id_map_.GetServiceId(c.program, &program)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ GLenum pname = static_cast<GLenum>(c.pname);
+ GLint* params;
+ GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+ uint32 params_size = num_values * sizeof(*params);
+ params = GetSharedMemoryAs<GLint*>(
+ c.params_shm_id, c.params_shm_offset, params_size);
+ parse_error::ParseError result =
+ ValidateGetProgramiv(this, arg_count, program, pname, params);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glGetProgramiv(program, pname, params);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetProgramInfoLog(
+ unsigned int arg_count, const gles2::GetProgramInfoLog& c) {
+ GLuint program;
+ if (!id_map_.GetServiceId(c.program, &program)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ GLsizei bufsize = static_cast<GLsizei>(c.bufsize);
+ GLsizei* length = GetSharedMemoryAs<GLsizei*>(
+ c.length_shm_id, c.length_shm_offset, 0 /* TODO(gman): size */);
+ char* infolog = GetSharedMemoryAs<char*>(
+ c.infolog_shm_id, c.infolog_shm_offset, 0 /* TODO(gman): size */);
+ parse_error::ParseError result =
+ ValidateGetProgramInfoLog(
+ this, arg_count, program, bufsize, length, infolog);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glGetProgramInfoLog(program, bufsize, length, infolog);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetRenderbufferParameteriv(
+ unsigned int arg_count, const gles2::GetRenderbufferParameteriv& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ GLenum pname = static_cast<GLenum>(c.pname);
+ GLint* params;
+ GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+ uint32 params_size = num_values * sizeof(*params);
+ params = GetSharedMemoryAs<GLint*>(
+ c.params_shm_id, c.params_shm_offset, params_size);
+ parse_error::ParseError result =
+ ValidateGetRenderbufferParameteriv(
+ this, arg_count, target, pname, params);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glGetRenderbufferParameterivEXT(target, pname, params);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetShaderiv(
+ unsigned int arg_count, const gles2::GetShaderiv& c) {
+ GLuint shader;
+ if (!id_map_.GetServiceId(c.shader, &shader)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ GLenum pname = static_cast<GLenum>(c.pname);
+ GLint* params;
+ GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+ uint32 params_size = num_values * sizeof(*params);
+ params = GetSharedMemoryAs<GLint*>(
+ c.params_shm_id, c.params_shm_offset, params_size);
+ parse_error::ParseError result =
+ ValidateGetShaderiv(this, arg_count, shader, pname, params);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glGetShaderiv(shader, pname, params);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetShaderInfoLog(
+ unsigned int arg_count, const gles2::GetShaderInfoLog& c) {
+ GLuint shader;
+ if (!id_map_.GetServiceId(c.shader, &shader)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ GLsizei bufsize = static_cast<GLsizei>(c.bufsize);
+ GLsizei* length = GetSharedMemoryAs<GLsizei*>(
+ c.length_shm_id, c.length_shm_offset, 0 /* TODO(gman): size */);
+ char* infolog = GetSharedMemoryAs<char*>(
+ c.infolog_shm_id, c.infolog_shm_offset, 0 /* TODO(gman): size */);
+ parse_error::ParseError result =
+ ValidateGetShaderInfoLog(
+ this, arg_count, shader, bufsize, length, infolog);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glGetShaderInfoLog(shader, bufsize, length, infolog);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetShaderSource(
+ unsigned int arg_count, const gles2::GetShaderSource& c) {
+ GLuint shader;
+ if (!id_map_.GetServiceId(c.shader, &shader)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ GLsizei bufsize = static_cast<GLsizei>(c.bufsize);
+ GLsizei* length = GetSharedMemoryAs<GLsizei*>(
+ c.length_shm_id, c.length_shm_offset, 0 /* TODO(gman): size */);
+ char* source = GetSharedMemoryAs<char*>(
+ c.source_shm_id, c.source_shm_offset, 0 /* TODO(gman): size */);
+ parse_error::ParseError result =
+ ValidateGetShaderSource(
+ this, arg_count, shader, bufsize, length, source);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glGetShaderSource(shader, bufsize, length, source);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetString(
+ unsigned int arg_count, const gles2::GetString& c) {
+ GLenum name = static_cast<GLenum>(c.name);
+ parse_error::ParseError result =
+ ValidateGetString(this, arg_count, name);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glGetString(name);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetTexParameterfv(
+ unsigned int arg_count, const gles2::GetTexParameterfv& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ GLenum pname = static_cast<GLenum>(c.pname);
+ GLfloat* params;
+ GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+ uint32 params_size = num_values * sizeof(*params);
+ params = GetSharedMemoryAs<GLfloat*>(
+ c.params_shm_id, c.params_shm_offset, params_size);
+ parse_error::ParseError result =
+ ValidateGetTexParameterfv(this, arg_count, target, pname, params);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glGetTexParameterfv(target, pname, params);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetTexParameteriv(
+ unsigned int arg_count, const gles2::GetTexParameteriv& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ GLenum pname = static_cast<GLenum>(c.pname);
+ GLint* params;
+ GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+ uint32 params_size = num_values * sizeof(*params);
+ params = GetSharedMemoryAs<GLint*>(
+ c.params_shm_id, c.params_shm_offset, params_size);
+ parse_error::ParseError result =
+ ValidateGetTexParameteriv(this, arg_count, target, pname, params);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glGetTexParameteriv(target, pname, params);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetUniformLocation(
+ unsigned int arg_count, const gles2::GetUniformLocation& c) {
+ GLuint program;
+ if (!id_map_.GetServiceId(c.program, &program)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ uint32 name_size = c.data_size;
+ const char* name = GetSharedMemoryAs<const char*>(
+ c.name_shm_id, c.name_shm_offset, name_size);
+ parse_error::ParseError result =
+ ValidateGetUniformLocation(this, arg_count, program, name);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ String name_str(name, name_size);
+ GLint location = glGetUniformLocation(program, name_str.c_str());
+ DCHECK(false); // TODO: return result.
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetUniformLocationImmediate(
+ unsigned int arg_count, const gles2::GetUniformLocationImmediate& c) {
+ GLuint program;
+ if (!id_map_.GetServiceId(c.program, &program)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ uint32 name_size = c.data_size;
+ const char* name = GetImmediateDataAs<const char*>(c);
+ // TODO(gman): Make sure validate checks arg_count
+ // covers data_size.
+ parse_error::ParseError result =
+ ValidateGetUniformLocationImmediate(this, arg_count, program, name);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ String name_str(name, name_size);
+ GLint location = glGetUniformLocation(program, name_str.c_str());
+ DCHECK(false); // TODO: return result.
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetVertexAttribfv(
+ unsigned int arg_count, const gles2::GetVertexAttribfv& c) {
+ GLuint index = static_cast<GLuint>(c.index);
+ GLenum pname = static_cast<GLenum>(c.pname);
+ GLfloat* params;
+ GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+ uint32 params_size = num_values * sizeof(*params);
+ params = GetSharedMemoryAs<GLfloat*>(
+ c.params_shm_id, c.params_shm_offset, params_size);
+ parse_error::ParseError result =
+ ValidateGetVertexAttribfv(this, arg_count, index, pname, params);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glGetVertexAttribfv(index, pname, params);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleGetVertexAttribiv(
+ unsigned int arg_count, const gles2::GetVertexAttribiv& c) {
+ GLuint index = static_cast<GLuint>(c.index);
+ GLenum pname = static_cast<GLenum>(c.pname);
+ GLint* params;
+ GLsizei num_values = util_.GLGetNumValuesReturned(pname);
+ uint32 params_size = num_values * sizeof(*params);
+ params = GetSharedMemoryAs<GLint*>(
+ c.params_shm_id, c.params_shm_offset, params_size);
+ parse_error::ParseError result =
+ ValidateGetVertexAttribiv(this, arg_count, index, pname, params);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glGetVertexAttribiv(index, pname, params);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleHint(
+ unsigned int arg_count, const gles2::Hint& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ GLenum mode = static_cast<GLenum>(c.mode);
+ parse_error::ParseError result =
+ ValidateHint(this, arg_count, target, mode);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glHint(target, mode);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleIsBuffer(
+ unsigned int arg_count, const gles2::IsBuffer& c) {
+ GLuint buffer;
+ if (!id_map_.GetServiceId(c.buffer, &buffer)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ GLboolean* result_dst = GetSharedMemoryAs<GLboolean*>(
+ c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
+ parse_error::ParseError result =
+ ValidateIsBuffer(this, arg_count, buffer);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ *result_dst = glIsBuffer(buffer);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleIsEnabled(
+ unsigned int arg_count, const gles2::IsEnabled& c) {
+ GLenum cap = static_cast<GLenum>(c.cap);
+ GLboolean* result_dst = GetSharedMemoryAs<GLboolean*>(
+ c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
+ parse_error::ParseError result =
+ ValidateIsEnabled(this, arg_count, cap);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ *result_dst = glIsEnabled(cap);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleIsFramebuffer(
+ unsigned int arg_count, const gles2::IsFramebuffer& c) {
+ GLuint framebuffer;
+ if (!id_map_.GetServiceId(c.framebuffer, &framebuffer)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ GLboolean* result_dst = GetSharedMemoryAs<GLboolean*>(
+ c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
+ parse_error::ParseError result =
+ ValidateIsFramebuffer(this, arg_count, framebuffer);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ *result_dst = glIsFramebufferEXT(framebuffer);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleIsProgram(
+ unsigned int arg_count, const gles2::IsProgram& c) {
+ GLuint program;
+ if (!id_map_.GetServiceId(c.program, &program)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ GLboolean* result_dst = GetSharedMemoryAs<GLboolean*>(
+ c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
+ parse_error::ParseError result =
+ ValidateIsProgram(this, arg_count, program);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ *result_dst = glIsProgram(program);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleIsRenderbuffer(
+ unsigned int arg_count, const gles2::IsRenderbuffer& c) {
+ GLuint renderbuffer;
+ if (!id_map_.GetServiceId(c.renderbuffer, &renderbuffer)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ GLboolean* result_dst = GetSharedMemoryAs<GLboolean*>(
+ c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
+ parse_error::ParseError result =
+ ValidateIsRenderbuffer(this, arg_count, renderbuffer);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ *result_dst = glIsRenderbufferEXT(renderbuffer);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleIsShader(
+ unsigned int arg_count, const gles2::IsShader& c) {
+ GLuint shader;
+ if (!id_map_.GetServiceId(c.shader, &shader)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ GLboolean* result_dst = GetSharedMemoryAs<GLboolean*>(
+ c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
+ parse_error::ParseError result =
+ ValidateIsShader(this, arg_count, shader);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ *result_dst = glIsShader(shader);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleIsTexture(
+ unsigned int arg_count, const gles2::IsTexture& c) {
+ GLuint texture;
+ if (!id_map_.GetServiceId(c.texture, &texture)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ GLboolean* result_dst = GetSharedMemoryAs<GLboolean*>(
+ c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
+ parse_error::ParseError result =
+ ValidateIsTexture(this, arg_count, texture);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ *result_dst = glIsTexture(texture);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleLineWidth(
+ unsigned int arg_count, const gles2::LineWidth& c) {
+ GLfloat width = static_cast<GLfloat>(c.width);
+ parse_error::ParseError result =
+ ValidateLineWidth(this, arg_count, width);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glLineWidth(width);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleLinkProgram(
+ unsigned int arg_count, const gles2::LinkProgram& c) {
+ GLuint program;
+ if (!id_map_.GetServiceId(c.program, &program)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ parse_error::ParseError result =
+ ValidateLinkProgram(this, arg_count, program);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glLinkProgram(program);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandlePolygonOffset(
+ unsigned int arg_count, const gles2::PolygonOffset& c) {
+ GLfloat factor = static_cast<GLfloat>(c.factor);
+ GLfloat units = static_cast<GLfloat>(c.units);
+ parse_error::ParseError result =
+ ValidatePolygonOffset(this, arg_count, factor, units);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glPolygonOffset(factor, units);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleRenderbufferStorage(
+ unsigned int arg_count, const gles2::RenderbufferStorage& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ GLenum internalformat = static_cast<GLenum>(c.internalformat);
+ GLsizei width = static_cast<GLsizei>(c.width);
+ GLsizei height = static_cast<GLsizei>(c.height);
+ parse_error::ParseError result =
+ ValidateRenderbufferStorage(
+ this, arg_count, target, internalformat, width, height);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glRenderbufferStorageEXT(target, internalformat, width, height);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleSampleCoverage(
+ unsigned int arg_count, const gles2::SampleCoverage& c) {
+ GLclampf value = static_cast<GLclampf>(c.value);
+ GLboolean invert = static_cast<GLboolean>(c.invert);
+ parse_error::ParseError result =
+ ValidateSampleCoverage(this, arg_count, value, invert);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glSampleCoverage(value, invert);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleScissor(
+ unsigned int arg_count, const gles2::Scissor& c) {
+ 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);
+ parse_error::ParseError result =
+ ValidateScissor(this, arg_count, x, y, width, height);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glScissor(x, y, width, height);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleStencilFunc(
+ unsigned int arg_count, const gles2::StencilFunc& c) {
+ GLenum func = static_cast<GLenum>(c.func);
+ GLint ref = static_cast<GLint>(c.ref);
+ GLuint mask = static_cast<GLuint>(c.mask);
+ parse_error::ParseError result =
+ ValidateStencilFunc(this, arg_count, func, ref, mask);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glStencilFunc(func, ref, mask);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleStencilFuncSeparate(
+ unsigned int arg_count, const gles2::StencilFuncSeparate& c) {
+ GLenum face = static_cast<GLenum>(c.face);
+ GLenum func = static_cast<GLenum>(c.func);
+ GLint ref = static_cast<GLint>(c.ref);
+ GLuint mask = static_cast<GLuint>(c.mask);
+ parse_error::ParseError result =
+ ValidateStencilFuncSeparate(this, arg_count, face, func, ref, mask);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glStencilFuncSeparate(face, func, ref, mask);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleStencilMask(
+ unsigned int arg_count, const gles2::StencilMask& c) {
+ GLuint mask = static_cast<GLuint>(c.mask);
+ parse_error::ParseError result =
+ ValidateStencilMask(this, arg_count, mask);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glStencilMask(mask);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleStencilMaskSeparate(
+ unsigned int arg_count, const gles2::StencilMaskSeparate& c) {
+ GLenum face = static_cast<GLenum>(c.face);
+ GLuint mask = static_cast<GLuint>(c.mask);
+ parse_error::ParseError result =
+ ValidateStencilMaskSeparate(this, arg_count, face, mask);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glStencilMaskSeparate(face, mask);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleStencilOp(
+ unsigned int arg_count, const gles2::StencilOp& c) {
+ GLenum fail = static_cast<GLenum>(c.fail);
+ GLenum zfail = static_cast<GLenum>(c.zfail);
+ GLenum zpass = static_cast<GLenum>(c.zpass);
+ parse_error::ParseError result =
+ ValidateStencilOp(this, arg_count, fail, zfail, zpass);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glStencilOp(fail, zfail, zpass);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleStencilOpSeparate(
+ unsigned int arg_count, const gles2::StencilOpSeparate& c) {
+ GLenum face = static_cast<GLenum>(c.face);
+ GLenum fail = static_cast<GLenum>(c.fail);
+ GLenum zfail = static_cast<GLenum>(c.zfail);
+ GLenum zpass = static_cast<GLenum>(c.zpass);
+ parse_error::ParseError result =
+ ValidateStencilOpSeparate(this, arg_count, face, fail, zfail, zpass);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glStencilOpSeparate(face, fail, zfail, zpass);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleTexImage2D(
+ unsigned int arg_count, const gles2::TexImage2D& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ GLint level = static_cast<GLint>(c.level);
+ GLint internalformat = static_cast<GLint>(c.internalformat);
+ GLsizei width = static_cast<GLsizei>(c.width);
+ GLsizei height = static_cast<GLsizei>(c.height);
+ GLint border = static_cast<GLint>(c.border);
+ GLenum format = static_cast<GLenum>(c.format);
+ GLenum type = static_cast<GLenum>(c.type);
+ uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
+ uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
+ uint32 pixels_size = GLES2Util::ComputeImageDataSize(
+ width, height, format, type, unpack_alignment_);
+ const void* pixels = GetSharedMemoryAs<const void*>(
+ pixels_shm_id, pixels_shm_offset, pixels_size);
+ parse_error::ParseError result =
+ ValidateTexImage2D(
+ this, arg_count, target, level, internalformat, width, height, border,
+ format, type, pixels);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glTexImage2D(
+ target, level, internalformat, width, height, border, format, type,
+ pixels);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleTexImage2DImmediate(
+ unsigned int arg_count, const gles2::TexImage2DImmediate& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ GLint level = static_cast<GLint>(c.level);
+ GLint internalformat = static_cast<GLint>(c.internalformat);
+ GLsizei width = static_cast<GLsizei>(c.width);
+ GLsizei height = static_cast<GLsizei>(c.height);
+ GLint border = static_cast<GLint>(c.border);
+ GLenum format = static_cast<GLenum>(c.format);
+ GLenum type = static_cast<GLenum>(c.type);
+ const void* pixels = GetImmediateDataAs<const void*>(c);
+ // Immediate version.
+ parse_error::ParseError result =
+ ValidateTexImage2DImmediate(
+ this, arg_count, target, level, internalformat, width, height, border,
+ format, type, pixels);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glTexImage2D(
+ target, level, internalformat, width, height, border, format, type,
+ pixels);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleTexParameterf(
+ unsigned int arg_count, const gles2::TexParameterf& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ GLenum pname = static_cast<GLenum>(c.pname);
+ GLfloat param = static_cast<GLfloat>(c.param);
+ parse_error::ParseError result =
+ ValidateTexParameterf(this, arg_count, target, pname, param);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glTexParameterf(target, pname, param);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleTexParameterfv(
+ unsigned int arg_count, const gles2::TexParameterfv& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ GLenum pname = static_cast<GLenum>(c.pname);
+ const GLfloat* params = GetSharedMemoryAs<const GLfloat*>(
+ c.params_shm_id, c.params_shm_offset, 0 /* TODO(gman): size */);
+ parse_error::ParseError result =
+ ValidateTexParameterfv(this, arg_count, target, pname, params);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glTexParameterfv(target, pname, params);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleTexParameterfvImmediate(
+ unsigned int arg_count, const gles2::TexParameterfvImmediate& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ GLenum pname = static_cast<GLenum>(c.pname);
+ const GLfloat* params = GetImmediateDataAs<const GLfloat*>(c);
+ // Immediate version.
+ parse_error::ParseError result =
+ ValidateTexParameterfvImmediate(this, arg_count, target, pname, params);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glTexParameterfv(target, pname, params);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleTexParameteri(
+ unsigned int arg_count, const gles2::TexParameteri& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ GLenum pname = static_cast<GLenum>(c.pname);
+ GLint param = static_cast<GLint>(c.param);
+ parse_error::ParseError result =
+ ValidateTexParameteri(this, arg_count, target, pname, param);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glTexParameteri(target, pname, param);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleTexParameteriv(
+ unsigned int arg_count, const gles2::TexParameteriv& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ GLenum pname = static_cast<GLenum>(c.pname);
+ const GLint* params = GetSharedMemoryAs<const GLint*>(
+ c.params_shm_id, c.params_shm_offset, 0 /* TODO(gman): size */);
+ parse_error::ParseError result =
+ ValidateTexParameteriv(this, arg_count, target, pname, params);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glTexParameteriv(target, pname, params);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleTexParameterivImmediate(
+ unsigned int arg_count, const gles2::TexParameterivImmediate& c) {
+ GLenum target = static_cast<GLenum>(c.target);
+ GLenum pname = static_cast<GLenum>(c.pname);
+ const GLint* params = GetImmediateDataAs<const GLint*>(c);
+ // Immediate version.
+ parse_error::ParseError result =
+ ValidateTexParameterivImmediate(this, arg_count, target, pname, params);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glTexParameteriv(target, pname, params);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleTexSubImage2D(
+ unsigned int arg_count, const gles2::TexSubImage2D& c) {
+ 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);
+ GLsizei width = static_cast<GLsizei>(c.width);
+ GLsizei height = static_cast<GLsizei>(c.height);
+ GLenum format = static_cast<GLenum>(c.format);
+ GLenum type = static_cast<GLenum>(c.type);
+ uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
+ uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
+ uint32 pixels_size = GLES2Util::ComputeImageDataSize(
+ width, height, format, type, unpack_alignment_);
+ const void* pixels = GetSharedMemoryAs<const void*>(
+ pixels_shm_id, pixels_shm_offset, pixels_size);
+ parse_error::ParseError result =
+ ValidateTexSubImage2D(
+ this, arg_count, target, level, xoffset, yoffset, width, height,
+ format, type, pixels);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glTexSubImage2D(
+ target, level, xoffset, yoffset, width, height, format, type, pixels);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleTexSubImage2DImmediate(
+ unsigned int arg_count, const gles2::TexSubImage2DImmediate& c) {
+ 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);
+ GLsizei width = static_cast<GLsizei>(c.width);
+ GLsizei height = static_cast<GLsizei>(c.height);
+ GLenum format = static_cast<GLenum>(c.format);
+ GLenum type = static_cast<GLenum>(c.type);
+ const void* pixels = GetImmediateDataAs<const void*>(c);
+ // Immediate version.
+ parse_error::ParseError result =
+ ValidateTexSubImage2DImmediate(
+ this, arg_count, target, level, xoffset, yoffset, width, height,
+ format, type, pixels);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glTexSubImage2D(
+ target, level, xoffset, yoffset, width, height, format, type, pixels);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform1f(
+ unsigned int arg_count, const gles2::Uniform1f& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLfloat x = static_cast<GLfloat>(c.x);
+ parse_error::ParseError result =
+ ValidateUniform1f(this, arg_count, location, x);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniform1f(location, x);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform1fv(
+ unsigned int arg_count, const gles2::Uniform1fv& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLsizei count = static_cast<GLsizei>(c.count);
+ const GLfloat* v = GetSharedMemoryAs<const GLfloat*>(
+ c.v_shm_id, c.v_shm_offset, 0 /* TODO(gman): size */);
+ parse_error::ParseError result =
+ ValidateUniform1fv(this, arg_count, location, count, v);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniform1fv(location, count, v);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform1fvImmediate(
+ unsigned int arg_count, const gles2::Uniform1fvImmediate& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLsizei count = static_cast<GLsizei>(c.count);
+ const GLfloat* v = GetImmediateDataAs<const GLfloat*>(c);
+ // Immediate version.
+ parse_error::ParseError result =
+ ValidateUniform1fvImmediate(this, arg_count, location, count, v);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniform1fv(location, count, v);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform1i(
+ unsigned int arg_count, const gles2::Uniform1i& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLint x = static_cast<GLint>(c.x);
+ parse_error::ParseError result =
+ ValidateUniform1i(this, arg_count, location, x);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniform1i(location, x);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform1iv(
+ unsigned int arg_count, const gles2::Uniform1iv& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLsizei count = static_cast<GLsizei>(c.count);
+ const GLint* v = GetSharedMemoryAs<const GLint*>(
+ c.v_shm_id, c.v_shm_offset, 0 /* TODO(gman): size */);
+ parse_error::ParseError result =
+ ValidateUniform1iv(this, arg_count, location, count, v);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniform1iv(location, count, v);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform1ivImmediate(
+ unsigned int arg_count, const gles2::Uniform1ivImmediate& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLsizei count = static_cast<GLsizei>(c.count);
+ const GLint* v = GetImmediateDataAs<const GLint*>(c);
+ // Immediate version.
+ parse_error::ParseError result =
+ ValidateUniform1ivImmediate(this, arg_count, location, count, v);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniform1iv(location, count, v);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform2f(
+ unsigned int arg_count, const gles2::Uniform2f& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLfloat x = static_cast<GLfloat>(c.x);
+ GLfloat y = static_cast<GLfloat>(c.y);
+ parse_error::ParseError result =
+ ValidateUniform2f(this, arg_count, location, x, y);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniform2f(location, x, y);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform2fv(
+ unsigned int arg_count, const gles2::Uniform2fv& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLsizei count = static_cast<GLsizei>(c.count);
+ const GLfloat* v = GetSharedMemoryAs<const GLfloat*>(
+ c.v_shm_id, c.v_shm_offset, 0 /* TODO(gman): size */);
+ parse_error::ParseError result =
+ ValidateUniform2fv(this, arg_count, location, count, v);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniform2fv(location, count, v);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform2fvImmediate(
+ unsigned int arg_count, const gles2::Uniform2fvImmediate& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLsizei count = static_cast<GLsizei>(c.count);
+ const GLfloat* v = GetImmediateDataAs<const GLfloat*>(c);
+ // Immediate version.
+ parse_error::ParseError result =
+ ValidateUniform2fvImmediate(this, arg_count, location, count, v);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniform2fv(location, count, v);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform2i(
+ unsigned int arg_count, const gles2::Uniform2i& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLint x = static_cast<GLint>(c.x);
+ GLint y = static_cast<GLint>(c.y);
+ parse_error::ParseError result =
+ ValidateUniform2i(this, arg_count, location, x, y);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniform2i(location, x, y);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform2iv(
+ unsigned int arg_count, const gles2::Uniform2iv& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLsizei count = static_cast<GLsizei>(c.count);
+ const GLint* v = GetSharedMemoryAs<const GLint*>(
+ c.v_shm_id, c.v_shm_offset, 0 /* TODO(gman): size */);
+ parse_error::ParseError result =
+ ValidateUniform2iv(this, arg_count, location, count, v);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniform2iv(location, count, v);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform2ivImmediate(
+ unsigned int arg_count, const gles2::Uniform2ivImmediate& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLsizei count = static_cast<GLsizei>(c.count);
+ const GLint* v = GetImmediateDataAs<const GLint*>(c);
+ // Immediate version.
+ parse_error::ParseError result =
+ ValidateUniform2ivImmediate(this, arg_count, location, count, v);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniform2iv(location, count, v);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform3f(
+ unsigned int arg_count, const gles2::Uniform3f& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLfloat x = static_cast<GLfloat>(c.x);
+ GLfloat y = static_cast<GLfloat>(c.y);
+ GLfloat z = static_cast<GLfloat>(c.z);
+ parse_error::ParseError result =
+ ValidateUniform3f(this, arg_count, location, x, y, z);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniform3f(location, x, y, z);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform3fv(
+ unsigned int arg_count, const gles2::Uniform3fv& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLsizei count = static_cast<GLsizei>(c.count);
+ const GLfloat* v = GetSharedMemoryAs<const GLfloat*>(
+ c.v_shm_id, c.v_shm_offset, 0 /* TODO(gman): size */);
+ parse_error::ParseError result =
+ ValidateUniform3fv(this, arg_count, location, count, v);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniform3fv(location, count, v);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform3fvImmediate(
+ unsigned int arg_count, const gles2::Uniform3fvImmediate& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLsizei count = static_cast<GLsizei>(c.count);
+ const GLfloat* v = GetImmediateDataAs<const GLfloat*>(c);
+ // Immediate version.
+ parse_error::ParseError result =
+ ValidateUniform3fvImmediate(this, arg_count, location, count, v);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniform3fv(location, count, v);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform3i(
+ unsigned int arg_count, const gles2::Uniform3i& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLint x = static_cast<GLint>(c.x);
+ GLint y = static_cast<GLint>(c.y);
+ GLint z = static_cast<GLint>(c.z);
+ parse_error::ParseError result =
+ ValidateUniform3i(this, arg_count, location, x, y, z);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniform3i(location, x, y, z);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform3iv(
+ unsigned int arg_count, const gles2::Uniform3iv& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLsizei count = static_cast<GLsizei>(c.count);
+ const GLint* v = GetSharedMemoryAs<const GLint*>(
+ c.v_shm_id, c.v_shm_offset, 0 /* TODO(gman): size */);
+ parse_error::ParseError result =
+ ValidateUniform3iv(this, arg_count, location, count, v);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniform3iv(location, count, v);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform3ivImmediate(
+ unsigned int arg_count, const gles2::Uniform3ivImmediate& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLsizei count = static_cast<GLsizei>(c.count);
+ const GLint* v = GetImmediateDataAs<const GLint*>(c);
+ // Immediate version.
+ parse_error::ParseError result =
+ ValidateUniform3ivImmediate(this, arg_count, location, count, v);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniform3iv(location, count, v);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform4f(
+ unsigned int arg_count, const gles2::Uniform4f& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLfloat x = static_cast<GLfloat>(c.x);
+ GLfloat y = static_cast<GLfloat>(c.y);
+ GLfloat z = static_cast<GLfloat>(c.z);
+ GLfloat w = static_cast<GLfloat>(c.w);
+ parse_error::ParseError result =
+ ValidateUniform4f(this, arg_count, location, x, y, z, w);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniform4f(location, x, y, z, w);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform4fv(
+ unsigned int arg_count, const gles2::Uniform4fv& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLsizei count = static_cast<GLsizei>(c.count);
+ const GLfloat* v = GetSharedMemoryAs<const GLfloat*>(
+ c.v_shm_id, c.v_shm_offset, 0 /* TODO(gman): size */);
+ parse_error::ParseError result =
+ ValidateUniform4fv(this, arg_count, location, count, v);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniform4fv(location, count, v);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform4fvImmediate(
+ unsigned int arg_count, const gles2::Uniform4fvImmediate& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLsizei count = static_cast<GLsizei>(c.count);
+ const GLfloat* v = GetImmediateDataAs<const GLfloat*>(c);
+ // Immediate version.
+ parse_error::ParseError result =
+ ValidateUniform4fvImmediate(this, arg_count, location, count, v);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniform4fv(location, count, v);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform4i(
+ unsigned int arg_count, const gles2::Uniform4i& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLint x = static_cast<GLint>(c.x);
+ GLint y = static_cast<GLint>(c.y);
+ GLint z = static_cast<GLint>(c.z);
+ GLint w = static_cast<GLint>(c.w);
+ parse_error::ParseError result =
+ ValidateUniform4i(this, arg_count, location, x, y, z, w);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniform4i(location, x, y, z, w);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform4iv(
+ unsigned int arg_count, const gles2::Uniform4iv& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLsizei count = static_cast<GLsizei>(c.count);
+ const GLint* v = GetSharedMemoryAs<const GLint*>(
+ c.v_shm_id, c.v_shm_offset, 0 /* TODO(gman): size */);
+ parse_error::ParseError result =
+ ValidateUniform4iv(this, arg_count, location, count, v);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniform4iv(location, count, v);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniform4ivImmediate(
+ unsigned int arg_count, const gles2::Uniform4ivImmediate& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLsizei count = static_cast<GLsizei>(c.count);
+ const GLint* v = GetImmediateDataAs<const GLint*>(c);
+ // Immediate version.
+ parse_error::ParseError result =
+ ValidateUniform4ivImmediate(this, arg_count, location, count, v);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniform4iv(location, count, v);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniformMatrix2fv(
+ unsigned int arg_count, const gles2::UniformMatrix2fv& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLsizei count = static_cast<GLsizei>(c.count);
+ GLboolean transpose = static_cast<GLboolean>(c.transpose);
+ const GLfloat* value = GetSharedMemoryAs<const GLfloat*>(
+ c.value_shm_id, c.value_shm_offset, 0 /* TODO(gman): size */);
+ parse_error::ParseError result =
+ ValidateUniformMatrix2fv(
+ this, arg_count, location, count, transpose, value);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniformMatrix2fv(location, count, transpose, value);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniformMatrix2fvImmediate(
+ unsigned int arg_count, const gles2::UniformMatrix2fvImmediate& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLsizei count = static_cast<GLsizei>(c.count);
+ GLboolean transpose = static_cast<GLboolean>(c.transpose);
+ const GLfloat* value = GetImmediateDataAs<const GLfloat*>(c);
+ // Immediate version.
+ parse_error::ParseError result =
+ ValidateUniformMatrix2fvImmediate(
+ this, arg_count, location, count, transpose, value);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniformMatrix2fv(location, count, transpose, value);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniformMatrix3fv(
+ unsigned int arg_count, const gles2::UniformMatrix3fv& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLsizei count = static_cast<GLsizei>(c.count);
+ GLboolean transpose = static_cast<GLboolean>(c.transpose);
+ const GLfloat* value = GetSharedMemoryAs<const GLfloat*>(
+ c.value_shm_id, c.value_shm_offset, 0 /* TODO(gman): size */);
+ parse_error::ParseError result =
+ ValidateUniformMatrix3fv(
+ this, arg_count, location, count, transpose, value);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniformMatrix3fv(location, count, transpose, value);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniformMatrix3fvImmediate(
+ unsigned int arg_count, const gles2::UniformMatrix3fvImmediate& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLsizei count = static_cast<GLsizei>(c.count);
+ GLboolean transpose = static_cast<GLboolean>(c.transpose);
+ const GLfloat* value = GetImmediateDataAs<const GLfloat*>(c);
+ // Immediate version.
+ parse_error::ParseError result =
+ ValidateUniformMatrix3fvImmediate(
+ this, arg_count, location, count, transpose, value);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniformMatrix3fv(location, count, transpose, value);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniformMatrix4fv(
+ unsigned int arg_count, const gles2::UniformMatrix4fv& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLsizei count = static_cast<GLsizei>(c.count);
+ GLboolean transpose = static_cast<GLboolean>(c.transpose);
+ const GLfloat* value = GetSharedMemoryAs<const GLfloat*>(
+ c.value_shm_id, c.value_shm_offset, 0 /* TODO(gman): size */);
+ parse_error::ParseError result =
+ ValidateUniformMatrix4fv(
+ this, arg_count, location, count, transpose, value);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniformMatrix4fv(location, count, transpose, value);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUniformMatrix4fvImmediate(
+ unsigned int arg_count, const gles2::UniformMatrix4fvImmediate& c) {
+ GLint location = static_cast<GLint>(c.location);
+ GLsizei count = static_cast<GLsizei>(c.count);
+ GLboolean transpose = static_cast<GLboolean>(c.transpose);
+ const GLfloat* value = GetImmediateDataAs<const GLfloat*>(c);
+ // Immediate version.
+ parse_error::ParseError result =
+ ValidateUniformMatrix4fvImmediate(
+ this, arg_count, location, count, transpose, value);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUniformMatrix4fv(location, count, transpose, value);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleUseProgram(
+ unsigned int arg_count, const gles2::UseProgram& c) {
+ GLuint program;
+ if (!id_map_.GetServiceId(c.program, &program)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ parse_error::ParseError result =
+ ValidateUseProgram(this, arg_count, program);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glUseProgram(program);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleValidateProgram(
+ unsigned int arg_count, const gles2::ValidateProgram& c) {
+ GLuint program;
+ if (!id_map_.GetServiceId(c.program, &program)) {
+ SetGLError(GL_INVALID_VALUE);
+ return parse_error::kParseNoError;
+ }
+ parse_error::ParseError result =
+ ValidateValidateProgram(this, arg_count, program);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glValidateProgram(program);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib1f(
+ unsigned int arg_count, const gles2::VertexAttrib1f& c) {
+ GLuint indx = static_cast<GLuint>(c.indx);
+ GLfloat x = static_cast<GLfloat>(c.x);
+ parse_error::ParseError result =
+ ValidateVertexAttrib1f(this, arg_count, indx, x);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glVertexAttrib1f(indx, x);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib1fv(
+ unsigned int arg_count, const gles2::VertexAttrib1fv& c) {
+ GLuint indx = static_cast<GLuint>(c.indx);
+ const GLfloat* values = GetSharedMemoryAs<const GLfloat*>(
+ c.values_shm_id, c.values_shm_offset, 0 /* TODO(gman): size */);
+ parse_error::ParseError result =
+ ValidateVertexAttrib1fv(this, arg_count, indx, values);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glVertexAttrib1fv(indx, values);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib1fvImmediate(
+ unsigned int arg_count, const gles2::VertexAttrib1fvImmediate& c) {
+ GLuint indx = static_cast<GLuint>(c.indx);
+ const GLfloat* values = GetImmediateDataAs<const GLfloat*>(c);
+ // Immediate version.
+ parse_error::ParseError result =
+ ValidateVertexAttrib1fvImmediate(this, arg_count, indx, values);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glVertexAttrib1fv(indx, values);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib2f(
+ unsigned int arg_count, const gles2::VertexAttrib2f& c) {
+ GLuint indx = static_cast<GLuint>(c.indx);
+ GLfloat x = static_cast<GLfloat>(c.x);
+ GLfloat y = static_cast<GLfloat>(c.y);
+ parse_error::ParseError result =
+ ValidateVertexAttrib2f(this, arg_count, indx, x, y);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glVertexAttrib2f(indx, x, y);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib2fv(
+ unsigned int arg_count, const gles2::VertexAttrib2fv& c) {
+ GLuint indx = static_cast<GLuint>(c.indx);
+ const GLfloat* values = GetSharedMemoryAs<const GLfloat*>(
+ c.values_shm_id, c.values_shm_offset, 0 /* TODO(gman): size */);
+ parse_error::ParseError result =
+ ValidateVertexAttrib2fv(this, arg_count, indx, values);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glVertexAttrib2fv(indx, values);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib2fvImmediate(
+ unsigned int arg_count, const gles2::VertexAttrib2fvImmediate& c) {
+ GLuint indx = static_cast<GLuint>(c.indx);
+ const GLfloat* values = GetImmediateDataAs<const GLfloat*>(c);
+ // Immediate version.
+ parse_error::ParseError result =
+ ValidateVertexAttrib2fvImmediate(this, arg_count, indx, values);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glVertexAttrib2fv(indx, values);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib3f(
+ unsigned int arg_count, const gles2::VertexAttrib3f& c) {
+ GLuint indx = static_cast<GLuint>(c.indx);
+ GLfloat x = static_cast<GLfloat>(c.x);
+ GLfloat y = static_cast<GLfloat>(c.y);
+ GLfloat z = static_cast<GLfloat>(c.z);
+ parse_error::ParseError result =
+ ValidateVertexAttrib3f(this, arg_count, indx, x, y, z);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glVertexAttrib3f(indx, x, y, z);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib3fv(
+ unsigned int arg_count, const gles2::VertexAttrib3fv& c) {
+ GLuint indx = static_cast<GLuint>(c.indx);
+ const GLfloat* values = GetSharedMemoryAs<const GLfloat*>(
+ c.values_shm_id, c.values_shm_offset, 0 /* TODO(gman): size */);
+ parse_error::ParseError result =
+ ValidateVertexAttrib3fv(this, arg_count, indx, values);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glVertexAttrib3fv(indx, values);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib3fvImmediate(
+ unsigned int arg_count, const gles2::VertexAttrib3fvImmediate& c) {
+ GLuint indx = static_cast<GLuint>(c.indx);
+ const GLfloat* values = GetImmediateDataAs<const GLfloat*>(c);
+ // Immediate version.
+ parse_error::ParseError result =
+ ValidateVertexAttrib3fvImmediate(this, arg_count, indx, values);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glVertexAttrib3fv(indx, values);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib4f(
+ unsigned int arg_count, const gles2::VertexAttrib4f& c) {
+ GLuint indx = static_cast<GLuint>(c.indx);
+ GLfloat x = static_cast<GLfloat>(c.x);
+ GLfloat y = static_cast<GLfloat>(c.y);
+ GLfloat z = static_cast<GLfloat>(c.z);
+ GLfloat w = static_cast<GLfloat>(c.w);
+ parse_error::ParseError result =
+ ValidateVertexAttrib4f(this, arg_count, indx, x, y, z, w);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glVertexAttrib4f(indx, x, y, z, w);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib4fv(
+ unsigned int arg_count, const gles2::VertexAttrib4fv& c) {
+ GLuint indx = static_cast<GLuint>(c.indx);
+ const GLfloat* values = GetSharedMemoryAs<const GLfloat*>(
+ c.values_shm_id, c.values_shm_offset, 0 /* TODO(gman): size */);
+ parse_error::ParseError result =
+ ValidateVertexAttrib4fv(this, arg_count, indx, values);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glVertexAttrib4fv(indx, values);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib4fvImmediate(
+ unsigned int arg_count, const gles2::VertexAttrib4fvImmediate& c) {
+ GLuint indx = static_cast<GLuint>(c.indx);
+ const GLfloat* values = GetImmediateDataAs<const GLfloat*>(c);
+ // Immediate version.
+ parse_error::ParseError result =
+ ValidateVertexAttrib4fvImmediate(this, arg_count, indx, values);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glVertexAttrib4fv(indx, values);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleViewport(
+ unsigned int arg_count, const gles2::Viewport& c) {
+ 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);
+ parse_error::ParseError result =
+ ValidateViewport(this, arg_count, x, y, width, height);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ glViewport(x, y, width, height);
+ return parse_error::kParseNoError;
+}
+
+parse_error::ParseError GLES2DecoderImpl::HandleSwapBuffers(
+ unsigned int arg_count, const gles2::SwapBuffers& c) {
+ parse_error::ParseError result =
+ ValidateSwapBuffers(this, arg_count);
+ if (result != parse_error::kParseNoError) {
+ return result;
+ }
+ DoSwapBuffers();
+ return parse_error::kParseNoError;
+}
+
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_validate.h b/gpu/command_buffer/service/gles2_cmd_decoder_validate.h
new file mode 100644
index 0000000..616d3fc
--- /dev/null
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_validate.h
@@ -0,0 +1,1255 @@
+
+// Copyright (c) 2006-2008 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.
+
+
+namespace command_buffer {
+namespace gles2 {
+
+namespace {
+
+parse_error::ParseError ValidateActiveTexture(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum texture) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateAttachShader(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint program,
+ GLuint shader) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBindAttribLocation(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint program, GLuint index,
+ const char* name) {
+ if (name == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBindAttribLocationImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint program, GLuint index,
+ const char* name) {
+ if (name == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBindBuffer(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target,
+ GLuint buffer) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBindFramebuffer(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target,
+ GLuint framebuffer) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBindRenderbuffer(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target,
+ GLuint renderbuffer) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBindTexture(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target,
+ GLuint texture) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBlendColor(
+ GLES2Decoder* decoder, unsigned int arg_count, GLclampf red, GLclampf green,
+ GLclampf blue, GLclampf alpha) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBlendEquation(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum mode) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBlendEquationSeparate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum modeRGB,
+ GLenum modeAlpha) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBlendFunc(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum sfactor,
+ GLenum dfactor) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBlendFuncSeparate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum srcRGB, GLenum dstRGB,
+ GLenum srcAlpha, GLenum dstAlpha) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBufferData(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target,
+ GLsizeiptr size, const void* data, GLenum usage) {
+ if (data == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBufferDataImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target,
+ GLsizeiptr size, const void* data, GLenum usage) {
+ if (data == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBufferSubData(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target,
+ GLintptr offset, GLsizeiptr size, const void* data) {
+ if (data == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateBufferSubDataImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target,
+ GLintptr offset, GLsizeiptr size, const void* data) {
+ if (data == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateCheckFramebufferStatus(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateClear(
+ GLES2Decoder* decoder, unsigned int arg_count, GLbitfield mask) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateClearColor(
+ GLES2Decoder* decoder, unsigned int arg_count, GLclampf red, GLclampf green,
+ GLclampf blue, GLclampf alpha) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateClearDepthf(
+ GLES2Decoder* decoder, unsigned int arg_count, GLclampf depth) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateClearStencil(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint s) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateColorMask(
+ GLES2Decoder* decoder, unsigned int arg_count, GLboolean red,
+ GLboolean green, GLboolean blue, GLboolean alpha) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateCompileShader(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint shader) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateCompressedTexImage2D(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLint level,
+ GLenum internalformat, GLsizei width, GLsizei height, GLint border,
+ GLsizei imageSize, const void* data) {
+ if (data == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateCompressedTexImage2DImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLint level,
+ GLenum internalformat, GLsizei width, GLsizei height, GLint border,
+ GLsizei imageSize, const void* data) {
+ if (data == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateCompressedTexSubImage2D(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
+ GLsizei imageSize, const void* data) {
+ if (data == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateCompressedTexSubImage2DImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
+ GLsizei imageSize, const void* data) {
+ if (data == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateCopyTexImage2D(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLint level,
+ GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height,
+ GLint border) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateCopyTexSubImage2D(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width,
+ GLsizei height) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateCreateProgram(
+ GLES2Decoder* decoder, unsigned int arg_count) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateCreateShader(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum type) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateCullFace(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum mode) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDeleteBuffers(
+ GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+ const GLuint* buffers) {
+ if (buffers == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDeleteBuffersImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+ const GLuint* buffers) {
+ if (buffers == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDeleteFramebuffers(
+ GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+ const GLuint* framebuffers) {
+ if (framebuffers == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDeleteFramebuffersImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+ const GLuint* framebuffers) {
+ if (framebuffers == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDeleteProgram(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint program) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDeleteRenderbuffers(
+ GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+ const GLuint* renderbuffers) {
+ if (renderbuffers == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDeleteRenderbuffersImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+ const GLuint* renderbuffers) {
+ if (renderbuffers == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDeleteShader(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint shader) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDeleteTextures(
+ GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+ const GLuint* textures) {
+ if (textures == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDeleteTexturesImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+ const GLuint* textures) {
+ if (textures == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDepthFunc(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum func) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDepthMask(
+ GLES2Decoder* decoder, unsigned int arg_count, GLboolean flag) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDepthRangef(
+ GLES2Decoder* decoder, unsigned int arg_count, GLclampf zNear,
+ GLclampf zFar) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDetachShader(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint program,
+ GLuint shader) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDisable(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum cap) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDisableVertexAttribArray(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint index) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDrawArrays(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum mode, GLint first,
+ GLsizei count) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateDrawElements(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum mode, GLsizei count,
+ GLenum type, const void* indices) {
+ if (indices == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateEnable(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum cap) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateEnableVertexAttribArray(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint index) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateFinish(
+ GLES2Decoder* decoder, unsigned int arg_count) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateFlush(
+ GLES2Decoder* decoder, unsigned int arg_count) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateFramebufferRenderbuffer(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target,
+ GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateFramebufferTexture2D(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target,
+ GLenum attachment, GLenum textarget, GLuint texture, GLint level) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateFrontFace(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum mode) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGenBuffers(
+ GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+ GLuint* buffers) {
+ if (buffers == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGenBuffersImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+ GLuint* buffers) {
+ if (buffers == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGenerateMipmap(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGenFramebuffers(
+ GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+ GLuint* framebuffers) {
+ if (framebuffers == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGenFramebuffersImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+ GLuint* framebuffers) {
+ if (framebuffers == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGenRenderbuffers(
+ GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+ GLuint* renderbuffers) {
+ if (renderbuffers == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGenRenderbuffersImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+ GLuint* renderbuffers) {
+ if (renderbuffers == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGenTextures(
+ GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+ GLuint* textures) {
+ if (textures == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGenTexturesImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLsizei n,
+ GLuint* textures) {
+ if (textures == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetActiveAttrib(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint program, GLuint index,
+ GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) {
+ if (length == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (size == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (type == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (name == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetActiveUniform(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint program, GLuint index,
+ GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) {
+ if (length == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (size == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (type == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (name == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetAttachedShaders(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint program,
+ GLsizei maxcount, GLsizei* count, GLuint* shaders) {
+ if (count == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (shaders == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetAttribLocation(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint program,
+ const char* name) {
+ if (name == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetAttribLocationImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint program,
+ const char* name) {
+ if (name == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetBooleanv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum pname,
+ GLboolean* params) {
+ if (params == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetBufferParameteriv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLenum pname,
+ GLint* params) {
+ if (params == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetError(
+ GLES2Decoder* decoder, unsigned int arg_count) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetFloatv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum pname,
+ GLfloat* params) {
+ if (params == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetFramebufferAttachmentParameteriv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target,
+ GLenum attachment, GLenum pname, GLint* params) {
+ if (params == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetIntegerv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum pname,
+ GLint* params) {
+ if (params == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetProgramiv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint program, GLenum pname,
+ GLint* params) {
+ if (params == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetProgramInfoLog(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint program,
+ GLsizei bufsize, GLsizei* length, char* infolog) {
+ if (length == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (infolog == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetRenderbufferParameteriv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLenum pname,
+ GLint* params) {
+ if (params == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetShaderiv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint shader, GLenum pname,
+ GLint* params) {
+ if (params == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetShaderInfoLog(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint shader,
+ GLsizei bufsize, GLsizei* length, char* infolog) {
+ if (length == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (infolog == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetShaderPrecisionFormat(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum shadertype,
+ GLenum precisiontype, GLint* range, GLint* precision) {
+ if (range == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (precision == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetShaderSource(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint shader,
+ GLsizei bufsize, GLsizei* length, char* source) {
+ if (length == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (source == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetString(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum name) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetTexParameterfv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLenum pname,
+ GLfloat* params) {
+ if (params == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetTexParameteriv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLenum pname,
+ GLint* params) {
+ if (params == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetUniformfv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint program,
+ GLint location, GLfloat* params) {
+ if (params == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetUniformiv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint program,
+ GLint location, GLint* params) {
+ if (params == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetUniformLocation(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint program,
+ const char* name) {
+ if (name == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetUniformLocationImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint program,
+ const char* name) {
+ if (name == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetVertexAttribfv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint index, GLenum pname,
+ GLfloat* params) {
+ if (params == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetVertexAttribiv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint index, GLenum pname,
+ GLint* params) {
+ if (params == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateGetVertexAttribPointerv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint index, GLenum pname,
+ void** pointer) {
+ if (pointer == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateHint(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target,
+ GLenum mode) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateIsBuffer(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint buffer) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateIsEnabled(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum cap) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateIsFramebuffer(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint framebuffer) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateIsProgram(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint program) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateIsRenderbuffer(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint renderbuffer) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateIsShader(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint shader) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateIsTexture(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint texture) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateLineWidth(
+ GLES2Decoder* decoder, unsigned int arg_count, GLfloat width) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateLinkProgram(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint program) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidatePixelStorei(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum pname, GLint param) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidatePolygonOffset(
+ GLES2Decoder* decoder, unsigned int arg_count, GLfloat factor,
+ GLfloat units) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateReadPixels(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint x, GLint y,
+ GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) {
+ if (pixels == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateRenderbufferStorage(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target,
+ GLenum internalformat, GLsizei width, GLsizei height) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateSampleCoverage(
+ GLES2Decoder* decoder, unsigned int arg_count, GLclampf value,
+ GLboolean invert) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateScissor(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint x, GLint y,
+ GLsizei width, GLsizei height) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateShaderSource(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint shader, GLsizei count,
+ const char** string, const GLint* length) {
+ if (string == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (length == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateShaderSourceImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint shader, GLsizei count,
+ const char** string, const GLint* length) {
+ if (string == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (length == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateStencilFunc(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum func, GLint ref,
+ GLuint mask) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateStencilFuncSeparate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum face, GLenum func,
+ GLint ref, GLuint mask) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateStencilMask(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint mask) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateStencilMaskSeparate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum face, GLuint mask) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateStencilOp(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum fail, GLenum zfail,
+ GLenum zpass) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateStencilOpSeparate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum face, GLenum fail,
+ GLenum zfail, GLenum zpass) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateTexImage2D(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLint level,
+ GLint internalformat, GLsizei width, GLsizei height, GLint border,
+ GLenum format, GLenum type, const void* pixels) {
+ if (pixels == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateTexImage2DImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLint level,
+ GLint internalformat, GLsizei width, GLsizei height, GLint border,
+ GLenum format, GLenum type, const void* pixels) {
+ if (pixels == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateTexParameterf(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLenum pname,
+ GLfloat param) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateTexParameterfv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLenum pname,
+ const GLfloat* params) {
+ if (params == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateTexParameterfvImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLenum pname,
+ const GLfloat* params) {
+ if (params == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (!CheckImmediateDataSize<TexParameterfvImmediate>(
+ arg_count, 1, sizeof(GLfloat), 1)) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateTexParameteri(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLenum pname,
+ GLint param) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateTexParameteriv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLenum pname,
+ const GLint* params) {
+ if (params == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateTexParameterivImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLenum pname,
+ const GLint* params) {
+ if (params == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (!CheckImmediateDataSize<TexParameterivImmediate>(
+ arg_count, 1, sizeof(GLint), 1)) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateTexSubImage2D(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
+ GLenum type, const void* pixels) {
+ if (pixels == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateTexSubImage2DImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
+ GLenum type, const void* pixels) {
+ if (pixels == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform1f(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location, GLfloat x) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform1fv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+ GLsizei count, const GLfloat* v) {
+ if (v == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform1fvImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+ GLsizei count, const GLfloat* v) {
+ if (v == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (!CheckImmediateDataSize<Uniform1fvImmediate>(
+ arg_count, count, sizeof(GLfloat), 1)) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform1i(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location, GLint x) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform1iv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+ GLsizei count, const GLint* v) {
+ if (v == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform1ivImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+ GLsizei count, const GLint* v) {
+ if (v == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (!CheckImmediateDataSize<Uniform1ivImmediate>(
+ arg_count, count, sizeof(GLint), 1)) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform2f(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location, GLfloat x,
+ GLfloat y) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform2fv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+ GLsizei count, const GLfloat* v) {
+ if (v == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform2fvImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+ GLsizei count, const GLfloat* v) {
+ if (v == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (!CheckImmediateDataSize<Uniform2fvImmediate>(
+ arg_count, count, sizeof(GLfloat), 2)) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform2i(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location, GLint x,
+ GLint y) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform2iv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+ GLsizei count, const GLint* v) {
+ if (v == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform2ivImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+ GLsizei count, const GLint* v) {
+ if (v == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (!CheckImmediateDataSize<Uniform2ivImmediate>(
+ arg_count, count, sizeof(GLint), 2)) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform3f(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location, GLfloat x,
+ GLfloat y, GLfloat z) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform3fv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+ GLsizei count, const GLfloat* v) {
+ if (v == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform3fvImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+ GLsizei count, const GLfloat* v) {
+ if (v == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (!CheckImmediateDataSize<Uniform3fvImmediate>(
+ arg_count, count, sizeof(GLfloat), 3)) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform3i(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location, GLint x,
+ GLint y, GLint z) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform3iv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+ GLsizei count, const GLint* v) {
+ if (v == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform3ivImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+ GLsizei count, const GLint* v) {
+ if (v == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (!CheckImmediateDataSize<Uniform3ivImmediate>(
+ arg_count, count, sizeof(GLint), 3)) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform4f(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location, GLfloat x,
+ GLfloat y, GLfloat z, GLfloat w) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform4fv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+ GLsizei count, const GLfloat* v) {
+ if (v == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform4fvImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+ GLsizei count, const GLfloat* v) {
+ if (v == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (!CheckImmediateDataSize<Uniform4fvImmediate>(
+ arg_count, count, sizeof(GLfloat), 4)) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform4i(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location, GLint x,
+ GLint y, GLint z, GLint w) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform4iv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+ GLsizei count, const GLint* v) {
+ if (v == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniform4ivImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+ GLsizei count, const GLint* v) {
+ if (v == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (!CheckImmediateDataSize<Uniform4ivImmediate>(
+ arg_count, count, sizeof(GLint), 4)) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniformMatrix2fv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+ GLsizei count, GLboolean transpose, const GLfloat* value) {
+ if (value == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniformMatrix2fvImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+ GLsizei count, GLboolean transpose, const GLfloat* value) {
+ if (value == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (!CheckImmediateDataSize<UniformMatrix2fvImmediate>(
+ arg_count, count, sizeof(GLfloat), 4)) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniformMatrix3fv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+ GLsizei count, GLboolean transpose, const GLfloat* value) {
+ if (value == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniformMatrix3fvImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+ GLsizei count, GLboolean transpose, const GLfloat* value) {
+ if (value == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (!CheckImmediateDataSize<UniformMatrix3fvImmediate>(
+ arg_count, count, sizeof(GLfloat), 9)) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniformMatrix4fv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+ GLsizei count, GLboolean transpose, const GLfloat* value) {
+ if (value == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUniformMatrix4fvImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint location,
+ GLsizei count, GLboolean transpose, const GLfloat* value) {
+ if (value == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (!CheckImmediateDataSize<UniformMatrix4fvImmediate>(
+ arg_count, count, sizeof(GLfloat), 16)) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateUseProgram(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint program) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateValidateProgram(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint program) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateVertexAttrib1f(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint indx, GLfloat x) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateVertexAttrib1fv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint indx,
+ const GLfloat* values) {
+ if (values == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateVertexAttrib1fvImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint indx,
+ const GLfloat* values) {
+ if (values == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (!CheckImmediateDataSize<VertexAttrib1fvImmediate>(
+ arg_count, 1, sizeof(GLfloat), 1)) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateVertexAttrib2f(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint indx, GLfloat x,
+ GLfloat y) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateVertexAttrib2fv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint indx,
+ const GLfloat* values) {
+ if (values == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateVertexAttrib2fvImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint indx,
+ const GLfloat* values) {
+ if (values == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (!CheckImmediateDataSize<VertexAttrib2fvImmediate>(
+ arg_count, 1, sizeof(GLfloat), 2)) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateVertexAttrib3f(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint indx, GLfloat x,
+ GLfloat y, GLfloat z) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateVertexAttrib3fv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint indx,
+ const GLfloat* values) {
+ if (values == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateVertexAttrib3fvImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint indx,
+ const GLfloat* values) {
+ if (values == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (!CheckImmediateDataSize<VertexAttrib3fvImmediate>(
+ arg_count, 1, sizeof(GLfloat), 3)) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateVertexAttrib4f(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint indx, GLfloat x,
+ GLfloat y, GLfloat z, GLfloat w) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateVertexAttrib4fv(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint indx,
+ const GLfloat* values) {
+ if (values == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateVertexAttrib4fvImmediate(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint indx,
+ const GLfloat* values) {
+ if (values == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ if (!CheckImmediateDataSize<VertexAttrib4fvImmediate>(
+ arg_count, 1, sizeof(GLfloat), 4)) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateVertexAttribPointer(
+ GLES2Decoder* decoder, unsigned int arg_count, GLuint indx, GLint size,
+ GLenum type, GLboolean normalized, GLsizei stride, const void* ptr) {
+ if (ptr == NULL) {
+ return parse_error::kParseOutOfBounds;
+ }
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateViewport(
+ GLES2Decoder* decoder, unsigned int arg_count, GLint x, GLint y,
+ GLsizei width, GLsizei height) {
+ return parse_error::kParseNoError;
+}
+parse_error::ParseError ValidateSwapBuffers(
+ GLES2Decoder* decoder, unsigned int arg_count) {
+ return parse_error::kParseNoError;
+}
+} // anonymous namespace
+} // namespace gles2
+} // namespace command_buffer
+
diff --git a/gpu/command_buffer/service/gpu_processor.cc b/gpu/command_buffer/service/gpu_processor.cc
new file mode 100644
index 0000000..845d5b6
--- /dev/null
+++ b/gpu/command_buffer/service/gpu_processor.cc
@@ -0,0 +1,84 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/command_buffer/service/gpu_processor.h"
+#include "gpu/np_utils/np_browser.h"
+
+using ::base::SharedMemory;
+using np_utils::NPBrowser;
+
+namespace command_buffer {
+
+GPUProcessor::~GPUProcessor() {
+}
+
+namespace {
+void InvokeProcessCommands(void* data) {
+ static_cast<GPUProcessor*>(data)->ProcessCommands();
+}
+} // namespace anonymous
+
+void GPUProcessor::ProcessCommands() {
+ if (command_buffer_->GetErrorStatus())
+ return;
+
+ parser_->set_put(command_buffer_->GetPutOffset());
+
+ int commands_processed = 0;
+ while (commands_processed < commands_per_update_ && !parser_->IsEmpty()) {
+ command_buffer::parse_error::ParseError parse_error =
+ parser_->ProcessCommand();
+ switch (parse_error) {
+ case command_buffer::parse_error::kParseUnknownCommand:
+ case command_buffer::parse_error::kParseInvalidArguments:
+ command_buffer_->SetParseError(parse_error);
+ break;
+
+ case command_buffer::parse_error::kParseInvalidSize:
+ case command_buffer::parse_error::kParseOutOfBounds:
+ command_buffer_->SetParseError(parse_error);
+ command_buffer_->RaiseErrorStatus();
+ return;
+ }
+
+ ++commands_processed;
+ }
+
+ command_buffer_->SetGetOffset(static_cast<int32>(parser_->get()));
+
+ if (!parser_->IsEmpty()) {
+ NPBrowser::get()->PluginThreadAsyncCall(npp_, InvokeProcessCommands, this);
+ }
+}
+
+void *GPUProcessor::GetSharedMemoryAddress(int32 shm_id) {
+ ::base::SharedMemory* shared_memory =
+ command_buffer_->GetTransferBuffer(shm_id);
+ if (!shared_memory)
+ return NULL;
+
+ if (!shared_memory->memory()) {
+ if (!shared_memory->Map(shared_memory->max_size()))
+ return NULL;
+ }
+
+ return shared_memory->memory();
+}
+
+// TODO(apatrick): Consolidate this with the above and return both the address
+// and size.
+size_t GPUProcessor::GetSharedMemorySize(int32 shm_id) {
+ ::base::SharedMemory* shared_memory =
+ command_buffer_->GetTransferBuffer(shm_id);
+ if (!shared_memory)
+ return 0;
+
+ return shared_memory->max_size();
+}
+
+void GPUProcessor::set_token(int32 token) {
+ command_buffer_->SetToken(token);
+}
+
+} // namespace command_buffer
diff --git a/gpu/command_buffer/service/gpu_processor.h b/gpu/command_buffer/service/gpu_processor.h
new file mode 100644
index 0000000..786e504
--- /dev/null
+++ b/gpu/command_buffer/service/gpu_processor.h
@@ -0,0 +1,99 @@
+// Copyright (c) 2006-2008 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 GPU_COMMAND_BUFFER_SERVICE_GPU_PROCESSOR_H_
+#define GPU_COMMAND_BUFFER_SERVICE_GPU_PROCESSOR_H_
+
+#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+#include "base/shared_memory.h"
+#include "gpu/command_buffer/common/command_buffer.h"
+#include "gpu/command_buffer/service/cmd_buffer_engine.h"
+#include "gpu/command_buffer/service/cmd_parser.h"
+#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
+#include "gpu/np_utils/np_object_pointer.h"
+
+namespace command_buffer {
+
+// This class processes commands in a command buffer. It is event driven and
+// posts tasks to the current message loop to do additional work.
+class GPUProcessor : public ::base::RefCounted<GPUProcessor>,
+ public command_buffer::CommandBufferEngine {
+ public:
+ GPUProcessor(NPP npp, CommandBuffer* command_buffer);
+
+ // This constructor is for unit tests.
+ GPUProcessor(CommandBuffer* command_buffer,
+ gles2::GLES2Decoder* decoder,
+ CommandParser* parser,
+ int commands_per_update);
+
+ virtual bool Initialize(HWND hwnd);
+
+ virtual ~GPUProcessor();
+
+ virtual void Destroy();
+
+ virtual void ProcessCommands();
+
+#if defined(OS_WIN)
+ virtual bool SetWindow(HWND handle, int width, int height);
+#endif
+
+ // Implementation of CommandBufferEngine.
+
+ // Gets the base address of a registered shared memory buffer.
+ // Parameters:
+ // shm_id: the identifier for the shared memory buffer.
+ virtual void *GetSharedMemoryAddress(int32 shm_id);
+
+ // Gets the size of a registered shared memory buffer.
+ // Parameters:
+ // shm_id: the identifier for the shared memory buffer.
+ virtual size_t GetSharedMemorySize(int32 shm_id);
+
+ // Sets the token value.
+ virtual void set_token(int32 token);
+
+ private:
+ NPP npp_;
+
+ // The GPUProcessor holds a weak reference to the CommandBuffer. The
+ // CommandBuffer owns the GPUProcessor and holds a strong reference to it
+ // through the ProcessCommands callback.
+ CommandBuffer* command_buffer_;
+
+ scoped_ptr< ::base::SharedMemory> mapped_ring_buffer_;
+ int commands_per_update_;
+
+ scoped_ptr<gles2::GLES2Decoder> decoder_;
+ scoped_ptr<CommandParser> parser_;
+};
+
+} // namespace command_buffer
+
+// Callbacks to the GPUProcessor hold a reference count.
+template <typename Method>
+class CallbackStorage<command_buffer::GPUProcessor, Method> {
+ public:
+ CallbackStorage(command_buffer::GPUProcessor* obj, Method method)
+ : obj_(obj),
+ meth_(method) {
+ DCHECK(obj_);
+ obj_->AddRef();
+ }
+
+ ~CallbackStorage() {
+ obj_->Release();
+ }
+
+ protected:
+ command_buffer::GPUProcessor* obj_;
+ Method meth_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CallbackStorage);
+};
+
+#endif // GPU_COMMAND_BUFFER_SERVICE_GPU_PROCESSOR_H_
diff --git a/gpu/command_buffer/service/gpu_processor_mock.h b/gpu/command_buffer/service/gpu_processor_mock.h
new file mode 100644
index 0000000..d65965f
--- /dev/null
+++ b/gpu/command_buffer/service/gpu_processor_mock.h
@@ -0,0 +1,40 @@
+// Copyright (c) 2006-2008 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 GPU_COMMAND_BUFFER_SERVICE_GPU_PROCESSOR_MOCK_H_
+#define GPU_COMMAND_BUFFER_SERVICE_GPU_PROCESSOR_MOCK_H_
+
+#include "gpu/command_buffer/service/gpu_processor.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace command_buffer {
+
+class MockGPUProcessor : public GPUProcessor {
+ public:
+ explicit MockGPUProcessor(CommandBuffer* command_buffer)
+ : GPUProcessor(NULL, command_buffer) {
+ }
+
+#if defined(OS_WIN)
+ MOCK_METHOD1(Initialize, bool(HWND handle));
+#endif
+
+ MOCK_METHOD0(Destroy, void());
+ MOCK_METHOD0(ProcessCommands, void());
+
+#if defined(OS_WIN)
+ MOCK_METHOD3(SetWindow, bool(HWND handle, int width, int height));
+#endif
+
+ MOCK_METHOD1(GetSharedMemoryAddress, void*(int32 shm_id));
+ MOCK_METHOD1(GetSharedMemorySize, size_t(int32 shm_id));
+ MOCK_METHOD1(set_token, void(int32 token));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockGPUProcessor);
+};
+
+} // namespace command_buffer
+
+#endif // GPU_COMMAND_BUFFER_SERVICE_GPU_PROCESSOR_MOCK_H_
diff --git a/gpu/command_buffer/service/gpu_processor_unittest.cc b/gpu/command_buffer/service/gpu_processor_unittest.cc
new file mode 100644
index 0000000..89a9392
--- /dev/null
+++ b/gpu/command_buffer/service/gpu_processor_unittest.cc
@@ -0,0 +1,285 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/at_exit.h"
+#include "base/message_loop.h"
+#include "gpu/command_buffer/common/command_buffer_mock.h"
+#include "gpu/command_buffer/service/mocks.h"
+#include "gpu/command_buffer/service/gpu_processor.h"
+#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
+#include "gpu/np_utils/np_browser_mock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+using testing::_;
+using testing::DoAll;
+using testing::Invoke;
+using testing::NiceMock;
+using testing::Return;
+using testing::SetArgumentPointee;
+using testing::StrictMock;
+
+namespace command_buffer {
+
+const size_t kRingBufferSize = 1024;
+const size_t kRingBufferEntries = kRingBufferSize / sizeof(int32);
+
+class GPUProcessorTest : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ shared_memory_.reset(new ::base::SharedMemory);
+ shared_memory_->Create(std::wstring(), false, false, kRingBufferSize);
+ shared_memory_->Map(kRingBufferSize);
+ buffer_ = static_cast<int32*>(shared_memory_->memory());
+
+ memset(buffer_, 0, kRingBufferSize);
+
+ // Don't mock PluginThreadAsyncCall. Have it schedule the task.
+ ON_CALL(mock_browser_, PluginThreadAsyncCall(_, _, _))
+ .WillByDefault(
+ Invoke(&mock_browser_,
+ &np_utils::MockNPBrowser::ConcretePluginThreadAsyncCall));
+
+ command_buffer_.reset(new MockCommandBuffer);
+ ON_CALL(*command_buffer_.get(), GetRingBuffer())
+ .WillByDefault(Return(shared_memory_.get()));
+ ON_CALL(*command_buffer_.get(), GetSize())
+ .WillByDefault(Return(kRingBufferEntries));
+
+ async_api_.reset(new StrictMock<command_buffer::AsyncAPIMock>);
+
+ decoder_ = gles2::GLES2Decoder::Create();
+
+ parser_ = new command_buffer::CommandParser(buffer_,
+ kRingBufferEntries,
+ 0,
+ kRingBufferEntries,
+ 0,
+ async_api_.get());
+
+ processor_ = new GPUProcessor(command_buffer_.get(),
+ decoder_,
+ parser_,
+ 2);
+ }
+
+ virtual void TearDown() {
+ // Ensure that any unexpected tasks posted by the GPU processor are executed
+ // in order to fail the test.
+ MessageLoop::current()->RunAllPending();
+ }
+
+ base::AtExitManager at_exit_manager;
+ MessageLoop message_loop;
+ np_utils::MockNPBrowser mock_browser_;
+ scoped_ptr<MockCommandBuffer> command_buffer_;
+ scoped_ptr<::base::SharedMemory> shared_memory_;
+ int32* buffer_;
+ command_buffer::gles2::GLES2Decoder* decoder_;
+ command_buffer::CommandParser* parser_;
+ scoped_ptr<command_buffer::AsyncAPIMock> async_api_;
+ scoped_refptr<GPUProcessor> processor_;
+};
+
+TEST_F(GPUProcessorTest, ProcessorDoesNothingIfRingBufferIsEmpty) {
+ EXPECT_CALL(*command_buffer_, GetPutOffset())
+ .WillOnce(Return(0));
+ EXPECT_CALL(*command_buffer_, SetGetOffset(0));
+
+ processor_->ProcessCommands();
+
+ EXPECT_EQ(command_buffer::parse_error::kParseNoError,
+ command_buffer_->ResetParseError());
+ EXPECT_FALSE(command_buffer_->GetErrorStatus());
+}
+
+TEST_F(GPUProcessorTest, ProcessesOneCommand) {
+ command_buffer::CommandHeader* header =
+ reinterpret_cast<command_buffer::CommandHeader*>(&buffer_[0]);
+ header[0].command = 7;
+ header[0].size = 2;
+ buffer_[1] = 123;
+
+ EXPECT_CALL(*command_buffer_, GetPutOffset())
+ .WillOnce(Return(2));
+ EXPECT_CALL(*command_buffer_, SetGetOffset(2));
+
+ EXPECT_CALL(*async_api_, DoCommand(7, 1, &buffer_[0]))
+ .WillOnce(Return(command_buffer::parse_error::kParseNoError));
+
+ processor_->ProcessCommands();
+
+ EXPECT_EQ(command_buffer::parse_error::kParseNoError,
+ command_buffer_->ResetParseError());
+ EXPECT_FALSE(command_buffer_->GetErrorStatus());
+}
+
+TEST_F(GPUProcessorTest, ProcessesTwoCommands) {
+ command_buffer::CommandHeader* header =
+ reinterpret_cast<command_buffer::CommandHeader*>(&buffer_[0]);
+ header[0].command = 7;
+ header[0].size = 2;
+ buffer_[1] = 123;
+ header[2].command = 8;
+ header[2].size = 1;
+
+ EXPECT_CALL(*command_buffer_, GetPutOffset())
+ .WillOnce(Return(3));
+ EXPECT_CALL(*command_buffer_, SetGetOffset(3));
+
+ EXPECT_CALL(*async_api_, DoCommand(7, 1, &buffer_[0]))
+ .WillOnce(Return(command_buffer::parse_error::kParseNoError));
+
+ EXPECT_CALL(*async_api_, DoCommand(8, 0, &buffer_[2]))
+ .WillOnce(Return(command_buffer::parse_error::kParseNoError));
+
+ processor_->ProcessCommands();
+}
+
+TEST_F(GPUProcessorTest, PostsTaskToFinishRemainingCommands) {
+ command_buffer::CommandHeader* header =
+ reinterpret_cast<command_buffer::CommandHeader*>(&buffer_[0]);
+ header[0].command = 7;
+ header[0].size = 2;
+ buffer_[1] = 123;
+ header[2].command = 8;
+ header[2].size = 1;
+ header[3].command = 9;
+ header[3].size = 1;
+
+ EXPECT_CALL(*command_buffer_, GetPutOffset())
+ .WillOnce(Return(4));
+
+ EXPECT_CALL(*async_api_, DoCommand(7, 1, &buffer_[0]))
+ .WillOnce(Return(command_buffer::parse_error::kParseNoError));
+
+ EXPECT_CALL(*async_api_, DoCommand(8, 0, &buffer_[2]))
+ .WillOnce(Return(command_buffer::parse_error::kParseNoError));
+
+ EXPECT_CALL(*command_buffer_, SetGetOffset(3));
+
+ processor_->ProcessCommands();
+
+ // ProcessCommands is called a second time when the pending task is run.
+
+ EXPECT_CALL(*command_buffer_, GetPutOffset())
+ .WillOnce(Return(4));
+
+ EXPECT_CALL(*async_api_, DoCommand(9, 0, &buffer_[3]))
+ .WillOnce(Return(command_buffer::parse_error::kParseNoError));
+
+ EXPECT_CALL(*command_buffer_, SetGetOffset(4));
+
+ MessageLoop::current()->RunAllPending();
+}
+
+TEST_F(GPUProcessorTest, SetsErrorCodeOnCommandBuffer) {
+ command_buffer::CommandHeader* header =
+ reinterpret_cast<command_buffer::CommandHeader*>(&buffer_[0]);
+ header[0].command = 7;
+ header[0].size = 1;
+
+ EXPECT_CALL(*command_buffer_, GetPutOffset())
+ .WillOnce(Return(1));
+ EXPECT_CALL(*command_buffer_, SetGetOffset(1));
+
+ EXPECT_CALL(*async_api_, DoCommand(7, 0, &buffer_[0]))
+ .WillOnce(Return(
+ command_buffer::parse_error::kParseUnknownCommand));
+
+ EXPECT_CALL(*command_buffer_,
+ SetParseError(command_buffer::parse_error::kParseUnknownCommand));
+
+ processor_->ProcessCommands();
+}
+
+TEST_F(GPUProcessorTest,
+ RecoverableParseErrorsAreNotClearedByFollowingSuccessfulCommands) {
+ command_buffer::CommandHeader* header =
+ reinterpret_cast<command_buffer::CommandHeader*>(&buffer_[0]);
+ header[0].command = 7;
+ header[0].size = 1;
+ header[1].command = 8;
+ header[1].size = 1;
+
+ EXPECT_CALL(*command_buffer_, GetPutOffset())
+ .WillOnce(Return(2));
+ EXPECT_CALL(*command_buffer_, SetGetOffset(2));
+
+ EXPECT_CALL(*async_api_, DoCommand(7, 0, &buffer_[0]))
+ .WillOnce(Return(
+ command_buffer::parse_error::kParseUnknownCommand));
+
+ EXPECT_CALL(*async_api_, DoCommand(8, 0, &buffer_[1]))
+ .WillOnce(Return(command_buffer::parse_error::kParseNoError));
+
+ EXPECT_CALL(*command_buffer_,
+ SetParseError(command_buffer::parse_error::kParseUnknownCommand));
+
+ processor_->ProcessCommands();
+}
+
+TEST_F(GPUProcessorTest, UnrecoverableParseErrorsRaiseTheErrorStatus) {
+ command_buffer::CommandHeader* header =
+ reinterpret_cast<command_buffer::CommandHeader*>(&buffer_[0]);
+ header[0].command = 7;
+ header[0].size = 1;
+ header[1].command = 8;
+ header[1].size = 1;
+
+ EXPECT_CALL(*command_buffer_, GetPutOffset())
+ .WillOnce(Return(2));
+
+ EXPECT_CALL(*async_api_, DoCommand(7, 0, &buffer_[0]))
+ .WillOnce(Return(command_buffer::parse_error::kParseInvalidSize));
+
+ EXPECT_CALL(*command_buffer_,
+ SetParseError(command_buffer::parse_error::kParseInvalidSize));
+
+ EXPECT_CALL(*command_buffer_, RaiseErrorStatus());
+
+ processor_->ProcessCommands();
+}
+
+TEST_F(GPUProcessorTest, ProcessCommandsDoesNothingAfterUnrecoverableError) {
+ EXPECT_CALL(*command_buffer_, GetErrorStatus())
+ .WillOnce(Return(true));
+
+ EXPECT_CALL(*command_buffer_, GetPutOffset())
+ .Times(0);
+
+ processor_->ProcessCommands();
+}
+
+TEST_F(GPUProcessorTest, CanGetAddressOfSharedMemory) {
+ EXPECT_CALL(*command_buffer_.get(), GetTransferBuffer(7))
+ .WillOnce(Return(shared_memory_.get()));
+
+ EXPECT_EQ(&buffer_[0], processor_->GetSharedMemoryAddress(7));
+}
+
+ACTION_P2(SetPointee, address, value) {
+ *address = value;
+}
+
+TEST_F(GPUProcessorTest, GetAddressOfSharedMemoryMapsMemoryIfUnmapped) {
+ EXPECT_CALL(*command_buffer_.get(), GetTransferBuffer(7))
+ .WillOnce(Return(shared_memory_.get()));
+
+ EXPECT_EQ(&buffer_[0], processor_->GetSharedMemoryAddress(7));
+}
+
+TEST_F(GPUProcessorTest, CanGetSizeOfSharedMemory) {
+ EXPECT_CALL(*command_buffer_.get(), GetTransferBuffer(7))
+ .WillOnce(Return(shared_memory_.get()));
+
+ EXPECT_EQ(kRingBufferSize, processor_->GetSharedMemorySize(7));
+}
+
+TEST_F(GPUProcessorTest, SetTokenForwardsToCommandBuffer) {
+ EXPECT_CALL(*command_buffer_, SetToken(7));
+ processor_->set_token(7);
+}
+
+} // namespace command_buffer
diff --git a/gpu/command_buffer/service/gpu_processor_win.cc b/gpu/command_buffer/service/gpu_processor_win.cc
new file mode 100644
index 0000000..d672c12
--- /dev/null
+++ b/gpu/command_buffer/service/gpu_processor_win.cc
@@ -0,0 +1,80 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <windows.h>
+
+#include "gpu/command_buffer/service/gpu_processor.h"
+
+using ::base::SharedMemory;
+
+namespace command_buffer {
+
+GPUProcessor::GPUProcessor(NPP npp, CommandBuffer* command_buffer)
+ : npp_(npp),
+ command_buffer_(command_buffer),
+ commands_per_update_(100) {
+ DCHECK(command_buffer);
+ decoder_.reset(gles2::GLES2Decoder::Create());
+ decoder_->set_engine(this);
+}
+
+GPUProcessor::GPUProcessor(CommandBuffer* command_buffer,
+ gles2::GLES2Decoder* decoder,
+ CommandParser* parser,
+ int commands_per_update)
+ : npp_(NULL),
+ command_buffer_(command_buffer),
+ commands_per_update_(commands_per_update) {
+ DCHECK(command_buffer);
+ decoder_.reset(decoder);
+ parser_.reset(parser);
+}
+
+bool GPUProcessor::Initialize(HWND handle) {
+ DCHECK(handle);
+
+ // Cannot reinitialize.
+ if (decoder_->hwnd() != NULL)
+ return false;
+
+ // Map the ring buffer and create the parser.
+ ::base::SharedMemory* ring_buffer = command_buffer_->GetRingBuffer();
+ if (ring_buffer) {
+ size_t size = ring_buffer->max_size();
+ if (!ring_buffer->Map(size)) {
+ return false;
+ }
+
+ void* ptr = ring_buffer->memory();
+ parser_.reset(new command_buffer::CommandParser(ptr, size, 0, size, 0,
+ decoder_.get()));
+ } else {
+ parser_.reset(new command_buffer::CommandParser(NULL, 0, 0, 0, 0,
+ decoder_.get()));
+ }
+
+ // Initialize GAPI immediately if the window handle is valid.
+ decoder_->set_hwnd(handle);
+ return decoder_->Initialize();
+}
+
+void GPUProcessor::Destroy() {
+ // Destroy GAPI if window handle has not already become invalid.
+ if (decoder_->hwnd()) {
+ decoder_->Destroy();
+ decoder_->set_hwnd(NULL);
+ }
+}
+
+bool GPUProcessor::SetWindow(HWND handle, int width, int height) {
+ if (handle == NULL) {
+ // Destroy GAPI when the window handle becomes invalid.
+ Destroy();
+ return true;
+ } else {
+ return Initialize(handle);
+ }
+}
+
+} // namespace command_buffer
diff --git a/gpu/command_buffer/service/mocks.h b/gpu/command_buffer/service/mocks.h
new file mode 100644
index 0000000..dbfb160
--- /dev/null
+++ b/gpu/command_buffer/service/mocks.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains definitions for mock objects, used for testing.
+
+// TODO: This file "manually" defines some mock objects. Using gMock
+// would be definitely preferable, unfortunately it doesn't work on Windows
+// yet.
+
+#ifndef GPU_COMMAND_BUFFER_SERVICE_CROSS_MOCKS_H_
+#define GPU_COMMAND_BUFFER_SERVICE_CROSS_MOCKS_H_
+
+#include <vector>
+#include "gmock/gmock.h"
+#include "gpu/command_buffer/service/cmd_parser.h"
+#include "gpu/command_buffer/service/cmd_buffer_engine.h"
+
+namespace command_buffer {
+
+// Mocks an AsyncAPIInterface, using GMock.
+class AsyncAPIMock : public AsyncAPIInterface {
+ public:
+ AsyncAPIMock() {
+ testing::DefaultValue<parse_error::ParseError>::Set(
+ parse_error::kParseNoError);
+ }
+
+ // Predicate that matches args passed to DoCommand, by looking at the values.
+ class IsArgs {
+ public:
+ IsArgs(unsigned int arg_count, const void* args)
+ : arg_count_(arg_count),
+ args_(static_cast<CommandBufferEntry*>(const_cast<void*>(args))) {
+ }
+
+ bool operator() (const void* _args) const {
+ const CommandBufferEntry* args =
+ static_cast<const CommandBufferEntry*>(_args) + 1;
+ for (unsigned int i = 0; i < arg_count_; ++i) {
+ if (args[i].value_uint32 != args_[i].value_uint32) return false;
+ }
+ return true;
+ }
+
+ private:
+ unsigned int arg_count_;
+ CommandBufferEntry *args_;
+ };
+
+ MOCK_METHOD3(DoCommand, parse_error::ParseError(
+ unsigned int command,
+ unsigned int arg_count,
+ const void* cmd_data));
+
+ const char* GetCommandName(unsigned int command_id) const {
+ return "";
+ };
+
+ // Sets the engine, to forward SetToken commands to it.
+ void set_engine(CommandBufferEngine *engine) { engine_ = engine; }
+
+ // Forwards the SetToken commands to the engine.
+ void SetToken(unsigned int command,
+ unsigned int arg_count,
+ const void* _args) {
+ DCHECK(engine_);
+ DCHECK_EQ(1u, command);
+ DCHECK_EQ(1u, arg_count);
+ const CommandBufferEntry* args =
+ static_cast<const CommandBufferEntry*>(_args);
+ engine_->set_token(args[0].value_uint32);
+ }
+ private:
+ CommandBufferEngine *engine_;
+};
+
+} // namespace command_buffer
+
+#endif // GPU_COMMAND_BUFFER_SERVICE_CROSS_MOCKS_H_
diff --git a/gpu/command_buffer/service/precompile.cc b/gpu/command_buffer/service/precompile.cc
new file mode 100644
index 0000000..3e219b0
--- /dev/null
+++ b/gpu/command_buffer/service/precompile.cc
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "gpu/command_buffer/service/precompile.h"
diff --git a/gpu/command_buffer/service/precompile.h b/gpu/command_buffer/service/precompile.h
new file mode 100644
index 0000000..55d2b21
--- /dev/null
+++ b/gpu/command_buffer/service/precompile.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains includes for common headers used by command buffer server
+// files. It is used for pre-compiled header support.
+
+#ifndef GPU_COMMAND_BUFFER_SERVICE_CROSS_PRECOMPILE_H_
+#define GPU_COMMAND_BUFFER_SERVICE_CROSS_PRECOMPILE_H_
+
+#include <build/build_config.h>
+
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
+
+#include <assert.h>
+#include <algorithm>
+#include <map>
+#include <vector>
+
+#endif // O3D_CORE_CROSS_PRECOMPILE_H_
diff --git a/gpu/command_buffer/service/resource.cc b/gpu/command_buffer/service/resource.cc
new file mode 100644
index 0000000..1208d30
--- /dev/null
+++ b/gpu/command_buffer/service/resource.cc
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the implementation of ResourceMapBase.
+
+#include "gpu/command_buffer/service/precompile.h"
+#include "gpu/command_buffer/service/resource.h"
+
+namespace command_buffer {
+
+// Assigns a resource to a resource ID, by setting it at the right location
+// into the list, resizing the list if necessary, and destroying an existing
+// resource if one existed already.
+void ResourceMapBase::Assign(ResourceId id, Resource *resource) {
+ if (id >= resources_.size()) {
+ resources_.resize(id + 1, NULL);
+ } else {
+ Resource *&entry = resources_[id];
+ if (entry) {
+ delete entry;
+ entry = NULL;
+ }
+ }
+ DCHECK(resources_[id] == NULL);
+ resources_[id] = resource;
+}
+
+// Destroys a resource contained in the map, setting its entry to NULL. If
+// necessary, this will trim the list.
+bool ResourceMapBase::Destroy(ResourceId id) {
+ if (id >= resources_.size()) {
+ return false;
+ }
+ Resource *&entry = resources_[id];
+ if (entry) {
+ delete entry;
+ entry = NULL;
+
+ // Removing the last element, we can trim the list.
+ // TODO: this may not be optimal to do every time. Investigate if it
+ // becomes an issue, and add a threshold before we resize.
+ if (id == resources_.size() - 1) {
+ size_t last_valid = resources_.max_size();
+ for (unsigned int i = id; i < resources_.size(); --i) {
+ if (resources_[i]) {
+ last_valid = i;
+ break;
+ }
+ }
+ if (last_valid == resources_.max_size()) {
+ resources_.clear();
+ } else {
+ resources_.resize(last_valid + 1);
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+// Goes over all non-NULL entries in the list, destroying them, then clears the
+// list.
+void ResourceMapBase::DestroyAllResources() {
+ for (Container::iterator i = resources_.begin(); i != resources_.end(); ++i) {
+ if (*i) {
+ delete *i;
+ }
+ }
+ resources_.clear();
+}
+
+} // namespace command_buffer
diff --git a/gpu/command_buffer/service/resource.h b/gpu/command_buffer/service/resource.h
new file mode 100644
index 0000000..20e3038
--- /dev/null
+++ b/gpu/command_buffer/service/resource.h
@@ -0,0 +1,268 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the definition for resource classes and the resource map.
+
+#ifndef GPU_COMMAND_BUFFER_SERVICE_CROSS_RESOURCE_H_
+#define GPU_COMMAND_BUFFER_SERVICE_CROSS_RESOURCE_H_
+
+#include <vector>
+#include "base/scoped_ptr.h"
+#include "gpu/command_buffer/common/resource.h"
+
+namespace command_buffer {
+
+// Base class for resources, just providing a common Destroy function.
+class Resource {
+ public:
+ Resource() {}
+ virtual ~Resource() {}
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Resource);
+};
+
+// VertexBuffer class, representing a vertex buffer resource.
+class VertexBuffer: public Resource {
+ public:
+ VertexBuffer(unsigned int size, unsigned int flags)
+ : size_(size),
+ flags_(flags) {}
+ virtual ~VertexBuffer() {}
+
+ // Returns the vertex buffer flags.
+ unsigned int flags() const { return flags_; }
+ // Sets the vertex buffer flags.
+ void set_flags(unsigned int flags) { flags_ = flags; }
+ // Returns the vertex buffer size.
+ unsigned int size() const { return size_; }
+ // Sets the vertex buffer size.
+ void set_size(unsigned int size) { size_ = size; }
+ protected:
+ unsigned int size_;
+ unsigned int flags_;
+ private:
+ DISALLOW_COPY_AND_ASSIGN(VertexBuffer);
+};
+
+// IndexBuffer class, representing an index buffer resource.
+class IndexBuffer: public Resource {
+ public:
+ IndexBuffer(unsigned int size, unsigned int flags)
+ : size_(size),
+ flags_(flags) {}
+ virtual ~IndexBuffer() {}
+
+ // Returns the index buffer flags.
+ unsigned int flags() const { return flags_; }
+ // Sets the index buffer flags.
+ void set_flags(unsigned int flags) { flags_ = flags; }
+ // Returns the index buffer size.
+ unsigned int size() const { return size_; }
+ // Sets the index buffer size.
+ void set_size(unsigned int size) { size_ = size; }
+ protected:
+ unsigned int size_;
+ unsigned int flags_;
+ private:
+ DISALLOW_COPY_AND_ASSIGN(IndexBuffer);
+};
+
+// VertexStruct class, representing a vertex struct resource.
+class VertexStruct: public Resource {
+ public:
+ // The representation of an input data stream.
+ struct Element {
+ ResourceId vertex_buffer;
+ unsigned int offset;
+ unsigned int stride;
+ vertex_struct::Type type;
+ vertex_struct::Semantic semantic;
+ unsigned int semantic_index;
+ };
+
+ explicit VertexStruct(unsigned int count)
+ : count_(count),
+ elements_(new Element[count]) {
+ memset(elements_.get(), 0, count * sizeof(Element)); // NOLINT
+ }
+
+ // Returns the number of inputs in this struct.
+ unsigned int count() const { return count_; }
+ // Returns an element by index.
+ Element &GetElement(unsigned int i) {
+ DCHECK_GT(count_, i);
+ return elements_[i];
+ }
+ protected:
+ unsigned int count_;
+ scoped_array<Element> elements_;
+ private:
+ DISALLOW_COPY_AND_ASSIGN(VertexStruct);
+};
+
+// Effect class, representing an effect.
+class Effect: public Resource {
+ public:
+ Effect() {}
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Effect);
+};
+
+// EffectParam class, representing an effect parameter.
+class EffectParam: public Resource {
+ public:
+ explicit EffectParam(effect_param::DataType data_type)
+ : data_type_(data_type) {
+ }
+
+ // Gets the data type of this parameter.
+ effect_param::DataType data_type() const { return data_type_; }
+ private:
+ effect_param::DataType data_type_;
+ DISALLOW_COPY_AND_ASSIGN(EffectParam);
+};
+
+// Texture class, representing a texture resource.
+class Texture: public Resource {
+ public:
+ Texture(texture::Type type,
+ unsigned int levels,
+ texture::Format format,
+ bool enable_render_surfaces,
+ unsigned int flags)
+ : type_(type),
+ levels_(levels),
+ format_(format),
+ render_surfaces_enabled_(enable_render_surfaces),
+ flags_(flags) {}
+ virtual ~Texture() {}
+
+ // Returns the type of the texture.
+ texture::Type type() const { return type_; }
+ // Returns the texture flags.
+ unsigned int flags() const { return flags_; }
+ // Returns the texture format.
+ texture::Format format() const { return format_; }
+ // Returns whether the texture supports render surfaces
+ bool render_surfaces_enabled() const { return render_surfaces_enabled_; }
+ // Returns the number of mipmap levels in the texture.
+ unsigned int levels() const { return levels_; }
+ private:
+ texture::Type type_;
+ unsigned int levels_;
+ texture::Format format_;
+ bool render_surfaces_enabled_;
+ unsigned int flags_;
+ DISALLOW_COPY_AND_ASSIGN(Texture);
+};
+
+// RenderSurface class, representing a render surface/target
+class RenderSurface: public Resource {
+ public:
+ RenderSurface() {}
+ private:
+ DISALLOW_COPY_AND_ASSIGN(RenderSurface);
+};
+
+// RenderSurface class, representing a render surface/target
+class RenderDepthStencilSurface: public Resource {
+ public:
+ RenderDepthStencilSurface() {}
+ private:
+ DISALLOW_COPY_AND_ASSIGN(RenderDepthStencilSurface);
+};
+
+
+// Texture class, representing a sampler resource.
+class Sampler: public Resource {
+ public:
+ Sampler() {}
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Sampler);
+};
+
+// Base of ResourceMap. Contains most of the implementation of ResourceMap, to
+// avoid template bloat.
+class ResourceMapBase {
+ public:
+ ResourceMapBase() : resources_() {}
+ ~ResourceMapBase() {}
+
+ // Assigns a resource to a resource ID. Assigning a resource to an ID that
+ // already has an existing resource will destroy that existing resource. The
+ // map takes ownership of the resource.
+ void Assign(ResourceId id, Resource* resource);
+ // Destroys a resource.
+ bool Destroy(ResourceId id);
+ // Destroy all resources.
+ void DestroyAllResources();
+ // Gets a resource by ID.
+ Resource *Get(ResourceId id) {
+ return (id < resources_.size()) ? resources_[id] : NULL;
+ }
+ private:
+ typedef std::vector<Resource *> Container;
+ Container resources_;
+};
+
+// Resource Map class, allowing resource ID <-> Resource association. This is a
+// dense map, optimized for retrieval (O(1)).
+template<class T> class ResourceMap {
+ public:
+ ResourceMap() : container_() {}
+ ~ResourceMap() {}
+
+ // Assigns a resource to a resource ID. Assigning a resource to an ID that
+ // already has an existing resource will destroy that existing resource. The
+ // map takes ownership of the resource.
+ void Assign(ResourceId id, T* resource) {
+ container_.Assign(id, resource);
+ }
+ // Destroys a resource.
+ bool Destroy(ResourceId id) {
+ return container_.Destroy(id);
+ }
+ // Destroy all resources.
+ void DestroyAllResources() {
+ return container_.DestroyAllResources();
+ }
+ // Gets a resource by ID.
+ T *Get(ResourceId id) {
+ return static_cast<T*>(container_.Get(id));
+ }
+ private:
+ ResourceMapBase container_;
+};
+
+} // namespace command_buffer
+
+#endif // GPU_COMMAND_BUFFER_SERVICE_CROSS_RESOURCE_H_
diff --git a/gpu/command_buffer/service/resource_test.cc b/gpu/command_buffer/service/resource_test.cc
new file mode 100644
index 0000000..7a9438b
--- /dev/null
+++ b/gpu/command_buffer/service/resource_test.cc
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// Tests for the ResourceMap.
+
+#include "gpu/command_buffer/service/precompile.h"
+#include "gpu/command_buffer/service/resource.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace command_buffer {
+
+// Mock resource implementation that checks for leaks.
+class ResourceMock : public Resource {
+ public:
+ ResourceMock() : Resource() {
+ ++instance_count_;
+ }
+ virtual ~ResourceMock() {
+ --instance_count_;
+ }
+
+ // Returns the instance count. The instance count is increased in the
+ // constructor and decreased in the destructor, to track leaks. The reason is
+ // that we can't mock the destructor, though we want to make sure the mock is
+ // destroyed.
+ static int instance_count() { return instance_count_; }
+ private:
+ static int instance_count_;
+ DISALLOW_COPY_AND_ASSIGN(ResourceMock);
+};
+int ResourceMock::instance_count_ = 0;
+
+// Test fixture for ResourceMap test. Creates a ResourceMap using a mock
+// Resource, and checks for ResourceMock leaks.
+class ResourceMapTest : public testing::Test {
+ protected:
+ typedef ResourceMap<ResourceMock> Map;
+ virtual void SetUp() {
+ instance_count_ = ResourceMock::instance_count();
+ map_.reset(new Map());
+ }
+ virtual void TearDown() {
+ CheckLeaks();
+ }
+
+ // Makes sure we didn't leak any ResourceMock object.
+ void CheckLeaks() {
+ EXPECT_EQ(instance_count_, ResourceMock::instance_count());
+ }
+
+ Map *map() const { return map_.get(); }
+ private:
+ int instance_count_;
+ scoped_ptr<Map> map_;
+};
+
+TEST_F(ResourceMapTest, TestMap) {
+ // check that initial mapping is empty.
+ EXPECT_EQ(NULL, map()->Get(0));
+ EXPECT_EQ(NULL, map()->Get(1));
+ EXPECT_EQ(NULL, map()->Get(392));
+
+ // create a new resource, assign it to an ID.
+ ResourceMock *resource = new ResourceMock();
+ map()->Assign(123, resource);
+ EXPECT_EQ(resource, map()->Get(123));
+
+ // Destroy the resource, making sure the object is deleted.
+ EXPECT_EQ(true, map()->Destroy(123));
+ EXPECT_EQ(false, map()->Destroy(123)); // destroying again should fail.
+ resource = NULL;
+ CheckLeaks();
+
+ // create a new resource, add it to the map, and make sure it gets deleted
+ // when we assign a new resource to that ID.
+ resource = new ResourceMock();
+ map()->Assign(1, resource);
+ resource = new ResourceMock();
+ map()->Assign(1, resource);
+ EXPECT_EQ(resource, map()->Get(1)); // check that we have the new resource.
+ EXPECT_EQ(true, map()->Destroy(1));
+ CheckLeaks();
+
+ // Adds 3 resources, then call DestroyAllResources().
+ resource = new ResourceMock();
+ map()->Assign(1, resource);
+ resource = new ResourceMock();
+ map()->Assign(2, resource);
+ resource = new ResourceMock();
+ map()->Assign(3, resource);
+ map()->DestroyAllResources();
+ EXPECT_EQ(NULL, map()->Get(1));
+ EXPECT_EQ(NULL, map()->Get(2));
+ EXPECT_EQ(NULL, map()->Get(3));
+ CheckLeaks();
+}
+
+} // namespace command_buffer
diff --git a/gpu/command_buffer/service/x_utils.cc b/gpu/command_buffer/service/x_utils.cc
new file mode 100644
index 0000000..b9eb9d9
--- /dev/null
+++ b/gpu/command_buffer/service/x_utils.cc
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This class implements the XWindowWrapper class.
+
+#include "gpu/command_buffer/service/precompile.h"
+#include "gpu/command_buffer/common/cross/logging.h"
+#include "gpu/command_buffer/service/linux/x_utils.h"
+
+namespace command_buffer {
+
+bool XWindowWrapper::Initialize() {
+ XWindowAttributes attributes;
+ XGetWindowAttributes(display_, window_, &attributes);
+ XVisualInfo visual_info_template;
+ visual_info_template.visualid = XVisualIDFromVisual(attributes.visual);
+ int visual_info_count = 0;
+ XVisualInfo *visual_info_list = XGetVisualInfo(display_, VisualIDMask,
+ &visual_info_template,
+ &visual_info_count);
+ DCHECK(visual_info_list);
+ DCHECK_GT(visual_info_count, 0);
+ context_ = 0;
+ for (int i = 0; i < visual_info_count; ++i) {
+ context_ = glXCreateContext(display_, visual_info_list + i, 0,
+ True);
+ if (context_) break;
+ }
+ XFree(visual_info_list);
+ if (!context_) {
+ DLOG(ERROR) << "Couldn't create GL context.";
+ return false;
+ }
+ return true;
+}
+
+bool XWindowWrapper::MakeCurrent() {
+ if (glXMakeCurrent(display_, window_, context_) != True) {
+ glXDestroyContext(display_, context_);
+ context_ = 0;
+ DLOG(ERROR) << "Couldn't make context current.";
+ return false;
+ }
+ return true;
+}
+
+void XWindowWrapper::Destroy() {
+ Bool result = glXMakeCurrent(display_, 0, 0);
+ // glXMakeCurrent isn't supposed to fail when unsetting the context, unless
+ // we have pending draws on an invalid window - which shouldn't be the case
+ // here.
+ DCHECK(result);
+ if (context_) {
+ glXDestroyContext(display_, context_);
+ context_ = 0;
+ }
+}
+
+void XWindowWrapper::SwapBuffers() {
+ glXSwapBuffers(display_, window_);
+}
+
+} // namespace command_buffer
diff --git a/gpu/command_buffer/service/x_utils.h b/gpu/command_buffer/service/x_utils.h
new file mode 100644
index 0000000..0d8c26a
--- /dev/null
+++ b/gpu/command_buffer/service/x_utils.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file declares the XWindowWrapper class.
+
+#ifndef GPU_COMMAND_BUFFER_SERVICE_X_UTILS_H_
+#define GPU_COMMAND_BUFFER_SERVICE_X_UTILS_H_
+
+#include <GL/glx.h>
+#include "base/basictypes.h"
+#include "gpu/command_buffer/common/cross/logging.h"
+
+namespace command_buffer {
+
+// This class is a wrapper around an X Window and associated GL context. It is
+// useful to isolate intrusive X headers, since it can be forward declared
+// (Window and GLXContext can't).
+class XWindowWrapper {
+ public:
+ XWindowWrapper(Display *display, Window window)
+ : display_(display),
+ window_(window) {
+ DCHECK(display_);
+ DCHECK(window_);
+ }
+ // Initializes the GL context.
+ bool Initialize();
+
+ // Destroys the GL context.
+ void Destroy();
+
+ // Makes the GL context current on the current thread.
+ bool MakeCurrent();
+
+ // Swaps front and back buffers.
+ void SwapBuffers();
+
+ private:
+ Display *display_;
+ Window window_;
+ GLXContext context_;
+ DISALLOW_COPY_AND_ASSIGN(XWindowWrapper);
+};
+
+} // namespace command_buffer
+
+#endif // GPU_COMMAND_BUFFER_SERVICE_X_UTILS_H_