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
3 // found in the LICENSE file.
5 // This file contains the implementation of the command parser.
7 #include "gpu/command_buffer/service/cmd_parser.h"
9 #include "base/logging.h"
10 #include "base/debug/trace_event.h"
14 CommandParser::CommandParser(AsyncAPIInterface
* handler
)
22 void CommandParser::SetBuffer(
27 // check proper alignments.
28 DCHECK_EQ(0, (reinterpret_cast<intptr_t>(shm_address
)) % 4);
29 DCHECK_EQ(0, offset
% 4);
30 DCHECK_EQ(0u, size
% 4);
31 // check that the command buffer fits into the memory buffer.
32 DCHECK_GE(shm_size
, offset
+ size
);
35 char* buffer_begin
= static_cast<char*>(shm_address
) + offset
;
36 buffer_
= reinterpret_cast<CommandBufferEntry
*>(buffer_begin
);
37 entry_count_
= size
/ 4;
40 // Process one command, reading the header from the command buffer, and
41 // forwarding the command index and the arguments to the handler.
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
45 // validation to the handler, so it can pass a reference to them.
46 // - get_ is modified *after* the command has been executed.
47 error::Error
CommandParser::ProcessCommand() {
48 CommandBufferOffset get
= get_
;
50 return error::kNoError
;
52 CommandHeader header
= buffer_
[get
].value_header
;
53 if (header
.size
== 0) {
54 DVLOG(1) << "Error: zero sized command in command buffer";
55 return error::kInvalidSize
;
58 if (static_cast<int>(header
.size
) + get
> entry_count_
) {
59 DVLOG(1) << "Error: get offset out of bounds";
60 return error::kOutOfBounds
;
63 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
64 handler_
->GetCommandName(header
.command
));
66 error::Error result
= handler_
->DoCommand(
67 header
.command
, header
.size
- 1, buffer_
+ get
);
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
72 if (error::IsError(result
)) {
73 ReportError(header
.command
, result
);
76 // If get was not set somewhere else advance it.
77 if (get
== get_
&& result
!= error::kDeferCommandUntilLater
)
78 get_
= (get
+ header
.size
) % entry_count_
;
83 void CommandParser::ReportError(unsigned int command_id
,
84 error::Error result
) {
85 DVLOG(1) << "Error: " << result
<< " for Command "
86 << handler_
->GetCommandName(command_id
);
89 // Processes all the commands, while the buffer is not empty. Stop if an error
91 error::Error
CommandParser::ProcessAllCommands() {
93 error::Error error
= ProcessCommand();
97 return error::kNoError
;