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 11namespace gpu { 12namespace gles2 { 13 14ProgramCache::ProgramCache() {} 15ProgramCache::~ProgramCache() {} 16 17void ProgramCache::Clear() { 18 ClearBackend(); 19 link_status_.clear(); 20} 21 22ProgramCache::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 48void 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 68void ProgramCache::LinkedProgramCacheSuccess(const std::string& program_hash) { 69 link_status_[program_hash] = LINK_SUCCEEDED; 70} 71 72void 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 83void ProgramCache::Evict(const std::string& program_hash) { 84 link_status_.erase(program_hash); 85} 86 87namespace { 88size_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 101void 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