Home | History | Annotate | Download | only in service
      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