summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorkbr@google.com <kbr@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-06 18:07:24 +0000
committerkbr@google.com <kbr@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-06 18:07:24 +0000
commitc2f8c84089f32aac6377c95da14d52153a165b39 (patch)
tree91e39d58e5b54b21d2f6070654a0e89208cd5236 /gpu
parent5ac981e18bcad738dbe3e34a59c5814a9f00ea08 (diff)
downloadchromium_src-c2f8c84089f32aac6377c95da14d52153a165b39.zip
chromium_src-c2f8c84089f32aac6377c95da14d52153a165b39.tar.gz
chromium_src-c2f8c84089f32aac6377c95da14d52153a165b39.tar.bz2
Exposed support for dynamically enabling extensions in command buffer
implementation via new glGetRequestableExtensionsCHROMIUM and glRequestExtensionCHROMIUM entry points. These entry points are needed in order to allow WebGL to both query the available extensions and enable them individually. Added these entry points to WebGraphicsContext3DCommandBufferImpl. A subsequent WebKit checkin under https://bugs.webkit.org/show_bug.cgi?id=40316 will utilize them and implement the OES_texture_float extension for WebGL. BUG=none TEST=none (ran with new oes-texture-float.html WebGL conformance test) Review URL: http://codereview.chromium.org/5626008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@68352 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rw-r--r--gpu/GLES2/gl2ext.h28
-rwxr-xr-xgpu/command_buffer/build_gles2_cmd_buffer.py20
-rw-r--r--gpu/command_buffer/client/gles2_c_lib_autogen.h11
-rw-r--r--gpu/command_buffer/client/gles2_cmd_helper_autogen.h12
-rw-r--r--gpu/command_buffer/client/gles2_implementation.cc31
-rw-r--r--gpu/command_buffer/client/gles2_implementation.h4
-rw-r--r--gpu/command_buffer/client/gles2_implementation_autogen.h4
-rw-r--r--gpu/command_buffer/common/gles2_cmd_format_autogen.h68
-rw-r--r--gpu/command_buffer/common/gles2_cmd_format_test_autogen.h26
-rw-r--r--gpu/command_buffer/common/gles2_cmd_ids_autogen.h2
-rw-r--r--gpu/command_buffer/service/feature_info.cc21
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc134
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc11
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h42
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc12
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h46
-rw-r--r--gpu/command_buffer/service/mocks.h5
-rw-r--r--gpu/command_buffer/service/shader_translator.cc33
-rw-r--r--gpu/command_buffer/service/shader_translator.h10
-rw-r--r--gpu/command_buffer/service/shader_translator_unittest.cc4
20 files changed, 413 insertions, 111 deletions
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);