diff options
22 files changed, 427 insertions, 112 deletions
diff --git a/chrome/renderer/webgraphicscontext3d_command_buffer_impl.cc b/chrome/renderer/webgraphicscontext3d_command_buffer_impl.cc index b269151..6479a7a 100644 --- a/chrome/renderer/webgraphicscontext3d_command_buffer_impl.cc +++ b/chrome/renderer/webgraphicscontext3d_command_buffer_impl.cc @@ -90,7 +90,7 @@ bool WebGraphicsContext3DCommandBufferImpl::initialize( GPUInfo gpu_info = host->gpu_info(); UMA_HISTOGRAM_ENUMERATION( "GPU.WebGraphicsContext3D_Init_CanLoseContext", - attributes.canRecoverFromContextLoss * 2 + gpu_info.can_lose_context(), + attributes.canRecoverFromContextLoss * 2 + gpu_info.can_lose_context(), 4); if (attributes.canRecoverFromContextLoss == false) { if (gpu_info.can_lose_context()) @@ -371,6 +371,16 @@ void WebGraphicsContext3DCommandBufferImpl::copyTextureToParentTextureCHROMIUM( copyTextureToCompositor(texture, parentTexture); } +WebKit::WebString WebGraphicsContext3DCommandBufferImpl:: + getRequestableExtensionsCHROMIUM() { + return WebKit::WebString::fromUTF8(glGetRequestableExtensionsCHROMIUM()); +} + +void WebGraphicsContext3DCommandBufferImpl::requestExtensionCHROMIUM( + const char* extension) { + glRequestExtensionCHROMIUM(extension); +} + // Helper macros to reduce the amount of code. #define DELEGATE_TO_GL(name, glname) \ diff --git a/chrome/renderer/webgraphicscontext3d_command_buffer_impl.h b/chrome/renderer/webgraphicscontext3d_command_buffer_impl.h index bf9ecfe..b4f99d2 100644 --- a/chrome/renderer/webgraphicscontext3d_command_buffer_impl.h +++ b/chrome/renderer/webgraphicscontext3d_command_buffer_impl.h @@ -361,6 +361,9 @@ class WebGraphicsContext3DCommandBufferImpl virtual void copyTextureToParentTextureCHROMIUM( unsigned texture, unsigned parentTexture); + virtual WebKit::WebString getRequestableExtensionsCHROMIUM(); + virtual void requestExtensionCHROMIUM(const char*); + virtual unsigned createCompositorTexture(unsigned width, unsigned height); virtual void deleteCompositorTexture(unsigned parent_texture); virtual void copyTextureToCompositor(unsigned texture, diff --git a/gpu/GLES2/gl2ext.h b/gpu/GLES2/gl2ext.h index 287b122..4a1f828 100644 --- a/gpu/GLES2/gl2ext.h +++ b/gpu/GLES2/gl2ext.h @@ -922,6 +922,34 @@ typedef void (GL_APIENTRYP PFNGLRESIZECHROMIUM) (GLuint width, GLuint height); #endif #endif +/* GL_CHROMIUM_request_extension */ +/* + * This extension allows other extensions to be turned on at run time. + * + * glGetRequestableExtensionsCHROMIUM returns a space-separated and + * null-terminated string containing all of the extension names that + * can be successfully requested on the current hardware. This may + * include the names of extensions that have already been enabled. + * + * glRequestExtensionCHROMIUM requests that the given extension be + * enabled. Call glGetString(GL_EXTENSIONS) to find out whether the + * extension request succeeded. + */ +#ifndef GL_CHROMIUM_request_extension +#define GL_CHROMIUM_request_extension 1 +#ifdef GL_GLEXT_PROTOTYPES +#define glGetRequestableExtensionsCHROMIUM GLES2_GET_FUN(GetRequestableExtensionsCHROMIUM) +#define glRequestExtensionCHROMIUM GLES2_GET_FUN(RequestExtensionCHROMIUM) +#if !defined(GLES2_USE_CPP_BINDINGS) +GL_APICALL const GLchar* GL_APIENTRY glGetRequestableExtensionsCHROMIUM (void); +GL_APICALL void GL_APIENTRY glRequestExtensionCHROMIUM (const GLchar *extension); +#endif +#else +typedef const GLchar* (GL_APIENTRYP PFNGLGETREQUESTABLEEXTENSIONSCHROMIUM) (void); +typedef void (GL_APIENTRYP PFNGLREQUESTEXTENSIONCHROMIUM) (const GLchar *extension); +#endif +#endif + #ifdef __cplusplus } diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index 0e9d7e5..01a321f 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -209,6 +209,8 @@ GL_APICALL void* GL_APIENTRY glMapTexSubImage2DCHROMIUM (GLenum target, G GL_APICALL void GL_APIENTRY glUnmapTexSubImage2DCHROMIUM (const void* mem); GL_APICALL void GL_APIENTRY glCopyTextureToParentTextureCHROMIUM (GLidBindTexture client_child_id, GLidBindTexture client_parent_id); GL_APICALL void GL_APIENTRY glResizeCHROMIUM (GLuint width, GLuint height); +GL_APICALL const GLchar* GL_APIENTRY glGetRequestableExtensionsCHROMIUM (void); +GL_APICALL void GL_APIENTRY glRequestExtensionCHROMIUM (const char* extension); """ # This is the list of all commmands that will be generated and their Id. @@ -410,6 +412,8 @@ _CMD_ID_TABLE = { 'BlitFramebufferEXT': 446, 'CopyTextureToParentTextureCHROMIUM': 447, 'ResizeCHROMIUM': 448, + 'GetRequestableExtensionsCHROMIUM': 449, + 'RequestExtensionCHROMIUM': 450, } # This is a list of enum names and their valid values. It is used to map @@ -1579,6 +1583,22 @@ _FUNCTION_INFO = { 'extension': True, 'chromium': True, }, + 'GetRequestableExtensionsCHROMIUM': { + 'type': 'Custom', + 'impl_func': False, + 'immediate': False, + 'cmd_args': 'uint32 bucket_id', + 'extension': True, + 'chromium': True, + }, + 'RequestExtensionCHROMIUM': { + 'type': 'Custom', + 'impl_func': False, + 'immediate': False, + 'cmd_args': 'uint32 bucket_id', + 'extension': True, + 'chromium': True, + }, } diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h index ab54997..01cb485 100644 --- a/gpu/command_buffer/client/gles2_c_lib_autogen.h +++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h @@ -844,6 +844,17 @@ void GLES2ResizeCHROMIUM(GLuint width, GLuint height) { GPU_CLIENT_LOG("ResizeCHROMIUM" << "(" << width << ", " << height << ")"); gles2::GetGLContext()->ResizeCHROMIUM(width, height); } +const GLchar* GLES2GetRequestableExtensionsCHROMIUM() { + GPU_CLIENT_LOG("GetRequestableExtensionsCHROMIUM" << "(" << ")"); + const GLchar* result = + gles2::GetGLContext()->GetRequestableExtensionsCHROMIUM(); + GPU_CLIENT_LOG("return:" << result) + return result; +} +void GLES2RequestExtensionCHROMIUM(const char* extension) { + GPU_CLIENT_LOG("RequestExtensionCHROMIUM" << "(" << extension << ")"); + gles2::GetGLContext()->RequestExtensionCHROMIUM(extension); +} #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_C_LIB_AUTOGEN_H_ diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h index 1f2b87b..e69b7ee 100644 --- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h +++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h @@ -1203,5 +1203,17 @@ c.Init(width, height); } + void GetRequestableExtensionsCHROMIUM(uint32 bucket_id) { + gles2::GetRequestableExtensionsCHROMIUM& c = + GetCmdSpace<gles2::GetRequestableExtensionsCHROMIUM>(); + c.Init(bucket_id); + } + + void RequestExtensionCHROMIUM(uint32 bucket_id) { + gles2::RequestExtensionCHROMIUM& c = + GetCmdSpace<gles2::RequestExtensionCHROMIUM>(); + c.Init(bucket_id); + } + #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_CMD_HELPER_AUTOGEN_H_ diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index 0debcd0..64bcbe2 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc @@ -1581,5 +1581,36 @@ void GLES2Implementation::UnmapTexSubImage2DCHROMIUM(const void* mem) { mapped_textures_.erase(it); } +const GLchar* GLES2Implementation::GetRequestableExtensionsCHROMIUM() { + const char* result = NULL; + // Clear the bucket so if the command fails nothing will be in it. + helper_->SetBucketSize(kResultBucketId, 0); + helper_->GetRequestableExtensionsCHROMIUM(kResultBucketId); + std::string str; + if (GetBucketAsString(kResultBucketId, &str)) { + // The set of requestable extensions shrinks as we enable + // 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); + GPU_DCHECK(insert_result.second); + result = insert_result.first->c_str(); + } + } + return reinterpret_cast<const GLchar*>(result); +} + +void GLES2Implementation::RequestExtensionCHROMIUM(const char* extension) { + SetBucketAsCString(kResultBucketId, extension); + helper_->RequestExtensionCHROMIUM(kResultBucketId); + helper_->SetBucketSize(kResultBucketId, 0); +} + } // namespace gles2 } // namespace gpu diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h index 0b0e242..d56e32e 100644 --- a/gpu/command_buffer/client/gles2_implementation.h +++ b/gpu/command_buffer/client/gles2_implementation.h @@ -379,6 +379,10 @@ class GLES2Implementation { typedef std::map<uint32, std::set<std::string> > GLStringMap; GLStringMap gl_strings_; + // Similar cache for glGetRequestableExtensionsCHROMIUM. We don't + // have an enum for this so handle it separately. + std::set<std::string> requestable_extensions_set_; + typedef std::map<const void*, MappedBuffer> MappedBufferMap; MappedBufferMap mapped_buffers_; diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h index 6bf924e..bb22143 100644 --- a/gpu/command_buffer/client/gles2_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_autogen.h @@ -888,5 +888,9 @@ void ResizeCHROMIUM(GLuint width, GLuint height) { helper_->ResizeCHROMIUM(width, height); } +const GLchar* GetRequestableExtensionsCHROMIUM(); + +void RequestExtensionCHROMIUM(const char* extension); + #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_AUTOGEN_H_ diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h index 9e10aa7..22fb23a 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h @@ -8833,6 +8833,74 @@ COMPILE_ASSERT(offsetof(ResizeCHROMIUM, width) == 4, COMPILE_ASSERT(offsetof(ResizeCHROMIUM, height) == 8, OffsetOf_ResizeCHROMIUM_height_not_8); +struct GetRequestableExtensionsCHROMIUM { + typedef GetRequestableExtensionsCHROMIUM ValueType; + static const CommandId kCmdId = kGetRequestableExtensionsCHROMIUM; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + + static uint32 ComputeSize() { + return static_cast<uint32>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { + header.SetCmd<ValueType>(); + } + + void Init(uint32 _bucket_id) { + SetHeader(); + bucket_id = _bucket_id; + } + + void* Set(void* cmd, uint32 _bucket_id) { + static_cast<ValueType*>(cmd)->Init(_bucket_id); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32 bucket_id; +}; + +COMPILE_ASSERT(sizeof(GetRequestableExtensionsCHROMIUM) == 8, + Sizeof_GetRequestableExtensionsCHROMIUM_is_not_8); +COMPILE_ASSERT(offsetof(GetRequestableExtensionsCHROMIUM, header) == 0, + OffsetOf_GetRequestableExtensionsCHROMIUM_header_not_0); +COMPILE_ASSERT(offsetof(GetRequestableExtensionsCHROMIUM, bucket_id) == 4, + OffsetOf_GetRequestableExtensionsCHROMIUM_bucket_id_not_4); + +struct RequestExtensionCHROMIUM { + typedef RequestExtensionCHROMIUM ValueType; + static const CommandId kCmdId = kRequestExtensionCHROMIUM; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + + static uint32 ComputeSize() { + return static_cast<uint32>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { + header.SetCmd<ValueType>(); + } + + void Init(uint32 _bucket_id) { + SetHeader(); + bucket_id = _bucket_id; + } + + void* Set(void* cmd, uint32 _bucket_id) { + static_cast<ValueType*>(cmd)->Init(_bucket_id); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32 bucket_id; +}; + +COMPILE_ASSERT(sizeof(RequestExtensionCHROMIUM) == 8, + Sizeof_RequestExtensionCHROMIUM_is_not_8); +COMPILE_ASSERT(offsetof(RequestExtensionCHROMIUM, header) == 0, + OffsetOf_RequestExtensionCHROMIUM_header_not_0); +COMPILE_ASSERT(offsetof(RequestExtensionCHROMIUM, bucket_id) == 4, + OffsetOf_RequestExtensionCHROMIUM_bucket_id_not_4); + #endif // GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_FORMAT_AUTOGEN_H_ diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h index 75fa9ba..e62ca7c 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h @@ -3480,5 +3480,31 @@ TEST(GLES2FormatTest, ResizeCHROMIUM) { EXPECT_EQ(static_cast<GLuint>(12), cmd.height); } +TEST(GLES2FormatTest, GetRequestableExtensionsCHROMIUM) { + GetRequestableExtensionsCHROMIUM cmd = { { 0 } }; + void* next_cmd = cmd.Set( + &cmd, + static_cast<uint32>(11)); + EXPECT_EQ(static_cast<uint32>(GetRequestableExtensionsCHROMIUM::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<char*>(next_cmd), + reinterpret_cast<char*>(&cmd) + sizeof(cmd)); + EXPECT_EQ(static_cast<uint32>(11), cmd.bucket_id); +} + +TEST(GLES2FormatTest, RequestExtensionCHROMIUM) { + RequestExtensionCHROMIUM cmd = { { 0 } }; + void* next_cmd = cmd.Set( + &cmd, + static_cast<uint32>(11)); + EXPECT_EQ(static_cast<uint32>(RequestExtensionCHROMIUM::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<char*>(next_cmd), + reinterpret_cast<char*>(&cmd) + sizeof(cmd)); + EXPECT_EQ(static_cast<uint32>(11), cmd.bucket_id); +} + #endif // GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_FORMAT_TEST_AUTOGEN_H_ diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h index 3702b6c..fafbada 100644 --- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h @@ -201,6 +201,8 @@ OP(BlitFramebufferEXT) /* 446 */ \ OP(CopyTextureToParentTextureCHROMIUM) /* 447 */ \ OP(ResizeCHROMIUM) /* 448 */ \ + OP(GetRequestableExtensionsCHROMIUM) /* 449 */ \ + OP(RequestExtensionCHROMIUM) /* 450 */ \ enum CommandId { kStartPoint = cmd::kLastCommonId, // All GLES2 commands start after this. diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc index cf755d8..5d9403e 100644 --- a/gpu/command_buffer/service/feature_info.cc +++ b/gpu/command_buffer/service/feature_info.cc @@ -215,21 +215,32 @@ void FeatureInfo::AddFeatures(const char* desired_features) { bool enable_texture_float_linear = false; bool enable_texture_half_float = false; bool enable_texture_half_float_linear = false; - if (ext.HaveAndDesire("GL_ARB_texture_float")) { + + bool have_arb_texture_float = ext.Have("GL_ARB_texture_float"); + + if (have_arb_texture_float && ext.Desire("GL_ARB_texture_float")) { enable_texture_float = true; enable_texture_float_linear = true; enable_texture_half_float = true; enable_texture_half_float_linear = true; } else { - if (ext.HaveAndDesire("GL_OES_texture_float")) { + if (ext.HaveAndDesire("GL_OES_texture_float") || + (have_arb_texture_float && + ext.Desire("GL_OES_texture_float"))) { enable_texture_float = true; - if (ext.HaveAndDesire("GL_OES_texture_float_linear")) { + if (ext.HaveAndDesire("GL_OES_texture_float_linear") || + (have_arb_texture_float && + ext.Desire("GL_OES_texture_float_linear"))) { enable_texture_float_linear = true; } } - if (ext.HaveAndDesire("GL_OES_texture_half_float")) { + if (ext.HaveAndDesire("GL_OES_texture_half_float") || + (have_arb_texture_float && + ext.Desire("GL_OES_texture_half_float"))) { enable_texture_half_float = true; - if (ext.HaveAndDesire("GL_OES_texture_half_float_linear")) { + if (ext.HaveAndDesire("GL_OES_texture_half_float_linear") || + (have_arb_texture_float && + ext.Desire("GL_OES_texture_half_float_linear"))) { enable_texture_half_float_linear = true; } } diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 6c468ca..5d373fc 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -708,6 +708,9 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, TextureManager::TextureInfo::Ref bound_texture_cube_map; }; + // Initialize or re-initialize the shader translator. + bool InitializeShaderTranslator(); + // Helpers for the glGen and glDelete functions. bool GenTexturesHelper(GLsizei n, const GLuint* client_ids); void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids); @@ -1767,12 +1770,15 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group) attrib_0_value_.v[2] = 0.0f; attrib_0_value_.v[3] = 1.0f; - // The shader translator is not needed for EGL because it already uses the - // GLSL ES syntax. It is translated for the unit tests because - // GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes the empty - // string to CompileShader and this is not a valid shader. TODO(apatrick): - // fix this test. - if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 || + // The shader translator is used for WebGL even when running on EGL + // because additional restrictions are needed (like only enabling + // GL_OES_standard_derivatives on demand). It is used for the unit + // tests because + // GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes the + // empty string to CompileShader and this is not a valid shader. + // TODO(apatrick): fix this test. + if ((gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 && + !feature_info_->feature_flags().chromium_webglsl) || gfx::GetGLImplementation() == gfx::kGLImplementationMockGL) { use_shader_translator_ = false; } @@ -1981,42 +1987,59 @@ bool GLES2DecoderImpl::Initialize(gfx::GLContext* context, glEnable(GL_POINT_SPRITE); } - if (use_shader_translator_) { - ShBuiltInResources resources; - ShInitBuiltInResources(&resources); - resources.MaxVertexAttribs = group_->max_vertex_attribs(); - resources.MaxVertexUniformVectors = - group_->max_vertex_uniform_vectors(); - resources.MaxVaryingVectors = group_->max_varying_vectors(); - resources.MaxVertexTextureImageUnits = - group_->max_vertex_texture_image_units(); - resources.MaxCombinedTextureImageUnits = group_->max_texture_units(); - resources.MaxTextureImageUnits = group_->max_texture_image_units(); - resources.MaxFragmentUniformVectors = - group_->max_fragment_uniform_vectors(); - resources.MaxDrawBuffers = 1; - resources.OES_standard_derivatives = - feature_info_->feature_flags().oes_standard_derivatives ? 1 : 0; - vertex_translator_.reset(new ShaderTranslator); - ShShaderSpec shader_spec = feature_info_->feature_flags().chromium_webglsl ? - SH_WEBGL_SPEC : SH_GLES2_SPEC; - if (!vertex_translator_->Init(SH_VERTEX_SHADER, shader_spec, &resources)) { - LOG(ERROR) << "Could not initialize vertex shader translator."; - Destroy(); - return false; - } - fragment_translator_.reset(new ShaderTranslator); - if (!fragment_translator_->Init( - SH_FRAGMENT_SHADER, shader_spec, &resources)) { - LOG(ERROR) << "Could not initialize fragment shader translator."; - Destroy(); - return false; - } + if (!InitializeShaderTranslator()) { + return false; } return true; } +bool GLES2DecoderImpl::InitializeShaderTranslator() { + // Re-check the state of use_shader_translator_ each time this is called. + if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 && + feature_info_->feature_flags().chromium_webglsl && + !use_shader_translator_) { + use_shader_translator_ = true; + } + if (!use_shader_translator_) { + return true; + } + ShBuiltInResources resources; + ShInitBuiltInResources(&resources); + resources.MaxVertexAttribs = group_->max_vertex_attribs(); + resources.MaxVertexUniformVectors = + group_->max_vertex_uniform_vectors(); + resources.MaxVaryingVectors = group_->max_varying_vectors(); + resources.MaxVertexTextureImageUnits = + group_->max_vertex_texture_image_units(); + resources.MaxCombinedTextureImageUnits = group_->max_texture_units(); + resources.MaxTextureImageUnits = group_->max_texture_image_units(); + resources.MaxFragmentUniformVectors = + group_->max_fragment_uniform_vectors(); + resources.MaxDrawBuffers = 1; + resources.OES_standard_derivatives = + feature_info_->feature_flags().oes_standard_derivatives ? 1 : 0; + vertex_translator_.reset(new ShaderTranslator); + ShShaderSpec shader_spec = feature_info_->feature_flags().chromium_webglsl ? + SH_WEBGL_SPEC : SH_GLES2_SPEC; + bool is_glsl_es = + gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2; + if (!vertex_translator_->Init( + SH_VERTEX_SHADER, shader_spec, &resources, is_glsl_es)) { + LOG(ERROR) << "Could not initialize vertex shader translator."; + Destroy(); + return false; + } + fragment_translator_.reset(new ShaderTranslator); + if (!fragment_translator_->Init( + SH_FRAGMENT_SHADER, shader_spec, &resources, is_glsl_es)) { + LOG(ERROR) << "Could not initialize fragment shader translator."; + Destroy(); + return false; + } + return true; +} + bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) { for (GLsizei ii = 0; ii < n; ++ii) { if (GetBufferInfo(client_ids[ii])) { @@ -5935,6 +5958,43 @@ error::Error GLES2DecoderImpl::HandleCommandBufferEnableCHROMIUM( return error::kNoError; } +error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM( + uint32 immediate_data_size, + const gles2::GetRequestableExtensionsCHROMIUM& c) { + Bucket* bucket = CreateBucket(c.bucket_id); + scoped_ptr<FeatureInfo> info(new FeatureInfo()); + info->Initialize(NULL); + bucket->SetFromString(info->extensions().c_str()); + return error::kNoError; +} + +error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM( + uint32 immediate_data_size, const gles2::RequestExtensionCHROMIUM& c) { + Bucket* bucket = GetBucket(c.bucket_id); + std::string feature_str; + if (!bucket->GetAsString(&feature_str)) { + return error::kInvalidArguments; + } + + bool std_derivatives_enabled = + feature_info_->feature_flags().oes_standard_derivatives; + bool webglsl_enabled = + feature_info_->feature_flags().chromium_webglsl; + + feature_info_->AddFeatures(feature_str.c_str()); + + // If we just enabled a feature which affects the shader translator, + // we may need to re-initialize it. + if (std_derivatives_enabled != + feature_info_->feature_flags().oes_standard_derivatives || + webglsl_enabled != + feature_info_->feature_flags().chromium_webglsl) { + InitializeShaderTranslator(); + } + + return error::kNoError; +} + // 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. diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc index 9237a20..75597fa 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc @@ -119,6 +119,17 @@ void GLES2DecoderTestBase::SpecializedSetup<GetProgramInfoLog, 0>( info->set_log_info("hello"); }; +template <> +void GLES2DecoderTestBase::SpecializedSetup<GetVertexAttribfv, 0>(bool valid) { + DoBindBuffer(GL_ARRAY_BUFFER, client_buffer_id_, kServiceBufferId); + DoVertexAttribPointer(1, 1, GL_FLOAT, 0, 0); + if (valid) { + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + } +}; #include "gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h" diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h index eaa7af3..786ad92 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h @@ -1755,5 +1755,47 @@ TEST_F(GLES2DecoderTest1, GetTexParameterivInvalidArgs2_1) { // TODO(gman): GetUniformLocationBucket + +TEST_F(GLES2DecoderTest1, GetVertexAttribfvValidArgs) { + SpecializedSetup<GetVertexAttribfv, 0>(true); + typedef GetVertexAttribfv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + result->size = 0; + GetVertexAttribfv cmd; + cmd.Init( + 1, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned( + GL_VERTEX_ATTRIB_ARRAY_NORMALIZED), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_F(GLES2DecoderTest1, GetVertexAttribfvInvalidArgs2_0) { + EXPECT_CALL(*gl_, GetVertexAttribfv(_, _, _)).Times(0); + SpecializedSetup<GetVertexAttribfv, 0>(false); + GetVertexAttribfv::Result* result = + static_cast<GetVertexAttribfv::Result*>(shared_memory_address_); + result->size = 0; + GetVertexAttribfv cmd; + cmd.Init(1, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, kInvalidSharedMemoryId, 0); + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); + EXPECT_EQ(0u, result->size); +} + +TEST_F(GLES2DecoderTest1, GetVertexAttribfvInvalidArgs2_1) { + EXPECT_CALL(*gl_, GetVertexAttribfv(_, _, _)).Times(0); + SpecializedSetup<GetVertexAttribfv, 0>(false); + GetVertexAttribfv::Result* result = + static_cast<GetVertexAttribfv::Result*>(shared_memory_address_); + result->size = 0; + GetVertexAttribfv cmd; + cmd.Init( + 1, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, shared_memory_id_, + kInvalidSharedMemoryOffset); + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); + EXPECT_EQ(0u, result->size); +} #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_1_AUTOGEN_H_ diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc index 925e28f..a86149f 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc @@ -224,18 +224,6 @@ void GLES2DecoderTestBase::SpecializedSetup<TexParameterivImmediate, 0>( }; template <> -void GLES2DecoderTestBase::SpecializedSetup<GetVertexAttribfv, 0>(bool valid) { - DoBindBuffer(GL_ARRAY_BUFFER, client_buffer_id_, kServiceBufferId); - DoVertexAttribPointer(1, 1, GL_FLOAT, 0, 0); - if (valid) { - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - } -}; - -template <> void GLES2DecoderTestBase::SpecializedSetup<GetVertexAttribiv, 0>(bool valid) { DoBindBuffer(GL_ARRAY_BUFFER, client_buffer_id_, kServiceBufferId); DoVertexAttribPointer(1, 1, GL_FLOAT, 0, 0); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h index 7b0d1c9..7549fa9e 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h @@ -9,48 +9,6 @@ #define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_ -TEST_F(GLES2DecoderTest2, GetVertexAttribfvValidArgs) { - SpecializedSetup<GetVertexAttribfv, 0>(true); - typedef GetVertexAttribfv::Result Result; - Result* result = static_cast<Result*>(shared_memory_address_); - result->size = 0; - GetVertexAttribfv cmd; - cmd.Init( - 1, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, shared_memory_id_, - shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned( - GL_VERTEX_ATTRIB_ARRAY_NORMALIZED), - result->GetNumResults()); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_F(GLES2DecoderTest2, GetVertexAttribfvInvalidArgs2_0) { - EXPECT_CALL(*gl_, GetVertexAttribfv(_, _, _)).Times(0); - SpecializedSetup<GetVertexAttribfv, 0>(false); - GetVertexAttribfv::Result* result = - static_cast<GetVertexAttribfv::Result*>(shared_memory_address_); - result->size = 0; - GetVertexAttribfv cmd; - cmd.Init(1, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, kInvalidSharedMemoryId, 0); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); - EXPECT_EQ(0u, result->size); -} - -TEST_F(GLES2DecoderTest2, GetVertexAttribfvInvalidArgs2_1) { - EXPECT_CALL(*gl_, GetVertexAttribfv(_, _, _)).Times(0); - SpecializedSetup<GetVertexAttribfv, 0>(false); - GetVertexAttribfv::Result* result = - static_cast<GetVertexAttribfv::Result*>(shared_memory_address_); - result->size = 0; - GetVertexAttribfv cmd; - cmd.Init( - 1, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, shared_memory_id_, - kInvalidSharedMemoryOffset); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); - EXPECT_EQ(0u, result->size); -} - TEST_F(GLES2DecoderTest2, GetVertexAttribivValidArgs) { SpecializedSetup<GetVertexAttribiv, 0>(true); typedef GetVertexAttribiv::Result Result; @@ -1611,5 +1569,9 @@ TEST_F(GLES2DecoderTest2, ViewportInvalidArgs3_0) { // TODO(gman): CopyTextureToParentTextureCHROMIUM // TODO(gman): ResizeCHROMIUM +// TODO(gman): GetRequestableExtensionsCHROMIUM + +// TODO(gman): RequestExtensionCHROMIUM + #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_ diff --git a/gpu/command_buffer/service/mocks.h b/gpu/command_buffer/service/mocks.h index 8c84547..8a11aee 100644 --- a/gpu/command_buffer/service/mocks.h +++ b/gpu/command_buffer/service/mocks.h @@ -83,10 +83,11 @@ class MockShaderTranslator : public ShaderTranslatorInterface { public: virtual ~MockShaderTranslator() { } - MOCK_METHOD3(Init, bool( + MOCK_METHOD4(Init, bool( ShShaderType shader_type, ShShaderSpec shader_spec, - const ShBuiltInResources* resources)); + const ShBuiltInResources* resources, + bool implementation_is_glsl_es)); MOCK_METHOD1(Translate, bool(const char* shader)); MOCK_CONST_METHOD0(translated_shader, const char*()); MOCK_CONST_METHOD0(info_log, const char*()); diff --git a/gpu/command_buffer/service/shader_translator.cc b/gpu/command_buffer/service/shader_translator.cc index 551ae14..eb5b265 100644 --- a/gpu/command_buffer/service/shader_translator.cc +++ b/gpu/command_buffer/service/shader_translator.cc @@ -4,6 +4,8 @@ #include "gpu/command_buffer/service/shader_translator.h" +#include <string.h> + #include "base/at_exit.h" #include "base/logging.h" @@ -62,7 +64,9 @@ void GetVariableInfo(ShHandle compiler, ShShaderInfo var_type, namespace gpu { namespace gles2 { -ShaderTranslator::ShaderTranslator() : compiler_(NULL) { +ShaderTranslator::ShaderTranslator() + : compiler_(NULL), + implementation_is_glsl_es_(false) { } ShaderTranslator::~ShaderTranslator() { @@ -72,7 +76,8 @@ ShaderTranslator::~ShaderTranslator() { bool ShaderTranslator::Init(ShShaderType shader_type, ShShaderSpec shader_spec, - const ShBuiltInResources* resources) { + const ShBuiltInResources* resources, + bool implementation_is_glsl_es) { // Make sure Init is called only once. DCHECK(compiler_ == NULL); DCHECK(shader_type == SH_FRAGMENT_SHADER || shader_type == SH_VERTEX_SHADER); @@ -83,6 +88,7 @@ bool ShaderTranslator::Init(ShShaderType shader_type, return false; compiler_ = ShConstructCompiler(shader_type, shader_spec, resources); + implementation_is_glsl_es_ = implementation_is_glsl_es; return compiler_ != NULL; } @@ -96,12 +102,23 @@ bool ShaderTranslator::Translate(const char* shader) { int compile_options = SH_OBJECT_CODE | SH_ATTRIBUTES_UNIFORMS; if (ShCompile(compiler_, &shader, 1, compile_options)) { success = true; - // Get translated shader. - int obj_code_len = 0; - ShGetInfo(compiler_, SH_OBJECT_CODE_LENGTH, &obj_code_len); - if (obj_code_len > 1) { - translated_shader_.reset(new char[obj_code_len]); - ShGetObjectCode(compiler_, translated_shader_.get()); + if (!implementation_is_glsl_es_) { + // Get translated shader. + int obj_code_len = 0; + ShGetInfo(compiler_, SH_OBJECT_CODE_LENGTH, &obj_code_len); + if (obj_code_len > 1) { + translated_shader_.reset(new char[obj_code_len]); + ShGetObjectCode(compiler_, translated_shader_.get()); + } + } else { + // Pass down the original shader's source rather than the + // compiler's output. TODO(kbr): once the shader compiler has a + // GLSL ES backend, use its output. + int shader_code_len = 1 + strlen(shader); + if (shader_code_len > 1) { + translated_shader_.reset(new char[shader_code_len]); + strncpy(translated_shader_.get(), shader, shader_code_len); + } } // Get info for attribs and uniforms. GetVariableInfo(compiler_, SH_ACTIVE_ATTRIBUTES, &attrib_map_); diff --git a/gpu/command_buffer/service/shader_translator.h b/gpu/command_buffer/service/shader_translator.h index 852ee5f..084d1b8 100644 --- a/gpu/command_buffer/service/shader_translator.h +++ b/gpu/command_buffer/service/shader_translator.h @@ -15,7 +15,8 @@ namespace gpu { namespace gles2 { -// Translates GLSL ES 2.0 shader to desktop GLSL shader. +// Translates a GLSL ES 2.0 shader to desktop GLSL shader, or just +// validates GLSL ES 2.0 shaders on a true GLSL ES implementation. class ShaderTranslatorInterface { public: virtual ~ShaderTranslatorInterface() { } @@ -25,7 +26,8 @@ class ShaderTranslatorInterface { virtual bool Init( ShShaderType shader_type, ShShaderSpec shader_spec, - const ShBuiltInResources* resources) = 0; + const ShBuiltInResources* resources, + bool implementation_is_glsl_es) = 0; // Translates the given shader source. // Returns true if translation is successful, false otherwise. @@ -66,7 +68,8 @@ class ShaderTranslator : public ShaderTranslatorInterface { virtual bool Init( ShShaderType shader_type, ShShaderSpec shader_spec, - const ShBuiltInResources* resources); + const ShBuiltInResources* resources, + bool implementation_is_glsl_es); // Overridden from ShaderTranslatorInterface. virtual bool Translate(const char* shader); @@ -88,6 +91,7 @@ class ShaderTranslator : public ShaderTranslatorInterface { scoped_array<char> info_log_; VariableMap attrib_map_; VariableMap uniform_map_; + bool implementation_is_glsl_es_; DISALLOW_COPY_AND_ASSIGN(ShaderTranslator); }; diff --git a/gpu/command_buffer/service/shader_translator_unittest.cc b/gpu/command_buffer/service/shader_translator_unittest.cc index dbd9c60..5238859 100644 --- a/gpu/command_buffer/service/shader_translator_unittest.cc +++ b/gpu/command_buffer/service/shader_translator_unittest.cc @@ -22,9 +22,9 @@ class ShaderTranslatorTest : public testing::Test { ShInitBuiltInResources(&resources); ASSERT_TRUE(vertex_translator_.Init( - SH_VERTEX_SHADER, SH_GLES2_SPEC, &resources)); + SH_VERTEX_SHADER, SH_GLES2_SPEC, &resources, false)); ASSERT_TRUE(fragment_translator_.Init( - SH_FRAGMENT_SHADER, SH_GLES2_SPEC, &resources)); + SH_FRAGMENT_SHADER, SH_GLES2_SPEC, &resources, false)); // Post-init the results must be empty. // Vertex translator results. EXPECT_TRUE(vertex_translator_.translated_shader() == NULL); |
