| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // A class to emulate GLES2 over command buffers. | 5 // A class to emulate GLES2 over command buffers. |
| 6 | 6 |
| 7 #include "gpu/command_buffer/client/gles2_implementation.h" | 7 #include "gpu/command_buffer/client/gles2_implementation.h" |
| 8 | 8 |
| 9 #include <GLES2/gl2.h> | 9 #include <GLES2/gl2.h> |
| 10 #include <GLES2/gl2ext.h> | 10 #include <GLES2/gl2ext.h> |
| 11 #include <GLES2/gl2extchromium.h> | 11 #include <GLES2/gl2extchromium.h> |
| 12 #include <GLES3/gl3.h> | 12 #include <GLES3/gl3.h> |
| 13 #include <stddef.h> | 13 #include <stddef.h> |
| 14 #include <stdint.h> | 14 #include <stdint.h> |
| 15 #include <algorithm> | 15 #include <algorithm> |
| 16 #include <map> | 16 #include <map> |
| 17 #include <set> | 17 #include <set> |
| 18 #include <sstream> | 18 #include <sstream> |
| 19 #include <string> | 19 #include <string> |
| 20 #include "base/compiler_specific.h" | 20 #include "base/compiler_specific.h" |
| 21 #include "base/strings/string_split.h" |
| 21 #include "base/strings/stringprintf.h" | 22 #include "base/strings/stringprintf.h" |
| 22 #include "base/sys_info.h" | 23 #include "base/sys_info.h" |
| 23 #include "base/thread_task_runner_handle.h" | 24 #include "base/thread_task_runner_handle.h" |
| 24 #include "base/trace_event/memory_allocator_dump.h" | 25 #include "base/trace_event/memory_allocator_dump.h" |
| 25 #include "base/trace_event/memory_dump_manager.h" | 26 #include "base/trace_event/memory_dump_manager.h" |
| 26 #include "base/trace_event/process_memory_dump.h" | 27 #include "base/trace_event/process_memory_dump.h" |
| 27 #include "base/trace_event/trace_event.h" | 28 #include "base/trace_event/trace_event.h" |
| 28 #include "gpu/command_buffer/client/buffer_tracker.h" | 29 #include "gpu/command_buffer/client/buffer_tracker.h" |
| 29 #include "gpu/command_buffer/client/gles2_cmd_helper.h" | 30 #include "gpu/command_buffer/client/gles2_cmd_helper.h" |
| 30 #include "gpu/command_buffer/client/gpu_control.h" | 31 #include "gpu/command_buffer/client/gpu_control.h" |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 base::SysInfo::AmountOfPhysicalMemory() > 1024 * 1024 * 1024 | 125 base::SysInfo::AmountOfPhysicalMemory() > 1024 * 1024 * 1024 |
| 125 ? base::saturated_cast<uint32_t>( | 126 ? base::saturated_cast<uint32_t>( |
| 126 base::SysInfo::AmountOfPhysicalMemory() / 20) | 127 base::SysInfo::AmountOfPhysicalMemory() / 20) |
| 127 : 0), | 128 : 0), |
| 128 #endif | 129 #endif |
| 129 error_message_callback_(NULL), | 130 error_message_callback_(NULL), |
| 130 current_trace_stack_(0), | 131 current_trace_stack_(0), |
| 131 gpu_control_(gpu_control), | 132 gpu_control_(gpu_control), |
| 132 capabilities_(gpu_control->GetCapabilities()), | 133 capabilities_(gpu_control->GetCapabilities()), |
| 133 aggressively_free_resources_(false), | 134 aggressively_free_resources_(false), |
| 135 cached_extension_string_(nullptr), |
| 134 weak_ptr_factory_(this) { | 136 weak_ptr_factory_(this) { |
| 135 DCHECK(helper); | 137 DCHECK(helper); |
| 136 DCHECK(transfer_buffer); | 138 DCHECK(transfer_buffer); |
| 137 DCHECK(gpu_control); | 139 DCHECK(gpu_control); |
| 138 | 140 |
| 139 std::stringstream ss; | 141 std::stringstream ss; |
| 140 ss << std::hex << this; | 142 ss << std::hex << this; |
| 141 this_in_hex_ = ss.str(); | 143 this_in_hex_ = ss.str(); |
| 142 | 144 |
| 143 GPU_CLIENT_LOG_CODE_BLOCK({ | 145 GPU_CLIENT_LOG_CODE_BLOCK({ |
| (...skipping 799 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 943 case GL_MAX_VERTEX_UNIFORM_COMPONENTS: | 945 case GL_MAX_VERTEX_UNIFORM_COMPONENTS: |
| 944 *params = capabilities_.max_vertex_uniform_components; | 946 *params = capabilities_.max_vertex_uniform_components; |
| 945 return true; | 947 return true; |
| 946 case GL_MIN_PROGRAM_TEXEL_OFFSET: | 948 case GL_MIN_PROGRAM_TEXEL_OFFSET: |
| 947 *params = capabilities_.min_program_texel_offset; | 949 *params = capabilities_.min_program_texel_offset; |
| 948 return true; | 950 return true; |
| 949 case GL_MINOR_VERSION: | 951 case GL_MINOR_VERSION: |
| 950 *params = capabilities_.minor_version; | 952 *params = capabilities_.minor_version; |
| 951 return true; | 953 return true; |
| 952 case GL_NUM_EXTENSIONS: | 954 case GL_NUM_EXTENSIONS: |
| 953 *params = capabilities_.num_extensions; | 955 UpdateCachedExtensionsIfNeeded(); |
| 956 *params = cached_extensions_.size(); |
| 954 return true; | 957 return true; |
| 955 case GL_NUM_PROGRAM_BINARY_FORMATS: | 958 case GL_NUM_PROGRAM_BINARY_FORMATS: |
| 956 *params = capabilities_.num_program_binary_formats; | 959 *params = capabilities_.num_program_binary_formats; |
| 957 return true; | 960 return true; |
| 958 case GL_PIXEL_PACK_BUFFER_BINDING: | 961 case GL_PIXEL_PACK_BUFFER_BINDING: |
| 959 *params = bound_pixel_pack_buffer_; | 962 *params = bound_pixel_pack_buffer_; |
| 960 return true; | 963 return true; |
| 961 case GL_PIXEL_UNPACK_BUFFER_BINDING: | 964 case GL_PIXEL_UNPACK_BUFFER_BINDING: |
| 962 *params = bound_pixel_unpack_buffer_; | 965 *params = bound_pixel_unpack_buffer_; |
| 963 return true; | 966 return true; |
| (...skipping 2321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3285 } | 3288 } |
| 3286 if (precision) { | 3289 if (precision) { |
| 3287 precision[0] = result->precision; | 3290 precision[0] = result->precision; |
| 3288 GPU_CLIENT_LOG(" min_range: " << precision[0]); | 3291 GPU_CLIENT_LOG(" min_range: " << precision[0]); |
| 3289 } | 3292 } |
| 3290 } | 3293 } |
| 3291 CheckGLError(); | 3294 CheckGLError(); |
| 3292 } | 3295 } |
| 3293 | 3296 |
| 3294 const GLubyte* GLES2Implementation::GetStringHelper(GLenum name) { | 3297 const GLubyte* GLES2Implementation::GetStringHelper(GLenum name) { |
| 3298 if (name == GL_EXTENSIONS && cached_extension_string_) { |
| 3299 return reinterpret_cast<const GLubyte*>(cached_extension_string_); |
| 3300 } |
| 3295 const char* result = NULL; | 3301 const char* result = NULL; |
| 3296 // Clears the bucket so if the command fails nothing will be in it. | 3302 // Clears the bucket so if the command fails nothing will be in it. |
| 3297 helper_->SetBucketSize(kResultBucketId, 0); | 3303 helper_->SetBucketSize(kResultBucketId, 0); |
| 3298 helper_->GetString(name, kResultBucketId); | 3304 helper_->GetString(name, kResultBucketId); |
| 3299 std::string str; | 3305 std::string str; |
| 3300 if (GetBucketAsString(kResultBucketId, &str)) { | 3306 if (GetBucketAsString(kResultBucketId, &str)) { |
| 3301 // Adds extensions implemented on client side only. | 3307 // Adds extensions implemented on client side only. |
| 3302 switch (name) { | 3308 if (name == GL_EXTENSIONS) { |
| 3303 case GL_EXTENSIONS: | 3309 str += std::string(str.empty() ? "" : " ") + |
| 3304 str += std::string(str.empty() ? "" : " ") + | 3310 "GL_EXT_unpack_subimage " |
| 3305 "GL_EXT_unpack_subimage " | 3311 "GL_CHROMIUM_map_sub"; |
| 3306 "GL_CHROMIUM_map_sub"; | 3312 if (capabilities_.image) |
| 3307 if (capabilities_.image) | 3313 str += " GL_CHROMIUM_image GL_CHROMIUM_gpu_memory_buffer_image"; |
| 3308 str += " GL_CHROMIUM_image GL_CHROMIUM_gpu_memory_buffer_image"; | 3314 if (capabilities_.future_sync_points) |
| 3309 if (capabilities_.future_sync_points) | 3315 str += " GL_CHROMIUM_future_sync_point"; |
| 3310 str += " GL_CHROMIUM_future_sync_point"; | |
| 3311 break; | |
| 3312 default: | |
| 3313 break; | |
| 3314 } | 3316 } |
| 3315 | 3317 |
| 3316 // Because of WebGL the extensions can change. We have to cache each unique | 3318 // Because of WebGL the extensions can change. We have to cache each unique |
| 3317 // result since we don't know when the client will stop referring to a | 3319 // result since we don't know when the client will stop referring to a |
| 3318 // previous one it queries. | 3320 // previous one it queries. |
| 3319 GLStringMap::iterator it = gl_strings_.find(name); | 3321 // TODO: Here we could save memory by defining RequestExtensions |
| 3320 if (it == gl_strings_.end()) { | 3322 // invalidating the GL_EXTENSIONS string. http://crbug.com/586414 |
| 3321 std::set<std::string> strings; | 3323 const std::string& cache = *gl_strings_.insert(str).first; |
| 3322 std::pair<GLStringMap::iterator, bool> insert_result = | 3324 result = cache.c_str(); |
| 3323 gl_strings_.insert(std::make_pair(name, strings)); | 3325 |
| 3324 DCHECK(insert_result.second); | 3326 if (name == GL_EXTENSIONS) { |
| 3325 it = insert_result.first; | 3327 cached_extension_string_ = result; |
| 3326 } | 3328 std::vector<std::string> extensions = |
| 3327 std::set<std::string>& string_set = it->second; | 3329 base::SplitString(cache, base::kWhitespaceASCII, |
| 3328 std::set<std::string>::const_iterator sit = string_set.find(str); | 3330 base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); |
| 3329 if (sit != string_set.end()) { | 3331 for (const std::string& extension : extensions) { |
| 3330 result = sit->c_str(); | 3332 cached_extensions_.push_back( |
| 3331 } else { | 3333 gl_strings_.insert(extension).first->c_str()); |
| 3332 std::pair<std::set<std::string>::const_iterator, bool> insert_result = | 3334 } |
| 3333 string_set.insert(str); | |
| 3334 DCHECK(insert_result.second); | |
| 3335 result = insert_result.first->c_str(); | |
| 3336 } | 3335 } |
| 3337 } | 3336 } |
| 3338 return reinterpret_cast<const GLubyte*>(result); | 3337 return reinterpret_cast<const GLubyte*>(result); |
| 3339 } | 3338 } |
| 3340 | 3339 |
| 3341 const GLubyte* GLES2Implementation::GetString(GLenum name) { | 3340 const GLubyte* GLES2Implementation::GetString(GLenum name) { |
| 3342 GPU_CLIENT_SINGLE_THREAD_CHECK(); | 3341 GPU_CLIENT_SINGLE_THREAD_CHECK(); |
| 3343 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetString(" | 3342 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetString(" |
| 3344 << GLES2Util::GetStringStringType(name) << ")"); | 3343 << GLES2Util::GetStringStringType(name) << ")"); |
| 3345 TRACE_EVENT0("gpu", "GLES2::GetString"); | 3344 TRACE_EVENT0("gpu", "GLES2::GetString"); |
| 3346 const GLubyte* result = GetStringHelper(name); | 3345 const GLubyte* result = GetStringHelper(name); |
| 3347 GPU_CLIENT_LOG(" returned " << reinterpret_cast<const char*>(result)); | 3346 GPU_CLIENT_LOG(" returned " << reinterpret_cast<const char*>(result)); |
| 3348 CheckGLError(); | 3347 CheckGLError(); |
| 3349 return result; | 3348 return result; |
| 3350 } | 3349 } |
| 3351 | 3350 |
| 3351 const GLubyte* GLES2Implementation::GetStringi(GLenum name, GLuint index) { |
| 3352 GPU_CLIENT_SINGLE_THREAD_CHECK(); |
| 3353 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetStringi(" |
| 3354 << GLES2Util::GetStringStringType(name) << "," << index |
| 3355 << ")"); |
| 3356 TRACE_EVENT0("gpu", "GLES2::GetStringi"); |
| 3357 UpdateCachedExtensionsIfNeeded(); |
| 3358 if (name != GL_EXTENSIONS) { |
| 3359 SetGLError(GL_INVALID_ENUM, "glGetStringi", "name"); |
| 3360 return nullptr; |
| 3361 } |
| 3362 if (index >= cached_extensions_.size()) { |
| 3363 SetGLError(GL_INVALID_VALUE, "glGetStringi", "index too large"); |
| 3364 return nullptr; |
| 3365 } |
| 3366 |
| 3367 const char* result = cached_extensions_[index]; |
| 3368 GPU_CLIENT_LOG(" returned " << result); |
| 3369 CheckGLError(); |
| 3370 return reinterpret_cast<const GLubyte*>(result); |
| 3371 } |
| 3372 |
| 3352 bool GLES2Implementation::GetTransformFeedbackVaryingHelper( | 3373 bool GLES2Implementation::GetTransformFeedbackVaryingHelper( |
| 3353 GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, | 3374 GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, |
| 3354 GLenum* type, char* name) { | 3375 GLenum* type, char* name) { |
| 3355 // Clear the bucket so if the command fails nothing will be in it. | 3376 // Clear the bucket so if the command fails nothing will be in it. |
| 3356 helper_->SetBucketSize(kResultBucketId, 0); | 3377 helper_->SetBucketSize(kResultBucketId, 0); |
| 3357 typedef cmds::GetTransformFeedbackVarying::Result Result; | 3378 typedef cmds::GetTransformFeedbackVarying::Result Result; |
| 3358 Result* result = GetResultAs<Result*>(); | 3379 Result* result = GetResultAs<Result*>(); |
| 3359 if (!result) { | 3380 if (!result) { |
| 3360 return false; | 3381 return false; |
| 3361 } | 3382 } |
| (...skipping 1446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4808 const char* result = NULL; | 4829 const char* result = NULL; |
| 4809 // Clear the bucket so if the command fails nothing will be in it. | 4830 // Clear the bucket so if the command fails nothing will be in it. |
| 4810 helper_->SetBucketSize(kResultBucketId, 0); | 4831 helper_->SetBucketSize(kResultBucketId, 0); |
| 4811 helper_->GetRequestableExtensionsCHROMIUM(kResultBucketId); | 4832 helper_->GetRequestableExtensionsCHROMIUM(kResultBucketId); |
| 4812 std::string str; | 4833 std::string str; |
| 4813 if (GetBucketAsString(kResultBucketId, &str)) { | 4834 if (GetBucketAsString(kResultBucketId, &str)) { |
| 4814 // The set of requestable extensions shrinks as we enable | 4835 // The set of requestable extensions shrinks as we enable |
| 4815 // them. Because we don't know when the client will stop referring | 4836 // them. Because we don't know when the client will stop referring |
| 4816 // to a previous one it queries (see GetString) we need to cache | 4837 // to a previous one it queries (see GetString) we need to cache |
| 4817 // the unique results. | 4838 // the unique results. |
| 4818 std::set<std::string>::const_iterator sit = | 4839 // TODO: Here we could save memory by defining RequestExtensions |
| 4819 requestable_extensions_set_.find(str); | 4840 // invalidating the GL_EXTENSIONS string. http://crbug.com/586414 |
| 4820 if (sit != requestable_extensions_set_.end()) { | 4841 result = gl_strings_.insert(str).first->c_str(); |
| 4821 result = sit->c_str(); | |
| 4822 } else { | |
| 4823 std::pair<std::set<std::string>::const_iterator, bool> insert_result = | |
| 4824 requestable_extensions_set_.insert(str); | |
| 4825 DCHECK(insert_result.second); | |
| 4826 result = insert_result.first->c_str(); | |
| 4827 } | |
| 4828 } | 4842 } |
| 4829 GPU_CLIENT_LOG(" returned " << result); | 4843 GPU_CLIENT_LOG(" returned " << result); |
| 4830 return reinterpret_cast<const GLchar*>(result); | 4844 return reinterpret_cast<const GLchar*>(result); |
| 4831 } | 4845 } |
| 4832 | 4846 |
| 4833 // TODO(gman): Remove this command. It's here for WebGL but is incompatible | 4847 // TODO(gman): Remove this command. It's here for WebGL but is incompatible |
| 4834 // with VirtualGL contexts. | 4848 // with VirtualGL contexts. |
| 4835 void GLES2Implementation::RequestExtensionCHROMIUM(const char* extension) { | 4849 void GLES2Implementation::RequestExtensionCHROMIUM(const char* extension) { |
| 4836 GPU_CLIENT_SINGLE_THREAD_CHECK(); | 4850 GPU_CLIENT_SINGLE_THREAD_CHECK(); |
| 4837 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRequestExtensionCHROMIUM(" | 4851 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRequestExtensionCHROMIUM(" |
| 4838 << extension << ")"); | 4852 << extension << ")"); |
| 4853 InvalidateCachedExtensions(); |
| 4839 SetBucketAsCString(kResultBucketId, extension); | 4854 SetBucketAsCString(kResultBucketId, extension); |
| 4840 helper_->RequestExtensionCHROMIUM(kResultBucketId); | 4855 helper_->RequestExtensionCHROMIUM(kResultBucketId); |
| 4841 helper_->SetBucketSize(kResultBucketId, 0); | 4856 helper_->SetBucketSize(kResultBucketId, 0); |
| 4842 | 4857 |
| 4843 struct ExtensionCheck { | 4858 struct ExtensionCheck { |
| 4844 const char* extension; | 4859 const char* extension; |
| 4845 ExtensionStatus* status; | 4860 ExtensionStatus* status; |
| 4846 }; | 4861 }; |
| 4847 const ExtensionCheck checks[] = { | 4862 const ExtensionCheck checks[] = { |
| 4848 { | 4863 { |
| (...skipping 1691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6540 unsigned char* addr = static_cast<unsigned char*>(buffer.address()); | 6555 unsigned char* addr = static_cast<unsigned char*>(buffer.address()); |
| 6541 memcpy(addr, coeffs, coeffs_size); | 6556 memcpy(addr, coeffs, coeffs_size); |
| 6542 | 6557 |
| 6543 helper_->ProgramPathFragmentInputGenCHROMIUM(program, location, gen_mode, | 6558 helper_->ProgramPathFragmentInputGenCHROMIUM(program, location, gen_mode, |
| 6544 components, buffer.shm_id(), | 6559 components, buffer.shm_id(), |
| 6545 buffer.offset()); | 6560 buffer.offset()); |
| 6546 } | 6561 } |
| 6547 CheckGLError(); | 6562 CheckGLError(); |
| 6548 } | 6563 } |
| 6549 | 6564 |
| 6565 void GLES2Implementation::UpdateCachedExtensionsIfNeeded() { |
| 6566 if (cached_extension_string_) { |
| 6567 return; |
| 6568 } |
| 6569 GetStringHelper(GL_EXTENSIONS); |
| 6570 } |
| 6571 |
| 6572 void GLES2Implementation::InvalidateCachedExtensions() { |
| 6573 cached_extension_string_ = nullptr; |
| 6574 cached_extensions_.clear(); |
| 6575 } |
| 6576 |
| 6550 // Include the auto-generated part of this file. We split this because it means | 6577 // Include the auto-generated part of this file. We split this because it means |
| 6551 // we can easily edit the non-auto generated parts right here in this file | 6578 // we can easily edit the non-auto generated parts right here in this file |
| 6552 // instead of having to edit some template or the code generator. | 6579 // instead of having to edit some template or the code generator. |
| 6553 #include "gpu/command_buffer/client/gles2_implementation_impl_autogen.h" | 6580 #include "gpu/command_buffer/client/gles2_implementation_impl_autogen.h" |
| 6554 | 6581 |
| 6555 } // namespace gles2 | 6582 } // namespace gles2 |
| 6556 } // namespace gpu | 6583 } // namespace gpu |
| OLD | NEW |