| 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/service/program_manager.h" | 5 #include "gpu/command_buffer/service/program_manager.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <set> | 8 #include <set> |
| 9 | 9 |
| 10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
| 11 #include "base/bind.h" |
| 11 #include "base/command_line.h" | 12 #include "base/command_line.h" |
| 12 #include "base/logging.h" | 13 #include "base/logging.h" |
| 13 #include "base/memory/scoped_ptr.h" | 14 #include "base/memory/scoped_ptr.h" |
| 14 #include "base/string_number_conversions.h" | 15 #include "base/string_number_conversions.h" |
| 16 #include "net/base/net_log.h" |
| 15 #include "gpu/command_buffer/common/gles2_cmd_format.h" | 17 #include "gpu/command_buffer/common/gles2_cmd_format.h" |
| 16 #include "gpu/command_buffer/common/gles2_cmd_utils.h" | 18 #include "gpu/command_buffer/common/gles2_cmd_utils.h" |
| 17 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" | 19 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
| 18 #include "gpu/command_buffer/service/gpu_switches.h" | 20 #include "gpu/command_buffer/service/gpu_switches.h" |
| 19 | 21 |
| 20 namespace gpu { | 22 namespace gpu { |
| 21 namespace gles2 { | 23 namespace gles2 { |
| 22 | 24 |
| 23 static int ShaderTypeToIndex(GLenum shader_type) { | 25 static int ShaderTypeToIndex(GLenum shader_type) { |
| 24 switch (shader_type) { | 26 switch (shader_type) { |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 246 void ProgramManager::ProgramInfo::ExecuteBindAttribLocationCalls() { | 248 void ProgramManager::ProgramInfo::ExecuteBindAttribLocationCalls() { |
| 247 for (std::map<std::string, GLint>::const_iterator it = | 249 for (std::map<std::string, GLint>::const_iterator it = |
| 248 bind_attrib_location_map_.begin(); | 250 bind_attrib_location_map_.begin(); |
| 249 it != bind_attrib_location_map_.end(); ++it) { | 251 it != bind_attrib_location_map_.end(); ++it) { |
| 250 const std::string* mapped_name = GetAttribMappedName(it->first); | 252 const std::string* mapped_name = GetAttribMappedName(it->first); |
| 251 if (mapped_name && *mapped_name != it->first) | 253 if (mapped_name && *mapped_name != it->first) |
| 252 glBindAttribLocation(service_id_, it->second, mapped_name->c_str()); | 254 glBindAttribLocation(service_id_, it->second, mapped_name->c_str()); |
| 253 } | 255 } |
| 254 } | 256 } |
| 255 | 257 |
| 256 bool ProgramManager::ProgramInfo::Link() { | 258 void ProgramManager::DoCompileShader(ShaderManager::ShaderInfo* info, |
| 259 ShaderTranslator* translator, |
| 260 FeatureInfo* feature_info) { |
| 261 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to |
| 262 // glShaderSource and then glCompileShader. |
| 263 const char* shader_src = info->source() ? info->source()->c_str() : ""; |
| 264 if (translator) { |
| 265 if (!translator->Translate(shader_src)) { |
| 266 info->SetStatus(false, translator->info_log(), NULL); |
| 267 if(program_cache_) { |
| 268 program_cache_->SetShaderCompilationStatus( |
| 269 *info->source(), |
| 270 ProgramCache::COMPILATION_UNKNOWN); |
| 271 } |
| 272 return; |
| 273 } |
| 274 shader_src = translator->translated_shader(); |
| 275 if (!feature_info->feature_flags().angle_translated_shader_source) |
| 276 info->UpdateTranslatedSource(shader_src); |
| 277 } |
| 278 |
| 279 glShaderSource(info->service_id(), 1, &shader_src, NULL); |
| 280 glCompileShader(info->service_id()); |
| 281 if (feature_info->feature_flags().angle_translated_shader_source) { |
| 282 GLint max_len = 0; |
| 283 glGetShaderiv(info->service_id(), |
| 284 GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE, |
| 285 &max_len); |
| 286 scoped_array<char> temp(new char[max_len]); |
| 287 GLint len = 0; |
| 288 glGetTranslatedShaderSourceANGLE( |
| 289 info->service_id(), max_len, &len, temp.get()); |
| 290 DCHECK(max_len == 0 || len < max_len); |
| 291 DCHECK(len == 0 || temp[len] == '\0'); |
| 292 info->UpdateTranslatedSource(temp.get()); |
| 293 } |
| 294 |
| 295 GLint status = GL_FALSE; |
| 296 glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status); |
| 297 if (status) { |
| 298 info->SetStatus(true, "", translator); |
| 299 if(program_cache_) { |
| 300 program_cache_->SetShaderCompilationStatus( |
| 301 *info->source(), |
| 302 ProgramCache::COMPILATION_SUCCEEDED); |
| 303 } |
| 304 } else { |
| 305 // We cannot reach here if we are using the shader translator. |
| 306 // All invalid shaders must be rejected by the translator. |
| 307 // All translated shaders must compile. |
| 308 LOG_IF(ERROR, translator) |
| 309 << "Shader translator allowed/produced an invalid shader."; |
| 310 GLint max_len = 0; |
| 311 glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &max_len); |
| 312 scoped_array<char> temp(new char[max_len]); |
| 313 GLint len = 0; |
| 314 glGetShaderInfoLog(info->service_id(), max_len, &len, temp.get()); |
| 315 DCHECK(max_len == 0 || len < max_len); |
| 316 DCHECK(len == 0 || temp[len] == '\0'); |
| 317 info->SetStatus(false, std::string(temp.get(), len).c_str(), NULL); |
| 318 if(program_cache_) { |
| 319 program_cache_->SetShaderCompilationStatus( |
| 320 *info->source(), |
| 321 ProgramCache::COMPILATION_UNKNOWN); |
| 322 } |
| 323 } |
| 324 } |
| 325 |
| 326 bool ProgramManager::ProgramInfo::Link(ShaderManager* manager, |
| 327 ShaderTranslator* vertex_translator, |
| 328 ShaderTranslator* fragment_shader, |
| 329 FeatureInfo* feature_info) { |
| 257 ClearLinkStatus(); | 330 ClearLinkStatus(); |
| 258 if (!CanLink()) { | 331 if (!CanLink()) { |
| 259 set_log_info("missing shaders"); | 332 set_log_info("missing shaders"); |
| 260 return false; | 333 return false; |
| 261 } | 334 } |
| 262 if (DetectAttribLocationBindingConflicts()) { | 335 if (DetectAttribLocationBindingConflicts()) { |
| 263 set_log_info("glBindAttribLocation() conflicts"); | 336 set_log_info("glBindAttribLocation() conflicts"); |
| 264 return false; | 337 return false; |
| 265 } | 338 } |
| 266 ExecuteBindAttribLocationCalls(); | 339 ExecuteBindAttribLocationCalls(); |
| 267 glLinkProgram(service_id()); | 340 |
| 341 bool link = true; |
| 342 ProgramCache* cache = manager_->program_cache_; |
| 343 const std::string* shader_a = attached_shaders_[0]->source(); |
| 344 const std::string* shader_b = attached_shaders_[1]->source(); |
| 345 if(cache) { |
| 346 ProgramCache::LinkedProgramStatus status = cache->GetLinkedProgramStatus( |
| 347 *shader_a, |
| 348 *shader_b, |
| 349 &bind_attrib_location_map_); |
| 350 switch(status) { |
| 351 case ProgramCache::LINK_UNKNOWN: |
| 352 fprintf(stderr, |
| 353 "program %i not linked yet compiling and linking\n", |
| 354 service_id()); |
| 355 // compile our shaders + attach |
| 356 if (attached_shaders_[0]->IsPendingCacheMissCompilation()) { |
| 357 manager_->DoCompileShader(attached_shaders_[0], |
| 358 vertex_translator, |
| 359 feature_info); |
| 360 AttachShader(manager, attached_shaders_[0]); |
| 361 glAttachShader(service_id(), attached_shaders_[0]->service_id()); |
| 362 attached_shaders_[0]->SetPendingCompilation(false); |
| 363 } |
| 364 if(attached_shaders_[1]->IsPendingCacheMissCompilation()) { |
| 365 manager_->DoCompileShader(attached_shaders_[1], |
| 366 fragment_shader, |
| 367 feature_info); |
| 368 AttachShader(manager, attached_shaders_[1]); |
| 369 glAttachShader(service_id(), attached_shaders_[1]->service_id()); |
| 370 attached_shaders_[1]->SetPendingCompilation(false); |
| 371 } |
| 372 link = true; |
| 373 break; |
| 374 case ProgramCache::LINK_SUCCEEDED: |
| 375 fprintf(stderr, "## program %i linked and cached!\n", service_id()); |
| 376 cache->LoadLinkedProgram(service_id(), |
| 377 attached_shaders_[0], |
| 378 attached_shaders_[1], |
| 379 &bind_attrib_location_map_); |
| 380 link = false; |
| 381 break; |
| 382 } |
| 383 } |
| 384 |
| 385 if(link) { |
| 386 glLinkProgram(service_id()); |
| 387 } |
| 388 |
| 268 GLint success = 0; | 389 GLint success = 0; |
| 269 glGetProgramiv(service_id(), GL_LINK_STATUS, &success); | 390 glGetProgramiv(service_id(), GL_LINK_STATUS, &success); |
| 270 if (success == GL_TRUE) { | 391 if (success == GL_TRUE) { |
| 271 Update(); | 392 Update(); |
| 393 if(cache && link) { |
| 394 fprintf(stderr, "program %i just linked, caching\n", service_id()); |
| 395 cache->SaveLinkedProgram(service_id(), |
| 396 attached_shaders_[0], |
| 397 attached_shaders_[1], |
| 398 &bind_attrib_location_map_); |
| 399 |
| 400 } |
| 272 } else { | 401 } else { |
| 273 UpdateLogInfo(); | 402 UpdateLogInfo(); |
| 403 if(cache) { |
| 404 fprintf(stderr, "program %i not linked correctly\n", service_id()); |
| 405 } |
| 274 } | 406 } |
| 275 return success == GL_TRUE; | 407 return success == GL_TRUE; |
| 276 } | 408 } |
| 277 | 409 |
| 278 void ProgramManager::ProgramInfo::Validate() { | 410 void ProgramManager::ProgramInfo::Validate() { |
| 279 if (!IsValid()) { | 411 if (!IsValid()) { |
| 280 set_log_info("program not linked"); | 412 set_log_info("program not linked"); |
| 281 return; | 413 return; |
| 282 } | 414 } |
| 283 glValidateProgram(service_id()); | 415 glValidateProgram(service_id()); |
| (...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 676 manager_->StopTracking(this); | 808 manager_->StopTracking(this); |
| 677 manager_ = NULL; | 809 manager_ = NULL; |
| 678 } | 810 } |
| 679 } | 811 } |
| 680 | 812 |
| 681 // TODO(gman): make this some kind of random number. Base::RandInt is not | 813 // TODO(gman): make this some kind of random number. Base::RandInt is not |
| 682 // callable because of the sandbox. What matters is that it's possibly different | 814 // callable because of the sandbox. What matters is that it's possibly different |
| 683 // by at least 1 bit each time chrome is run. | 815 // by at least 1 bit each time chrome is run. |
| 684 static int uniform_random_offset_ = 3; | 816 static int uniform_random_offset_ = 3; |
| 685 | 817 |
| 686 ProgramManager::ProgramManager() | 818 ProgramManager::ProgramManager(base::WeakPtr<ProgramCache> program_cache) |
| 687 : uniform_swizzle_(uniform_random_offset_++ % 15), | 819 : uniform_swizzle_(uniform_random_offset_++ % 15), |
| 688 program_info_count_(0), | 820 program_info_count_(0), |
| 689 have_context_(true), | 821 have_context_(true), |
| 690 disable_workarounds_( | 822 disable_workarounds_( |
| 691 CommandLine::ForCurrentProcess()->HasSwitch( | 823 CommandLine::ForCurrentProcess()->HasSwitch( |
| 692 switches::kDisableGpuDriverBugWorkarounds)) { | 824 switches::kDisableGpuDriverBugWorkarounds)), |
| 693 } | 825 program_cache_(program_cache){ } |
| 694 | 826 |
| 695 ProgramManager::~ProgramManager() { | 827 ProgramManager::~ProgramManager() { |
| 696 DCHECK(program_infos_.empty()); | 828 DCHECK(program_infos_.empty()); |
| 697 } | 829 } |
| 698 | 830 |
| 699 void ProgramManager::Destroy(bool have_context) { | 831 void ProgramManager::Destroy(bool have_context) { |
| 700 have_context_ = have_context; | 832 have_context_ = have_context; |
| 701 program_infos_.clear(); | 833 program_infos_.clear(); |
| 702 } | 834 } |
| 703 | 835 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 729 for (ProgramInfoMap::const_iterator it = program_infos_.begin(); | 861 for (ProgramInfoMap::const_iterator it = program_infos_.begin(); |
| 730 it != program_infos_.end(); ++it) { | 862 it != program_infos_.end(); ++it) { |
| 731 if (it->second->service_id() == service_id) { | 863 if (it->second->service_id() == service_id) { |
| 732 *client_id = it->first; | 864 *client_id = it->first; |
| 733 return true; | 865 return true; |
| 734 } | 866 } |
| 735 } | 867 } |
| 736 return false; | 868 return false; |
| 737 } | 869 } |
| 738 | 870 |
| 871 ProgramCache* ProgramManager::GetProgramCache() const { |
| 872 return program_cache_; |
| 873 } |
| 874 |
| 739 bool ProgramManager::IsOwned(ProgramManager::ProgramInfo* info) { | 875 bool ProgramManager::IsOwned(ProgramManager::ProgramInfo* info) { |
| 740 for (ProgramInfoMap::iterator it = program_infos_.begin(); | 876 for (ProgramInfoMap::iterator it = program_infos_.begin(); |
| 741 it != program_infos_.end(); ++it) { | 877 it != program_infos_.end(); ++it) { |
| 742 if (it->second.get() == info) { | 878 if (it->second.get() == info) { |
| 743 return true; | 879 return true; |
| 744 } | 880 } |
| 745 } | 881 } |
| 746 return false; | 882 return false; |
| 747 } | 883 } |
| 748 | 884 |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 814 } | 950 } |
| 815 | 951 |
| 816 GLint ProgramManager::UnswizzleLocation(GLint v) const { | 952 GLint ProgramManager::UnswizzleLocation(GLint v) const { |
| 817 return v < 0 ? v : Swizzle(v - uniform_swizzle_); | 953 return v < 0 ? v : Swizzle(v - uniform_swizzle_); |
| 818 } | 954 } |
| 819 | 955 |
| 820 } // namespace gles2 | 956 } // namespace gles2 |
| 821 } // namespace gpu | 957 } // namespace gpu |
| 822 | 958 |
| 823 | 959 |
| OLD | NEW |