Chromium Code Reviews| Index: gpu/command_buffer/client/gles2_implementation.cc |
| diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc |
| index a53b9b0e9e8cd88f05d59e620532b78a0ce5c1e4..9fbd12a7218d4dddf67a4c9352aed7264d64893d 100644 |
| --- a/gpu/command_buffer/client/gles2_implementation.cc |
| +++ b/gpu/command_buffer/client/gles2_implementation.cc |
| @@ -18,6 +18,7 @@ |
| #include <sstream> |
| #include <string> |
| #include "base/compiler_specific.h" |
| +#include "base/strings/string_split.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/sys_info.h" |
| #include "base/thread_task_runner_handle.h" |
| @@ -131,6 +132,7 @@ GLES2Implementation::GLES2Implementation( |
| gpu_control_(gpu_control), |
| capabilities_(gpu_control->GetCapabilities()), |
| aggressively_free_resources_(false), |
| + cached_extension_string_(nullptr), |
| weak_ptr_factory_(this) { |
| DCHECK(helper); |
| DCHECK(transfer_buffer); |
| @@ -949,7 +951,8 @@ bool GLES2Implementation::GetHelper(GLenum pname, GLint* params) { |
| *params = capabilities_.minor_version; |
| return true; |
| case GL_NUM_EXTENSIONS: |
| - *params = capabilities_.num_extensions; |
| + UpdateCachedExtensionsIfNeeded(); |
| + *params = cached_extensions_.size(); |
| return true; |
| case GL_NUM_PROGRAM_BINARY_FORMATS: |
| *params = capabilities_.num_program_binary_formats; |
| @@ -3297,6 +3300,9 @@ void GLES2Implementation::GetShaderPrecisionFormat( |
| } |
| const GLubyte* GLES2Implementation::GetStringHelper(GLenum name) { |
| + if (name == GL_EXTENSIONS && cached_extension_string_) { |
| + return reinterpret_cast<const GLubyte*>(cached_extension_string_); |
| + } |
| const char* result = NULL; |
| // Clears the bucket so if the command fails nothing will be in it. |
| helper_->SetBucketSize(kResultBucketId, 0); |
| @@ -3304,40 +3310,31 @@ const GLubyte* GLES2Implementation::GetStringHelper(GLenum name) { |
| std::string str; |
| if (GetBucketAsString(kResultBucketId, &str)) { |
| // Adds extensions implemented on client side only. |
| - switch (name) { |
| - case GL_EXTENSIONS: |
| - str += std::string(str.empty() ? "" : " ") + |
| - "GL_EXT_unpack_subimage " |
| - "GL_CHROMIUM_map_sub"; |
| - if (capabilities_.image) |
| - str += " GL_CHROMIUM_image GL_CHROMIUM_gpu_memory_buffer_image"; |
| - if (capabilities_.future_sync_points) |
| - str += " GL_CHROMIUM_future_sync_point"; |
| - break; |
| - default: |
| - break; |
| + if (name == GL_EXTENSIONS) { |
| + str += std::string(str.empty() ? "" : " ") + |
| + "GL_EXT_unpack_subimage " |
| + "GL_CHROMIUM_map_sub"; |
| + if (capabilities_.image) |
| + str += " GL_CHROMIUM_image GL_CHROMIUM_gpu_memory_buffer_image"; |
| + if (capabilities_.future_sync_points) |
| + str += " GL_CHROMIUM_future_sync_point"; |
| } |
| // Because of WebGL the extensions can change. We have to cache each unique |
| // result since we don't know when the client will stop referring to a |
| // previous one it queries. |
| - GLStringMap::iterator it = gl_strings_.find(name); |
| - if (it == gl_strings_.end()) { |
| - std::set<std::string> strings; |
| - std::pair<GLStringMap::iterator, bool> insert_result = |
| - gl_strings_.insert(std::make_pair(name, strings)); |
| - DCHECK(insert_result.second); |
| - it = insert_result.first; |
| - } |
| - std::set<std::string>& string_set = it->second; |
| - std::set<std::string>::const_iterator sit = string_set.find(str); |
| - if (sit != string_set.end()) { |
| - result = sit->c_str(); |
| - } else { |
| - std::pair<std::set<std::string>::const_iterator, bool> insert_result = |
| - string_set.insert(str); |
| - DCHECK(insert_result.second); |
| - result = insert_result.first->c_str(); |
| + const std::string& cache = *gl_strings_.insert(str).first; |
|
piman
2016/02/11 18:50:38
Is it really advantageous to change gl_strings_ fr
Kimmo Kinnunen
2016/02/11 18:55:42
It is changed from many sets to sets.
map of sets
piman
2016/02/11 19:15:27
Mmh, ok, I misread the former code. I was under th
|
| + result = cache.c_str(); |
| + |
| + if (name == GL_EXTENSIONS) { |
| + cached_extension_string_ = result; |
| + std::vector<std::string> extensions = |
| + base::SplitString(cache, base::kWhitespaceASCII, |
| + base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); |
| + for (auto extension : extensions) { |
| + cached_extensions_.push_back( |
| + gl_strings_.insert(extension).first->c_str()); |
| + } |
| } |
| } |
| return reinterpret_cast<const GLubyte*>(result); |
| @@ -3354,6 +3351,28 @@ const GLubyte* GLES2Implementation::GetString(GLenum name) { |
| return result; |
| } |
| +const GLubyte* GLES2Implementation::GetStringi(GLenum name, GLuint index) { |
| + GPU_CLIENT_SINGLE_THREAD_CHECK(); |
| + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetStringi(" |
| + << GLES2Util::GetStringStringType(name) << "," << index |
| + << ")"); |
| + TRACE_EVENT0("gpu", "GLES2::GetStringi"); |
| + UpdateCachedExtensionsIfNeeded(); |
| + if (name != GL_EXTENSIONS) { |
| + SetGLError(GL_INVALID_ENUM, "glGetStringi", "name"); |
| + return nullptr; |
| + } |
| + if (index >= cached_extensions_.size()) { |
| + SetGLError(GL_INVALID_VALUE, "glGetStringi", "index too large"); |
| + return nullptr; |
| + } |
| + |
| + const char* result = cached_extensions_[index]; |
| + GPU_CLIENT_LOG(" returned " << result); |
| + CheckGLError(); |
| + return reinterpret_cast<const GLubyte*>(result); |
| +} |
| + |
| bool GLES2Implementation::GetTransformFeedbackVaryingHelper( |
| GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, |
| GLenum* type, char* name) { |
| @@ -4820,16 +4839,7 @@ const GLchar* GLES2Implementation::GetRequestableExtensionsCHROMIUM() { |
| // them. Because we don't know when the client will stop referring |
| // to a previous one it queries (see GetString) we need to cache |
| // the unique results. |
| - std::set<std::string>::const_iterator sit = |
| - requestable_extensions_set_.find(str); |
| - if (sit != requestable_extensions_set_.end()) { |
| - result = sit->c_str(); |
| - } else { |
| - std::pair<std::set<std::string>::const_iterator, bool> insert_result = |
| - requestable_extensions_set_.insert(str); |
| - DCHECK(insert_result.second); |
| - result = insert_result.first->c_str(); |
| - } |
| + result = gl_strings_.insert(str).first->c_str(); |
| } |
| GPU_CLIENT_LOG(" returned " << result); |
| return reinterpret_cast<const GLchar*>(result); |
| @@ -4841,6 +4851,7 @@ void GLES2Implementation::RequestExtensionCHROMIUM(const char* extension) { |
| GPU_CLIENT_SINGLE_THREAD_CHECK(); |
| GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRequestExtensionCHROMIUM(" |
| << extension << ")"); |
| + InvalidateCachedExtensions(); |
| SetBucketAsCString(kResultBucketId, extension); |
| helper_->RequestExtensionCHROMIUM(kResultBucketId); |
| helper_->SetBucketSize(kResultBucketId, 0); |
| @@ -6551,6 +6562,18 @@ void GLES2Implementation::ProgramPathFragmentInputGenCHROMIUM( |
| CheckGLError(); |
| } |
| +void GLES2Implementation::UpdateCachedExtensionsIfNeeded() { |
| + if (cached_extension_string_) { |
| + return; |
| + } |
| + GetStringHelper(GL_EXTENSIONS); |
| +} |
| + |
| +void GLES2Implementation::InvalidateCachedExtensions() { |
| + cached_extension_string_ = nullptr; |
| + cached_extensions_.clear(); |
| +} |
| + |
| // Include the auto-generated part of this file. We split this because it means |
| // we can easily edit the non-auto generated parts right here in this file |
| // instead of having to edit some template or the code generator. |