OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // This file contains the implementation of the command parser. | 5 // This file contains the implementation of the command parser. |
6 | 6 |
7 #include "gpu/command_buffer/service/cmd_parser.h" | 7 #include "gpu/command_buffer/service/cmd_parser.h" |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
(...skipping 26 matching lines...) Expand all Loading... |
37 entry_count_ = size / 4; | 37 entry_count_ = size / 4; |
38 } | 38 } |
39 | 39 |
40 // Process one command, reading the header from the command buffer, and | 40 // Process one command, reading the header from the command buffer, and |
41 // forwarding the command index and the arguments to the handler. | 41 // forwarding the command index and the arguments to the handler. |
42 // Note that: | 42 // Note that: |
43 // - validation needs to happen on a copy of the data (to avoid race | 43 // - validation needs to happen on a copy of the data (to avoid race |
44 // conditions). This function only validates the header, leaving the arguments | 44 // conditions). This function only validates the header, leaving the arguments |
45 // validation to the handler, so it can pass a reference to them. | 45 // validation to the handler, so it can pass a reference to them. |
46 // - get_ is modified *after* the command has been executed. | 46 // - get_ is modified *after* the command has been executed. |
47 error::Error CommandParser::ProcessCommand() { | 47 error::Error CommandParser::ProcessCommands(int num_commands) { |
48 CommandBufferOffset get = get_; | 48 int num_entries = put_ < get_ ? entry_count_ - get_ : put_ - get_; |
49 if (get == put_) | 49 int entries_processed = 0; |
50 return error::kNoError; | |
51 | 50 |
52 CommandHeader header = buffer_[get].value_header; | 51 error::Error result = handler_->DoCommands( |
53 if (header.size == 0) { | 52 num_commands, buffer_ + get_, num_entries, &entries_processed); |
54 DVLOG(1) << "Error: zero sized command in command buffer"; | |
55 return error::kInvalidSize; | |
56 } | |
57 | 53 |
58 if (static_cast<int>(header.size) + get > entry_count_) { | 54 get_ += entries_processed; |
59 DVLOG(1) << "Error: get offset out of bounds"; | 55 if (get_ == entry_count_) |
60 return error::kOutOfBounds; | 56 get_ = 0; |
61 } | |
62 | |
63 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cb_command"), | |
64 handler_->GetCommandName(header.command)); | |
65 | |
66 error::Error result = handler_->DoCommand( | |
67 header.command, header.size - 1, buffer_ + get); | |
68 | |
69 // TODO(gman): If you want to log errors this is the best place to catch them. | |
70 // It seems like we need an official way to turn on a debug mode and | |
71 // get these errors. | |
72 if (error::IsError(result)) { | |
73 ReportError(header.command, result); | |
74 } | |
75 | |
76 // If get was not set somewhere else advance it. | |
77 if (get == get_ && result != error::kDeferCommandUntilLater) | |
78 get_ = (get + header.size) % entry_count_; | |
79 | 57 |
80 return result; | 58 return result; |
81 } | 59 } |
82 | 60 |
83 void CommandParser::ReportError(unsigned int command_id, | 61 void CommandParser::ReportError(unsigned int command_id, |
84 error::Error result) { | 62 error::Error result) { |
85 DVLOG(1) << "Error: " << result << " for Command " | 63 DVLOG(1) << "Error: " << result << " for Command " |
86 << handler_->GetCommandName(command_id); | 64 << handler_->GetCommandName(command_id); |
87 } | 65 } |
88 | 66 |
89 // Processes all the commands, while the buffer is not empty. Stop if an error | 67 // Processes all the commands, while the buffer is not empty. Stop if an error |
90 // is encountered. | 68 // is encountered. |
91 error::Error CommandParser::ProcessAllCommands() { | 69 error::Error CommandParser::ProcessAllCommands() { |
92 while (!IsEmpty()) { | 70 while (!IsEmpty()) { |
93 error::Error error = ProcessCommand(); | 71 error::Error error = ProcessCommands(kParseCommandsSlice); |
94 if (error) | 72 if (error) |
95 return error; | 73 return error; |
96 } | 74 } |
97 return error::kNoError; | 75 return error::kNoError; |
98 } | 76 } |
99 | 77 |
| 78 // Decode multiple commands, and call the corresponding GL functions. |
| 79 // NOTE: buffer is a pointer to the command buffer. As such, it could be |
| 80 // changed by a (malicious) client at any time, so if validation has to happen, |
| 81 // it should operate on a copy of them. |
| 82 error::Error AsyncAPIInterface::DoCommands(unsigned int num_commands, |
| 83 const void* buffer, |
| 84 int num_entries, |
| 85 int* entries_processed) { |
| 86 int commands_to_process = num_commands; |
| 87 error::Error result = error::kNoError; |
| 88 const CommandBufferEntry* cmd_data = |
| 89 static_cast<const CommandBufferEntry*>(buffer); |
| 90 int process_pos = 0; |
| 91 |
| 92 while (process_pos < num_entries && result == error::kNoError && |
| 93 commands_to_process--) { |
| 94 CommandHeader header = cmd_data->value_header; |
| 95 if (header.size == 0) { |
| 96 DVLOG(1) << "Error: zero sized command in command buffer"; |
| 97 return error::kInvalidSize; |
| 98 } |
| 99 |
| 100 if (static_cast<int>(header.size) + process_pos > num_entries) { |
| 101 DVLOG(1) << "Error: get offset out of bounds"; |
| 102 return error::kOutOfBounds; |
| 103 } |
| 104 |
| 105 const unsigned int command = header.command; |
| 106 const unsigned int arg_count = header.size - 1; |
| 107 |
| 108 result = DoCommand(command, arg_count, cmd_data); |
| 109 |
| 110 if (result != error::kDeferCommandUntilLater) { |
| 111 process_pos += header.size; |
| 112 cmd_data += header.size; |
| 113 } |
| 114 } |
| 115 |
| 116 if (entries_processed) |
| 117 *entries_processed = process_pos; |
| 118 |
| 119 return result; |
| 120 } |
| 121 |
100 } // namespace gpu | 122 } // namespace gpu |
OLD | NEW |