Index: gpu/command_buffer/service/memory_program_cache.cc |
diff --git a/gpu/command_buffer/service/memory_program_cache.cc b/gpu/command_buffer/service/memory_program_cache.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..0a061cb1ed430edd7374cbf93781ec1195e818eb |
--- /dev/null |
+++ b/gpu/command_buffer/service/memory_program_cache.cc |
@@ -0,0 +1,173 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "gpu/command_buffer/service/memory_program_cache.h" |
+ |
+#include "base/command_line.h" |
+#include "base/metrics/histogram.h" |
+#include "base/sha1.h" |
+#include "base/string_number_conversions.h" |
+#include "gpu/command_buffer/service/gl_utils.h" |
+#include "gpu/command_buffer/service/gpu_switches.h" |
+#include "ui/gl/gl_bindings.h" |
+ |
+namespace { |
+size_t GetCacheSize() { |
+ size_t size; |
+ const CommandLine* command_line = CommandLine::ForCurrentProcess(); |
+ if (command_line->HasSwitch(switches::kGpuProgramCacheSizeKb) && |
+ base::StringToSizeT(command_line->GetSwitchValueNative( |
+ switches::kGpuProgramCacheSizeKb), |
+ &size)) { |
+ return size; |
+ } |
+ return gpu::gles2::MemoryProgramCache::kDefaultMaxProgramCacheMemoryBytes; |
+} |
+} // anonymous namespace |
+ |
+namespace gpu { |
+namespace gles2 { |
+ |
+MemoryProgramCache::MemoryProgramCache() |
+ : max_size_bytes_(GetCacheSize()), |
+ curr_size_bytes_(0) { } |
+ |
+MemoryProgramCache::MemoryProgramCache(const size_t max_cache_size_bytes) |
+ : max_size_bytes_(max_cache_size_bytes), |
+ curr_size_bytes_(0) {} |
+ |
+MemoryProgramCache::~MemoryProgramCache() {} |
+ |
+void MemoryProgramCache::ClearBackend() { |
+ curr_size_bytes_ = 0; |
+ store_.clear(); |
+ eviction_helper_.Clear(); |
+} |
+ |
+ProgramCache::ProgramLoadResult MemoryProgramCache::LoadLinkedProgram( |
+ GLuint program, |
+ ShaderManager::ShaderInfo* shader_a, |
+ ShaderManager::ShaderInfo* shader_b, |
+ const LocationMap* bind_attrib_location_map) const { |
+ char a_sha[kHashLength]; |
+ char b_sha[kHashLength]; |
+ ComputeShaderHash(*shader_a->deferred_compilation_source(), a_sha); |
+ ComputeShaderHash(*shader_b->deferred_compilation_source(), b_sha); |
+ |
+ char sha[kHashLength]; |
+ ComputeProgramHash(a_sha, |
+ b_sha, |
+ bind_attrib_location_map, |
+ sha); |
+ const std::string sha_string(sha, kHashLength); |
+ |
+ StoreMap::const_iterator found = store_.find(sha_string); |
+ if (found == store_.end()) { |
+ return PROGRAM_LOAD_FAILURE; |
+ } |
+ const scoped_refptr<ProgramCacheValue> value = found->second; |
+ glProgramBinary(program, |
+ value->format, |
+ static_cast<const GLvoid*>(value->data.get()), |
+ value->length); |
+ GLint success = 0; |
+ glGetProgramiv(program, GL_LINK_STATUS, &success); |
+ if (success == GL_FALSE) { |
+ return PROGRAM_LOAD_FAILURE; |
+ } |
+ shader_a->set_attrib_map(value->attrib_map_0); |
+ shader_a->set_uniform_map(value->uniform_map_0); |
+ shader_b->set_attrib_map(value->attrib_map_1); |
+ shader_b->set_uniform_map(value->uniform_map_1); |
+ return PROGRAM_LOAD_SUCCESS; |
+} |
+ |
+void MemoryProgramCache::SaveLinkedProgram( |
+ GLuint program, |
+ const ShaderManager::ShaderInfo* shader_a, |
+ const ShaderManager::ShaderInfo* shader_b, |
+ const LocationMap* bind_attrib_location_map) { |
+ GLsizei length; |
+ GLenum format; |
+ GLsizei buffer_length = 0; |
+ glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH_OES, &buffer_length); |
+ if (static_cast<unsigned int>(buffer_length) > max_size_bytes_) { |
+ return; |
+ } |
+ scoped_array<char> binary(new char[buffer_length]); |
+ glGetProgramBinary(program, |
+ buffer_length, |
+ &length, |
+ &format, |
+ binary.get()); |
+ if (length == 0) { |
+ return; |
+ } |
+ |
+ char a_sha[kHashLength]; |
+ char b_sha[kHashLength]; |
+ ComputeShaderHash(*shader_a->deferred_compilation_source(), a_sha); |
+ ComputeShaderHash(*shader_b->deferred_compilation_source(), b_sha); |
+ |
+ char sha[kHashLength]; |
+ ComputeProgramHash(a_sha, |
+ b_sha, |
+ bind_attrib_location_map, |
+ sha); |
+ const std::string sha_string(sha, sizeof(sha)); |
+ |
+ if (store_.find(sha_string) != store_.end()) { |
+ return; |
+ } |
+ |
+ while (curr_size_bytes_ + length > max_size_bytes_) { |
+ DCHECK(!eviction_helper_.IsEmpty()); |
+ const std::string* program = eviction_helper_.PeekKey(); |
+ const StoreMap::iterator found = store_.find(*program); |
+ const ProgramCacheValue* evicting = found->second.get(); |
+ curr_size_bytes_ -= evicting->length; |
+ Evict(*program, evicting->shader_0_hash, evicting->shader_1_hash); |
+ store_.erase(found); |
+ eviction_helper_.PopKey(); |
+ } |
+ store_[sha_string] = new ProgramCacheValue(length, |
+ format, |
+ binary.release(), |
+ a_sha, |
+ shader_a->attrib_map(), |
+ shader_a->uniform_map(), |
+ b_sha, |
+ shader_b->attrib_map(), |
+ shader_b->uniform_map()); |
+ curr_size_bytes_ += length; |
+ eviction_helper_.KeyUsed(sha_string); |
+ LinkedProgramCacheSuccess(sha_string, |
+ std::string(a_sha, kHashLength), |
+ std::string(b_sha, kHashLength)); |
+} |
+ |
+MemoryProgramCache::ProgramCacheValue::ProgramCacheValue( |
+ GLsizei _length, |
+ GLenum _format, |
+ const char* _data, |
+ const char* _shader_0_hash, |
+ const ShaderTranslator::VariableMap& _attrib_map_0, |
+ const ShaderTranslator::VariableMap& _uniform_map_0, |
+ const char* _shader_1_hash, |
+ const ShaderTranslator::VariableMap& _attrib_map_1, |
+ const ShaderTranslator::VariableMap& _uniform_map_1) |
+ : length(_length), |
+ format(_format), |
+ data(_data), |
+ shader_0_hash(_shader_0_hash, kHashLength), |
+ attrib_map_0(_attrib_map_0), |
+ uniform_map_0(_uniform_map_0), |
+ shader_1_hash(_shader_1_hash, kHashLength), |
+ attrib_map_1(_attrib_map_1), |
+ uniform_map_1(_uniform_map_1) {} |
+ |
+MemoryProgramCache::ProgramCacheValue::~ProgramCacheValue() {} |
+ |
+} // namespace gles2 |
+} // namespace gpu |