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. 4 5 #include "gpu/command_buffer/service/program_manager.h" 6 7 #include <algorithm> 8 #include <set> 9 #include <utility> 10 #include <vector> 11 12 #include "base/basictypes.h" 13 #include "base/command_line.h" 14 #include "base/logging.h" 15 #include "base/memory/scoped_ptr.h" 16 #include "base/metrics/histogram.h" 17 #include "base/strings/string_number_conversions.h" 18 #include "base/time/time.h" 19 #include "gpu/command_buffer/common/gles2_cmd_format.h" 20 #include "gpu/command_buffer/common/gles2_cmd_utils.h" 21 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" 22 #include "gpu/command_buffer/service/gpu_switches.h" 23 #include "gpu/command_buffer/service/program_cache.h" 24 #include "gpu/command_buffer/service/shader_manager.h" 25 #include "gpu/command_buffer/service/shader_translator.h" 26 #include "third_party/re2/re2/re2.h" 27 28 using base::TimeDelta; 29 using base::TimeTicks; 30 31 namespace gpu { 32 namespace gles2 { 33 34 namespace { 35 36 struct UniformType { 37 explicit UniformType(const ShaderTranslator::VariableInfo uniform) 38 : type(uniform.type), 39 size(uniform.size), 40 precision(uniform.precision) { } 41 42 UniformType() 43 : type(0), 44 size(0), 45 precision(SH_PRECISION_MEDIUMP) { } 46 47 bool operator==(const UniformType& other) const { 48 return type == other.type && 49 size == other.size && 50 precision == other.precision; 51 } 52 53 int type; 54 int size; 55 int precision; 56 }; 57 58 int ShaderTypeToIndex(GLenum shader_type) { 59 switch (shader_type) { 60 case GL_VERTEX_SHADER: 61 return 0; 62 case GL_FRAGMENT_SHADER: 63 return 1; 64 default: 65 NOTREACHED(); 66 return 0; 67 } 68 } 69 70 // Given a name like "foo.bar[123].moo[456]" sets new_name to "foo.bar[123].moo" 71 // and sets element_index to 456. returns false if element expression was not a 72 // whole decimal number. For example: "foo[1b2]" 73 bool GetUniformNameSansElement( 74 const std::string& name, int* element_index, std::string* new_name) { 75 DCHECK(element_index); 76 DCHECK(new_name); 77 if (name.size() < 3 || name[name.size() - 1] != ']') { 78 *element_index = 0; 79 *new_name = name; 80 return true; 81 } 82 83 // Look for an array specification. 84 size_t open_pos = name.find_last_of('['); 85 if (open_pos == std::string::npos || 86 open_pos >= name.size() - 2) { 87 return false; 88 } 89 90 GLint index = 0; 91 size_t last = name.size() - 1; 92 for (size_t pos = open_pos + 1; pos < last; ++pos) { 93 int8 digit = name[pos] - '0'; 94 if (digit < 0 || digit > 9) { 95 return false; 96 } 97 index = index * 10 + digit; 98 } 99 100 *element_index = index; 101 *new_name = name.substr(0, open_pos); 102 return true; 103 } 104 105 bool IsBuiltInVarying(const std::string& name) { 106 // Built-in variables. 107 const char* kBuiltInVaryings[] = { 108 "gl_FragCoord", 109 "gl_FrontFacing", 110 "gl_PointCoord" 111 }; 112 for (size_t ii = 0; ii < arraysize(kBuiltInVaryings); ++ii) { 113 if (name == kBuiltInVaryings[ii]) 114 return true; 115 } 116 return false; 117 } 118 119 } // anonymous namespace. 120 121 Program::UniformInfo::UniformInfo() 122 : size(0), 123 type(GL_NONE), 124 fake_location_base(0), 125 is_array(false) { 126 } 127 128 Program::UniformInfo::UniformInfo(GLsizei _size, 129 GLenum _type, 130 int _fake_location_base, 131 const std::string& _name) 132 : size(_size), 133 type(_type), 134 accepts_api_type(0), 135 fake_location_base(_fake_location_base), 136 is_array(false), 137 name(_name) { 138 switch (type) { 139 case GL_INT: 140 accepts_api_type = kUniform1i; 141 break; 142 case GL_INT_VEC2: 143 accepts_api_type = kUniform2i; 144 break; 145 case GL_INT_VEC3: 146 accepts_api_type = kUniform3i; 147 break; 148 case GL_INT_VEC4: 149 accepts_api_type = kUniform4i; 150 break; 151 152 case GL_BOOL: 153 accepts_api_type = kUniform1i | kUniform1f; 154 break; 155 case GL_BOOL_VEC2: 156 accepts_api_type = kUniform2i | kUniform2f; 157 break; 158 case GL_BOOL_VEC3: 159 accepts_api_type = kUniform3i | kUniform3f; 160 break; 161 case GL_BOOL_VEC4: 162 accepts_api_type = kUniform4i | kUniform4f; 163 break; 164 165 case GL_FLOAT: 166 accepts_api_type = kUniform1f; 167 break; 168 case GL_FLOAT_VEC2: 169 accepts_api_type = kUniform2f; 170 break; 171 case GL_FLOAT_VEC3: 172 accepts_api_type = kUniform3f; 173 break; 174 case GL_FLOAT_VEC4: 175 accepts_api_type = kUniform4f; 176 break; 177 178 case GL_FLOAT_MAT2: 179 accepts_api_type = kUniformMatrix2f; 180 break; 181 case GL_FLOAT_MAT3: 182 accepts_api_type = kUniformMatrix3f; 183 break; 184 case GL_FLOAT_MAT4: 185 accepts_api_type = kUniformMatrix4f; 186 break; 187 188 case GL_SAMPLER_2D: 189 case GL_SAMPLER_2D_RECT_ARB: 190 case GL_SAMPLER_CUBE: 191 case GL_SAMPLER_3D_OES: 192 case GL_SAMPLER_EXTERNAL_OES: 193 accepts_api_type = kUniform1i; 194 break; 195 default: 196 NOTREACHED() << "Unhandled UniformInfo type " << type; 197 break; 198 } 199 } 200 201 Program::UniformInfo::~UniformInfo() {} 202 203 bool ProgramManager::IsInvalidPrefix(const char* name, size_t length) { 204 static const char kInvalidPrefix[] = { 'g', 'l', '_' }; 205 return (length >= sizeof(kInvalidPrefix) && 206 memcmp(name, kInvalidPrefix, sizeof(kInvalidPrefix)) == 0); 207 } 208 209 Program::Program( 210 ProgramManager* manager, GLuint service_id) 211 : manager_(manager), 212 use_count_(0), 213 max_attrib_name_length_(0), 214 max_uniform_name_length_(0), 215 service_id_(service_id), 216 deleted_(false), 217 valid_(false), 218 link_status_(false), 219 uniforms_cleared_(false), 220 num_uniforms_(0) { 221 manager_->StartTracking(this); 222 } 223 224 void Program::Reset() { 225 valid_ = false; 226 link_status_ = false; 227 num_uniforms_ = 0; 228 max_uniform_name_length_ = 0; 229 max_attrib_name_length_ = 0; 230 attrib_infos_.clear(); 231 uniform_infos_.clear(); 232 sampler_indices_.clear(); 233 attrib_location_to_index_map_.clear(); 234 } 235 236 std::string Program::ProcessLogInfo( 237 const std::string& log) { 238 std::string output; 239 re2::StringPiece input(log); 240 std::string prior_log; 241 std::string hashed_name; 242 while (RE2::Consume(&input, 243 "(.*?)(webgl_[0123456789abcdefABCDEF]+)", 244 &prior_log, 245 &hashed_name)) { 246 output += prior_log; 247 248 const std::string* original_name = 249 GetOriginalNameFromHashedName(hashed_name); 250 if (original_name) 251 output += *original_name; 252 else 253 output += hashed_name; 254 } 255 256 return output + input.as_string(); 257 } 258 259 void Program::UpdateLogInfo() { 260 GLint max_len = 0; 261 glGetProgramiv(service_id_, GL_INFO_LOG_LENGTH, &max_len); 262 if (max_len == 0) { 263 set_log_info(NULL); 264 return; 265 } 266 scoped_ptr<char[]> temp(new char[max_len]); 267 GLint len = 0; 268 glGetProgramInfoLog(service_id_, max_len, &len, temp.get()); 269 DCHECK(max_len == 0 || len < max_len); 270 DCHECK(len == 0 || temp[len] == '\0'); 271 std::string log(temp.get(), len); 272 set_log_info(ProcessLogInfo(log).c_str()); 273 } 274 275 void Program::ClearUniforms( 276 std::vector<uint8>* zero_buffer) { 277 DCHECK(zero_buffer); 278 if (uniforms_cleared_) { 279 return; 280 } 281 uniforms_cleared_ = true; 282 for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) { 283 const UniformInfo& uniform_info = uniform_infos_[ii]; 284 if (!uniform_info.IsValid()) { 285 continue; 286 } 287 GLint location = uniform_info.element_locations[0]; 288 GLsizei size = uniform_info.size; 289 uint32 unit_size = GLES2Util::GetGLDataTypeSizeForUniforms( 290 uniform_info.type); 291 uint32 size_needed = size * unit_size; 292 if (size_needed > zero_buffer->size()) { 293 zero_buffer->resize(size_needed, 0u); 294 } 295 const void* zero = &(*zero_buffer)[0]; 296 switch (uniform_info.type) { 297 case GL_FLOAT: 298 glUniform1fv(location, size, reinterpret_cast<const GLfloat*>(zero)); 299 break; 300 case GL_FLOAT_VEC2: 301 glUniform2fv(location, size, reinterpret_cast<const GLfloat*>(zero)); 302 break; 303 case GL_FLOAT_VEC3: 304 glUniform3fv(location, size, reinterpret_cast<const GLfloat*>(zero)); 305 break; 306 case GL_FLOAT_VEC4: 307 glUniform4fv(location, size, reinterpret_cast<const GLfloat*>(zero)); 308 break; 309 case GL_INT: 310 case GL_BOOL: 311 case GL_SAMPLER_2D: 312 case GL_SAMPLER_CUBE: 313 case GL_SAMPLER_EXTERNAL_OES: 314 case GL_SAMPLER_3D_OES: 315 case GL_SAMPLER_2D_RECT_ARB: 316 glUniform1iv(location, size, reinterpret_cast<const GLint*>(zero)); 317 break; 318 case GL_INT_VEC2: 319 case GL_BOOL_VEC2: 320 glUniform2iv(location, size, reinterpret_cast<const GLint*>(zero)); 321 break; 322 case GL_INT_VEC3: 323 case GL_BOOL_VEC3: 324 glUniform3iv(location, size, reinterpret_cast<const GLint*>(zero)); 325 break; 326 case GL_INT_VEC4: 327 case GL_BOOL_VEC4: 328 glUniform4iv(location, size, reinterpret_cast<const GLint*>(zero)); 329 break; 330 case GL_FLOAT_MAT2: 331 glUniformMatrix2fv( 332 location, size, false, reinterpret_cast<const GLfloat*>(zero)); 333 break; 334 case GL_FLOAT_MAT3: 335 glUniformMatrix3fv( 336 location, size, false, reinterpret_cast<const GLfloat*>(zero)); 337 break; 338 case GL_FLOAT_MAT4: 339 glUniformMatrix4fv( 340 location, size, false, reinterpret_cast<const GLfloat*>(zero)); 341 break; 342 default: 343 NOTREACHED(); 344 break; 345 } 346 } 347 } 348 349 namespace { 350 351 struct UniformData { 352 UniformData() : size(-1), type(GL_NONE), location(0), added(false) { 353 } 354 std::string queried_name; 355 std::string corrected_name; 356 std::string original_name; 357 GLsizei size; 358 GLenum type; 359 GLint location; 360 bool added; 361 }; 362 363 struct UniformDataComparer { 364 bool operator()(const UniformData& lhs, const UniformData& rhs) const { 365 return lhs.queried_name < rhs.queried_name; 366 } 367 }; 368 369 } // anonymous namespace 370 371 void Program::Update() { 372 Reset(); 373 UpdateLogInfo(); 374 link_status_ = true; 375 uniforms_cleared_ = false; 376 GLint num_attribs = 0; 377 GLint max_len = 0; 378 GLint max_location = -1; 379 glGetProgramiv(service_id_, GL_ACTIVE_ATTRIBUTES, &num_attribs); 380 glGetProgramiv(service_id_, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_len); 381 // TODO(gman): Should we check for error? 382 scoped_ptr<char[]> name_buffer(new char[max_len]); 383 for (GLint ii = 0; ii < num_attribs; ++ii) { 384 GLsizei length = 0; 385 GLsizei size = 0; 386 GLenum type = 0; 387 glGetActiveAttrib( 388 service_id_, ii, max_len, &length, &size, &type, name_buffer.get()); 389 DCHECK(max_len == 0 || length < max_len); 390 DCHECK(length == 0 || name_buffer[length] == '\0'); 391 if (!ProgramManager::IsInvalidPrefix(name_buffer.get(), length)) { 392 std::string name; 393 std::string original_name; 394 GetCorrectedVariableInfo( 395 false, name_buffer.get(), &name, &original_name, &size, &type); 396 // TODO(gman): Should we check for error? 397 GLint location = glGetAttribLocation(service_id_, name_buffer.get()); 398 if (location > max_location) { 399 max_location = location; 400 } 401 attrib_infos_.push_back( 402 VertexAttrib(size, type, original_name, location)); 403 max_attrib_name_length_ = std::max( 404 max_attrib_name_length_, static_cast<GLsizei>(original_name.size())); 405 } 406 } 407 408 // Create attrib location to index map. 409 attrib_location_to_index_map_.resize(max_location + 1); 410 for (GLint ii = 0; ii <= max_location; ++ii) { 411 attrib_location_to_index_map_[ii] = -1; 412 } 413 for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) { 414 const VertexAttrib& info = attrib_infos_[ii]; 415 attrib_location_to_index_map_[info.location] = ii; 416 } 417 418 #if !defined(NDEBUG) 419 if (CommandLine::ForCurrentProcess()->HasSwitch( 420 switches::kEnableGPUServiceLoggingGPU)) { 421 DVLOG(1) << "----: attribs for service_id: " << service_id(); 422 for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) { 423 const VertexAttrib& info = attrib_infos_[ii]; 424 DVLOG(1) << ii << ": loc = " << info.location 425 << ", size = " << info.size 426 << ", type = " << GLES2Util::GetStringEnum(info.type) 427 << ", name = " << info.name; 428 } 429 } 430 #endif 431 432 max_len = 0; 433 GLint num_uniforms = 0; 434 glGetProgramiv(service_id_, GL_ACTIVE_UNIFORMS, &num_uniforms); 435 glGetProgramiv(service_id_, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_len); 436 name_buffer.reset(new char[max_len]); 437 438 // Reads all the names. 439 std::vector<UniformData> uniform_data; 440 for (GLint ii = 0; ii < num_uniforms; ++ii) { 441 GLsizei length = 0; 442 UniformData data; 443 glGetActiveUniform( 444 service_id_, ii, max_len, &length, 445 &data.size, &data.type, name_buffer.get()); 446 DCHECK(max_len == 0 || length < max_len); 447 DCHECK(length == 0 || name_buffer[length] == '\0'); 448 if (!ProgramManager::IsInvalidPrefix(name_buffer.get(), length)) { 449 data.queried_name = std::string(name_buffer.get()); 450 GetCorrectedVariableInfo( 451 true, name_buffer.get(), &data.corrected_name, &data.original_name, 452 &data.size, &data.type); 453 uniform_data.push_back(data); 454 } 455 } 456 457 // NOTE: We don't care if 2 uniforms are bound to the same location. 458 // One of them will take preference. The spec allows this, same as 459 // BindAttribLocation. 460 // 461 // The reason we don't check is if we were to fail we'd have to 462 // restore the previous program but since we've already linked successfully 463 // at this point the previous program is gone. 464 465 // Assigns the uniforms with bindings. 466 size_t next_available_index = 0; 467 for (size_t ii = 0; ii < uniform_data.size(); ++ii) { 468 UniformData& data = uniform_data[ii]; 469 data.location = glGetUniformLocation( 470 service_id_, data.queried_name.c_str()); 471 // remove "[0]" 472 std::string short_name; 473 int element_index = 0; 474 bool good ALLOW_UNUSED = GetUniformNameSansElement( 475 data.queried_name, &element_index, &short_name);\ 476 DCHECK(good); 477 LocationMap::const_iterator it = bind_uniform_location_map_.find( 478 short_name); 479 if (it != bind_uniform_location_map_.end()) { 480 data.added = AddUniformInfo( 481 data.size, data.type, data.location, it->second, data.corrected_name, 482 data.original_name, &next_available_index); 483 } 484 } 485 486 // Assigns the uniforms that were not bound. 487 for (size_t ii = 0; ii < uniform_data.size(); ++ii) { 488 const UniformData& data = uniform_data[ii]; 489 if (!data.added) { 490 AddUniformInfo( 491 data.size, data.type, data.location, -1, data.corrected_name, 492 data.original_name, &next_available_index); 493 } 494 } 495 496 #if !defined(NDEBUG) 497 if (CommandLine::ForCurrentProcess()->HasSwitch( 498 switches::kEnableGPUServiceLoggingGPU)) { 499 DVLOG(1) << "----: uniforms for service_id: " << service_id(); 500 for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) { 501 const UniformInfo& info = uniform_infos_[ii]; 502 if (info.IsValid()) { 503 DVLOG(1) << ii << ": loc = " << info.element_locations[0] 504 << ", size = " << info.size 505 << ", type = " << GLES2Util::GetStringEnum(info.type) 506 << ", name = " << info.name; 507 } 508 } 509 } 510 #endif 511 512 valid_ = true; 513 } 514 515 void Program::ExecuteBindAttribLocationCalls() { 516 for (LocationMap::const_iterator it = bind_attrib_location_map_.begin(); 517 it != bind_attrib_location_map_.end(); ++it) { 518 const std::string* mapped_name = GetAttribMappedName(it->first); 519 if (mapped_name && *mapped_name != it->first) 520 glBindAttribLocation(service_id_, it->second, mapped_name->c_str()); 521 } 522 } 523 524 void ProgramManager::DoCompileShader( 525 Shader* shader, 526 ShaderTranslator* translator, 527 ProgramManager::TranslatedShaderSourceType translated_shader_source_type) { 528 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to 529 // glShaderSource and then glCompileShader. 530 const std::string* source = shader->source(); 531 const char* shader_src = source ? source->c_str() : ""; 532 if (translator) { 533 if (!translator->Translate(shader_src)) { 534 shader->SetStatus(false, translator->info_log(), NULL); 535 return; 536 } 537 shader_src = translator->translated_shader(); 538 if (translated_shader_source_type != kANGLE) 539 shader->UpdateTranslatedSource(shader_src); 540 } 541 542 glShaderSource(shader->service_id(), 1, &shader_src, NULL); 543 glCompileShader(shader->service_id()); 544 if (translated_shader_source_type == kANGLE) { 545 GLint max_len = 0; 546 glGetShaderiv(shader->service_id(), 547 GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE, 548 &max_len); 549 scoped_ptr<char[]> temp(new char[max_len]); 550 GLint len = 0; 551 glGetTranslatedShaderSourceANGLE( 552 shader->service_id(), max_len, &len, temp.get()); 553 DCHECK(max_len == 0 || len < max_len); 554 DCHECK(len == 0 || temp[len] == '\0'); 555 shader->UpdateTranslatedSource(max_len ? temp.get() : NULL); 556 } 557 558 GLint status = GL_FALSE; 559 glGetShaderiv(shader->service_id(), GL_COMPILE_STATUS, &status); 560 if (status) { 561 shader->SetStatus(true, "", translator); 562 } else { 563 // We cannot reach here if we are using the shader translator. 564 // All invalid shaders must be rejected by the translator. 565 // All translated shaders must compile. 566 GLint max_len = 0; 567 glGetShaderiv(shader->service_id(), GL_INFO_LOG_LENGTH, &max_len); 568 scoped_ptr<char[]> temp(new char[max_len]); 569 GLint len = 0; 570 glGetShaderInfoLog(shader->service_id(), max_len, &len, temp.get()); 571 DCHECK(max_len == 0 || len < max_len); 572 DCHECK(len == 0 || temp[len] == '\0'); 573 shader->SetStatus(false, std::string(temp.get(), len).c_str(), NULL); 574 LOG_IF(ERROR, translator) 575 << "Shader translator allowed/produced an invalid shader " 576 << "unless the driver is buggy:" 577 << "\n--original-shader--\n" << (source ? *source : std::string()) 578 << "\n--translated-shader--\n" << shader_src << "\n--info-log--\n" 579 << *shader->log_info(); 580 } 581 } 582 583 bool Program::Link(ShaderManager* manager, 584 ShaderTranslator* vertex_translator, 585 ShaderTranslator* fragment_translator, 586 Program::VaryingsPackingOption varyings_packing_option, 587 const ShaderCacheCallback& shader_callback) { 588 ClearLinkStatus(); 589 if (!CanLink()) { 590 set_log_info("missing shaders"); 591 return false; 592 } 593 if (DetectAttribLocationBindingConflicts()) { 594 set_log_info("glBindAttribLocation() conflicts"); 595 return false; 596 } 597 std::string conflicting_name; 598 if (DetectUniformsMismatch(&conflicting_name)) { 599 std::string info_log = "Uniforms with the same name but different " 600 "type/precision: " + conflicting_name; 601 set_log_info(ProcessLogInfo(info_log).c_str()); 602 return false; 603 } 604 if (DetectVaryingsMismatch(&conflicting_name)) { 605 std::string info_log = "Varyings with the same name but different type, " 606 "or statically used varyings in fragment shader are " 607 "not declared in vertex shader: " + conflicting_name; 608 set_log_info(ProcessLogInfo(info_log).c_str()); 609 return false; 610 } 611 if (DetectGlobalNameConflicts(&conflicting_name)) { 612 std::string info_log = "Name conflicts between an uniform and an " 613 "attribute: " + conflicting_name; 614 set_log_info(ProcessLogInfo(info_log).c_str()); 615 return false; 616 } 617 if (!CheckVaryingsPacking(varyings_packing_option)) { 618 set_log_info("Varyings over maximum register limit"); 619 return false; 620 } 621 622 TimeTicks before_time = TimeTicks::HighResNow(); 623 bool link = true; 624 ProgramCache* cache = manager_->program_cache_; 625 if (cache) { 626 DCHECK(attached_shaders_[0]->signature_source() && 627 attached_shaders_[1]->signature_source()); 628 ProgramCache::LinkedProgramStatus status = cache->GetLinkedProgramStatus( 629 *attached_shaders_[0]->signature_source(), 630 vertex_translator, 631 *attached_shaders_[1]->signature_source(), 632 fragment_translator, 633 &bind_attrib_location_map_); 634 635 if (status == ProgramCache::LINK_SUCCEEDED) { 636 ProgramCache::ProgramLoadResult success = 637 cache->LoadLinkedProgram(service_id(), 638 attached_shaders_[0].get(), 639 vertex_translator, 640 attached_shaders_[1].get(), 641 fragment_translator, 642 &bind_attrib_location_map_, 643 shader_callback); 644 link = success != ProgramCache::PROGRAM_LOAD_SUCCESS; 645 UMA_HISTOGRAM_BOOLEAN("GPU.ProgramCache.LoadBinarySuccess", !link); 646 } 647 } 648 649 if (link) { 650 ExecuteBindAttribLocationCalls(); 651 before_time = TimeTicks::HighResNow(); 652 if (cache && gfx::g_driver_gl.ext.b_GL_ARB_get_program_binary) { 653 glProgramParameteri(service_id(), 654 PROGRAM_BINARY_RETRIEVABLE_HINT, 655 GL_TRUE); 656 } 657 glLinkProgram(service_id()); 658 } 659 660 GLint success = 0; 661 glGetProgramiv(service_id(), GL_LINK_STATUS, &success); 662 if (success == GL_TRUE) { 663 Update(); 664 if (link) { 665 if (cache) { 666 cache->SaveLinkedProgram(service_id(), 667 attached_shaders_[0].get(), 668 vertex_translator, 669 attached_shaders_[1].get(), 670 fragment_translator, 671 &bind_attrib_location_map_, 672 shader_callback); 673 } 674 UMA_HISTOGRAM_CUSTOM_COUNTS( 675 "GPU.ProgramCache.BinaryCacheMissTime", 676 (TimeTicks::HighResNow() - before_time).InMicroseconds(), 677 0, 678 TimeDelta::FromSeconds(10).InMicroseconds(), 679 50); 680 } else { 681 UMA_HISTOGRAM_CUSTOM_COUNTS( 682 "GPU.ProgramCache.BinaryCacheHitTime", 683 (TimeTicks::HighResNow() - before_time).InMicroseconds(), 684 0, 685 TimeDelta::FromSeconds(1).InMicroseconds(), 686 50); 687 } 688 } else { 689 UpdateLogInfo(); 690 } 691 return success == GL_TRUE; 692 } 693 694 void Program::Validate() { 695 if (!IsValid()) { 696 set_log_info("program not linked"); 697 return; 698 } 699 glValidateProgram(service_id()); 700 UpdateLogInfo(); 701 } 702 703 GLint Program::GetUniformFakeLocation( 704 const std::string& name) const { 705 bool getting_array_location = false; 706 size_t open_pos = std::string::npos; 707 int index = 0; 708 if (!GLES2Util::ParseUniformName( 709 name, &open_pos, &index, &getting_array_location)) { 710 return -1; 711 } 712 for (GLuint ii = 0; ii < uniform_infos_.size(); ++ii) { 713 const UniformInfo& info = uniform_infos_[ii]; 714 if (!info.IsValid()) { 715 continue; 716 } 717 if (info.name == name || 718 (info.is_array && 719 info.name.compare(0, info.name.size() - 3, name) == 0)) { 720 return info.fake_location_base; 721 } else if (getting_array_location && info.is_array) { 722 // Look for an array specification. 723 size_t open_pos_2 = info.name.find_last_of('['); 724 if (open_pos_2 == open_pos && 725 name.compare(0, open_pos, info.name, 0, open_pos) == 0) { 726 if (index >= 0 && index < info.size) { 727 DCHECK_GT(static_cast<int>(info.element_locations.size()), index); 728 if (info.element_locations[index] == -1) 729 return -1; 730 return ProgramManager::MakeFakeLocation( 731 info.fake_location_base, index); 732 } 733 } 734 } 735 } 736 return -1; 737 } 738 739 GLint Program::GetAttribLocation( 740 const std::string& name) const { 741 for (GLuint ii = 0; ii < attrib_infos_.size(); ++ii) { 742 const VertexAttrib& info = attrib_infos_[ii]; 743 if (info.name == name) { 744 return info.location; 745 } 746 } 747 return -1; 748 } 749 750 const Program::UniformInfo* 751 Program::GetUniformInfoByFakeLocation( 752 GLint fake_location, GLint* real_location, GLint* array_index) const { 753 DCHECK(real_location); 754 DCHECK(array_index); 755 if (fake_location < 0) { 756 return NULL; 757 } 758 759 GLint uniform_index = GetUniformInfoIndexFromFakeLocation(fake_location); 760 if (uniform_index >= 0 && 761 static_cast<size_t>(uniform_index) < uniform_infos_.size()) { 762 const UniformInfo& uniform_info = uniform_infos_[uniform_index]; 763 if (!uniform_info.IsValid()) { 764 return NULL; 765 } 766 GLint element_index = GetArrayElementIndexFromFakeLocation(fake_location); 767 if (element_index < uniform_info.size) { 768 *real_location = uniform_info.element_locations[element_index]; 769 *array_index = element_index; 770 return &uniform_info; 771 } 772 } 773 return NULL; 774 } 775 776 const std::string* Program::GetAttribMappedName( 777 const std::string& original_name) const { 778 for (int ii = 0; ii < kMaxAttachedShaders; ++ii) { 779 Shader* shader = attached_shaders_[ii].get(); 780 if (shader) { 781 const std::string* mapped_name = 782 shader->GetAttribMappedName(original_name); 783 if (mapped_name) 784 return mapped_name; 785 } 786 } 787 return NULL; 788 } 789 790 const std::string* Program::GetOriginalNameFromHashedName( 791 const std::string& hashed_name) const { 792 for (int ii = 0; ii < kMaxAttachedShaders; ++ii) { 793 Shader* shader = attached_shaders_[ii].get(); 794 if (shader) { 795 const std::string* original_name = 796 shader->GetOriginalNameFromHashedName(hashed_name); 797 if (original_name) 798 return original_name; 799 } 800 } 801 return NULL; 802 } 803 804 bool Program::SetUniformLocationBinding( 805 const std::string& name, GLint location) { 806 std::string short_name; 807 int element_index = 0; 808 if (!GetUniformNameSansElement(name, &element_index, &short_name) || 809 element_index != 0) { 810 return false; 811 } 812 813 bind_uniform_location_map_[short_name] = location; 814 return true; 815 } 816 817 // Note: This is only valid to call right after a program has been linked 818 // successfully. 819 void Program::GetCorrectedVariableInfo( 820 bool use_uniforms, 821 const std::string& name, std::string* corrected_name, 822 std::string* original_name, 823 GLsizei* size, GLenum* type) const { 824 DCHECK(corrected_name); 825 DCHECK(original_name); 826 DCHECK(size); 827 DCHECK(type); 828 const char* kArraySpec = "[0]"; 829 for (int jj = 0; jj < 2; ++jj) { 830 std::string test_name(name + ((jj == 1) ? kArraySpec : "")); 831 for (int ii = 0; ii < kMaxAttachedShaders; ++ii) { 832 Shader* shader = attached_shaders_[ii].get(); 833 if (shader) { 834 const Shader::VariableInfo* variable_info = 835 use_uniforms ? shader->GetUniformInfo(test_name) : 836 shader->GetAttribInfo(test_name); 837 // Note: There is an assuption here that if an attrib is defined in more 838 // than 1 attached shader their types and sizes match. Should we check 839 // for that case? 840 if (variable_info) { 841 *corrected_name = test_name; 842 *original_name = variable_info->name; 843 *type = variable_info->type; 844 *size = variable_info->size; 845 return; 846 } 847 } 848 } 849 } 850 *corrected_name = name; 851 *original_name = name; 852 } 853 854 bool Program::AddUniformInfo( 855 GLsizei size, GLenum type, GLint location, GLint fake_base_location, 856 const std::string& name, const std::string& original_name, 857 size_t* next_available_index) { 858 DCHECK(next_available_index); 859 const char* kArraySpec = "[0]"; 860 size_t uniform_index = 861 fake_base_location >= 0 ? fake_base_location : *next_available_index; 862 if (uniform_infos_.size() < uniform_index + 1) { 863 uniform_infos_.resize(uniform_index + 1); 864 } 865 866 // return if this location is already in use. 867 if (uniform_infos_[uniform_index].IsValid()) { 868 DCHECK_GE(fake_base_location, 0); 869 return false; 870 } 871 872 uniform_infos_[uniform_index] = UniformInfo( 873 size, type, uniform_index, original_name); 874 ++num_uniforms_; 875 876 UniformInfo& info = uniform_infos_[uniform_index]; 877 info.element_locations.resize(size); 878 info.element_locations[0] = location; 879 DCHECK_GE(size, 0); 880 size_t num_texture_units = info.IsSampler() ? static_cast<size_t>(size) : 0u; 881 info.texture_units.clear(); 882 info.texture_units.resize(num_texture_units, 0); 883 884 if (size > 1) { 885 // Go through the array element locations looking for a match. 886 // We can skip the first element because it's the same as the 887 // the location without the array operators. 888 size_t array_pos = name.rfind(kArraySpec); 889 std::string base_name = name; 890 if (name.size() > 3) { 891 if (array_pos != name.size() - 3) { 892 info.name = name + kArraySpec; 893 } else { 894 base_name = name.substr(0, name.size() - 3); 895 } 896 } 897 for (GLsizei ii = 1; ii < info.size; ++ii) { 898 std::string element_name(base_name + "[" + base::IntToString(ii) + "]"); 899 info.element_locations[ii] = 900 glGetUniformLocation(service_id_, element_name.c_str()); 901 } 902 } 903 904 info.is_array = 905 (size > 1 || 906 (info.name.size() > 3 && 907 info.name.rfind(kArraySpec) == info.name.size() - 3)); 908 909 if (info.IsSampler()) { 910 sampler_indices_.push_back(info.fake_location_base); 911 } 912 max_uniform_name_length_ = 913 std::max(max_uniform_name_length_, 914 static_cast<GLsizei>(info.name.size())); 915 916 while (*next_available_index < uniform_infos_.size() && 917 uniform_infos_[*next_available_index].IsValid()) { 918 *next_available_index = *next_available_index + 1; 919 } 920 921 return true; 922 } 923 924 const Program::UniformInfo* 925 Program::GetUniformInfo( 926 GLint index) const { 927 if (static_cast<size_t>(index) >= uniform_infos_.size()) { 928 return NULL; 929 } 930 931 const UniformInfo& info = uniform_infos_[index]; 932 return info.IsValid() ? &info : NULL; 933 } 934 935 bool Program::SetSamplers( 936 GLint num_texture_units, GLint fake_location, 937 GLsizei count, const GLint* value) { 938 if (fake_location < 0) { 939 return true; 940 } 941 GLint uniform_index = GetUniformInfoIndexFromFakeLocation(fake_location); 942 if (uniform_index >= 0 && 943 static_cast<size_t>(uniform_index) < uniform_infos_.size()) { 944 UniformInfo& info = uniform_infos_[uniform_index]; 945 if (!info.IsValid()) { 946 return false; 947 } 948 GLint element_index = GetArrayElementIndexFromFakeLocation(fake_location); 949 if (element_index < info.size) { 950 count = std::min(info.size - element_index, count); 951 if (info.IsSampler() && count > 0) { 952 for (GLsizei ii = 0; ii < count; ++ii) { 953 if (value[ii] < 0 || value[ii] >= num_texture_units) { 954 return false; 955 } 956 } 957 std::copy(value, value + count, 958 info.texture_units.begin() + element_index); 959 return true; 960 } 961 } 962 } 963 return true; 964 } 965 966 void Program::GetProgramiv(GLenum pname, GLint* params) { 967 switch (pname) { 968 case GL_ACTIVE_ATTRIBUTES: 969 *params = attrib_infos_.size(); 970 break; 971 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: 972 // Notice +1 to accomodate NULL terminator. 973 *params = max_attrib_name_length_ + 1; 974 break; 975 case GL_ACTIVE_UNIFORMS: 976 *params = num_uniforms_; 977 break; 978 case GL_ACTIVE_UNIFORM_MAX_LENGTH: 979 // Notice +1 to accomodate NULL terminator. 980 *params = max_uniform_name_length_ + 1; 981 break; 982 case GL_LINK_STATUS: 983 *params = link_status_; 984 break; 985 case GL_INFO_LOG_LENGTH: 986 // Notice +1 to accomodate NULL terminator. 987 *params = log_info_.get() ? (log_info_->size() + 1) : 0; 988 break; 989 case GL_DELETE_STATUS: 990 *params = deleted_; 991 break; 992 case GL_VALIDATE_STATUS: 993 if (!IsValid()) { 994 *params = GL_FALSE; 995 } else { 996 glGetProgramiv(service_id_, pname, params); 997 } 998 break; 999 default: 1000 glGetProgramiv(service_id_, pname, params); 1001 break; 1002 } 1003 } 1004 1005 bool Program::AttachShader( 1006 ShaderManager* shader_manager, 1007 Shader* shader) { 1008 DCHECK(shader_manager); 1009 DCHECK(shader); 1010 int index = ShaderTypeToIndex(shader->shader_type()); 1011 if (attached_shaders_[index].get() != NULL) { 1012 return false; 1013 } 1014 attached_shaders_[index] = scoped_refptr<Shader>(shader); 1015 shader_manager->UseShader(shader); 1016 return true; 1017 } 1018 1019 bool Program::DetachShader( 1020 ShaderManager* shader_manager, 1021 Shader* shader) { 1022 DCHECK(shader_manager); 1023 DCHECK(shader); 1024 if (attached_shaders_[ShaderTypeToIndex(shader->shader_type())].get() != 1025 shader) { 1026 return false; 1027 } 1028 attached_shaders_[ShaderTypeToIndex(shader->shader_type())] = NULL; 1029 shader_manager->UnuseShader(shader); 1030 return true; 1031 } 1032 1033 void Program::DetachShaders(ShaderManager* shader_manager) { 1034 DCHECK(shader_manager); 1035 for (int ii = 0; ii < kMaxAttachedShaders; ++ii) { 1036 if (attached_shaders_[ii].get()) { 1037 DetachShader(shader_manager, attached_shaders_[ii].get()); 1038 } 1039 } 1040 } 1041 1042 bool Program::CanLink() const { 1043 for (int ii = 0; ii < kMaxAttachedShaders; ++ii) { 1044 if (!attached_shaders_[ii].get() || !attached_shaders_[ii]->IsValid()) { 1045 return false; 1046 } 1047 } 1048 return true; 1049 } 1050 1051 bool Program::DetectAttribLocationBindingConflicts() const { 1052 std::set<GLint> location_binding_used; 1053 for (LocationMap::const_iterator it = bind_attrib_location_map_.begin(); 1054 it != bind_attrib_location_map_.end(); ++it) { 1055 // Find out if an attribute is declared in this program's shaders. 1056 bool active = false; 1057 for (int ii = 0; ii < kMaxAttachedShaders; ++ii) { 1058 if (!attached_shaders_[ii].get() || !attached_shaders_[ii]->IsValid()) 1059 continue; 1060 if (attached_shaders_[ii]->GetAttribInfo(it->first)) { 1061 active = true; 1062 break; 1063 } 1064 } 1065 if (active) { 1066 std::pair<std::set<GLint>::iterator, bool> result = 1067 location_binding_used.insert(it->second); 1068 if (!result.second) 1069 return true; 1070 } 1071 } 1072 return false; 1073 } 1074 1075 bool Program::DetectUniformsMismatch(std::string* conflicting_name) const { 1076 typedef std::map<std::string, UniformType> UniformMap; 1077 UniformMap uniform_map; 1078 for (int ii = 0; ii < kMaxAttachedShaders; ++ii) { 1079 const ShaderTranslator::VariableMap& shader_uniforms = 1080 attached_shaders_[ii]->uniform_map(); 1081 for (ShaderTranslator::VariableMap::const_iterator iter = 1082 shader_uniforms.begin(); 1083 iter != shader_uniforms.end(); ++iter) { 1084 const std::string& name = iter->first; 1085 UniformType type(iter->second); 1086 UniformMap::iterator map_entry = uniform_map.find(name); 1087 if (map_entry == uniform_map.end()) { 1088 uniform_map[name] = type; 1089 } else { 1090 // If a uniform is already in the map, i.e., it has already been 1091 // declared by other shader, then the type and precision must match. 1092 if (map_entry->second == type) 1093 continue; 1094 *conflicting_name = name; 1095 return true; 1096 } 1097 } 1098 } 1099 return false; 1100 } 1101 1102 bool Program::DetectVaryingsMismatch(std::string* conflicting_name) const { 1103 DCHECK(attached_shaders_[0] && 1104 attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER && 1105 attached_shaders_[1] && 1106 attached_shaders_[1]->shader_type() == GL_FRAGMENT_SHADER); 1107 const ShaderTranslator::VariableMap* vertex_varyings = 1108 &(attached_shaders_[0]->varying_map()); 1109 const ShaderTranslator::VariableMap* fragment_varyings = 1110 &(attached_shaders_[1]->varying_map()); 1111 1112 for (ShaderTranslator::VariableMap::const_iterator iter = 1113 fragment_varyings->begin(); 1114 iter != fragment_varyings->end(); ++iter) { 1115 const std::string& name = iter->first; 1116 if (IsBuiltInVarying(name)) 1117 continue; 1118 1119 ShaderTranslator::VariableMap::const_iterator hit = 1120 vertex_varyings->find(name); 1121 if (hit == vertex_varyings->end()) { 1122 if (iter->second.static_use) { 1123 *conflicting_name = name; 1124 return true; 1125 } 1126 continue; 1127 } 1128 1129 if (hit->second.type != iter->second.type || 1130 hit->second.size != iter->second.size) { 1131 *conflicting_name = name; 1132 return true; 1133 } 1134 1135 } 1136 return false; 1137 } 1138 1139 bool Program::DetectGlobalNameConflicts(std::string* conflicting_name) const { 1140 DCHECK(attached_shaders_[0] && 1141 attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER && 1142 attached_shaders_[1] && 1143 attached_shaders_[1]->shader_type() == GL_FRAGMENT_SHADER); 1144 const ShaderTranslator::VariableMap* uniforms[2]; 1145 uniforms[0] = &(attached_shaders_[0]->uniform_map()); 1146 uniforms[1] = &(attached_shaders_[1]->uniform_map()); 1147 const ShaderTranslator::VariableMap* attribs = 1148 &(attached_shaders_[0]->attrib_map()); 1149 1150 for (ShaderTranslator::VariableMap::const_iterator iter = 1151 attribs->begin(); iter != attribs->end(); ++iter) { 1152 for (int ii = 0; ii < 2; ++ii) { 1153 if (uniforms[ii]->find(iter->first) != uniforms[ii]->end()) { 1154 *conflicting_name = iter->first; 1155 return true; 1156 } 1157 } 1158 } 1159 return false; 1160 } 1161 1162 bool Program::CheckVaryingsPacking( 1163 Program::VaryingsPackingOption option) const { 1164 DCHECK(attached_shaders_[0] && 1165 attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER && 1166 attached_shaders_[1] && 1167 attached_shaders_[1]->shader_type() == GL_FRAGMENT_SHADER); 1168 const ShaderTranslator::VariableMap* vertex_varyings = 1169 &(attached_shaders_[0]->varying_map()); 1170 const ShaderTranslator::VariableMap* fragment_varyings = 1171 &(attached_shaders_[1]->varying_map()); 1172 1173 std::map<std::string, ShVariableInfo> combined_map; 1174 1175 for (ShaderTranslator::VariableMap::const_iterator iter = 1176 fragment_varyings->begin(); 1177 iter != fragment_varyings->end(); ++iter) { 1178 if (!iter->second.static_use && option == kCountOnlyStaticallyUsed) 1179 continue; 1180 if (!IsBuiltInVarying(iter->first)) { 1181 ShaderTranslator::VariableMap::const_iterator vertex_iter = 1182 vertex_varyings->find(iter->first); 1183 if (vertex_iter == vertex_varyings->end() || 1184 (!vertex_iter->second.static_use && 1185 option == kCountOnlyStaticallyUsed)) 1186 continue; 1187 } 1188 1189 ShVariableInfo var; 1190 var.type = static_cast<ShDataType>(iter->second.type); 1191 var.size = iter->second.size; 1192 combined_map[iter->first] = var; 1193 } 1194 1195 if (combined_map.size() == 0) 1196 return true; 1197 scoped_ptr<ShVariableInfo[]> variables( 1198 new ShVariableInfo[combined_map.size()]); 1199 size_t index = 0; 1200 for (std::map<std::string, ShVariableInfo>::const_iterator iter = 1201 combined_map.begin(); 1202 iter != combined_map.end(); ++iter) { 1203 variables[index].type = iter->second.type; 1204 variables[index].size = iter->second.size; 1205 ++index; 1206 } 1207 return ShCheckVariablesWithinPackingLimits( 1208 static_cast<int>(manager_->max_varying_vectors()), 1209 variables.get(), 1210 combined_map.size()) == 1; 1211 } 1212 1213 static uint32 ComputeOffset(const void* start, const void* position) { 1214 return static_cast<const uint8*>(position) - 1215 static_cast<const uint8*>(start); 1216 } 1217 1218 void Program::GetProgramInfo( 1219 ProgramManager* manager, CommonDecoder::Bucket* bucket) const { 1220 // NOTE: It seems to me the math in here does not need check for overflow 1221 // because the data being calucated from has various small limits. The max 1222 // number of attribs + uniforms is somewhere well under 1024. The maximum size 1223 // of an identifier is 256 characters. 1224 uint32 num_locations = 0; 1225 uint32 total_string_size = 0; 1226 1227 for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) { 1228 const VertexAttrib& info = attrib_infos_[ii]; 1229 num_locations += 1; 1230 total_string_size += info.name.size(); 1231 } 1232 1233 for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) { 1234 const UniformInfo& info = uniform_infos_[ii]; 1235 if (info.IsValid()) { 1236 num_locations += info.element_locations.size(); 1237 total_string_size += info.name.size(); 1238 } 1239 } 1240 1241 uint32 num_inputs = attrib_infos_.size() + num_uniforms_; 1242 uint32 input_size = num_inputs * sizeof(ProgramInput); 1243 uint32 location_size = num_locations * sizeof(int32); 1244 uint32 size = sizeof(ProgramInfoHeader) + 1245 input_size + location_size + total_string_size; 1246 1247 bucket->SetSize(size); 1248 ProgramInfoHeader* header = bucket->GetDataAs<ProgramInfoHeader*>(0, size); 1249 ProgramInput* inputs = bucket->GetDataAs<ProgramInput*>( 1250 sizeof(ProgramInfoHeader), input_size); 1251 int32* locations = bucket->GetDataAs<int32*>( 1252 sizeof(ProgramInfoHeader) + input_size, location_size); 1253 char* strings = bucket->GetDataAs<char*>( 1254 sizeof(ProgramInfoHeader) + input_size + location_size, 1255 total_string_size); 1256 DCHECK(header); 1257 DCHECK(inputs); 1258 DCHECK(locations); 1259 DCHECK(strings); 1260 1261 header->link_status = link_status_; 1262 header->num_attribs = attrib_infos_.size(); 1263 header->num_uniforms = num_uniforms_; 1264 1265 for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) { 1266 const VertexAttrib& info = attrib_infos_[ii]; 1267 inputs->size = info.size; 1268 inputs->type = info.type; 1269 inputs->location_offset = ComputeOffset(header, locations); 1270 inputs->name_offset = ComputeOffset(header, strings); 1271 inputs->name_length = info.name.size(); 1272 *locations++ = info.location; 1273 memcpy(strings, info.name.c_str(), info.name.size()); 1274 strings += info.name.size(); 1275 ++inputs; 1276 } 1277 1278 for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) { 1279 const UniformInfo& info = uniform_infos_[ii]; 1280 if (info.IsValid()) { 1281 inputs->size = info.size; 1282 inputs->type = info.type; 1283 inputs->location_offset = ComputeOffset(header, locations); 1284 inputs->name_offset = ComputeOffset(header, strings); 1285 inputs->name_length = info.name.size(); 1286 DCHECK(static_cast<size_t>(info.size) == info.element_locations.size()); 1287 for (size_t jj = 0; jj < info.element_locations.size(); ++jj) { 1288 if (info.element_locations[jj] == -1) 1289 *locations++ = -1; 1290 else 1291 *locations++ = ProgramManager::MakeFakeLocation(ii, jj); 1292 } 1293 memcpy(strings, info.name.c_str(), info.name.size()); 1294 strings += info.name.size(); 1295 ++inputs; 1296 } 1297 } 1298 1299 DCHECK_EQ(ComputeOffset(header, strings), size); 1300 } 1301 1302 Program::~Program() { 1303 if (manager_) { 1304 if (manager_->have_context_) { 1305 glDeleteProgram(service_id()); 1306 } 1307 manager_->StopTracking(this); 1308 manager_ = NULL; 1309 } 1310 } 1311 1312 1313 ProgramManager::ProgramManager(ProgramCache* program_cache, 1314 uint32 max_varying_vectors) 1315 : program_count_(0), 1316 have_context_(true), 1317 program_cache_(program_cache), 1318 max_varying_vectors_(max_varying_vectors) { } 1319 1320 ProgramManager::~ProgramManager() { 1321 DCHECK(programs_.empty()); 1322 } 1323 1324 void ProgramManager::Destroy(bool have_context) { 1325 have_context_ = have_context; 1326 programs_.clear(); 1327 } 1328 1329 void ProgramManager::StartTracking(Program* /* program */) { 1330 ++program_count_; 1331 } 1332 1333 void ProgramManager::StopTracking(Program* /* program */) { 1334 --program_count_; 1335 } 1336 1337 Program* ProgramManager::CreateProgram( 1338 GLuint client_id, GLuint service_id) { 1339 std::pair<ProgramMap::iterator, bool> result = 1340 programs_.insert( 1341 std::make_pair(client_id, 1342 scoped_refptr<Program>( 1343 new Program(this, service_id)))); 1344 DCHECK(result.second); 1345 return result.first->second.get(); 1346 } 1347 1348 Program* ProgramManager::GetProgram(GLuint client_id) { 1349 ProgramMap::iterator it = programs_.find(client_id); 1350 return it != programs_.end() ? it->second.get() : NULL; 1351 } 1352 1353 bool ProgramManager::GetClientId(GLuint service_id, GLuint* client_id) const { 1354 // This doesn't need to be fast. It's only used during slow queries. 1355 for (ProgramMap::const_iterator it = programs_.begin(); 1356 it != programs_.end(); ++it) { 1357 if (it->second->service_id() == service_id) { 1358 *client_id = it->first; 1359 return true; 1360 } 1361 } 1362 return false; 1363 } 1364 1365 ProgramCache* ProgramManager::program_cache() const { 1366 return program_cache_; 1367 } 1368 1369 bool ProgramManager::IsOwned(Program* program) { 1370 for (ProgramMap::iterator it = programs_.begin(); 1371 it != programs_.end(); ++it) { 1372 if (it->second.get() == program) { 1373 return true; 1374 } 1375 } 1376 return false; 1377 } 1378 1379 void ProgramManager::RemoveProgramInfoIfUnused( 1380 ShaderManager* shader_manager, Program* program) { 1381 DCHECK(shader_manager); 1382 DCHECK(program); 1383 DCHECK(IsOwned(program)); 1384 if (program->IsDeleted() && !program->InUse()) { 1385 program->DetachShaders(shader_manager); 1386 for (ProgramMap::iterator it = programs_.begin(); 1387 it != programs_.end(); ++it) { 1388 if (it->second.get() == program) { 1389 programs_.erase(it); 1390 return; 1391 } 1392 } 1393 NOTREACHED(); 1394 } 1395 } 1396 1397 void ProgramManager::MarkAsDeleted( 1398 ShaderManager* shader_manager, 1399 Program* program) { 1400 DCHECK(shader_manager); 1401 DCHECK(program); 1402 DCHECK(IsOwned(program)); 1403 program->MarkAsDeleted(); 1404 RemoveProgramInfoIfUnused(shader_manager, program); 1405 } 1406 1407 void ProgramManager::UseProgram(Program* program) { 1408 DCHECK(program); 1409 DCHECK(IsOwned(program)); 1410 program->IncUseCount(); 1411 } 1412 1413 void ProgramManager::UnuseProgram( 1414 ShaderManager* shader_manager, 1415 Program* program) { 1416 DCHECK(shader_manager); 1417 DCHECK(program); 1418 DCHECK(IsOwned(program)); 1419 program->DecUseCount(); 1420 RemoveProgramInfoIfUnused(shader_manager, program); 1421 } 1422 1423 void ProgramManager::ClearUniforms(Program* program) { 1424 DCHECK(program); 1425 program->ClearUniforms(&zero_); 1426 } 1427 1428 int32 ProgramManager::MakeFakeLocation(int32 index, int32 element) { 1429 return index + element * 0x10000; 1430 } 1431 1432 } // namespace gles2 1433 } // namespace gpu 1434