OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 #include "gpu/command_buffer/service/shader_manager.h" | 5 #include "gpu/command_buffer/service/shader_manager.h" |
6 #include "base/logging.h" | 6 #include "base/logging.h" |
| 7 #include "base/string_util.h" |
7 | 8 |
8 namespace gpu { | 9 namespace gpu { |
9 namespace gles2 { | 10 namespace gles2 { |
10 | 11 |
11 ShaderManager::ShaderInfo::ShaderInfo(GLuint service_id, GLenum shader_type) | 12 ShaderManager::ShaderInfo::ShaderInfo(GLuint service_id, GLenum shader_type) |
12 : use_count_(0), | 13 : use_count_(0), |
13 service_id_(service_id), | 14 service_id_(service_id), |
14 shader_type_(shader_type), | 15 shader_type_(shader_type), |
15 valid_(false) { | 16 valid_(false) { |
16 } | 17 } |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 info->IncUseCount(); | 145 info->IncUseCount(); |
145 } | 146 } |
146 | 147 |
147 void ShaderManager::UnuseShader(ShaderManager::ShaderInfo* info) { | 148 void ShaderManager::UnuseShader(ShaderManager::ShaderInfo* info) { |
148 DCHECK(info); | 149 DCHECK(info); |
149 DCHECK(IsOwned(info)); | 150 DCHECK(IsOwned(info)); |
150 info->DecUseCount(); | 151 info->DecUseCount(); |
151 RemoveShaderInfoIfUnused(info); | 152 RemoveShaderInfoIfUnused(info); |
152 } | 153 } |
153 | 154 |
| 155 namespace { |
| 156 |
| 157 // Strips comments from shader text. This allows non-ASCII characters |
| 158 // to be used in comments without potentially breaking OpenGL |
| 159 // implementations not expecting characters outside the GLSL ES set. |
| 160 class Stripper { |
| 161 public: |
| 162 Stripper(const std::string& str) |
| 163 : parse_state_(kBeginningOfLine) |
| 164 , source_string_(str) |
| 165 , length_(str.length()) |
| 166 , position_(0) { |
| 167 Parse(); |
| 168 } |
| 169 |
| 170 const std::string& result() { |
| 171 return result_; |
| 172 } |
| 173 |
| 174 private: |
| 175 bool HasMoreCharacters() { |
| 176 return position_ < length_; |
| 177 } |
| 178 |
| 179 void Parse() { |
| 180 while (HasMoreCharacters()) { |
| 181 Process(Current()); |
| 182 // Process() might Advance the position. |
| 183 if (HasMoreCharacters()) { |
| 184 Advance(); |
| 185 } |
| 186 } |
| 187 } |
| 188 |
| 189 void Process(char); |
| 190 |
| 191 bool Peek(char* character) { |
| 192 DCHECK(character); |
| 193 if (position_ + 1 >= length_) { |
| 194 return false; |
| 195 } |
| 196 *character = source_string_[position_ + 1]; |
| 197 return true; |
| 198 } |
| 199 |
| 200 char Current() { |
| 201 DCHECK_LT(position_, length_); |
| 202 return source_string_[position_]; |
| 203 } |
| 204 |
| 205 void Advance() { |
| 206 ++position_; |
| 207 } |
| 208 |
| 209 bool IsNewline(char character) { |
| 210 // Don't attempt to canonicalize newline related characters. |
| 211 return (character == '\n' || character == '\r'); |
| 212 } |
| 213 |
| 214 void Emit(char character) { |
| 215 result_.push_back(character); |
| 216 } |
| 217 |
| 218 enum ParseState { |
| 219 // Have not seen an ASCII non-whitespace character yet on |
| 220 // this line. Possible that we might see a preprocessor |
| 221 // directive. |
| 222 kBeginningOfLine, |
| 223 |
| 224 // Have seen at least one ASCII non-whitespace character |
| 225 // on this line. |
| 226 kMiddleOfLine, |
| 227 |
| 228 // Handling a preprocessor directive. Passes through all |
| 229 // characters up to the end of the line. Disables comment |
| 230 // processing. |
| 231 kInPreprocessorDirective, |
| 232 |
| 233 // Handling a single-line comment. The comment text is |
| 234 // replaced with a single space. |
| 235 kInSingleLineComment, |
| 236 |
| 237 // Handling a multi-line comment. Newlines are passed |
| 238 // through to preserve line numbers. |
| 239 kInMultiLineComment |
| 240 }; |
| 241 |
| 242 ParseState parse_state_; |
| 243 std::string source_string_; |
| 244 unsigned length_; |
| 245 unsigned position_; |
| 246 std::string result_; |
| 247 }; |
| 248 |
| 249 void Stripper::Process(char c) { |
| 250 if (IsNewline(c)) { |
| 251 // No matter what state we are in, pass through newlines |
| 252 // so we preserve line numbers. |
| 253 Emit(c); |
| 254 |
| 255 if (parse_state_ != kInMultiLineComment) |
| 256 parse_state_ = kBeginningOfLine; |
| 257 |
| 258 return; |
| 259 } |
| 260 |
| 261 char temp = 0; |
| 262 switch (parse_state_) { |
| 263 case kBeginningOfLine: |
| 264 if (IsAsciiWhitespace(c)) { |
| 265 Emit(c); |
| 266 break; |
| 267 } |
| 268 |
| 269 if (c == '#') { |
| 270 parse_state_ = kInPreprocessorDirective; |
| 271 Emit(c); |
| 272 break; |
| 273 } |
| 274 |
| 275 // Transition to normal state and re-handle character. |
| 276 parse_state_ = kMiddleOfLine; |
| 277 Process(c); |
| 278 break; |
| 279 |
| 280 case kMiddleOfLine: |
| 281 if (c == '/' && Peek(&temp)) { |
| 282 if (temp == '/') { |
| 283 parse_state_ = kInSingleLineComment; |
| 284 Emit(' '); |
| 285 Advance(); |
| 286 break; |
| 287 } |
| 288 |
| 289 if (temp == '*') { |
| 290 parse_state_ = kInMultiLineComment; |
| 291 // Emit the comment start in case the user has |
| 292 // an unclosed comment and we want to later |
| 293 // signal an error. |
| 294 Emit('/'); |
| 295 Emit('*'); |
| 296 Advance(); |
| 297 break; |
| 298 } |
| 299 } |
| 300 |
| 301 Emit(c); |
| 302 break; |
| 303 |
| 304 case kInPreprocessorDirective: |
| 305 // No matter what the character is, just pass it |
| 306 // through. Do not Parse comments in this state. This |
| 307 // might not be the right thing to do long term, but it |
| 308 // should handle the #error preprocessor directive. |
| 309 Emit(c); |
| 310 break; |
| 311 |
| 312 case kInSingleLineComment: |
| 313 // The newline code at the top of this function takes care |
| 314 // of resetting our state when we get out of the |
| 315 // single-line comment. Swallow all other characters. |
| 316 break; |
| 317 |
| 318 case kInMultiLineComment: |
| 319 if (c == '*' && Peek(&temp) && temp == '/') { |
| 320 Emit('*'); |
| 321 Emit('/'); |
| 322 parse_state_ = kMiddleOfLine; |
| 323 Advance(); |
| 324 break; |
| 325 } |
| 326 |
| 327 // Swallow all other characters. Unclear whether we may |
| 328 // want or need to just Emit a space per character to try |
| 329 // to preserve column numbers for debugging purposes. |
| 330 break; |
| 331 } |
| 332 } |
| 333 |
| 334 } // anonymous namespace |
| 335 |
| 336 std::string ShaderManager::StripComments(const std::string source) { |
| 337 Stripper stripper(source); |
| 338 return stripper.result(); |
| 339 } |
| 340 |
154 } // namespace gles2 | 341 } // namespace gles2 |
155 } // namespace gpu | 342 } // namespace gpu |
156 | 343 |
157 | 344 |
OLD | NEW |