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 #include "gpu/command_buffer/client/program_info_manager.h" | 5 #include "gpu/command_buffer/client/program_info_manager.h" |
6 | 6 |
7 namespace { | 7 namespace { |
8 | 8 |
9 template<typename T> static T LocalGetAs( | 9 template<typename T> static T LocalGetAs( |
10 const std::vector<int8>& data, uint32 offset, size_t size) { | 10 const std::vector<int8>& data, uint32 offset, size_t size) { |
(...skipping 26 matching lines...) Expand all Loading... |
37 : size(_size), | 37 : size(_size), |
38 type(_type), | 38 type(_type), |
39 name(_name) { | 39 name(_name) { |
40 is_array = (!name.empty() && name[name.size() - 1] == ']'); | 40 is_array = (!name.empty() && name[name.size() - 1] == ']'); |
41 DCHECK(!(size > 1 && !is_array)); | 41 DCHECK(!(size > 1 && !is_array)); |
42 } | 42 } |
43 | 43 |
44 ProgramInfoManager::Program::UniformInfo::~UniformInfo() { | 44 ProgramInfoManager::Program::UniformInfo::~UniformInfo() { |
45 } | 45 } |
46 | 46 |
| 47 ProgramInfoManager::Program::UniformES3::UniformES3() |
| 48 : block_index(-1), |
| 49 offset(-1), |
| 50 array_stride(-1), |
| 51 matrix_stride(-1), |
| 52 is_row_major(0) { |
| 53 } |
| 54 |
| 55 ProgramInfoManager::Program::UniformES3::~UniformES3() { |
| 56 } |
| 57 |
47 ProgramInfoManager::Program::UniformBlock::UniformBlock() | 58 ProgramInfoManager::Program::UniformBlock::UniformBlock() |
48 : binding(0), | 59 : binding(0), |
49 data_size(0), | 60 data_size(0), |
50 referenced_by_vertex_shader(false), | 61 referenced_by_vertex_shader(false), |
51 referenced_by_fragment_shader(false) { | 62 referenced_by_fragment_shader(false) { |
52 } | 63 } |
53 | 64 |
54 ProgramInfoManager::Program::UniformBlock::~UniformBlock() { | 65 ProgramInfoManager::Program::UniformBlock::~UniformBlock() { |
55 } | 66 } |
56 | 67 |
57 ProgramInfoManager::Program::TransformFeedbackVarying:: | 68 ProgramInfoManager::Program::TransformFeedbackVarying:: |
58 TransformFeedbackVarying() | 69 TransformFeedbackVarying() |
59 : size(0), | 70 : size(0), |
60 type(0) { | 71 type(0) { |
61 } | 72 } |
62 | 73 |
63 ProgramInfoManager::Program::TransformFeedbackVarying:: | 74 ProgramInfoManager::Program::TransformFeedbackVarying:: |
64 ~TransformFeedbackVarying() { | 75 ~TransformFeedbackVarying() { |
65 } | 76 } |
66 | 77 |
67 ProgramInfoManager::Program::Program() | 78 ProgramInfoManager::Program::Program() |
68 : cached_es2_(false), | 79 : cached_es2_(false), |
69 max_attrib_name_length_(0), | 80 max_attrib_name_length_(0), |
70 max_uniform_name_length_(0), | 81 max_uniform_name_length_(0), |
71 link_status_(false), | 82 link_status_(false), |
72 cached_es3_uniform_blocks_(false), | 83 cached_es3_uniform_blocks_(false), |
73 active_uniform_block_max_name_length_(0), | 84 active_uniform_block_max_name_length_(0), |
74 cached_es3_transform_feedback_varyings_(false), | 85 cached_es3_transform_feedback_varyings_(false), |
75 transform_feedback_varying_max_length_(0) { | 86 transform_feedback_varying_max_length_(0), |
| 87 cached_es3_uniformsiv_(false) { |
76 } | 88 } |
77 | 89 |
78 ProgramInfoManager::Program::~Program() { | 90 ProgramInfoManager::Program::~Program() { |
79 } | 91 } |
80 | 92 |
81 // TODO(gman): Add a faster lookup. | 93 // TODO(gman): Add a faster lookup. |
82 GLint ProgramInfoManager::Program::GetAttribLocation( | 94 GLint ProgramInfoManager::Program::GetAttribLocation( |
83 const std::string& name) const { | 95 const std::string& name) const { |
84 for (GLuint ii = 0; ii < attrib_infos_.size(); ++ii) { | 96 for (GLuint ii = 0; ii < attrib_infos_.size(); ++ii) { |
85 const VertexAttrib& info = attrib_infos_[ii]; | 97 const VertexAttrib& info = attrib_infos_[ii]; |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
219 uniform_blocks_[index].binding = binding; | 231 uniform_blocks_[index].binding = binding; |
220 } | 232 } |
221 } | 233 } |
222 | 234 |
223 const ProgramInfoManager::Program::TransformFeedbackVarying* | 235 const ProgramInfoManager::Program::TransformFeedbackVarying* |
224 ProgramInfoManager::Program::GetTransformFeedbackVarying(GLuint index) const { | 236 ProgramInfoManager::Program::GetTransformFeedbackVarying(GLuint index) const { |
225 return (index < transform_feedback_varyings_.size()) ? | 237 return (index < transform_feedback_varyings_.size()) ? |
226 &transform_feedback_varyings_[index] : NULL; | 238 &transform_feedback_varyings_[index] : NULL; |
227 } | 239 } |
228 | 240 |
| 241 bool ProgramInfoManager::Program::GetUniformsiv( |
| 242 GLsizei count, const GLuint* indices, GLenum pname, GLint* params) { |
| 243 if (count == 0) { |
| 244 // At this point, pname has already been validated. |
| 245 return true; |
| 246 } |
| 247 DCHECK(count > 0 && indices); |
| 248 size_t num_uniforms = uniform_infos_.size(); |
| 249 if (num_uniforms == 0) { |
| 250 num_uniforms = uniforms_es3_.size(); |
| 251 } |
| 252 if (static_cast<size_t>(count) > num_uniforms) { |
| 253 return false; |
| 254 } |
| 255 for (GLsizei ii = 0; ii < count; ++ii) { |
| 256 if (indices[ii] >= num_uniforms) { |
| 257 return false; |
| 258 } |
| 259 } |
| 260 if (!params) { |
| 261 return true; |
| 262 } |
| 263 switch (pname) { |
| 264 case GL_UNIFORM_SIZE: |
| 265 DCHECK_EQ(num_uniforms, uniform_infos_.size()); |
| 266 for (GLsizei ii = 0; ii < count; ++ii) { |
| 267 params[ii] = static_cast<GLint>(uniform_infos_[indices[ii]].size); |
| 268 } |
| 269 return true; |
| 270 case GL_UNIFORM_TYPE: |
| 271 DCHECK_EQ(num_uniforms, uniform_infos_.size()); |
| 272 for (GLsizei ii = 0; ii < count; ++ii) { |
| 273 params[ii] = static_cast<GLint>(uniform_infos_[indices[ii]].type); |
| 274 } |
| 275 return true; |
| 276 case GL_UNIFORM_NAME_LENGTH: |
| 277 DCHECK_EQ(num_uniforms, uniform_infos_.size()); |
| 278 for (GLsizei ii = 0; ii < count; ++ii) { |
| 279 params[ii] = static_cast<GLint>( |
| 280 uniform_infos_[indices[ii]].name.length() + 1); |
| 281 } |
| 282 return true; |
| 283 case GL_UNIFORM_BLOCK_INDEX: |
| 284 DCHECK_EQ(num_uniforms, uniforms_es3_.size()); |
| 285 for (GLsizei ii = 0; ii < count; ++ii) { |
| 286 params[ii] = uniforms_es3_[indices[ii]].block_index; |
| 287 } |
| 288 return true; |
| 289 case GL_UNIFORM_OFFSET: |
| 290 DCHECK_EQ(num_uniforms, uniforms_es3_.size()); |
| 291 for (GLsizei ii = 0; ii < count; ++ii) { |
| 292 params[ii] = uniforms_es3_[indices[ii]].offset; |
| 293 } |
| 294 return true; |
| 295 case GL_UNIFORM_ARRAY_STRIDE: |
| 296 DCHECK_EQ(num_uniforms, uniforms_es3_.size()); |
| 297 for (GLsizei ii = 0; ii < count; ++ii) { |
| 298 params[ii] = uniforms_es3_[indices[ii]].array_stride; |
| 299 } |
| 300 return true; |
| 301 case GL_UNIFORM_MATRIX_STRIDE: |
| 302 DCHECK_EQ(num_uniforms, uniforms_es3_.size()); |
| 303 for (GLsizei ii = 0; ii < count; ++ii) { |
| 304 params[ii] = uniforms_es3_[indices[ii]].matrix_stride; |
| 305 } |
| 306 return true; |
| 307 case GL_UNIFORM_IS_ROW_MAJOR: |
| 308 DCHECK_EQ(num_uniforms, uniforms_es3_.size()); |
| 309 for (GLsizei ii = 0; ii < count; ++ii) { |
| 310 params[ii] = uniforms_es3_[indices[ii]].is_row_major; |
| 311 } |
| 312 return true; |
| 313 default: |
| 314 NOTREACHED(); |
| 315 break; |
| 316 } |
| 317 return false; |
| 318 } |
| 319 |
229 void ProgramInfoManager::Program::UpdateES2(const std::vector<int8>& result) { | 320 void ProgramInfoManager::Program::UpdateES2(const std::vector<int8>& result) { |
230 if (cached_es2_) { | 321 if (cached_es2_) { |
231 return; | 322 return; |
232 } | 323 } |
233 if (result.empty()) { | 324 if (result.empty()) { |
234 // This should only happen on a lost context. | 325 // This should only happen on a lost context. |
235 return; | 326 return; |
236 } | 327 } |
237 DCHECK_GE(result.size(), sizeof(ProgramInfoHeader)); | 328 DCHECK_GE(result.size(), sizeof(ProgramInfoHeader)); |
238 const ProgramInfoHeader* header = LocalGetAs<const ProgramInfoHeader*>( | 329 const ProgramInfoHeader* header = LocalGetAs<const ProgramInfoHeader*>( |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
346 uniform_blocks_[ii].active_uniform_indices[uu] = | 437 uniform_blocks_[ii].active_uniform_indices[uu] = |
347 static_cast<GLuint>(indices[uu]); | 438 static_cast<GLuint>(indices[uu]); |
348 } | 439 } |
349 indices += entries[ii].active_uniforms; | 440 indices += entries[ii].active_uniforms; |
350 data = reinterpret_cast<const char*>(indices); | 441 data = reinterpret_cast<const char*>(indices); |
351 } | 442 } |
352 DCHECK_EQ(data_size, size); | 443 DCHECK_EQ(data_size, size); |
353 cached_es3_uniform_blocks_ = true; | 444 cached_es3_uniform_blocks_ = true; |
354 } | 445 } |
355 | 446 |
| 447 void ProgramInfoManager::Program::UpdateES3Uniformsiv( |
| 448 const std::vector<int8>& result) { |
| 449 if (cached_es3_uniformsiv_) { |
| 450 return; |
| 451 } |
| 452 if (result.empty()) { |
| 453 // This should only happen on a lost context. |
| 454 return; |
| 455 } |
| 456 uniforms_es3_.clear(); |
| 457 |
| 458 // |result| comes from GPU process. We consider it trusted data. Therefore, |
| 459 // no need to check for overflows as the GPU side did the checks already. |
| 460 uint32_t header_size = sizeof(UniformsES3Header); |
| 461 DCHECK_GE(result.size(), header_size); |
| 462 const UniformsES3Header* header = LocalGetAs<const UniformsES3Header*>( |
| 463 result, 0, header_size); |
| 464 DCHECK(header); |
| 465 if (header->num_uniforms == 0) { |
| 466 DCHECK_EQ(result.size(), header_size); |
| 467 // TODO(zmo): Here we can't tell if no uniforms are defined, or |
| 468 // the previous link failed. |
| 469 return; |
| 470 } |
| 471 uniforms_es3_.resize(header->num_uniforms); |
| 472 |
| 473 uint32_t entry_size = sizeof(UniformES3Info) * header->num_uniforms; |
| 474 DCHECK_EQ(result.size(), header_size + entry_size); |
| 475 const UniformES3Info* entries = LocalGetAs<const UniformES3Info*>( |
| 476 result, header_size, entry_size); |
| 477 DCHECK(entries); |
| 478 |
| 479 for (uint32_t ii = 0; ii < header->num_uniforms; ++ii) { |
| 480 uniforms_es3_[ii].block_index = entries[ii].block_index; |
| 481 uniforms_es3_[ii].offset = entries[ii].offset; |
| 482 uniforms_es3_[ii].array_stride = entries[ii].array_stride; |
| 483 uniforms_es3_[ii].matrix_stride = entries[ii].matrix_stride; |
| 484 uniforms_es3_[ii].is_row_major = entries[ii].is_row_major; |
| 485 } |
| 486 cached_es3_uniformsiv_ = true; |
| 487 } |
| 488 |
356 void ProgramInfoManager::Program::UpdateES3TransformFeedbackVaryings( | 489 void ProgramInfoManager::Program::UpdateES3TransformFeedbackVaryings( |
357 const std::vector<int8>& result) { | 490 const std::vector<int8>& result) { |
358 if (cached_es3_transform_feedback_varyings_) { | 491 if (cached_es3_transform_feedback_varyings_) { |
359 return; | 492 return; |
360 } | 493 } |
361 if (result.empty()) { | 494 if (result.empty()) { |
362 // This should only happen on a lost context. | 495 // This should only happen on a lost context. |
363 return; | 496 return; |
364 } | 497 } |
365 transform_feedback_varyings_.clear(); | 498 transform_feedback_varyings_.clear(); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 } | 548 } |
416 | 549 |
417 bool ProgramInfoManager::Program::IsCached(ProgramInfoType type) const { | 550 bool ProgramInfoManager::Program::IsCached(ProgramInfoType type) const { |
418 switch (type) { | 551 switch (type) { |
419 case kES2: | 552 case kES2: |
420 return cached_es2_; | 553 return cached_es2_; |
421 case kES3UniformBlocks: | 554 case kES3UniformBlocks: |
422 return cached_es3_uniform_blocks_; | 555 return cached_es3_uniform_blocks_; |
423 case kES3TransformFeedbackVaryings: | 556 case kES3TransformFeedbackVaryings: |
424 return cached_es3_transform_feedback_varyings_; | 557 return cached_es3_transform_feedback_varyings_; |
| 558 case kES3Uniformsiv: |
| 559 return cached_es3_uniformsiv_; |
425 case kNone: | 560 case kNone: |
426 return true; | 561 return true; |
427 default: | 562 default: |
428 NOTREACHED(); | 563 NOTREACHED(); |
429 return true; | 564 return true; |
430 } | 565 } |
431 } | 566 } |
432 | 567 |
433 | 568 |
434 ProgramInfoManager::ProgramInfoManager() { | 569 ProgramInfoManager::ProgramInfoManager() { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
469 info->UpdateES3UniformBlocks(result); | 604 info->UpdateES3UniformBlocks(result); |
470 break; | 605 break; |
471 case kES3TransformFeedbackVaryings: | 606 case kES3TransformFeedbackVaryings: |
472 { | 607 { |
473 base::AutoUnlock unlock(lock_); | 608 base::AutoUnlock unlock(lock_); |
474 // lock_ can't be held across IPC call or else it may deadlock in | 609 // lock_ can't be held across IPC call or else it may deadlock in |
475 // pepper. http://crbug.com/418651 | 610 // pepper. http://crbug.com/418651 |
476 gl->GetTransformFeedbackVaryingsCHROMIUMHelper(program, &result); | 611 gl->GetTransformFeedbackVaryingsCHROMIUMHelper(program, &result); |
477 } | 612 } |
478 info->UpdateES3TransformFeedbackVaryings(result); | 613 info->UpdateES3TransformFeedbackVaryings(result); |
| 614 case kES3Uniformsiv: |
| 615 { |
| 616 base::AutoUnlock unlock(lock_); |
| 617 // lock_ can't be held across IPC call or else it may deadlock in |
| 618 // pepper. http://crbug.com/418651 |
| 619 gl->GetUniformsES3CHROMIUMHelper(program, &result); |
| 620 } |
| 621 info->UpdateES3Uniformsiv(result); |
479 default: | 622 default: |
480 NOTREACHED(); | 623 NOTREACHED(); |
481 return NULL; | 624 return NULL; |
482 } | 625 } |
483 return info; | 626 return info; |
484 } | 627 } |
485 | 628 |
486 void ProgramInfoManager::CreateInfo(GLuint program) { | 629 void ProgramInfoManager::CreateInfo(GLuint program) { |
487 base::AutoLock auto_lock(lock_); | 630 base::AutoLock auto_lock(lock_); |
488 program_infos_.erase(program); | 631 program_infos_.erase(program); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 default: | 663 default: |
521 return false; | 664 return false; |
522 } | 665 } |
523 Program* info = GetProgramInfo(gl, program, type); | 666 Program* info = GetProgramInfo(gl, program, type); |
524 if (!info) { | 667 if (!info) { |
525 return false; | 668 return false; |
526 } | 669 } |
527 return info->GetProgramiv(pname, params); | 670 return info->GetProgramiv(pname, params); |
528 } | 671 } |
529 | 672 |
| 673 bool ProgramInfoManager::GetActiveUniformsiv( |
| 674 GLES2Implementation* gl, GLuint program, GLsizei count, |
| 675 const GLuint* indices, GLenum pname, GLint* params) { |
| 676 base::AutoLock auto_lock(lock_); |
| 677 ProgramInfoType type = kNone; |
| 678 switch (pname) { |
| 679 case GL_UNIFORM_SIZE: |
| 680 case GL_UNIFORM_TYPE: |
| 681 case GL_UNIFORM_NAME_LENGTH: |
| 682 type = kES2; |
| 683 break; |
| 684 case GL_UNIFORM_BLOCK_INDEX: |
| 685 case GL_UNIFORM_OFFSET: |
| 686 case GL_UNIFORM_ARRAY_STRIDE: |
| 687 case GL_UNIFORM_MATRIX_STRIDE: |
| 688 case GL_UNIFORM_IS_ROW_MAJOR: |
| 689 type = kES3Uniformsiv; |
| 690 break; |
| 691 default: |
| 692 return false; |
| 693 } |
| 694 Program* info = GetProgramInfo(gl, program, type); |
| 695 if (info) { |
| 696 return info->GetUniformsiv(count, indices, pname, params); |
| 697 } |
| 698 return gl->GetActiveUniformsivHelper(program, count, indices, pname, params); |
| 699 } |
| 700 |
530 GLint ProgramInfoManager::GetAttribLocation( | 701 GLint ProgramInfoManager::GetAttribLocation( |
531 GLES2Implementation* gl, GLuint program, const char* name) { | 702 GLES2Implementation* gl, GLuint program, const char* name) { |
532 { | 703 { |
533 base::AutoLock auto_lock(lock_); | 704 base::AutoLock auto_lock(lock_); |
534 Program* info = GetProgramInfo(gl, program, kES2); | 705 Program* info = GetProgramInfo(gl, program, kES2); |
535 if (info) { | 706 if (info) { |
536 return info->GetAttribLocation(name); | 707 return info->GetAttribLocation(name); |
537 } | 708 } |
538 } | 709 } |
539 return gl->GetAttribLocationHelper(program, name); | 710 return gl->GetAttribLocationHelper(program, name); |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
820 } | 991 } |
821 return true; | 992 return true; |
822 } | 993 } |
823 } | 994 } |
824 return gl->GetUniformIndicesHelper(program, count, names, indices); | 995 return gl->GetUniformIndicesHelper(program, count, names, indices); |
825 } | 996 } |
826 | 997 |
827 } // namespace gles2 | 998 } // namespace gles2 |
828 } // namespace gpu | 999 } // namespace gpu |
829 | 1000 |
OLD | NEW |