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_cache.h" 6 7 #include <string> 8 #include "base/memory/scoped_ptr.h" 9 #include "gpu/command_buffer/service/shader_manager.h" 10 11 namespace gpu { 12 namespace gles2 { 13 14 ProgramCache::ProgramCache() {} 15 ProgramCache::~ProgramCache() {} 16 17 void ProgramCache::Clear() { 18 ClearBackend(); 19 link_status_.clear(); 20 } 21 22 ProgramCache::LinkedProgramStatus ProgramCache::GetLinkedProgramStatus( 23 const std::string& untranslated_a, 24 const ShaderTranslatorInterface* translator_a, 25 const std::string& untranslated_b, 26 const ShaderTranslatorInterface* translator_b, 27 const std::map<std::string, GLint>* bind_attrib_location_map) const { 28 char a_sha[kHashLength]; 29 char b_sha[kHashLength]; 30 ComputeShaderHash(untranslated_a, translator_a, a_sha); 31 ComputeShaderHash(untranslated_b, translator_b, b_sha); 32 33 char sha[kHashLength]; 34 ComputeProgramHash(a_sha, 35 b_sha, 36 bind_attrib_location_map, 37 sha); 38 const std::string sha_string(sha, kHashLength); 39 40 LinkStatusMap::const_iterator found = link_status_.find(sha_string); 41 if (found == link_status_.end()) { 42 return ProgramCache::LINK_UNKNOWN; 43 } else { 44 return found->second; 45 } 46 } 47 48 void ProgramCache::LinkedProgramCacheSuccess( 49 const std::string& shader_a, 50 const ShaderTranslatorInterface* translator_a, 51 const std::string& shader_b, 52 const ShaderTranslatorInterface* translator_b, 53 const LocationMap* bind_attrib_location_map) { 54 char a_sha[kHashLength]; 55 char b_sha[kHashLength]; 56 ComputeShaderHash(shader_a, translator_a, a_sha); 57 ComputeShaderHash(shader_b, translator_b, b_sha); 58 char sha[kHashLength]; 59 ComputeProgramHash(a_sha, 60 b_sha, 61 bind_attrib_location_map, 62 sha); 63 const std::string sha_string(sha, kHashLength); 64 65 LinkedProgramCacheSuccess(sha_string); 66 } 67 68 void ProgramCache::LinkedProgramCacheSuccess(const std::string& program_hash) { 69 link_status_[program_hash] = LINK_SUCCEEDED; 70 } 71 72 void ProgramCache::ComputeShaderHash( 73 const std::string& str, 74 const ShaderTranslatorInterface* translator, 75 char* result) const { 76 std::string s(( 77 translator ? translator->GetStringForOptionsThatWouldEffectCompilation() : 78 std::string()) + str); 79 base::SHA1HashBytes(reinterpret_cast<const unsigned char*>(s.c_str()), 80 s.length(), reinterpret_cast<unsigned char*>(result)); 81 } 82 83 void ProgramCache::Evict(const std::string& program_hash) { 84 link_status_.erase(program_hash); 85 } 86 87 namespace { 88 size_t CalculateMapSize(const std::map<std::string, GLint>* map) { 89 if (!map) { 90 return 0; 91 } 92 std::map<std::string, GLint>::const_iterator it; 93 size_t total = 0; 94 for (it = map->begin(); it != map->end(); ++it) { 95 total += 4 + it->first.length(); 96 } 97 return total; 98 } 99 } // anonymous namespace 100 101 void ProgramCache::ComputeProgramHash( 102 const char* hashed_shader_0, 103 const char* hashed_shader_1, 104 const std::map<std::string, GLint>* bind_attrib_location_map, 105 char* result) const { 106 const size_t shader0_size = kHashLength; 107 const size_t shader1_size = kHashLength; 108 const size_t map_size = CalculateMapSize(bind_attrib_location_map); 109 const size_t total_size = shader0_size + shader1_size + map_size; 110 111 scoped_ptr<unsigned char[]> buffer(new unsigned char[total_size]); 112 memcpy(buffer.get(), hashed_shader_0, shader0_size); 113 memcpy(&buffer[shader0_size], hashed_shader_1, shader1_size); 114 if (map_size != 0) { 115 // copy our map 116 size_t current_pos = shader0_size + shader1_size; 117 std::map<std::string, GLint>::const_iterator it; 118 for (it = bind_attrib_location_map->begin(); 119 it != bind_attrib_location_map->end(); 120 ++it) { 121 const size_t name_size = it->first.length(); 122 memcpy(&buffer.get()[current_pos], it->first.c_str(), name_size); 123 current_pos += name_size; 124 const GLint value = it->second; 125 buffer[current_pos++] = value >> 24; 126 buffer[current_pos++] = value >> 16; 127 buffer[current_pos++] = value >> 8; 128 buffer[current_pos++] = value; 129 } 130 } 131 base::SHA1HashBytes(buffer.get(), 132 total_size, reinterpret_cast<unsigned char*>(result)); 133 } 134 135 } // namespace gles2 136 } // namespace gpu 137