diff options
author | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-30 21:29:11 +0000 |
---|---|---|
committer | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-30 21:29:11 +0000 |
commit | 915a59a10d1a1bb008821fd4e4f2019a4c676142 (patch) | |
tree | bec2e4c963ea3f6da1e839799a144de14086945e /gpu | |
parent | d15e56c68d773261b98d20b61aeeb03cfa0fb24e (diff) | |
download | chromium_src-915a59a10d1a1bb008821fd4e4f2019a4c676142.zip chromium_src-915a59a10d1a1bb008821fd4e4f2019a4c676142.tar.gz chromium_src-915a59a10d1a1bb008821fd4e4f2019a4c676142.tar.bz2 |
A step in making it possible for WebGL to request no features
and the add them in as extensions are enabled.
The idea is when WebGL inits it's context it will pass ""
to FeatureInfo::Initialize. After that it can pass various
GL extension strings to FeatureInfo::AddFeatures
to turn on more features.
It can then call glGetString(GL_EXTENSIONS) to see if the
feature was turned on.
Questions: I started this CL trying to make it possible
so each context could have it's own FeatureInfo. I decided
against that. So that brings up the question, should I
get rid of FeatureInfo and just put this stuff back on
ContextGroup or leave it as is?
If I leave it as is, should I move all the max_XXX stuff
on ContextGroup to FeatureInfo?
TEST=unit tests
BUG=none
Review URL: http://codereview.chromium.org/3413038
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@61114 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
20 files changed, 1081 insertions, 786 deletions
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index 58ddd2b..d9cbd4c 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc @@ -1144,22 +1144,32 @@ void GLES2Implementation::GetShaderPrecisionFormat( } const GLubyte* GLES2Implementation::GetString(GLenum name) { - const char* result; - GLStringMap::const_iterator it = gl_strings_.find(name); - if (it != gl_strings_.end()) { - result = it->second.c_str(); - } else { - // Clear the bucket so if we the command fails nothing will be in it. - helper_->SetBucketSize(kResultBucketId, 0); - helper_->GetString(name, kResultBucketId); - std::string str; - if (GetBucketAsString(kResultBucketId, &str)) { - std::pair<GLStringMap::const_iterator, bool> insert_result = - gl_strings_.insert(std::make_pair(name, str)); + const char* result = NULL; + // Clear the bucket so if the command fails nothing will be in it. + helper_->SetBucketSize(kResultBucketId, 0); + helper_->GetString(name, kResultBucketId); + std::string str; + if (GetBucketAsString(kResultBucketId, &str)) { + // 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)); GPU_DCHECK(insert_result.second); - result = insert_result.first->second.c_str(); + 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 { - result = NULL; + std::pair<std::set<std::string>::const_iterator, bool> insert_result = + string_set.insert(str); + GPU_DCHECK(insert_result.second); + result = insert_result.first->c_str(); } } return reinterpret_cast<const GLubyte*>(result); diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h index ef702fd..0b0e242 100644 --- a/gpu/command_buffer/client/gles2_implementation.h +++ b/gpu/command_buffer/client/gles2_implementation.h @@ -8,6 +8,7 @@ #include <GLES2/gl2.h> #include <map> +#include <set> #include <string> #include <vector> @@ -375,7 +376,7 @@ class GLES2Implementation { // Map of GLenum to Strings for glGetString. We need to cache these because // the pointer passed back to the client has to remain valid for eternity. - typedef std::map<uint32, std::string> GLStringMap; + typedef std::map<uint32, std::set<std::string> > GLStringMap; GLStringMap gl_strings_; typedef std::map<const void*, MappedBuffer> MappedBufferMap; diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc index 358e149..c2c9c1f 100644 --- a/gpu/command_buffer/service/context_group.cc +++ b/gpu/command_buffer/service/context_group.cc @@ -43,189 +43,19 @@ static void GetIntegerv(GLenum pname, uint32* var) { *var = value; } -bool ContextGroup::Initialize() { - if (initialized_) { - return true; - } - - // Figure out what extensions to turn on. - const char* extensions = - reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); - bool npot_ok = false; - - AddExtensionString("GL_CHROMIUM_map_sub"); - - // Check if we should allow GL_EXT_texture_compression_dxt1 and - // GL_EXT_texture_compression_s3tc. - bool enable_dxt1 = false; - bool enable_s3tc = false; - if (strstr(extensions, "GL_EXT_texture_compression_dxt1")) { - enable_dxt1 = true; - } - if (strstr(extensions, "GL_EXT_texture_compression_s3tc")) { - enable_dxt1 = true; - enable_s3tc = true; - } - - if (enable_dxt1) { - AddExtensionString("GL_EXT_texture_compression_dxt1"); - validators_.compressed_texture_format.AddValue( - GL_COMPRESSED_RGB_S3TC_DXT1_EXT); - validators_.compressed_texture_format.AddValue( - GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); - } - - if (enable_s3tc) { - AddExtensionString("GL_EXT_texture_compression_s3tc"); - validators_.compressed_texture_format.AddValue( - GL_COMPRESSED_RGBA_S3TC_DXT3_EXT); - validators_.compressed_texture_format.AddValue( - GL_COMPRESSED_RGBA_S3TC_DXT5_EXT); - } - // Check if we should enable GL_EXT_texture_filter_anisotropic. - if (strstr(extensions, "GL_EXT_texture_filter_anisotropic")) { - AddExtensionString("GL_EXT_texture_filter_anisotropic"); - validators_.texture_parameter.AddValue( - GL_TEXTURE_MAX_ANISOTROPY_EXT); - validators_.g_l_state.AddValue( - GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT); - } - - // Check if we should support GL_OES_packed_depth_stencil and/or - // GL_GOOGLE_depth_texture. - // NOTE: GL_OES_depth_texture requires support for depth - // cubemaps. GL_ARB_depth_texture requires other features that - // GL_OES_packed_depth_stencil does not provide. Therefore we made up - // GL_GOOGLE_depth_texture. - bool enable_depth_texture = false; - if (strstr(extensions, "GL_ARB_depth_texture") || - strstr(extensions, "GL_OES_depth_texture")) { - enable_depth_texture = true; - AddExtensionString("GL_GOOGLE_depth_texture"); - validators_.texture_internal_format.AddValue(GL_DEPTH_COMPONENT); - validators_.texture_format.AddValue(GL_DEPTH_COMPONENT); - validators_.pixel_type.AddValue(GL_UNSIGNED_SHORT); - validators_.pixel_type.AddValue(GL_UNSIGNED_INT); - } - // TODO(gman): Add depth types fo ElementsPerGroup and BytesPerElement - - if (strstr(extensions, "GL_EXT_packed_depth_stencil") || - strstr(extensions, "GL_OES_packed_depth_stencil")) { - AddExtensionString("GL_OES_packed_depth_stencil"); - if (enable_depth_texture) { - validators_.texture_internal_format.AddValue(GL_DEPTH_STENCIL); - validators_.texture_format.AddValue(GL_DEPTH_STENCIL); - validators_.pixel_type.AddValue(GL_UNSIGNED_INT_24_8); - } - validators_.render_buffer_format.AddValue(GL_DEPTH24_STENCIL8); - } - - bool enable_texture_format_bgra8888 = false; - bool enable_read_format_bgra = false; - // Check if we should allow GL_EXT_texture_format_BGRA8888 - if (strstr(extensions, "GL_EXT_texture_format_BGRA8888") || - strstr(extensions, "GL_APPLE_texture_format_BGRA8888")) { - enable_texture_format_bgra8888 = true; - } - - if (strstr(extensions, "GL_EXT_bgra")) { - enable_texture_format_bgra8888 = true; - enable_read_format_bgra = true; - } - - if (strstr(extensions, "GL_EXT_read_format_bgra")) { - enable_read_format_bgra = true; - } - - if (enable_texture_format_bgra8888) { - AddExtensionString("GL_EXT_texture_format_BGRA8888"); - validators_.texture_internal_format.AddValue(GL_BGRA_EXT); - validators_.texture_format.AddValue(GL_BGRA_EXT); - } - - if (enable_read_format_bgra) { - AddExtensionString("GL_EXT_read_format_bgra"); - validators_.read_pixel_format.AddValue(GL_BGRA_EXT); - } - - // Check if we should allow GL_OES_texture_npot - if (strstr(extensions, "GL_ARB_texture_non_power_of_two") || - strstr(extensions, "GL_OES_texture_npot")) { - AddExtensionString("GL_OES_texture_npot"); - npot_ok = true; - } - - // Check if we should allow GL_OES_texture_float, GL_OES_texture_half_float, - // GL_OES_texture_float_linear, GL_OES_texture_half_float_linear - bool enable_texture_float = false; - bool enable_texture_float_linear = false; - bool enable_texture_half_float = false; - bool enable_texture_half_float_linear = false; - if (strstr(extensions, "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 (strstr(extensions, "GL_OES_texture_float")) { - enable_texture_float = true; - if (strstr(extensions, "GL_OES_texture_float_linear")) { - enable_texture_float_linear = true; - } - } - if (strstr(extensions, "GL_OES_texture_half_float")) { - enable_texture_half_float = true; - if (strstr(extensions, "GL_OES_texture_half_float_linear")) { - enable_texture_half_float_linear = true; - } - } - } - - if (enable_texture_float) { - validators_.pixel_type.AddValue(GL_FLOAT); - AddExtensionString("GL_OES_texture_float"); - if (enable_texture_float_linear) { - AddExtensionString("GL_OES_texture_float_linear"); - } - } - - if (enable_texture_half_float) { - validators_.pixel_type.AddValue(GL_HALF_FLOAT_OES); - AddExtensionString("GL_OES_texture_half_float"); - if (enable_texture_half_float_linear) { - AddExtensionString("GL_OES_texture_half_float_linear"); - } - } - - // Check for multisample support - if (strstr(extensions, "GL_EXT_framebuffer_multisample")) { - extension_flags_.ext_framebuffer_multisample = true; - validators_.frame_buffer_target.AddValue(GL_READ_FRAMEBUFFER_EXT); - validators_.frame_buffer_target.AddValue(GL_DRAW_FRAMEBUFFER_EXT); - validators_.g_l_state.AddValue(GL_READ_FRAMEBUFFER_BINDING_EXT); - validators_.render_buffer_parameter.AddValue(GL_MAX_SAMPLES_EXT); - AddExtensionString("GL_EXT_framebuffer_multisample"); - AddExtensionString("GL_EXT_framebuffer_blit"); - } - - if (strstr(extensions, "GL_OES_depth24") || - gfx::GetGLImplementation() == gfx::kGLImplementationDesktopGL) { - AddExtensionString("GL_OES_depth24"); - validators_.render_buffer_format.AddValue(GL_DEPTH_COMPONENT24); +bool ContextGroup::Initialize(const char* allowed_features) { + if (initialized_) { + return true; } - if (strstr(extensions, "GL_OES_standard_derivatives") || - gfx::GetGLImplementation() == gfx::kGLImplementationDesktopGL) { - AddExtensionString("GL_OES_standard_derivatives"); - extension_flags_.oes_standard_derivatives = true; + if (!feature_info_.Initialize(allowed_features)) { + LOG(ERROR) << "ContextGroup::Initialize failed because FeatureInfo " + << "initialization failed."; + return false; } - // TODO(gman): Add support for these extensions. - // GL_OES_depth32 - // GL_OES_element_index_uint - buffer_manager_.reset(new BufferManager()); framebuffer_manager_.reset(new FramebufferManager()); renderbuffer_manager_.reset(new RenderbufferManager()); @@ -253,10 +83,7 @@ bool ContextGroup::Initialize() { GLint max_cube_map_texture_size; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size); - texture_manager_.reset(new TextureManager(npot_ok, - enable_texture_float_linear, - enable_texture_half_float_linear, - max_texture_size, + texture_manager_.reset(new TextureManager(max_texture_size, max_cube_map_texture_size)); GetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_image_units_); @@ -320,10 +147,6 @@ void ContextGroup::Destroy(bool have_context) { } } -void ContextGroup::AddExtensionString(const std::string& str) { - extensions_ += (extensions_.empty() ? "" : " ") + str; -} - IdAllocator* ContextGroup::GetIdAllocator(unsigned namespace_id) { IdAllocatorMap::iterator it = id_namespaces_.find(namespace_id); if (it != id_namespaces_.end()) { diff --git a/gpu/command_buffer/service/context_group.h b/gpu/command_buffer/service/context_group.h index e48cacd..4df515c 100644 --- a/gpu/command_buffer/service/context_group.h +++ b/gpu/command_buffer/service/context_group.h @@ -11,6 +11,7 @@ #include "base/linked_ptr.h" #include "base/scoped_ptr.h" #include "gpu/command_buffer/service/gles2_cmd_validation.h" +#include "gpu/command_buffer/service/feature_info.h" namespace gpu { @@ -30,21 +31,11 @@ class TextureManager; // resources. class ContextGroup { public: - struct ExtensionFlags { - ExtensionFlags() - : ext_framebuffer_multisample(false), - oes_standard_derivatives(false) { - } - - bool ext_framebuffer_multisample; - bool oes_standard_derivatives; - }; - ContextGroup(); ~ContextGroup(); // This should only be called by GLES2Decoder. - bool Initialize(); + bool Initialize(const char* allowed_features); // Destroys all the resources. MUST be called before destruction. void Destroy(bool have_context); @@ -77,6 +68,10 @@ class ContextGroup { return max_vertex_uniform_vectors_; } + FeatureInfo* feature_info() { + return &feature_info_; + } + BufferManager* buffer_manager() const { return buffer_manager_.get(); } @@ -103,21 +98,7 @@ class ContextGroup { IdAllocator* GetIdAllocator(unsigned namepsace_id); - const Validators* validators() const { - return &validators_; - } - - const std::string& extensions() const { - return extensions_; - } - - const ExtensionFlags& extension_flags() const { - return extension_flags_; - } - private: - void AddExtensionString(const std::string& str); - // Whether or not this context is initialized. bool initialized_; @@ -144,13 +125,7 @@ class ContextGroup { typedef std::map<uint32, linked_ptr<IdAllocator> > IdAllocatorMap; IdAllocatorMap id_namespaces_; - Validators validators_; - - // The extensions string returned by glGetString(GL_EXTENSIONS); - std::string extensions_; - - // Flags for some extensions - ExtensionFlags extension_flags_; + FeatureInfo feature_info_; DISALLOW_COPY_AND_ASSIGN(ContextGroup); }; diff --git a/gpu/command_buffer/service/context_group_unittest.cc b/gpu/command_buffer/service/context_group_unittest.cc index 4384ea6..4cfd4c7 100644 --- a/gpu/command_buffer/service/context_group_unittest.cc +++ b/gpu/command_buffer/service/context_group_unittest.cc @@ -32,10 +32,6 @@ class ContextGroupTest : public testing::Test { ContextGroupTest() { } - void SetupInitExpectations(const char* extensions) { - TestHelper::SetupContextGroupInitExpectations(gl_.get(), extensions); - } - protected: virtual void SetUp() { gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>()); @@ -67,321 +63,31 @@ TEST_F(ContextGroupTest, Basic) { EXPECT_TRUE(group_.texture_manager() == NULL); EXPECT_TRUE(group_.program_manager() == NULL); EXPECT_TRUE(group_.shader_manager() == NULL); - EXPECT_FALSE(group_.extension_flags().ext_framebuffer_multisample); - EXPECT_FALSE(group_.extension_flags().oes_standard_derivatives); } TEST_F(ContextGroupTest, InitializeNoExtensions) { - SetupInitExpectations(""); - group_.Initialize(); - // Check a couple of random extensions that should not be there. - EXPECT_THAT(group_.extensions(), Not(HasSubstr("GL_OES_texture_npot"))); - EXPECT_THAT(group_.extensions(), - Not(HasSubstr("GL_EXT_texture_compression_dxt1"))); - EXPECT_FALSE(group_.texture_manager()->npot_ok()); - EXPECT_FALSE(group_.validators()->compressed_texture_format.IsValid( - GL_COMPRESSED_RGB_S3TC_DXT1_EXT)); - EXPECT_FALSE(group_.validators()->compressed_texture_format.IsValid( - GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)); - EXPECT_FALSE(group_.validators()->compressed_texture_format.IsValid( - GL_COMPRESSED_RGBA_S3TC_DXT3_EXT)); - EXPECT_FALSE(group_.validators()->compressed_texture_format.IsValid( - GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)); - EXPECT_FALSE(group_.validators()->read_pixel_format.IsValid( - GL_BGRA_EXT)); - EXPECT_FALSE(group_.validators()->texture_parameter.IsValid( - GL_TEXTURE_MAX_ANISOTROPY_EXT)); - EXPECT_FALSE(group_.validators()->g_l_state.IsValid( - GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT)); - EXPECT_FALSE(group_.validators()->frame_buffer_target.IsValid( - GL_READ_FRAMEBUFFER_EXT)); - EXPECT_FALSE(group_.validators()->frame_buffer_target.IsValid( - GL_DRAW_FRAMEBUFFER_EXT)); - EXPECT_FALSE(group_.validators()->g_l_state.IsValid( - GL_READ_FRAMEBUFFER_BINDING_EXT)); - EXPECT_FALSE(group_.validators()->render_buffer_parameter.IsValid( - GL_MAX_SAMPLES_EXT)); - EXPECT_FALSE(group_.validators()->texture_internal_format.IsValid( - GL_DEPTH_COMPONENT)); - EXPECT_FALSE(group_.validators()->texture_format.IsValid(GL_DEPTH_COMPONENT)); - EXPECT_FALSE(group_.validators()->pixel_type.IsValid(GL_UNSIGNED_SHORT)); - EXPECT_FALSE(group_.validators()->pixel_type.IsValid(GL_UNSIGNED_INT)); - EXPECT_FALSE(group_.validators()->render_buffer_format.IsValid( - GL_DEPTH24_STENCIL8)); - EXPECT_FALSE(group_.validators()->texture_internal_format.IsValid( - GL_DEPTH_STENCIL)); - EXPECT_FALSE(group_.validators()->texture_format.IsValid( - GL_DEPTH_STENCIL)); - EXPECT_FALSE(group_.validators()->pixel_type.IsValid( - GL_UNSIGNED_INT_24_8)); - EXPECT_FALSE(group_.validators()->render_buffer_format.IsValid( - GL_DEPTH_COMPONENT24)); -} - -TEST_F(ContextGroupTest, InitializeNPOTExtensionGLES) { - SetupInitExpectations("GL_OES_texture_npot"); - group_.Initialize(); - EXPECT_THAT(group_.extensions(), HasSubstr("GL_OES_texture_npot")); - EXPECT_TRUE(group_.texture_manager()->npot_ok()); -} - -TEST_F(ContextGroupTest, InitializeNPOTExtensionGL) { - SetupInitExpectations("GL_ARB_texture_non_power_of_two"); - group_.Initialize(); - EXPECT_THAT(group_.extensions(), HasSubstr("GL_OES_texture_npot")); - EXPECT_TRUE(group_.texture_manager()->npot_ok()); -} - -TEST_F(ContextGroupTest, InitializeDXTExtensionGLES2) { - SetupInitExpectations("GL_EXT_texture_compression_dxt1"); - group_.Initialize(); - EXPECT_THAT(group_.extensions(), - HasSubstr("GL_EXT_texture_compression_dxt1")); - EXPECT_TRUE(group_.validators()->compressed_texture_format.IsValid( - GL_COMPRESSED_RGB_S3TC_DXT1_EXT)); - EXPECT_TRUE(group_.validators()->compressed_texture_format.IsValid( - GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)); - EXPECT_FALSE(group_.validators()->compressed_texture_format.IsValid( - GL_COMPRESSED_RGBA_S3TC_DXT3_EXT)); - EXPECT_FALSE(group_.validators()->compressed_texture_format.IsValid( - GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)); -} - -TEST_F(ContextGroupTest, InitializeDXTExtensionGL) { - SetupInitExpectations("GL_EXT_texture_compression_s3tc"); - group_.Initialize(); - EXPECT_THAT(group_.extensions(), - HasSubstr("GL_EXT_texture_compression_dxt1")); - EXPECT_THAT(group_.extensions(), - HasSubstr("GL_EXT_texture_compression_s3tc")); - EXPECT_TRUE(group_.validators()->compressed_texture_format.IsValid( - GL_COMPRESSED_RGB_S3TC_DXT1_EXT)); - EXPECT_TRUE(group_.validators()->compressed_texture_format.IsValid( - GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)); - EXPECT_TRUE(group_.validators()->compressed_texture_format.IsValid( - GL_COMPRESSED_RGBA_S3TC_DXT3_EXT)); - EXPECT_TRUE(group_.validators()->compressed_texture_format.IsValid( - GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)); -} - -TEST_F(ContextGroupTest, InitializeEXT_texture_format_BGRA8888GLES2) { - SetupInitExpectations("GL_EXT_texture_format_BGRA8888"); - group_.Initialize(); - EXPECT_THAT(group_.extensions(), - HasSubstr("GL_EXT_texture_format_BGRA8888")); - EXPECT_TRUE(group_.validators()->texture_format.IsValid( - GL_BGRA_EXT)); - EXPECT_TRUE(group_.validators()->texture_internal_format.IsValid( - GL_BGRA_EXT)); -} - -TEST_F(ContextGroupTest, InitializeEXT_texture_format_BGRA8888GL) { - SetupInitExpectations("GL_EXT_bgra"); - group_.Initialize(); - EXPECT_THAT(group_.extensions(), - HasSubstr("GL_EXT_texture_format_BGRA8888")); - EXPECT_THAT(group_.extensions(), - HasSubstr("GL_EXT_read_format_bgra")); - EXPECT_TRUE(group_.validators()->texture_format.IsValid( - GL_BGRA_EXT)); - EXPECT_TRUE(group_.validators()->texture_internal_format.IsValid( - GL_BGRA_EXT)); - EXPECT_TRUE(group_.validators()->read_pixel_format.IsValid( - GL_BGRA_EXT)); -} - -TEST_F(ContextGroupTest, InitializeEXT_texture_format_BGRA8888Apple) { - SetupInitExpectations("GL_APPLE_texture_format_BGRA8888"); - group_.Initialize(); - EXPECT_THAT(group_.extensions(), - HasSubstr("GL_EXT_texture_format_BGRA8888")); - EXPECT_TRUE(group_.validators()->texture_format.IsValid( - GL_BGRA_EXT)); - EXPECT_TRUE(group_.validators()->texture_internal_format.IsValid( - GL_BGRA_EXT)); -} - -TEST_F(ContextGroupTest, InitializeEXT_read_format_bgra) { - SetupInitExpectations("GL_EXT_read_format_bgra"); - group_.Initialize(); - EXPECT_THAT(group_.extensions(), - HasSubstr("GL_EXT_read_format_bgra")); - EXPECT_FALSE(group_.validators()->texture_format.IsValid( - GL_BGRA_EXT)); - EXPECT_FALSE(group_.validators()->texture_internal_format.IsValid( - GL_BGRA_EXT)); - EXPECT_TRUE(group_.validators()->read_pixel_format.IsValid( - GL_BGRA_EXT)); -} - -TEST_F(ContextGroupTest, InitializeOES_texture_floatGLES2) { - SetupInitExpectations("GL_OES_texture_float"); - group_.Initialize(); - EXPECT_FALSE(group_.texture_manager()->enable_float_linear()); - EXPECT_FALSE(group_.texture_manager()->enable_half_float_linear()); - EXPECT_THAT(group_.extensions(), HasSubstr("GL_OES_texture_float")); - EXPECT_THAT(group_.extensions(), Not(HasSubstr("GL_OES_texture_half_float"))); - EXPECT_THAT(group_.extensions(), - Not(HasSubstr("GL_OES_texture_float_linear"))); - EXPECT_THAT(group_.extensions(), - Not(HasSubstr("GL_OES_texture_half_float_linear"))); - EXPECT_TRUE(group_.validators()->pixel_type.IsValid(GL_FLOAT)); - EXPECT_FALSE(group_.validators()->pixel_type.IsValid(GL_HALF_FLOAT_OES)); -} - -TEST_F(ContextGroupTest, InitializeOES_texture_float_linearGLES2) { - SetupInitExpectations("GL_OES_texture_float GL_OES_texture_float_linear"); - group_.Initialize(); - EXPECT_TRUE(group_.texture_manager()->enable_float_linear()); - EXPECT_FALSE(group_.texture_manager()->enable_half_float_linear()); - EXPECT_THAT(group_.extensions(), HasSubstr("GL_OES_texture_float")); - EXPECT_THAT(group_.extensions(), Not(HasSubstr("GL_OES_texture_half_float"))); - EXPECT_THAT(group_.extensions(), HasSubstr("GL_OES_texture_float_linear")); - EXPECT_THAT(group_.extensions(), - Not(HasSubstr("GL_OES_texture_half_float_linear"))); - EXPECT_TRUE(group_.validators()->pixel_type.IsValid(GL_FLOAT)); - EXPECT_FALSE(group_.validators()->pixel_type.IsValid(GL_HALF_FLOAT_OES)); -} - -TEST_F(ContextGroupTest, InitializeOES_texture_half_floatGLES2) { - SetupInitExpectations("GL_OES_texture_half_float"); - group_.Initialize(); - EXPECT_FALSE(group_.texture_manager()->enable_float_linear()); - EXPECT_FALSE(group_.texture_manager()->enable_half_float_linear()); - EXPECT_THAT(group_.extensions(), Not(HasSubstr("GL_OES_texture_float"))); - EXPECT_THAT(group_.extensions(), HasSubstr("GL_OES_texture_half_float")); - EXPECT_THAT(group_.extensions(), - Not(HasSubstr("GL_OES_texture_float_linear"))); - EXPECT_THAT(group_.extensions(), - Not(HasSubstr("GL_OES_texture_half_float_linear"))); - EXPECT_FALSE(group_.validators()->pixel_type.IsValid(GL_FLOAT)); - EXPECT_TRUE(group_.validators()->pixel_type.IsValid(GL_HALF_FLOAT_OES)); -} - -TEST_F(ContextGroupTest, InitializeOES_texture_half_float_linearGLES2) { - SetupInitExpectations( - "GL_OES_texture_half_float GL_OES_texture_half_float_linear"); - group_.Initialize(); - EXPECT_FALSE(group_.texture_manager()->enable_float_linear()); - EXPECT_TRUE(group_.texture_manager()->enable_half_float_linear()); - EXPECT_THAT(group_.extensions(), Not(HasSubstr("GL_OES_texture_float"))); - EXPECT_THAT(group_.extensions(), HasSubstr("GL_OES_texture_half_float")); - EXPECT_THAT(group_.extensions(), - Not(HasSubstr("GL_OES_texture_float_linear"))); - EXPECT_THAT(group_.extensions(), - HasSubstr("GL_OES_texture_half_float_linear")); - EXPECT_FALSE(group_.validators()->pixel_type.IsValid(GL_FLOAT)); - EXPECT_TRUE(group_.validators()->pixel_type.IsValid(GL_HALF_FLOAT_OES)); -} - -TEST_F(ContextGroupTest, InitializeEXT_framebuffer_multisample) { - SetupInitExpectations("GL_EXT_framebuffer_multisample"); - group_.Initialize(); - EXPECT_TRUE(group_.extension_flags().ext_framebuffer_multisample); - EXPECT_THAT(group_.extensions(), HasSubstr("GL_EXT_framebuffer_multisample")); - EXPECT_THAT(group_.extensions(), HasSubstr("GL_EXT_framebuffer_blit")); - EXPECT_TRUE(group_.validators()->frame_buffer_target.IsValid( - GL_READ_FRAMEBUFFER_EXT)); - EXPECT_TRUE(group_.validators()->frame_buffer_target.IsValid( - GL_DRAW_FRAMEBUFFER_EXT)); - EXPECT_TRUE(group_.validators()->g_l_state.IsValid( - GL_READ_FRAMEBUFFER_BINDING_EXT)); - EXPECT_TRUE(group_.validators()->render_buffer_parameter.IsValid( - GL_MAX_SAMPLES_EXT)); -} - -TEST_F(ContextGroupTest, InitializeEXT_texture_filter_anisotropic) { - SetupInitExpectations("GL_EXT_texture_filter_anisotropic"); - group_.Initialize(); - EXPECT_THAT(group_.extensions(), - HasSubstr("GL_EXT_texture_filter_anisotropic")); - EXPECT_TRUE(group_.validators()->texture_parameter.IsValid( - GL_TEXTURE_MAX_ANISOTROPY_EXT)); - EXPECT_TRUE(group_.validators()->g_l_state.IsValid( - GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT)); -} - -TEST_F(ContextGroupTest, InitializeEXT_ARB_depth_texture) { - SetupInitExpectations("GL_ARB_depth_texture"); - group_.Initialize(); - EXPECT_THAT(group_.extensions(), - HasSubstr("GL_GOOGLE_depth_texture")); - EXPECT_TRUE(group_.validators()->texture_internal_format.IsValid( - GL_DEPTH_COMPONENT)); - EXPECT_TRUE(group_.validators()->texture_format.IsValid(GL_DEPTH_COMPONENT)); - EXPECT_TRUE(group_.validators()->pixel_type.IsValid(GL_UNSIGNED_SHORT)); - EXPECT_TRUE(group_.validators()->pixel_type.IsValid(GL_UNSIGNED_INT)); -} - -TEST_F(ContextGroupTest, InitializeOES_ARB_depth_texture) { - SetupInitExpectations("GL_OES_depth_texture"); - group_.Initialize(); - EXPECT_THAT(group_.extensions(), - HasSubstr("GL_GOOGLE_depth_texture")); - EXPECT_TRUE(group_.validators()->texture_internal_format.IsValid( - GL_DEPTH_COMPONENT)); - EXPECT_TRUE(group_.validators()->texture_format.IsValid(GL_DEPTH_COMPONENT)); - EXPECT_TRUE(group_.validators()->pixel_type.IsValid(GL_UNSIGNED_SHORT)); - EXPECT_TRUE(group_.validators()->pixel_type.IsValid(GL_UNSIGNED_INT)); -} - -TEST_F(ContextGroupTest, InitializeEXT_packed_depth_stencil) { - SetupInitExpectations("GL_EXT_packed_depth_stencil"); - group_.Initialize(); - EXPECT_THAT(group_.extensions(), - HasSubstr("GL_OES_packed_depth_stencil")); - EXPECT_TRUE(group_.validators()->render_buffer_format.IsValid( - GL_DEPTH24_STENCIL8)); - EXPECT_FALSE(group_.validators()->texture_internal_format.IsValid( - GL_DEPTH_COMPONENT)); - EXPECT_FALSE(group_.validators()->texture_format.IsValid(GL_DEPTH_COMPONENT)); - EXPECT_FALSE(group_.validators()->pixel_type.IsValid(GL_UNSIGNED_SHORT)); - EXPECT_FALSE(group_.validators()->pixel_type.IsValid(GL_UNSIGNED_INT)); -} - -TEST_F(ContextGroupTest, InitializeOES_packed_depth_stencil) { - SetupInitExpectations("GL_OES_packed_depth_stencil"); - group_.Initialize(); - EXPECT_THAT(group_.extensions(), - HasSubstr("GL_OES_packed_depth_stencil")); - EXPECT_TRUE(group_.validators()->render_buffer_format.IsValid( - GL_DEPTH24_STENCIL8)); - EXPECT_FALSE(group_.validators()->texture_internal_format.IsValid( - GL_DEPTH_COMPONENT)); - EXPECT_FALSE(group_.validators()->texture_format.IsValid(GL_DEPTH_COMPONENT)); - EXPECT_FALSE(group_.validators()->pixel_type.IsValid(GL_UNSIGNED_SHORT)); - EXPECT_FALSE(group_.validators()->pixel_type.IsValid(GL_UNSIGNED_INT)); -} - -TEST_F(ContextGroupTest, - InitializeOES_packed_depth_stencil_and_GL_ARB_depth_texture) { - SetupInitExpectations("GL_OES_packed_depth_stencil GL_ARB_depth_texture"); - group_.Initialize(); - EXPECT_THAT(group_.extensions(), - HasSubstr("GL_OES_packed_depth_stencil")); - EXPECT_TRUE(group_.validators()->render_buffer_format.IsValid( - GL_DEPTH24_STENCIL8)); - EXPECT_TRUE(group_.validators()->texture_internal_format.IsValid( - GL_DEPTH_STENCIL)); - EXPECT_TRUE(group_.validators()->texture_format.IsValid( - GL_DEPTH_STENCIL)); - EXPECT_TRUE(group_.validators()->pixel_type.IsValid( - GL_UNSIGNED_INT_24_8)); -} - -TEST_F(ContextGroupTest, InitializeOES_depth24) { - SetupInitExpectations("GL_OES_depth24"); - group_.Initialize(); - EXPECT_THAT(group_.extensions(), HasSubstr("GL_OES_depth24")); - EXPECT_TRUE(group_.validators()->render_buffer_format.IsValid( - GL_DEPTH_COMPONENT24)); -} - -TEST_F(ContextGroupTest, InitializeOES_standard_derivatives) { - SetupInitExpectations("GL_OES_standard_derivatives"); - group_.Initialize(); - EXPECT_THAT(group_.extensions(), HasSubstr("GL_OES_standard_derivatives")); - EXPECT_TRUE(group_.extension_flags().oes_standard_derivatives); + TestHelper::SetupContextGroupInitExpectations(gl_.get(), ""); + group_.Initialize(""); + EXPECT_EQ(static_cast<uint32>(TestHelper::kNumVertexAttribs), + group_.max_vertex_attribs()); + EXPECT_EQ(static_cast<uint32>(TestHelper::kNumTextureUnits), + group_.max_texture_units()); + EXPECT_EQ(static_cast<uint32>(TestHelper::kMaxTextureImageUnits), + group_.max_texture_image_units()); + EXPECT_EQ(static_cast<uint32>(TestHelper::kMaxVertexTextureImageUnits), + group_.max_vertex_texture_image_units()); + EXPECT_EQ(static_cast<uint32>(TestHelper::kMaxFragmentUniformVectors), + group_.max_fragment_uniform_vectors()); + EXPECT_EQ(static_cast<uint32>(TestHelper::kMaxVaryingVectors), + group_.max_varying_vectors()); + EXPECT_EQ(static_cast<uint32>(TestHelper::kMaxVertexUniformVectors), + group_.max_vertex_uniform_vectors()); + EXPECT_TRUE(group_.buffer_manager() != NULL); + EXPECT_TRUE(group_.framebuffer_manager() != NULL); + EXPECT_TRUE(group_.renderbuffer_manager() != NULL); + EXPECT_TRUE(group_.texture_manager() != NULL); + EXPECT_TRUE(group_.program_manager() != NULL); + EXPECT_TRUE(group_.shader_manager() != NULL); } } // namespace gles2 diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc new file mode 100644 index 0000000..883dcd0 --- /dev/null +++ b/gpu/command_buffer/service/feature_info.cc @@ -0,0 +1,266 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <set> +#include <string> +#include "app/gfx/gl/gl_implementation.h" +#include "gpu/command_buffer/service/feature_info.h" +#include "gpu/command_buffer/service/gl_utils.h" +#include "gpu/GLES2/gles2_command_buffer.h" + +namespace gpu { +namespace gles2 { + +FeatureInfo::FeatureInfo() { +} + +// Helps query for extensions. +class ExtensionHelper { + public: + ExtensionHelper(const char* extensions, const char* allowed_features) { + std::set<std::string> sets[2]; + + for (int ii = 0; ii < 2; ++ii) { + const char* s = (ii == 0 ? extensions : allowed_features); + std::string str(s ? s : ""); + std::string::size_type lastPos = 0; + while (true) { + std::string::size_type pos = str.find_first_of(" ", lastPos); + if (pos != std::string::npos) { + sets[ii].insert(str.substr(lastPos, pos - lastPos)); + lastPos = pos + 1; + } else { + sets[ii].insert(str.substr(lastPos)); + break; + } + } + } + + if (allowed_features) { + std::set_intersection( + sets[0].begin(), sets[0].end(), sets[1].begin(), sets[1].end(), + std::inserter(extensions_, extensions_.begin())); + } else { + extensions_ = sets[0]; + } + } + + // Returns true if extension exists. + bool HasExtension(const char* extension) { + return extensions_.find(extension) != extensions_.end(); + } + + private: + std::set<std::string> extensions_; +}; + +bool FeatureInfo::Initialize(const char* allowed_features) { + AddFeatures(allowed_features); + return true; +} + +void FeatureInfo::AddFeatures(const char* desired_features) { + // Figure out what extensions to turn on. + std::string gl_extensions( + reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS))); + + ExtensionHelper helper( + (gl_extensions + + (gl_extensions.empty() ? "" : " ") + "GL_CHROMIUM_map_sub").c_str(), + desired_features); + + bool npot_ok = false; + + if (helper.HasExtension("GL_CHROMIUM_map_sub")) { + AddExtensionString("GL_CHROMIUM_map_sub"); + } + + // Check if we should allow GL_EXT_texture_compression_dxt1 and + // GL_EXT_texture_compression_s3tc. + bool enable_dxt1 = false; + bool enable_s3tc = false; + + if (helper.HasExtension("GL_EXT_texture_compression_dxt1")) { + enable_dxt1 = true; + } + if (helper.HasExtension("GL_EXT_texture_compression_s3tc")) { + enable_dxt1 = true; + enable_s3tc = true; + } + + if (enable_dxt1) { + AddExtensionString("GL_EXT_texture_compression_dxt1"); + validators_.compressed_texture_format.AddValue( + GL_COMPRESSED_RGB_S3TC_DXT1_EXT); + validators_.compressed_texture_format.AddValue( + GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); + } + + if (enable_s3tc) { + AddExtensionString("GL_EXT_texture_compression_s3tc"); + validators_.compressed_texture_format.AddValue( + GL_COMPRESSED_RGBA_S3TC_DXT3_EXT); + validators_.compressed_texture_format.AddValue( + GL_COMPRESSED_RGBA_S3TC_DXT5_EXT); + } + + // Check if we should enable GL_EXT_texture_filter_anisotropic. + if (helper.HasExtension("GL_EXT_texture_filter_anisotropic")) { + AddExtensionString("GL_EXT_texture_filter_anisotropic"); + validators_.texture_parameter.AddValue( + GL_TEXTURE_MAX_ANISOTROPY_EXT); + validators_.g_l_state.AddValue( + GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT); + } + + // Check if we should support GL_OES_packed_depth_stencil and/or + // GL_GOOGLE_depth_texture. + // NOTE: GL_OES_depth_texture requires support for depth + // cubemaps. GL_ARB_depth_texture requires other features that + // GL_OES_packed_depth_stencil does not provide. Therefore we made up + // GL_GOOGLE_depth_texture. + bool enable_depth_texture = false; + if (helper.HasExtension("GL_ARB_depth_texture") || + helper.HasExtension("GL_OES_depth_texture")) { + enable_depth_texture = true; + AddExtensionString("GL_GOOGLE_depth_texture"); + validators_.texture_internal_format.AddValue(GL_DEPTH_COMPONENT); + validators_.texture_format.AddValue(GL_DEPTH_COMPONENT); + validators_.pixel_type.AddValue(GL_UNSIGNED_SHORT); + validators_.pixel_type.AddValue(GL_UNSIGNED_INT); + } + // TODO(gman): Add depth types fo ElementsPerGroup and BytesPerElement + + if (helper.HasExtension("GL_EXT_packed_depth_stencil") || + helper.HasExtension("GL_OES_packed_depth_stencil")) { + AddExtensionString("GL_OES_packed_depth_stencil"); + if (enable_depth_texture) { + validators_.texture_internal_format.AddValue(GL_DEPTH_STENCIL); + validators_.texture_format.AddValue(GL_DEPTH_STENCIL); + validators_.pixel_type.AddValue(GL_UNSIGNED_INT_24_8); + } + validators_.render_buffer_format.AddValue(GL_DEPTH24_STENCIL8); + } + + bool enable_texture_format_bgra8888 = false; + bool enable_read_format_bgra = false; + // Check if we should allow GL_EXT_texture_format_BGRA8888 + if (helper.HasExtension("GL_EXT_texture_format_BGRA8888") || + helper.HasExtension("GL_APPLE_texture_format_BGRA8888")) { + enable_texture_format_bgra8888 = true; + } + + if (helper.HasExtension("GL_EXT_bgra")) { + enable_texture_format_bgra8888 = true; + enable_read_format_bgra = true; + } + + if (helper.HasExtension("GL_EXT_read_format_bgra")) { + enable_read_format_bgra = true; + } + + if (enable_texture_format_bgra8888) { + AddExtensionString("GL_EXT_texture_format_BGRA8888"); + validators_.texture_internal_format.AddValue(GL_BGRA_EXT); + validators_.texture_format.AddValue(GL_BGRA_EXT); + } + + if (enable_read_format_bgra) { + AddExtensionString("GL_EXT_read_format_bgra"); + validators_.read_pixel_format.AddValue(GL_BGRA_EXT); + } + + // Check if we should allow GL_OES_texture_npot + if (helper.HasExtension("GL_ARB_texture_non_power_of_two") || + helper.HasExtension("GL_OES_texture_npot")) { + AddExtensionString("GL_OES_texture_npot"); + npot_ok = true; + } + + // Check if we should allow GL_OES_texture_float, GL_OES_texture_half_float, + // GL_OES_texture_float_linear, GL_OES_texture_half_float_linear + bool enable_texture_float = false; + bool enable_texture_float_linear = false; + bool enable_texture_half_float = false; + bool enable_texture_half_float_linear = false; + if (helper.HasExtension("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 (helper.HasExtension("GL_OES_texture_float")) { + enable_texture_float = true; + if (helper.HasExtension("GL_OES_texture_float_linear")) { + enable_texture_float_linear = true; + } + } + if (helper.HasExtension("GL_OES_texture_half_float")) { + enable_texture_half_float = true; + if (helper.HasExtension("GL_OES_texture_half_float_linear")) { + enable_texture_half_float_linear = true; + } + } + } + + if (enable_texture_float) { + validators_.pixel_type.AddValue(GL_FLOAT); + AddExtensionString("GL_OES_texture_float"); + if (enable_texture_float_linear) { + AddExtensionString("GL_OES_texture_float_linear"); + } + } + + if (enable_texture_half_float) { + validators_.pixel_type.AddValue(GL_HALF_FLOAT_OES); + AddExtensionString("GL_OES_texture_half_float"); + if (enable_texture_half_float_linear) { + AddExtensionString("GL_OES_texture_half_float_linear"); + } + } + + // Check for multisample support + if (helper.HasExtension("GL_EXT_framebuffer_multisample")) { + feature_flags_.ext_framebuffer_multisample = true; + validators_.frame_buffer_target.AddValue(GL_READ_FRAMEBUFFER_EXT); + validators_.frame_buffer_target.AddValue(GL_DRAW_FRAMEBUFFER_EXT); + validators_.g_l_state.AddValue(GL_READ_FRAMEBUFFER_BINDING_EXT); + validators_.render_buffer_parameter.AddValue(GL_MAX_SAMPLES_EXT); + AddExtensionString("GL_EXT_framebuffer_multisample"); + AddExtensionString("GL_EXT_framebuffer_blit"); + } + + if (helper.HasExtension("GL_OES_depth24") || + gfx::GetGLImplementation() == gfx::kGLImplementationDesktopGL) { + AddExtensionString("GL_OES_depth24"); + validators_.render_buffer_format.AddValue(GL_DEPTH_COMPONENT24); + } + + if (helper.HasExtension("GL_OES_standard_derivatives") || + gfx::GetGLImplementation() == gfx::kGLImplementationDesktopGL) { + AddExtensionString("GL_OES_standard_derivatives"); + feature_flags_.oes_standard_derivatives = true; + } + + // TODO(gman): Add support for these extensions. + // GL_OES_depth32 + // GL_OES_element_index_uint + + feature_flags_.enable_texture_float_linear = enable_texture_float_linear; + feature_flags_.enable_texture_half_float_linear = + enable_texture_half_float_linear; + feature_flags_.npot_ok = npot_ok; +} + +void FeatureInfo::AddExtensionString(const std::string& str) { + if (extensions_.find(str) == std::string::npos) { + extensions_ += (extensions_.empty() ? "" : " ") + str; + } +} + +} // namespace gles2 +} // namespace gpu + + + diff --git a/gpu/command_buffer/service/feature_info.h b/gpu/command_buffer/service/feature_info.h new file mode 100644 index 0000000..ac6bbed --- /dev/null +++ b/gpu/command_buffer/service/feature_info.h @@ -0,0 +1,74 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_COMMAND_BUFFER_SERVICE_FEATURE_INFO_H_ +#define GPU_COMMAND_BUFFER_SERVICE_FEATURE_INFO_H_ + +#include <string> +#include "gpu/command_buffer/service/gles2_cmd_validation.h" + +namespace gpu { +namespace gles2 { + +// FeatureInfo records the features that are available for a particular context. +class FeatureInfo { + public: + struct FeatureFlags { + FeatureFlags() + : ext_framebuffer_multisample(false), + oes_standard_derivatives(false), + npot_ok(false), + enable_texture_float_linear(false), + enable_texture_half_float_linear(false) { + } + + bool ext_framebuffer_multisample; + bool oes_standard_derivatives; + bool npot_ok; + bool enable_texture_float_linear; + bool enable_texture_half_float_linear; + }; + + FeatureInfo(); + + // If allowed features = NULL, all features are allowed. Otherwise + // only features that match the strings in allowed_features are allowed. + bool Initialize(const char* allowed_features); + + // Turns on certain features if they can be turned on. NULL turns on + // all available features. + void AddFeatures(const char* desired_features); + + const Validators* validators() const { + return &validators_; + } + + const std::string& extensions() const { + return extensions_; + } + + const FeatureFlags& feature_flags() const { + return feature_flags_; + } + + private: + void AddExtensionString(const std::string& str); + + Validators validators_; + + // The extensions string returned by glGetString(GL_EXTENSIONS); + std::string extensions_; + + // Flags for some features + FeatureFlags feature_flags_; + + DISALLOW_COPY_AND_ASSIGN(FeatureInfo); +}; + +} // namespace gles2 +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_SERVICE_FEATURE_INFO_H_ + + diff --git a/gpu/command_buffer/service/feature_info_unittest.cc b/gpu/command_buffer/service/feature_info_unittest.cc new file mode 100644 index 0000000..ba9884b --- /dev/null +++ b/gpu/command_buffer/service/feature_info_unittest.cc @@ -0,0 +1,380 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/command_buffer/service/feature_info.h" +#include "app/gfx/gl/gl_mock.h" +#include "base/scoped_ptr.h" +#include "gpu/command_buffer/service/test_helper.h" +#include "gpu/command_buffer/service/texture_manager.h" +#include "gpu/GLES2/gles2_command_buffer.h" +#include "testing/gtest/include/gtest/gtest.h" + +using ::gfx::MockGLInterface; +using ::testing::_; +using ::testing::DoAll; +using ::testing::HasSubstr; +using ::testing::InSequence; +using ::testing::MatcherCast; +using ::testing::Not; +using ::testing::Pointee; +using ::testing::Return; +using ::testing::SetArrayArgument; +using ::testing::SetArgumentPointee; +using ::testing::StrEq; +using ::testing::StrictMock; + +namespace gpu { +namespace gles2 { + +class FeatureInfoTest : public testing::Test { + public: + FeatureInfoTest() { + } + + void SetupInitExpectations(const char* extensions) { + TestHelper::SetupFeatureInfoInitExpectations(gl_.get(), extensions); + } + + protected: + virtual void SetUp() { + gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>()); + ::gfx::GLInterface::SetGLInterface(gl_.get()); + } + + virtual void TearDown() { + ::gfx::GLInterface::SetGLInterface(NULL); + gl_.reset(); + } + + scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; + FeatureInfo info_; +}; + +TEST_F(FeatureInfoTest, Basic) { + // Test it starts off uninitialized. + EXPECT_FALSE(info_.feature_flags().ext_framebuffer_multisample); + EXPECT_FALSE(info_.feature_flags().oes_standard_derivatives); + EXPECT_FALSE(info_.feature_flags().npot_ok); + EXPECT_FALSE(info_.feature_flags().enable_texture_float_linear); + EXPECT_FALSE(info_.feature_flags().enable_texture_half_float_linear); +} + +TEST_F(FeatureInfoTest, InitializeNoExtensions) { + SetupInitExpectations(""); + info_.Initialize(NULL); + // Check a couple of random extensions that should not be there. + EXPECT_THAT(info_.extensions(), Not(HasSubstr("GL_OES_texture_npot"))); + EXPECT_THAT(info_.extensions(), + Not(HasSubstr("GL_EXT_texture_compression_dxt1"))); + EXPECT_FALSE(info_.feature_flags().npot_ok); + EXPECT_FALSE(info_.validators()->compressed_texture_format.IsValid( + GL_COMPRESSED_RGB_S3TC_DXT1_EXT)); + EXPECT_FALSE(info_.validators()->compressed_texture_format.IsValid( + GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)); + EXPECT_FALSE(info_.validators()->compressed_texture_format.IsValid( + GL_COMPRESSED_RGBA_S3TC_DXT3_EXT)); + EXPECT_FALSE(info_.validators()->compressed_texture_format.IsValid( + GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)); + EXPECT_FALSE(info_.validators()->read_pixel_format.IsValid( + GL_BGRA_EXT)); + EXPECT_FALSE(info_.validators()->texture_parameter.IsValid( + GL_TEXTURE_MAX_ANISOTROPY_EXT)); + EXPECT_FALSE(info_.validators()->g_l_state.IsValid( + GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT)); + EXPECT_FALSE(info_.validators()->frame_buffer_target.IsValid( + GL_READ_FRAMEBUFFER_EXT)); + EXPECT_FALSE(info_.validators()->frame_buffer_target.IsValid( + GL_DRAW_FRAMEBUFFER_EXT)); + EXPECT_FALSE(info_.validators()->g_l_state.IsValid( + GL_READ_FRAMEBUFFER_BINDING_EXT)); + EXPECT_FALSE(info_.validators()->render_buffer_parameter.IsValid( + GL_MAX_SAMPLES_EXT)); + EXPECT_FALSE(info_.validators()->texture_internal_format.IsValid( + GL_DEPTH_COMPONENT)); + EXPECT_FALSE(info_.validators()->texture_format.IsValid(GL_DEPTH_COMPONENT)); + EXPECT_FALSE(info_.validators()->pixel_type.IsValid(GL_UNSIGNED_SHORT)); + EXPECT_FALSE(info_.validators()->pixel_type.IsValid(GL_UNSIGNED_INT)); + EXPECT_FALSE(info_.validators()->render_buffer_format.IsValid( + GL_DEPTH24_STENCIL8)); + EXPECT_FALSE(info_.validators()->texture_internal_format.IsValid( + GL_DEPTH_STENCIL)); + EXPECT_FALSE(info_.validators()->texture_format.IsValid( + GL_DEPTH_STENCIL)); + EXPECT_FALSE(info_.validators()->pixel_type.IsValid( + GL_UNSIGNED_INT_24_8)); + EXPECT_FALSE(info_.validators()->render_buffer_format.IsValid( + GL_DEPTH_COMPONENT24)); +} + +TEST_F(FeatureInfoTest, InitializeNPOTExtensionGLES) { + SetupInitExpectations("GL_OES_texture_npot"); + info_.Initialize(NULL); + EXPECT_THAT(info_.extensions(), HasSubstr("GL_OES_texture_npot")); + EXPECT_TRUE(info_.feature_flags().npot_ok); +} + +TEST_F(FeatureInfoTest, InitializeNPOTExtensionGL) { + SetupInitExpectations("GL_ARB_texture_non_power_of_two"); + info_.Initialize(NULL); + EXPECT_THAT(info_.extensions(), HasSubstr("GL_OES_texture_npot")); + EXPECT_TRUE(info_.feature_flags().npot_ok); +} + +TEST_F(FeatureInfoTest, InitializeDXTExtensionGLES2) { + SetupInitExpectations("GL_EXT_texture_compression_dxt1"); + info_.Initialize(NULL); + EXPECT_THAT(info_.extensions(), + HasSubstr("GL_EXT_texture_compression_dxt1")); + EXPECT_TRUE(info_.validators()->compressed_texture_format.IsValid( + GL_COMPRESSED_RGB_S3TC_DXT1_EXT)); + EXPECT_TRUE(info_.validators()->compressed_texture_format.IsValid( + GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)); + EXPECT_FALSE(info_.validators()->compressed_texture_format.IsValid( + GL_COMPRESSED_RGBA_S3TC_DXT3_EXT)); + EXPECT_FALSE(info_.validators()->compressed_texture_format.IsValid( + GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)); +} + +TEST_F(FeatureInfoTest, InitializeDXTExtensionGL) { + SetupInitExpectations("GL_EXT_texture_compression_s3tc"); + info_.Initialize(NULL); + EXPECT_THAT(info_.extensions(), + HasSubstr("GL_EXT_texture_compression_dxt1")); + EXPECT_THAT(info_.extensions(), + HasSubstr("GL_EXT_texture_compression_s3tc")); + EXPECT_TRUE(info_.validators()->compressed_texture_format.IsValid( + GL_COMPRESSED_RGB_S3TC_DXT1_EXT)); + EXPECT_TRUE(info_.validators()->compressed_texture_format.IsValid( + GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)); + EXPECT_TRUE(info_.validators()->compressed_texture_format.IsValid( + GL_COMPRESSED_RGBA_S3TC_DXT3_EXT)); + EXPECT_TRUE(info_.validators()->compressed_texture_format.IsValid( + GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)); +} + +TEST_F(FeatureInfoTest, InitializeEXT_texture_format_BGRA8888GLES2) { + SetupInitExpectations("GL_EXT_texture_format_BGRA8888"); + info_.Initialize(NULL); + EXPECT_THAT(info_.extensions(), + HasSubstr("GL_EXT_texture_format_BGRA8888")); + EXPECT_TRUE(info_.validators()->texture_format.IsValid( + GL_BGRA_EXT)); + EXPECT_TRUE(info_.validators()->texture_internal_format.IsValid( + GL_BGRA_EXT)); +} + +TEST_F(FeatureInfoTest, InitializeEXT_texture_format_BGRA8888GL) { + SetupInitExpectations("GL_EXT_bgra"); + info_.Initialize(NULL); + EXPECT_THAT(info_.extensions(), + HasSubstr("GL_EXT_texture_format_BGRA8888")); + EXPECT_THAT(info_.extensions(), + HasSubstr("GL_EXT_read_format_bgra")); + EXPECT_TRUE(info_.validators()->texture_format.IsValid( + GL_BGRA_EXT)); + EXPECT_TRUE(info_.validators()->texture_internal_format.IsValid( + GL_BGRA_EXT)); + EXPECT_TRUE(info_.validators()->read_pixel_format.IsValid( + GL_BGRA_EXT)); +} + +TEST_F(FeatureInfoTest, InitializeEXT_texture_format_BGRA8888Apple) { + SetupInitExpectations("GL_APPLE_texture_format_BGRA8888"); + info_.Initialize(NULL); + EXPECT_THAT(info_.extensions(), + HasSubstr("GL_EXT_texture_format_BGRA8888")); + EXPECT_TRUE(info_.validators()->texture_format.IsValid( + GL_BGRA_EXT)); + EXPECT_TRUE(info_.validators()->texture_internal_format.IsValid( + GL_BGRA_EXT)); +} + +TEST_F(FeatureInfoTest, InitializeEXT_read_format_bgra) { + SetupInitExpectations("GL_EXT_read_format_bgra"); + info_.Initialize(NULL); + EXPECT_THAT(info_.extensions(), + HasSubstr("GL_EXT_read_format_bgra")); + EXPECT_FALSE(info_.validators()->texture_format.IsValid( + GL_BGRA_EXT)); + EXPECT_FALSE(info_.validators()->texture_internal_format.IsValid( + GL_BGRA_EXT)); + EXPECT_TRUE(info_.validators()->read_pixel_format.IsValid( + GL_BGRA_EXT)); +} + +TEST_F(FeatureInfoTest, InitializeOES_texture_floatGLES2) { + SetupInitExpectations("GL_OES_texture_float"); + info_.Initialize(NULL); + EXPECT_FALSE(info_.feature_flags().enable_texture_float_linear); + EXPECT_FALSE(info_.feature_flags().enable_texture_half_float_linear); + EXPECT_THAT(info_.extensions(), HasSubstr("GL_OES_texture_float")); + EXPECT_THAT(info_.extensions(), Not(HasSubstr("GL_OES_texture_half_float"))); + EXPECT_THAT(info_.extensions(), + Not(HasSubstr("GL_OES_texture_float_linear"))); + EXPECT_THAT(info_.extensions(), + Not(HasSubstr("GL_OES_texture_half_float_linear"))); + EXPECT_TRUE(info_.validators()->pixel_type.IsValid(GL_FLOAT)); + EXPECT_FALSE(info_.validators()->pixel_type.IsValid(GL_HALF_FLOAT_OES)); +} + +TEST_F(FeatureInfoTest, InitializeOES_texture_float_linearGLES2) { + SetupInitExpectations("GL_OES_texture_float GL_OES_texture_float_linear"); + info_.Initialize(NULL); + EXPECT_TRUE(info_.feature_flags().enable_texture_float_linear); + EXPECT_FALSE(info_.feature_flags().enable_texture_half_float_linear); + EXPECT_THAT(info_.extensions(), HasSubstr("GL_OES_texture_float")); + EXPECT_THAT(info_.extensions(), Not(HasSubstr("GL_OES_texture_half_float"))); + EXPECT_THAT(info_.extensions(), HasSubstr("GL_OES_texture_float_linear")); + EXPECT_THAT(info_.extensions(), + Not(HasSubstr("GL_OES_texture_half_float_linear"))); + EXPECT_TRUE(info_.validators()->pixel_type.IsValid(GL_FLOAT)); + EXPECT_FALSE(info_.validators()->pixel_type.IsValid(GL_HALF_FLOAT_OES)); +} + +TEST_F(FeatureInfoTest, InitializeOES_texture_half_floatGLES2) { + SetupInitExpectations("GL_OES_texture_half_float"); + info_.Initialize(NULL); + EXPECT_FALSE(info_.feature_flags().enable_texture_float_linear); + EXPECT_FALSE(info_.feature_flags().enable_texture_half_float_linear); + EXPECT_THAT(info_.extensions(), Not(HasSubstr("GL_OES_texture_float"))); + EXPECT_THAT(info_.extensions(), HasSubstr("GL_OES_texture_half_float")); + EXPECT_THAT(info_.extensions(), + Not(HasSubstr("GL_OES_texture_float_linear"))); + EXPECT_THAT(info_.extensions(), + Not(HasSubstr("GL_OES_texture_half_float_linear"))); + EXPECT_FALSE(info_.validators()->pixel_type.IsValid(GL_FLOAT)); + EXPECT_TRUE(info_.validators()->pixel_type.IsValid(GL_HALF_FLOAT_OES)); +} + +TEST_F(FeatureInfoTest, InitializeOES_texture_half_float_linearGLES2) { + SetupInitExpectations( + "GL_OES_texture_half_float GL_OES_texture_half_float_linear"); + info_.Initialize(NULL); + EXPECT_FALSE(info_.feature_flags().enable_texture_float_linear); + EXPECT_TRUE(info_.feature_flags().enable_texture_half_float_linear); + EXPECT_THAT(info_.extensions(), Not(HasSubstr("GL_OES_texture_float"))); + EXPECT_THAT(info_.extensions(), HasSubstr("GL_OES_texture_half_float")); + EXPECT_THAT(info_.extensions(), + Not(HasSubstr("GL_OES_texture_float_linear"))); + EXPECT_THAT(info_.extensions(), + HasSubstr("GL_OES_texture_half_float_linear")); + EXPECT_FALSE(info_.validators()->pixel_type.IsValid(GL_FLOAT)); + EXPECT_TRUE(info_.validators()->pixel_type.IsValid(GL_HALF_FLOAT_OES)); +} + +TEST_F(FeatureInfoTest, InitializeEXT_framebuffer_multisample) { + SetupInitExpectations("GL_EXT_framebuffer_multisample"); + info_.Initialize(NULL); + EXPECT_TRUE(info_.feature_flags().ext_framebuffer_multisample); + EXPECT_THAT(info_.extensions(), HasSubstr("GL_EXT_framebuffer_multisample")); + EXPECT_THAT(info_.extensions(), HasSubstr("GL_EXT_framebuffer_blit")); + EXPECT_TRUE(info_.validators()->frame_buffer_target.IsValid( + GL_READ_FRAMEBUFFER_EXT)); + EXPECT_TRUE(info_.validators()->frame_buffer_target.IsValid( + GL_DRAW_FRAMEBUFFER_EXT)); + EXPECT_TRUE(info_.validators()->g_l_state.IsValid( + GL_READ_FRAMEBUFFER_BINDING_EXT)); + EXPECT_TRUE(info_.validators()->render_buffer_parameter.IsValid( + GL_MAX_SAMPLES_EXT)); +} + +TEST_F(FeatureInfoTest, InitializeEXT_texture_filter_anisotropic) { + SetupInitExpectations("GL_EXT_texture_filter_anisotropic"); + info_.Initialize(NULL); + EXPECT_THAT(info_.extensions(), + HasSubstr("GL_EXT_texture_filter_anisotropic")); + EXPECT_TRUE(info_.validators()->texture_parameter.IsValid( + GL_TEXTURE_MAX_ANISOTROPY_EXT)); + EXPECT_TRUE(info_.validators()->g_l_state.IsValid( + GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT)); +} + +TEST_F(FeatureInfoTest, InitializeEXT_ARB_depth_texture) { + SetupInitExpectations("GL_ARB_depth_texture"); + info_.Initialize(NULL); + EXPECT_THAT(info_.extensions(), + HasSubstr("GL_GOOGLE_depth_texture")); + EXPECT_TRUE(info_.validators()->texture_internal_format.IsValid( + GL_DEPTH_COMPONENT)); + EXPECT_TRUE(info_.validators()->texture_format.IsValid(GL_DEPTH_COMPONENT)); + EXPECT_TRUE(info_.validators()->pixel_type.IsValid(GL_UNSIGNED_SHORT)); + EXPECT_TRUE(info_.validators()->pixel_type.IsValid(GL_UNSIGNED_INT)); +} + +TEST_F(FeatureInfoTest, InitializeOES_ARB_depth_texture) { + SetupInitExpectations("GL_OES_depth_texture"); + info_.Initialize(NULL); + EXPECT_THAT(info_.extensions(), + HasSubstr("GL_GOOGLE_depth_texture")); + EXPECT_TRUE(info_.validators()->texture_internal_format.IsValid( + GL_DEPTH_COMPONENT)); + EXPECT_TRUE(info_.validators()->texture_format.IsValid(GL_DEPTH_COMPONENT)); + EXPECT_TRUE(info_.validators()->pixel_type.IsValid(GL_UNSIGNED_SHORT)); + EXPECT_TRUE(info_.validators()->pixel_type.IsValid(GL_UNSIGNED_INT)); +} + +TEST_F(FeatureInfoTest, InitializeEXT_packed_depth_stencil) { + SetupInitExpectations("GL_EXT_packed_depth_stencil"); + info_.Initialize(NULL); + EXPECT_THAT(info_.extensions(), + HasSubstr("GL_OES_packed_depth_stencil")); + EXPECT_TRUE(info_.validators()->render_buffer_format.IsValid( + GL_DEPTH24_STENCIL8)); + EXPECT_FALSE(info_.validators()->texture_internal_format.IsValid( + GL_DEPTH_COMPONENT)); + EXPECT_FALSE(info_.validators()->texture_format.IsValid(GL_DEPTH_COMPONENT)); + EXPECT_FALSE(info_.validators()->pixel_type.IsValid(GL_UNSIGNED_SHORT)); + EXPECT_FALSE(info_.validators()->pixel_type.IsValid(GL_UNSIGNED_INT)); +} + +TEST_F(FeatureInfoTest, InitializeOES_packed_depth_stencil) { + SetupInitExpectations("GL_OES_packed_depth_stencil"); + info_.Initialize(NULL); + EXPECT_THAT(info_.extensions(), + HasSubstr("GL_OES_packed_depth_stencil")); + EXPECT_TRUE(info_.validators()->render_buffer_format.IsValid( + GL_DEPTH24_STENCIL8)); + EXPECT_FALSE(info_.validators()->texture_internal_format.IsValid( + GL_DEPTH_COMPONENT)); + EXPECT_FALSE(info_.validators()->texture_format.IsValid(GL_DEPTH_COMPONENT)); + EXPECT_FALSE(info_.validators()->pixel_type.IsValid(GL_UNSIGNED_SHORT)); + EXPECT_FALSE(info_.validators()->pixel_type.IsValid(GL_UNSIGNED_INT)); +} + +TEST_F(FeatureInfoTest, + InitializeOES_packed_depth_stencil_and_GL_ARB_depth_texture) { + SetupInitExpectations("GL_OES_packed_depth_stencil GL_ARB_depth_texture"); + info_.Initialize(NULL); + EXPECT_THAT(info_.extensions(), + HasSubstr("GL_OES_packed_depth_stencil")); + EXPECT_TRUE(info_.validators()->render_buffer_format.IsValid( + GL_DEPTH24_STENCIL8)); + EXPECT_TRUE(info_.validators()->texture_internal_format.IsValid( + GL_DEPTH_STENCIL)); + EXPECT_TRUE(info_.validators()->texture_format.IsValid( + GL_DEPTH_STENCIL)); + EXPECT_TRUE(info_.validators()->pixel_type.IsValid( + GL_UNSIGNED_INT_24_8)); +} + +TEST_F(FeatureInfoTest, InitializeOES_depth24) { + SetupInitExpectations("GL_OES_depth24"); + info_.Initialize(NULL); + EXPECT_THAT(info_.extensions(), HasSubstr("GL_OES_depth24")); + EXPECT_TRUE(info_.validators()->render_buffer_format.IsValid( + GL_DEPTH_COMPONENT24)); +} + +TEST_F(FeatureInfoTest, InitializeOES_standard_derivatives) { + SetupInitExpectations("GL_OES_standard_derivatives"); + info_.Initialize(NULL); + EXPECT_THAT(info_.extensions(), HasSubstr("GL_OES_standard_derivatives")); + EXPECT_TRUE(info_.feature_flags().oes_standard_derivatives); +} + +} // namespace gles2 +} // namespace gpu + + + diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 68fa2f3..df03682 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -26,6 +26,7 @@ #include "gpu/command_buffer/service/buffer_manager.h" #include "gpu/command_buffer/service/cmd_buffer_engine.h" #include "gpu/command_buffer/service/context_group.h" +#include "gpu/command_buffer/service/feature_info.h" #include "gpu/command_buffer/service/framebuffer_manager.h" #include "gpu/command_buffer/service/gl_utils.h" #include "gpu/command_buffer/service/gles2_cmd_validation.h" @@ -604,7 +605,8 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, // Creates a TextureInfo for the given texture. TextureManager::TextureInfo* CreateTextureInfo( GLuint client_id, GLuint service_id) { - return texture_manager()->CreateTextureInfo(client_id, service_id); + return texture_manager()->CreateTextureInfo( + feature_info_, client_id, service_id); } // Gets the texture info for the given texture. Returns NULL if none exists. @@ -616,7 +618,7 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, // Deletes the texture info for the given texture. void RemoveTextureInfo(GLuint client_id) { - texture_manager()->RemoveTextureInfo(client_id); + texture_manager()->RemoveTextureInfo(feature_info_, client_id); } // Get the size (in pixels) of the currently bound frame buffer (either FBO @@ -1264,8 +1266,9 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, scoped_ptr<ShaderTranslator> vertex_translator_; scoped_ptr<ShaderTranslator> fragment_translator_; - // Cached from the context group. + // Cached from ContextGroup const Validators* validators_; + FeatureInfo* feature_info_; // Supported extensions. bool depth24_stencil8_oes_supported_; @@ -1515,7 +1518,8 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group) anti_aliased_(false), current_decoder_error_(error::kNoError), use_shader_translator_(true), - validators_(group->validators()), + validators_(group_->feature_info()->validators()), + feature_info_(group_->feature_info()), depth24_stencil8_oes_supported_(false) { attrib_0_value_.v[0] = 0.0f; attrib_0_value_.v[1] = 0.0f; @@ -1557,13 +1561,6 @@ bool GLES2DecoderImpl::Initialize(gfx::GLContext* context, CHECK_GL_ERROR(); - if (!group_->Initialize()) { - LOG(ERROR) << "GLES2DecoderImpl::Initialize failed becaue " - << "ContextGroup failed to initialize."; - Destroy(); - return false; - } - vertex_attrib_manager_.Initialize(group_->max_vertex_attribs()); // Check supported extensions. @@ -1669,7 +1666,7 @@ bool GLES2DecoderImpl::Initialize(gfx::GLContext* context, group_->max_fragment_uniform_vectors(); resources.MaxDrawBuffers = 1; resources.OES_standard_derivatives = - group_->extension_flags().oes_standard_derivatives ? 1 : 0; + feature_info_->feature_flags().oes_standard_derivatives ? 1 : 0; vertex_translator_.reset(new ShaderTranslator); if (!vertex_translator_->Init(EShLangVertex, &resources)) { LOG(ERROR) << "Could not initialize vertex shader translator."; @@ -1827,7 +1824,7 @@ static void RebindCurrentFramebuffer( } void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() { - if (!group_->extension_flags().ext_framebuffer_multisample) { + if (!feature_info_->feature_flags().ext_framebuffer_multisample) { RebindCurrentFramebuffer( GL_FRAMEBUFFER, bound_draw_framebuffer_.get(), @@ -1862,7 +1859,7 @@ gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() { int width = 0; int height = 0; - GLenum target = group_->extension_flags().ext_framebuffer_multisample ? + GLenum target = feature_info_->feature_flags().ext_framebuffer_multisample ? GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER; // Assume we have to have COLOR_ATTACHMENT0. Should we check for depth and @@ -2033,6 +2030,7 @@ bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() { DCHECK(info); texture_manager()->SetLevelInfo( + feature_info_, info, GL_TEXTURE_2D, 0, // level @@ -2107,7 +2105,7 @@ void GLES2DecoderImpl::Destroy() { GLuint service_id = offscreen_saved_color_texture_->id(); GLuint client_id = 0; if (parent_->texture_manager()->GetClientId(service_id, &client_id)) { - parent_->texture_manager()->RemoveTextureInfo(client_id); + parent_->texture_manager()->RemoveTextureInfo(feature_info_, client_id); } glDeleteFramebuffersEXT(1, ©_texture_to_parent_texture_fb_); @@ -2435,7 +2433,7 @@ void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) { void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) { TextureManager::TextureInfo* info = GetTextureInfoForTarget(target); - if (!info || !texture_manager()->MarkMipmapsGenerated(info)) { + if (!info || !texture_manager()->MarkMipmapsGenerated(feature_info_, info)) { SetGLError(GL_INVALID_OPERATION, "glGenerateMipmaps: Can not generate mips for npot textures"); return; @@ -3131,7 +3129,7 @@ void GLES2DecoderImpl::DoBlitFramebufferEXT( GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { - if (!group_->extension_flags().ext_framebuffer_multisample) { + if (!feature_info_->feature_flags().ext_framebuffer_multisample) { SetGLError(GL_INVALID_OPERATION, "glBlitFramebufferEXT: function not available"); } @@ -3142,7 +3140,7 @@ void GLES2DecoderImpl::DoBlitFramebufferEXT( void GLES2DecoderImpl::DoRenderbufferStorageMultisample( GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) { - if (!group_->extension_flags().ext_framebuffer_multisample) { + if (!feature_info_->feature_flags().ext_framebuffer_multisample) { SetGLError(GL_INVALID_OPERATION, "glRenderbufferStorageMultisampleEXT: function not available"); return; @@ -3222,7 +3220,8 @@ void GLES2DecoderImpl::DoTexParameterf( if (!info) { SetGLError(GL_INVALID_VALUE, "glTexParameterf: unknown texture"); } else { - texture_manager()->SetParameter(info, pname, static_cast<GLint>(param)); + texture_manager()->SetParameter( + feature_info_, info, pname, static_cast<GLint>(param)); glTexParameterf(target, pname, param); } } @@ -3233,7 +3232,7 @@ void GLES2DecoderImpl::DoTexParameteri( if (!info) { SetGLError(GL_INVALID_VALUE, "glTexParameteri: unknown texture"); } else { - texture_manager()->SetParameter(info, pname, param); + texture_manager()->SetParameter(feature_info_, info, pname, param); glTexParameteri(target, pname, param); } } @@ -3245,7 +3244,7 @@ void GLES2DecoderImpl::DoTexParameterfv( SetGLError(GL_INVALID_VALUE, "glTexParameterfv: unknown texture"); } else { texture_manager()->SetParameter( - info, pname, *reinterpret_cast<const GLint*>(params)); + feature_info_, info, pname, *reinterpret_cast<const GLint*>(params)); glTexParameterfv(target, pname, params); } } @@ -3256,7 +3255,7 @@ void GLES2DecoderImpl::DoTexParameteriv( if (!info) { SetGLError(GL_INVALID_VALUE, "glTexParameteriv: unknown texture"); } else { - texture_manager()->SetParameter(info, pname, *params); + texture_manager()->SetParameter(feature_info_, info, pname, *params); glTexParameteriv(target, pname, params); } } @@ -3468,7 +3467,7 @@ bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() { uniform_info->type == GL_SAMPLER_2D ? texture_unit.bound_texture_2d : texture_unit.bound_texture_cube_map; - if (!texture_info || !texture_info->CanRender(texture_manager())) { + if (!texture_info || !texture_info->CanRender(feature_info_)) { textures_set = true; glActiveTexture(GL_TEXTURE0 + texture_unit_index); glBindTexture( @@ -3500,7 +3499,7 @@ void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() { uniform_info->type == GL_SAMPLER_2D ? texture_unit.bound_texture_2d : texture_unit.bound_texture_cube_map; - if (!texture_info || !texture_info->CanRender(texture_manager())) { + if (!texture_info || !texture_info->CanRender(feature_info_)) { glActiveTexture(GL_TEXTURE0 + texture_unit_index); // Get the texture info that was previously bound here. texture_info = texture_unit.bind_target == GL_TEXTURE_2D ? @@ -4491,7 +4490,7 @@ error::Error GLES2DecoderImpl::HandleGetString( str = "OpenGL ES GLSL ES 1.0 Chromium"; break; case GL_EXTENSIONS: - str = group_->extensions().c_str(); + str = feature_info_->extensions().c_str(); break; default: str = gl_str; @@ -4606,7 +4605,8 @@ error::Error GLES2DecoderImpl::DoCompressedTexImage2D( "glCompressedTexImage2D: internal_format GL_INVALID_ENUM"); return error::kNoError; } - if (!texture_manager()->ValidForTarget(target, level, width, height, 1) || + if (!texture_manager()->ValidForTarget( + feature_info_, target, level, width, height, 1) || border != 0) { SetGLError(GL_INVALID_VALUE, "glCompressedTexImage2D: dimensions out of range"); @@ -4630,6 +4630,7 @@ error::Error GLES2DecoderImpl::DoCompressedTexImage2D( GLenum error = glGetError(); if (error == GL_NO_ERROR) { texture_manager()->SetLevelInfo( + feature_info_, info, target, level, internal_format, width, height, 1, border, 0, 0); } return error::kNoError; @@ -4763,7 +4764,8 @@ error::Error GLES2DecoderImpl::DoTexImage2D( SetGLError(GL_INVALID_OPERATION, "glTexImage2D: format != internalFormat"); return error::kNoError; } - if (!texture_manager()->ValidForTarget(target, level, width, height, 1) || + if (!texture_manager()->ValidForTarget( + feature_info_, target, level, width, height, 1) || border != 0) { SetGLError(GL_INVALID_VALUE, "glTexImage2D: dimensions out of range"); return error::kNoError; @@ -4806,7 +4808,7 @@ error::Error GLES2DecoderImpl::DoTexImage2D( pixels); GLenum error = glGetError(); if (error == GL_NO_ERROR) { - texture_manager()->SetLevelInfo(info, + texture_manager()->SetLevelInfo(feature_info_, info, target, level, internal_format, width, height, 1, border, format, type); } return error::kNoError; @@ -4912,7 +4914,8 @@ void GLES2DecoderImpl::DoCopyTexImage2D( "glCopyTexImage2D: unknown texture for target"); return; } - if (!texture_manager()->ValidForTarget(target, level, width, height, 1) || + if (!texture_manager()->ValidForTarget( + feature_info_, target, level, width, height, 1) || border != 0) { SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions out of range"); return; @@ -4926,8 +4929,8 @@ void GLES2DecoderImpl::DoCopyTexImage2D( GLenum error = glGetError(); if (error == GL_NO_ERROR) { texture_manager()->SetLevelInfo( - info, target, level, internal_format, width, height, 1, border, - internal_format, GL_UNSIGNED_BYTE); + feature_info_, info, target, level, internal_format, width, height, 1, + border, internal_format, GL_UNSIGNED_BYTE); } } diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h index 694fa37..57ec8b5 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder.h @@ -48,10 +48,13 @@ class GLES2Decoder : public CommonDecoder { // Parameters: // context: the GL context to render to. // size: the size if the GL context is offscreen. + // allowed_features: A string in the same format as + // glGetString(GL_EXTENSIONS) that lists the extensions this context + // should allow. Passing NULL means allow all extensions. // parent: the GLES2 decoder that can access this decoder's front buffer - // through a texture ID in its namespace. + // through a texture ID in its namespace. // parent_client_texture_id: the texture ID of the front buffer in the - // parent's namespace. + // parent's namespace. // Returns: // true if successful. virtual bool Initialize(gfx::GLContext* context, diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc index 9f3f769..c1f3c46 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc @@ -42,7 +42,9 @@ void GLES2DecoderTestBase::InitDecoder(const char* extensions) { InSequence sequence; - TestHelper::SetupContextGroupInitExpectations(gl_.get(), ""); + TestHelper::SetupContextGroupInitExpectations(gl_.get(), extensions); + + EXPECT_TRUE(group_.Initialize(extensions)); EXPECT_CALL(*gl_, EnableVertexAttribArray(0)) .Times(1) diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h index dfd78dc..05c92d9 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h @@ -32,8 +32,8 @@ class GLES2DecoderTestBase : public testing::Test { client_program_id_(102), client_renderbuffer_id_(103), client_shader_id_(104), - client_texture_id_(105), - client_element_buffer_id_(106) { + client_texture_id_(106), + client_element_buffer_id_(107) { memset(immediate_buffer_, 0xEE, sizeof(immediate_buffer_)); } @@ -56,7 +56,7 @@ class GLES2DecoderTestBase : public testing::Test { static const GLuint kServiceTextureId = 304; static const GLuint kServiceProgramId = 305; static const GLuint kServiceShaderId = 306; - static const GLuint kServiceElementBufferId = 307; + static const GLuint kServiceElementBufferId = 308; static const int32 kSharedMemoryId = 401; static const size_t kSharedBufferSize = 2048; diff --git a/gpu/command_buffer/service/gles2_cmd_validation.h b/gpu/command_buffer/service/gles2_cmd_validation.h index 07ec6cd..d98212b 100644 --- a/gpu/command_buffer/service/gles2_cmd_validation.h +++ b/gpu/command_buffer/service/gles2_cmd_validation.h @@ -28,7 +28,9 @@ class ValueValidator { } void AddValue(const T value) { - valid_values_.push_back(value); + if (!IsValid(value)) { + valid_values_.push_back(value); + } } bool IsValid(const T value) const { diff --git a/gpu/command_buffer/service/gpu_processor.cc b/gpu/command_buffer/service/gpu_processor.cc index f4bc650..4bb0e64 100644 --- a/gpu/command_buffer/service/gpu_processor.cc +++ b/gpu/command_buffer/service/gpu_processor.cc @@ -57,6 +57,12 @@ bool GPUProcessor::InitializeCommon(gfx::GLContext* context, decoder_.get())); } + if (!group_.Initialize(NULL)) { + LOG(ERROR) << "GPUProcessor::InitializeCommon failed because group " + << "failed to initialize."; + Destroy(); + } + // Initialize the decoder with either the view or pbuffer GLContext. if (!decoder_->Initialize(context, size, diff --git a/gpu/command_buffer/service/test_helper.cc b/gpu/command_buffer/service/test_helper.cc index 9002e7f..578c3c9 100644 --- a/gpu/command_buffer/service/test_helper.cc +++ b/gpu/command_buffer/service/test_helper.cc @@ -36,8 +36,11 @@ const GLint TestHelper::kNumTextureUnits; const GLint TestHelper::kMaxTextureImageUnits; const GLint TestHelper::kMaxVertexTextureImageUnits; const GLint TestHelper::kMaxFragmentUniformVectors; +const GLint TestHelper::kMaxFragmentUniformComponents; const GLint TestHelper::kMaxVaryingVectors; +const GLint TestHelper::kMaxVaryingFloats; const GLint TestHelper::kMaxVertexUniformVectors; +const GLint TestHelper::kMaxVertexUniformComponents; #endif void TestHelper::SetupTextureManagerInitExpectations( @@ -90,9 +93,8 @@ void TestHelper::SetupContextGroupInitExpectations( ::gfx::MockGLInterface* gl, const char* extensions) { InSequence sequence; - EXPECT_CALL(*gl, GetString(GL_EXTENSIONS)) - .WillOnce(Return(reinterpret_cast<const uint8*>(extensions))) - .RetiresOnSaturation(); + SetupFeatureInfoInitExpectations(gl, extensions); + EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VERTEX_ATTRIBS, _)) .WillOnce(SetArgumentPointee<1>(kNumVertexAttribs)) .RetiresOnSaturation(); @@ -105,6 +107,7 @@ void TestHelper::SetupContextGroupInitExpectations( EXPECT_CALL(*gl, GetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, _)) .WillOnce(SetArgumentPointee<1>(kMaxCubeMapTextureSize)) .RetiresOnSaturation(); + EXPECT_CALL(*gl, GetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, _)) .WillOnce(SetArgumentPointee<1>(kMaxTextureImageUnits)) .RetiresOnSaturation(); @@ -112,18 +115,27 @@ void TestHelper::SetupContextGroupInitExpectations( .WillOnce(SetArgumentPointee<1>(kMaxVertexTextureImageUnits)) .RetiresOnSaturation(); EXPECT_CALL(*gl, GetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, _)) - .WillOnce(SetArgumentPointee<1>(kMaxFragmentUniformVectors)) + .WillOnce(SetArgumentPointee<1>(kMaxFragmentUniformComponents)) .RetiresOnSaturation(); EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VARYING_FLOATS, _)) - .WillOnce(SetArgumentPointee<1>(kMaxVaryingVectors)) + .WillOnce(SetArgumentPointee<1>(kMaxVaryingFloats)) .RetiresOnSaturation(); EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, _)) - .WillOnce(SetArgumentPointee<1>(kMaxVertexUniformVectors)) + .WillOnce(SetArgumentPointee<1>(kMaxVertexUniformComponents)) .RetiresOnSaturation(); SetupTextureManagerInitExpectations(gl); } +void TestHelper::SetupFeatureInfoInitExpectations( + ::gfx::MockGLInterface* gl, const char* extensions) { + InSequence sequence; + + EXPECT_CALL(*gl, GetString(GL_EXTENSIONS)) + .WillOnce(Return(reinterpret_cast<const uint8*>(extensions))) + .RetiresOnSaturation(); +} + } // namespace gles2 } // namespace gpu diff --git a/gpu/command_buffer/service/test_helper.h b/gpu/command_buffer/service/test_helper.h index 2858b50..159665c 100644 --- a/gpu/command_buffer/service/test_helper.h +++ b/gpu/command_buffer/service/test_helper.h @@ -25,11 +25,17 @@ class TestHelper { static const GLint kMaxTextureImageUnits = 8; static const GLint kMaxVertexTextureImageUnits = 2; static const GLint kMaxFragmentUniformVectors = 16; + static const GLint kMaxFragmentUniformComponents = + kMaxFragmentUniformVectors * 4; static const GLint kMaxVaryingVectors = 8; + static const GLint kMaxVaryingFloats = kMaxVaryingVectors * 4; static const GLint kMaxVertexUniformVectors = 128; + static const GLint kMaxVertexUniformComponents = kMaxVertexUniformVectors * 4; static void SetupContextGroupInitExpectations( ::gfx::MockGLInterface* gl, const char* extensions); + static void SetupFeatureInfoInitExpectations( + ::gfx::MockGLInterface* gl, const char* extensions); static void SetupTextureManagerInitExpectations(::gfx::MockGLInterface* gl); }; diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc index 66a8d55..250da70 100644 --- a/gpu/command_buffer/service/texture_manager.cc +++ b/gpu/command_buffer/service/texture_manager.cc @@ -5,7 +5,7 @@ #include "gpu/command_buffer/service/texture_manager.h" #include "base/bits.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" -#include "gpu/command_buffer/service/context_group.h" +#include "gpu/command_buffer/service/feature_info.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" #include "gpu/GLES2/gles2_command_buffer.h" @@ -87,13 +87,12 @@ void TextureManager::Destroy(bool have_context) { } bool TextureManager::TextureInfo::CanRender( - const TextureManager* manager) const { - DCHECK(manager); + const FeatureInfo* feature_info) const { if (target_ == 0 || IsDeleted()) { return false; } bool needs_mips = NeedsMips(); - if (npot() && !manager->npot_ok()) { + if (npot() && !feature_info->feature_flags().npot_ok) { return !needs_mips && wrap_s_ == GL_CLAMP_TO_EDGE && wrap_t_ == GL_CLAMP_TO_EDGE; @@ -110,8 +109,8 @@ bool TextureManager::TextureInfo::CanRender( } bool TextureManager::TextureInfo::MarkMipmapsGenerated( - const TextureManager* manager) { - if (!CanGenerateMipmaps(manager)) { + const FeatureInfo* feature_info) { + if (!CanGenerateMipmaps(feature_info)) { return false; } for (size_t ii = 0; ii < level_infos_.size(); ++ii) { @@ -124,7 +123,7 @@ bool TextureManager::TextureInfo::MarkMipmapsGenerated( width = std::max(1, width >> 1); height = std::max(1, height >> 1); depth = std::max(1, depth >> 1); - SetLevelInfo(manager, + SetLevelInfo(feature_info, target_ == GL_TEXTURE_2D ? GL_TEXTURE_2D : FaceIndexToGLTarget(ii), level, @@ -141,8 +140,9 @@ bool TextureManager::TextureInfo::MarkMipmapsGenerated( } bool TextureManager::TextureInfo::CanGenerateMipmaps( - const TextureManager* manager) const { - if ((npot() && !manager->npot_ok()) || level_infos_.empty() || IsDeleted()) { + const FeatureInfo* feature_info) const { + if ((npot() && !feature_info->feature_flags().npot_ok) || + level_infos_.empty() || IsDeleted()) { return false; } const TextureInfo::LevelInfo& first = level_infos_[0][0]; @@ -163,7 +163,7 @@ bool TextureManager::TextureInfo::CanGenerateMipmaps( } void TextureManager::TextureInfo::SetLevelInfo( - const TextureManager* manager, + const FeatureInfo* feature_info, GLenum target, GLint level, GLenum internal_format, @@ -192,7 +192,7 @@ void TextureManager::TextureInfo::SetLevelInfo( info.format = format; info.type = type; max_level_set_ = std::max(max_level_set_, level); - Update(manager); + Update(feature_info); } bool TextureManager::TextureInfo::ValidForTexture( @@ -253,8 +253,7 @@ bool TextureManager::TextureInfo::GetLevelType( } void TextureManager::TextureInfo::SetParameter( - const TextureManager* manager, GLenum pname, GLint param) { - DCHECK(manager); + const FeatureInfo* feature_info, GLenum pname, GLint param) { switch (pname) { case GL_TEXTURE_MIN_FILTER: min_filter_ = param; @@ -275,10 +274,10 @@ void TextureManager::TextureInfo::SetParameter( NOTREACHED(); break; } - Update(manager); + Update(feature_info); } -void TextureManager::TextureInfo::Update(const TextureManager* manager) { +void TextureManager::TextureInfo::Update(const FeatureInfo* feature_info) { // Update npot status. npot_ = false; for (size_t ii = 0; ii < level_infos_.size(); ++ii) { @@ -300,12 +299,13 @@ void TextureManager::TextureInfo::Update(const TextureManager* manager) { max_level_set_ >= 0; cube_complete_ = (level_infos_.size() == 6) && (first_face.width == first_face.height); - if (first_face.type == GL_FLOAT && !manager->enable_float_linear() && + if (first_face.type == GL_FLOAT && + !feature_info->feature_flags().enable_texture_float_linear && (min_filter_ != GL_NEAREST_MIPMAP_NEAREST || mag_filter_ != GL_NEAREST)) { texture_complete_ = false; } else if (first_face.type == GL_HALF_FLOAT_OES && - !manager->enable_half_float_linear() && + !feature_info->feature_flags().enable_texture_half_float_linear && (min_filter_ != GL_NEAREST_MIPMAP_NEAREST || mag_filter_ != GL_NEAREST)) { texture_complete_ = false; @@ -348,15 +348,9 @@ void TextureManager::TextureInfo::Update(const TextureManager* manager) { } TextureManager::TextureManager( - bool npot_ok, - bool enable_float_linear, - bool enable_half_float_linear, GLint max_texture_size, GLint max_cube_map_texture_size) - : npot_ok_(npot_ok), - enable_float_linear_(enable_float_linear), - enable_half_float_linear_(enable_half_float_linear), - max_texture_size_(max_texture_size), + : max_texture_size_(max_texture_size), max_cube_map_texture_size_(max_cube_map_texture_size), max_levels_(ComputeMipMapCount(max_texture_size, max_texture_size, @@ -392,15 +386,16 @@ bool TextureManager::Initialize() { glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_CUBE_MAP, 0); + FeatureInfo temp_feature_info; default_texture_2d_ = TextureInfo::Ref(new TextureInfo(ids[1])); SetInfoTarget(default_texture_2d_, GL_TEXTURE_2D); - default_texture_2d_->SetLevelInfo( - this, GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE); + default_texture_2d_->SetLevelInfo(&temp_feature_info, + GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE); default_texture_cube_map_ = TextureInfo::Ref(new TextureInfo(ids[3])); SetInfoTarget(default_texture_cube_map_, GL_TEXTURE_CUBE_MAP); for (int ii = 0; ii < GLES2Util::kNumFaces; ++ii) { default_texture_cube_map_->SetLevelInfo( - this, GLES2Util::IndexToGLFaceTarget(ii), + &temp_feature_info, GLES2Util::IndexToGLFaceTarget(ii), 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE); } @@ -411,6 +406,7 @@ bool TextureManager::Initialize() { } bool TextureManager::ValidForTarget( + const FeatureInfo* feature_info, GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth) { GLsizei max_size = MaxSizeForTarget(target); @@ -422,7 +418,7 @@ bool TextureManager::ValidForTarget( width <= max_size && height <= max_size && depth <= max_size && - (level == 0 || npot_ok() || + (level == 0 || feature_info->feature_flags().npot_ok || (!GLES2Util::IsNPOT(width) && !GLES2Util::IsNPOT(height) && !GLES2Util::IsNPOT(depth))) && @@ -431,6 +427,7 @@ bool TextureManager::ValidForTarget( } void TextureManager::SetLevelInfo( + const FeatureInfo* feature_info, TextureManager::TextureInfo* info, GLenum target, GLint level, @@ -443,50 +440,54 @@ void TextureManager::SetLevelInfo( GLenum type) { DCHECK(info); DCHECK(!info->IsDeleted()); - if (!info->CanRender(this)) { + if (!info->CanRender(feature_info)) { --num_unrenderable_textures_; } info->SetLevelInfo( - this, target, level, internal_format, width, height, depth, + feature_info, target, level, internal_format, width, height, depth, border, format, type); - if (!info->CanRender(this)) { + if (!info->CanRender(feature_info)) { ++num_unrenderable_textures_; } } void TextureManager::SetParameter( + const FeatureInfo* feature_info, TextureManager::TextureInfo* info, GLenum pname, GLint param) { DCHECK(info); DCHECK(!info->IsDeleted()); - if (!info->CanRender(this)) { + if (!info->CanRender(feature_info)) { --num_unrenderable_textures_; } - info->SetParameter(this, pname, param); - if (!info->CanRender(this)) { + info->SetParameter(feature_info, pname, param); + if (!info->CanRender(feature_info)) { ++num_unrenderable_textures_; } } -bool TextureManager::MarkMipmapsGenerated(TextureManager::TextureInfo* info) { +bool TextureManager::MarkMipmapsGenerated( + const FeatureInfo* feature_info, + TextureManager::TextureInfo* info) { DCHECK(info); DCHECK(!info->IsDeleted()); - if (!info->CanRender(this)) { + if (!info->CanRender(feature_info)) { --num_unrenderable_textures_; } - bool result = info->MarkMipmapsGenerated(this); - if (!info->CanRender(this)) { + bool result = info->MarkMipmapsGenerated(feature_info); + if (!info->CanRender(feature_info)) { ++num_unrenderable_textures_; } return result; } TextureManager::TextureInfo* TextureManager::CreateTextureInfo( + const FeatureInfo* feature_info, GLuint client_id, GLuint service_id) { TextureInfo::Ref info(new TextureInfo(service_id)); std::pair<TextureInfoMap::iterator, bool> result = texture_infos_.insert(std::make_pair(client_id, info)); DCHECK(result.second); - if (!info->CanRender(this)) { + if (!info->CanRender(feature_info)) { ++num_unrenderable_textures_; } return info.get(); @@ -498,11 +499,12 @@ TextureManager::TextureInfo* TextureManager::GetTextureInfo( return it != texture_infos_.end() ? it->second : NULL; } -void TextureManager::RemoveTextureInfo(GLuint client_id) { +void TextureManager::RemoveTextureInfo( + const FeatureInfo* feature_info, GLuint client_id) { TextureInfoMap::iterator it = texture_infos_.find(client_id); if (it != texture_infos_.end()) { TextureInfo* info = it->second; - if (!info->CanRender(this)) { + if (!info->CanRender(feature_info)) { --num_unrenderable_textures_; } info->MarkAsDeleted(); diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h index 2ec46c1..182e0d1 100644 --- a/gpu/command_buffer/service/texture_manager.h +++ b/gpu/command_buffer/service/texture_manager.h @@ -15,6 +15,8 @@ namespace gpu { namespace gles2 { +class FeatureInfo; + // This class keeps track of the textures and their sizes so we can do NPOT and // texture complete checking. // @@ -43,7 +45,7 @@ class TextureManager { // True if this texture meets all the GLES2 criteria for rendering. // See section 3.8.2 of the GLES2 spec. - bool CanRender(const TextureManager* manager) const; + bool CanRender(const FeatureInfo* feature_info) const; // The service side OpenGL id of the texture. GLuint service_id() const { @@ -76,7 +78,7 @@ class TextureManager { } // Returns true if mipmaps can be generated by GL. - bool CanGenerateMipmaps(const TextureManager* manager) const; + bool CanGenerateMipmaps(const FeatureInfo* feature_info) const; // Get the width and height for a particular level. Returns false if level // does not exist. @@ -133,7 +135,7 @@ class TextureManager { // Set the info for a particular level. void SetLevelInfo( - const TextureManager* manager, + const FeatureInfo* feature_info, GLenum target, GLint level, GLenum internal_format, @@ -146,10 +148,11 @@ class TextureManager { // Sets a texture parameter. // TODO(gman): Expand to SetParameteri,f,iv,fv - void SetParameter(const TextureManager* manager, GLenum pname, GLint param); + void SetParameter( + const FeatureInfo* feature_info, GLenum pname, GLint param); // Makes each of the mip levels as though they were generated. - bool MarkMipmapsGenerated(const TextureManager* manager); + bool MarkMipmapsGenerated(const FeatureInfo* feature_info); void MarkAsDeleted() { service_id_ = 0; @@ -175,7 +178,7 @@ class TextureManager { } // Update info about this texture. - void Update(const TextureManager* manager); + void Update(const FeatureInfo* feature_info); // Info about each face and level of texture. std::vector<std::vector<LevelInfo> > level_infos_; @@ -210,10 +213,7 @@ class TextureManager { DISALLOW_COPY_AND_ASSIGN(TextureInfo); }; - TextureManager(bool npot_ok, - bool enable_float_linear, - bool enable_half_float_linear, - GLsizei max_texture_size, + TextureManager(GLsizei max_texture_size, GLsizei max_cube_map_texture_size); ~TextureManager(); @@ -223,21 +223,6 @@ class TextureManager { // Must call before destruction. void Destroy(bool have_context); - // Whether or not npot textures can render. - bool npot_ok() const { - return npot_ok_; - } - - // Whether float textures can have linear filtering. - bool enable_float_linear() const { - return enable_float_linear_; - } - - // Whether half float textures can have linear filtering. - bool enable_half_float_linear() const { - return enable_half_float_linear_; - } - // Returns the maximum number of levels. GLint MaxLevelsForTarget(GLenum target) const { return (target == GL_TEXTURE_2D) ? max_levels_ : max_cube_map_levels_; @@ -251,6 +236,7 @@ class TextureManager { // Checks if a dimensions are valid for a given target. bool ValidForTarget( + const FeatureInfo* feature_info, GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth); @@ -265,6 +251,7 @@ class TextureManager { // Set the info for a particular level in a TexureInfo. void SetLevelInfo( + const FeatureInfo* feature_info, TextureInfo* info, GLenum target, GLint level, @@ -278,20 +265,25 @@ class TextureManager { // Sets a texture parameter of a TextureInfo // TODO(gman): Expand to SetParameteri,f,iv,fv - void SetParameter(TextureInfo* info, GLenum pname, GLint param); + void SetParameter( + const FeatureInfo* feature_info, + TextureInfo* info, GLenum pname, GLint param); // Makes each of the mip levels as though they were generated. // Returns false if that's not allowed for the given texture. - bool MarkMipmapsGenerated(TextureManager::TextureInfo* info); + bool MarkMipmapsGenerated( + const FeatureInfo* feature_info, + TextureManager::TextureInfo* info); // Creates a new texture info. - TextureInfo* CreateTextureInfo(GLuint client_id, GLuint service_id); + TextureInfo* CreateTextureInfo( + const FeatureInfo* feature_info, GLuint client_id, GLuint service_id); // Gets the texture info for the given texture. TextureInfo* GetTextureInfo(GLuint client_id); // Removes a texture info. - void RemoveTextureInfo(GLuint client_id); + void RemoveTextureInfo(const FeatureInfo* feature_info, GLuint client_id); // Gets a client id for a given service id. bool GetClientId(GLuint service_id, GLuint* client_id) const; @@ -306,8 +298,8 @@ class TextureManager { } GLuint black_texture_id(GLenum target) const { - return target == GL_SAMPLER_2D ? black_2d_texture_id_ : - black_cube_texture_id_; + return target == GL_SAMPLER_2D ? black_2d_texture_id_ : + black_cube_texture_id_; } private: @@ -316,9 +308,6 @@ class TextureManager { typedef std::map<GLuint, TextureInfo::Ref> TextureInfoMap; TextureInfoMap texture_infos_; - bool npot_ok_; - bool enable_float_linear_; - bool enable_half_float_linear_; GLsizei max_texture_size_; GLsizei max_cube_map_texture_size_; GLint max_levels_; diff --git a/gpu/command_buffer/service/texture_manager_unittest.cc b/gpu/command_buffer/service/texture_manager_unittest.cc index b313b32..b845e7f 100644 --- a/gpu/command_buffer/service/texture_manager_unittest.cc +++ b/gpu/command_buffer/service/texture_manager_unittest.cc @@ -7,6 +7,7 @@ #include "app/gfx/gl/gl_mock.h" #include "gpu/GLES2/gles2_command_buffer.h" #include "testing/gtest/include/gtest/gtest.h" +#include "gpu/command_buffer/service/feature_info.h" #include "gpu/command_buffer/service/test_helper.h" using ::testing::Pointee; @@ -29,7 +30,7 @@ class TextureManagerTest : public testing::Test { TextureManagerTest() - : manager_(false, false, false, kMaxTextureSize, kMaxCubeMapTextureSize) { + : manager_(kMaxTextureSize, kMaxCubeMapTextureSize) { } ~TextureManagerTest() { @@ -53,6 +54,7 @@ class TextureManagerTest : public testing::Test { // Use StrictMock to make 100% sure we know how GL will be called. scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; TextureManager manager_; + FeatureInfo feature_info_; }; // GCC requires these declarations, but MSVC requires they not be present @@ -73,7 +75,7 @@ TEST_F(TextureManagerTest, Basic) { const GLuint kClient2Id = 2; EXPECT_FALSE(manager_.HaveUnrenderableTextures()); // Check we can create texture. - manager_.CreateTextureInfo(kClient1Id, kService1Id); + manager_.CreateTextureInfo(&feature_info_, kClient1Id, kService1Id); // Check texture got created. TextureManager::TextureInfo* info1 = manager_.GetTextureInfo(kClient1Id); ASSERT_TRUE(info1 != NULL); @@ -84,9 +86,9 @@ TEST_F(TextureManagerTest, Basic) { // Check we get nothing for a non-existent texture. EXPECT_TRUE(manager_.GetTextureInfo(kClient2Id) == NULL); // Check trying to a remove non-existent textures does not crash. - manager_.RemoveTextureInfo(kClient2Id); + manager_.RemoveTextureInfo(&feature_info_, kClient2Id); // Check we can't get the texture after we remove it. - manager_.RemoveTextureInfo(kClient1Id); + manager_.RemoveTextureInfo(&feature_info_, kClient1Id); EXPECT_TRUE(manager_.GetTextureInfo(kClient1Id) == NULL); } @@ -95,7 +97,7 @@ TEST_F(TextureManagerTest, Destroy) { const GLuint kService1Id = 11; EXPECT_FALSE(manager_.HaveUnrenderableTextures()); // Check we can create texture. - manager_.CreateTextureInfo(kClient1Id, kService1Id); + manager_.CreateTextureInfo(&feature_info_, kClient1Id, kService1Id); // Check texture got created. TextureManager::TextureInfo* info1 = manager_.GetTextureInfo(kClient1Id); ASSERT_TRUE(info1 != NULL); @@ -124,66 +126,73 @@ TEST_F(TextureManagerTest, MaxValues) { TEST_F(TextureManagerTest, ValidForTarget) { // check 2d EXPECT_TRUE(manager_.ValidForTarget( - GL_TEXTURE_2D, 0, + &feature_info_, GL_TEXTURE_2D, 0, kMaxTextureSize, kMaxTextureSize, 1)); EXPECT_TRUE(manager_.ValidForTarget( - GL_TEXTURE_2D, kMax2dLevels - 1, + &feature_info_, GL_TEXTURE_2D, kMax2dLevels - 1, kMaxTextureSize, kMaxTextureSize, 1)); EXPECT_TRUE(manager_.ValidForTarget( - GL_TEXTURE_2D, kMax2dLevels - 1, + &feature_info_, GL_TEXTURE_2D, kMax2dLevels - 1, 1, kMaxTextureSize, 1)); EXPECT_TRUE(manager_.ValidForTarget( - GL_TEXTURE_2D, kMax2dLevels - 1, + &feature_info_, GL_TEXTURE_2D, kMax2dLevels - 1, kMaxTextureSize, 1, 1)); // check level out of range. EXPECT_FALSE(manager_.ValidForTarget( - GL_TEXTURE_2D, kMax2dLevels, + &feature_info_, GL_TEXTURE_2D, kMax2dLevels, kMaxTextureSize, 1, 1)); // check has depth. EXPECT_FALSE(manager_.ValidForTarget( - GL_TEXTURE_2D, kMax2dLevels, + &feature_info_, GL_TEXTURE_2D, kMax2dLevels, kMaxTextureSize, 1, 2)); // Check NPOT width on level 0 - EXPECT_TRUE(manager_.ValidForTarget(GL_TEXTURE_2D, 0, 5, 2, 1)); + EXPECT_TRUE(manager_.ValidForTarget( + &feature_info_, GL_TEXTURE_2D, 0, 5, 2, 1)); // Check NPOT height on level 0 - EXPECT_TRUE(manager_.ValidForTarget(GL_TEXTURE_2D, 0, 2, 5, 1)); + EXPECT_TRUE(manager_.ValidForTarget( + &feature_info_, GL_TEXTURE_2D, 0, 2, 5, 1)); // Check NPOT width on level 1 - EXPECT_FALSE(manager_.ValidForTarget(GL_TEXTURE_2D, 1, 5, 2, 1)); + EXPECT_FALSE(manager_.ValidForTarget( + &feature_info_, GL_TEXTURE_2D, 1, 5, 2, 1)); // Check NPOT height on level 1 - EXPECT_FALSE(manager_.ValidForTarget(GL_TEXTURE_2D, 1, 2, 5, 1)); + EXPECT_FALSE(manager_.ValidForTarget( + &feature_info_, GL_TEXTURE_2D, 1, 2, 5, 1)); // check cube EXPECT_TRUE(manager_.ValidForTarget( - GL_TEXTURE_CUBE_MAP, 0, + &feature_info_, GL_TEXTURE_CUBE_MAP, 0, kMaxCubeMapTextureSize, kMaxCubeMapTextureSize, 1)); EXPECT_TRUE(manager_.ValidForTarget( - GL_TEXTURE_CUBE_MAP, kMaxCubeMapLevels - 1, + &feature_info_, GL_TEXTURE_CUBE_MAP, kMaxCubeMapLevels - 1, kMaxCubeMapTextureSize, kMaxCubeMapTextureSize, 1)); // check level out of range. EXPECT_FALSE(manager_.ValidForTarget( - GL_TEXTURE_CUBE_MAP, kMaxCubeMapLevels, + &feature_info_, GL_TEXTURE_CUBE_MAP, kMaxCubeMapLevels, kMaxCubeMapTextureSize, 1, 1)); // check not square. EXPECT_FALSE(manager_.ValidForTarget( - GL_TEXTURE_CUBE_MAP, kMaxCubeMapLevels, + &feature_info_, GL_TEXTURE_CUBE_MAP, kMaxCubeMapLevels, kMaxCubeMapTextureSize, 1, 1)); // check has depth. EXPECT_FALSE(manager_.ValidForTarget( - GL_TEXTURE_CUBE_MAP, kMaxCubeMapLevels, + &feature_info_, GL_TEXTURE_CUBE_MAP, kMaxCubeMapLevels, kMaxCubeMapTextureSize, 1, 2)); } TEST_F(TextureManagerTest, ValidForTargetNPOT) { - TextureManager manager( - true, false, false, kMaxTextureSize, kMaxCubeMapTextureSize); + TextureManager manager(kMaxTextureSize, kMaxCubeMapTextureSize); + TestHelper::SetupFeatureInfoInitExpectations( + gl_.get(), "GL_OES_texture_npot"); + FeatureInfo feature_info; + feature_info.Initialize(NULL); // Check NPOT width on level 0 - EXPECT_TRUE(manager.ValidForTarget(GL_TEXTURE_2D, 0, 5, 2, 1)); + EXPECT_TRUE(manager.ValidForTarget(&feature_info, GL_TEXTURE_2D, 0, 5, 2, 1)); // Check NPOT height on level 0 - EXPECT_TRUE(manager.ValidForTarget(GL_TEXTURE_2D, 0, 2, 5, 1)); + EXPECT_TRUE(manager.ValidForTarget(&feature_info, GL_TEXTURE_2D, 0, 2, 5, 1)); // Check NPOT width on level 1 - EXPECT_TRUE(manager.ValidForTarget(GL_TEXTURE_2D, 1, 5, 2, 1)); + EXPECT_TRUE(manager.ValidForTarget(&feature_info, GL_TEXTURE_2D, 1, 5, 2, 1)); // Check NPOT height on level 1 - EXPECT_TRUE(manager.ValidForTarget(GL_TEXTURE_2D, 1, 2, 5, 1)); + EXPECT_TRUE(manager.ValidForTarget(&feature_info, GL_TEXTURE_2D, 1, 2, 5, 1)); manager.Destroy(false); } @@ -197,7 +206,7 @@ class TextureInfoTest : public testing::Test { static const GLuint kService1Id = 11; TextureInfoTest() - : manager_(false, false, false, kMaxTextureSize, kMaxCubeMapTextureSize) { + : manager_(kMaxTextureSize, kMaxCubeMapTextureSize) { } ~TextureInfoTest() { manager_.Destroy(false); @@ -207,7 +216,7 @@ class TextureInfoTest : public testing::Test { virtual void SetUp() { gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>()); ::gfx::GLInterface::SetGLInterface(gl_.get()); - manager_.CreateTextureInfo(kClient1Id, kService1Id); + manager_.CreateTextureInfo(&feature_info_, kClient1Id, kService1Id); info_ = manager_.GetTextureInfo(kClient1Id); ASSERT_TRUE(info_ != NULL); } @@ -221,15 +230,16 @@ class TextureInfoTest : public testing::Test { scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; TextureManager manager_; TextureManager::TextureInfo* info_; + FeatureInfo feature_info_; }; TEST_F(TextureInfoTest, Basic) { EXPECT_EQ(0u, info_->target()); EXPECT_FALSE(info_->texture_complete()); EXPECT_FALSE(info_->cube_complete()); - EXPECT_FALSE(info_->CanGenerateMipmaps(&manager_)); + EXPECT_FALSE(info_->CanGenerateMipmaps(&feature_info_)); EXPECT_FALSE(info_->npot()); - EXPECT_FALSE(info_->CanRender(&manager_)); + EXPECT_FALSE(info_->CanRender(&feature_info_)); EXPECT_TRUE(manager_.HaveUnrenderableTextures()); } @@ -237,41 +247,43 @@ TEST_F(TextureInfoTest, POT2D) { manager_.SetInfoTarget(info_, GL_TEXTURE_2D); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), info_->target()); // Check Setting level 0 to POT - manager_.SetLevelInfo(info_, + manager_.SetLevelInfo(&feature_info_, info_, GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE); EXPECT_FALSE(info_->npot()); EXPECT_FALSE(info_->texture_complete()); - EXPECT_FALSE(info_->CanRender(&manager_)); + EXPECT_FALSE(info_->CanRender(&feature_info_)); EXPECT_TRUE(manager_.HaveUnrenderableTextures()); // Set filters to something that will work with a single mip. - manager_.SetParameter(info_, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - EXPECT_TRUE(info_->CanRender(&manager_)); + manager_.SetParameter( + &feature_info_, info_, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + EXPECT_TRUE(info_->CanRender(&feature_info_)); EXPECT_FALSE(manager_.HaveUnrenderableTextures()); // Set them back. - manager_.SetParameter(info_, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + manager_.SetParameter( + &feature_info_, info_, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); EXPECT_TRUE(manager_.HaveUnrenderableTextures()); - EXPECT_TRUE(info_->CanGenerateMipmaps(&manager_)); + EXPECT_TRUE(info_->CanGenerateMipmaps(&feature_info_)); // Make mips. - EXPECT_TRUE(manager_.MarkMipmapsGenerated(info_)); + EXPECT_TRUE(manager_.MarkMipmapsGenerated(&feature_info_, info_)); EXPECT_TRUE(info_->texture_complete()); - EXPECT_TRUE(info_->CanRender(&manager_)); + EXPECT_TRUE(info_->CanRender(&feature_info_)); EXPECT_FALSE(manager_.HaveUnrenderableTextures()); // Change a mip. - manager_.SetLevelInfo(info_, + manager_.SetLevelInfo(&feature_info_, info_, GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE); EXPECT_FALSE(info_->npot()); EXPECT_FALSE(info_->texture_complete()); - EXPECT_TRUE(info_->CanGenerateMipmaps(&manager_)); - EXPECT_FALSE(info_->CanRender(&manager_)); + EXPECT_TRUE(info_->CanGenerateMipmaps(&feature_info_)); + EXPECT_FALSE(info_->CanRender(&feature_info_)); EXPECT_TRUE(manager_.HaveUnrenderableTextures()); // Set a level past the number of mips that would get generated. - manager_.SetLevelInfo(info_, + manager_.SetLevelInfo(&feature_info_, info_, GL_TEXTURE_2D, 3, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE); - EXPECT_TRUE(info_->CanGenerateMipmaps(&manager_)); + EXPECT_TRUE(info_->CanGenerateMipmaps(&feature_info_)); // Make mips. - EXPECT_TRUE(manager_.MarkMipmapsGenerated(info_)); - EXPECT_FALSE(info_->CanRender(&manager_)); + EXPECT_TRUE(manager_.MarkMipmapsGenerated(&feature_info_, info_)); + EXPECT_FALSE(info_->CanRender(&feature_info_)); EXPECT_FALSE(info_->texture_complete()); EXPECT_TRUE(manager_.HaveUnrenderableTextures()); } @@ -280,51 +292,57 @@ TEST_F(TextureInfoTest, NPOT2D) { manager_.SetInfoTarget(info_, GL_TEXTURE_2D); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), info_->target()); // Check Setting level 0 to NPOT - manager_.SetLevelInfo(info_, + manager_.SetLevelInfo(&feature_info_, info_, GL_TEXTURE_2D, 0, GL_RGBA, 4, 5, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE); EXPECT_TRUE(info_->npot()); EXPECT_FALSE(info_->texture_complete()); - EXPECT_FALSE(info_->CanGenerateMipmaps(&manager_)); - EXPECT_FALSE(info_->CanRender(&manager_)); + EXPECT_FALSE(info_->CanGenerateMipmaps(&feature_info_)); + EXPECT_FALSE(info_->CanRender(&feature_info_)); EXPECT_TRUE(manager_.HaveUnrenderableTextures()); - manager_.SetParameter(info_, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - EXPECT_FALSE(info_->CanRender(&manager_)); + manager_.SetParameter( + &feature_info_, info_, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + EXPECT_FALSE(info_->CanRender(&feature_info_)); EXPECT_TRUE(manager_.HaveUnrenderableTextures()); - manager_.SetParameter(info_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - EXPECT_FALSE(info_->CanRender(&manager_)); + manager_.SetParameter( + &feature_info_, info_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + EXPECT_FALSE(info_->CanRender(&feature_info_)); EXPECT_TRUE(manager_.HaveUnrenderableTextures()); - manager_.SetParameter(info_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - EXPECT_TRUE(info_->CanRender(&manager_)); + manager_.SetParameter( + &feature_info_, info_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + EXPECT_TRUE(info_->CanRender(&feature_info_)); EXPECT_FALSE(manager_.HaveUnrenderableTextures()); // Change it to POT. - manager_.SetLevelInfo(info_, + manager_.SetLevelInfo(&feature_info_, info_, GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE); EXPECT_FALSE(info_->npot()); EXPECT_FALSE(info_->texture_complete()); - EXPECT_TRUE(info_->CanGenerateMipmaps(&manager_)); + EXPECT_TRUE(info_->CanGenerateMipmaps(&feature_info_)); EXPECT_FALSE(manager_.HaveUnrenderableTextures()); } TEST_F(TextureInfoTest, NPOT2DNPOTOK) { - TextureManager manager( - true, false, false, kMaxTextureSize, kMaxCubeMapTextureSize); - manager.CreateTextureInfo(kClient1Id, kService1Id); + TextureManager manager(kMaxTextureSize, kMaxCubeMapTextureSize); + TestHelper::SetupFeatureInfoInitExpectations( + gl_.get(), "GL_OES_texture_npot"); + FeatureInfo feature_info; + feature_info.Initialize(NULL); + manager.CreateTextureInfo(&feature_info, kClient1Id, kService1Id); TextureManager::TextureInfo* info = manager_.GetTextureInfo(kClient1Id); ASSERT_TRUE(info_ != NULL); manager.SetInfoTarget(info, GL_TEXTURE_2D); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), info->target()); // Check Setting level 0 to NPOT - manager.SetLevelInfo(info, + manager.SetLevelInfo(&feature_info, info, GL_TEXTURE_2D, 0, GL_RGBA, 4, 5, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE); EXPECT_TRUE(info->npot()); EXPECT_FALSE(info->texture_complete()); - EXPECT_TRUE(info->CanGenerateMipmaps(&manager)); - EXPECT_FALSE(info->CanRender(&manager)); + EXPECT_TRUE(info->CanGenerateMipmaps(&feature_info)); + EXPECT_FALSE(info->CanRender(&feature_info)); EXPECT_TRUE(manager.HaveUnrenderableTextures()); - EXPECT_TRUE(manager.MarkMipmapsGenerated(info)); + EXPECT_TRUE(manager.MarkMipmapsGenerated(&feature_info, info)); EXPECT_TRUE(info->texture_complete()); - EXPECT_TRUE(info->CanRender(&manager)); + EXPECT_TRUE(info->CanRender(&feature_info)); EXPECT_FALSE(manager.HaveUnrenderableTextures()); manager.Destroy(false); } @@ -333,90 +351,90 @@ TEST_F(TextureInfoTest, POTCubeMap) { manager_.SetInfoTarget(info_, GL_TEXTURE_CUBE_MAP); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP), info_->target()); // Check Setting level 0 each face to POT - manager_.SetLevelInfo(info_, + manager_.SetLevelInfo(&feature_info_, info_, GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE); EXPECT_FALSE(info_->npot()); EXPECT_FALSE(info_->texture_complete()); EXPECT_FALSE(info_->cube_complete()); - EXPECT_FALSE(info_->CanGenerateMipmaps(&manager_)); - EXPECT_FALSE(info_->CanRender(&manager_)); + EXPECT_FALSE(info_->CanGenerateMipmaps(&feature_info_)); + EXPECT_FALSE(info_->CanRender(&feature_info_)); EXPECT_TRUE(manager_.HaveUnrenderableTextures()); - manager_.SetLevelInfo(info_, + manager_.SetLevelInfo(&feature_info_, info_, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE); EXPECT_FALSE(info_->npot()); EXPECT_FALSE(info_->texture_complete()); EXPECT_FALSE(info_->cube_complete()); - EXPECT_FALSE(info_->CanGenerateMipmaps(&manager_)); - EXPECT_FALSE(info_->CanRender(&manager_)); + EXPECT_FALSE(info_->CanGenerateMipmaps(&feature_info_)); + EXPECT_FALSE(info_->CanRender(&feature_info_)); EXPECT_TRUE(manager_.HaveUnrenderableTextures()); - manager_.SetLevelInfo(info_, + manager_.SetLevelInfo(&feature_info_, info_, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE); EXPECT_FALSE(info_->npot()); EXPECT_FALSE(info_->texture_complete()); EXPECT_FALSE(info_->cube_complete()); - EXPECT_FALSE(info_->CanGenerateMipmaps(&manager_)); - EXPECT_FALSE(info_->CanRender(&manager_)); + EXPECT_FALSE(info_->CanGenerateMipmaps(&feature_info_)); + EXPECT_FALSE(info_->CanRender(&feature_info_)); EXPECT_TRUE(manager_.HaveUnrenderableTextures()); - manager_.SetLevelInfo(info_, + manager_.SetLevelInfo(&feature_info_, info_, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE); EXPECT_FALSE(info_->npot()); EXPECT_FALSE(info_->texture_complete()); EXPECT_FALSE(info_->cube_complete()); - EXPECT_FALSE(info_->CanRender(&manager_)); - EXPECT_FALSE(info_->CanGenerateMipmaps(&manager_)); + EXPECT_FALSE(info_->CanRender(&feature_info_)); + EXPECT_FALSE(info_->CanGenerateMipmaps(&feature_info_)); EXPECT_TRUE(manager_.HaveUnrenderableTextures()); - manager_.SetLevelInfo(info_, + manager_.SetLevelInfo(&feature_info_, info_, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE); EXPECT_FALSE(info_->npot()); EXPECT_FALSE(info_->texture_complete()); EXPECT_FALSE(info_->cube_complete()); - EXPECT_FALSE(info_->CanGenerateMipmaps(&manager_)); - EXPECT_FALSE(info_->CanRender(&manager_)); + EXPECT_FALSE(info_->CanGenerateMipmaps(&feature_info_)); + EXPECT_FALSE(info_->CanRender(&feature_info_)); EXPECT_TRUE(manager_.HaveUnrenderableTextures()); - manager_.SetLevelInfo(info_, + manager_.SetLevelInfo(&feature_info_, info_, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE); EXPECT_FALSE(info_->npot()); EXPECT_FALSE(info_->texture_complete()); EXPECT_TRUE(info_->cube_complete()); - EXPECT_TRUE(info_->CanGenerateMipmaps(&manager_)); - EXPECT_FALSE(info_->CanRender(&manager_)); + EXPECT_TRUE(info_->CanGenerateMipmaps(&feature_info_)); + EXPECT_FALSE(info_->CanRender(&feature_info_)); EXPECT_TRUE(manager_.HaveUnrenderableTextures()); // Make mips. - EXPECT_TRUE(manager_.MarkMipmapsGenerated(info_)); + EXPECT_TRUE(manager_.MarkMipmapsGenerated(&feature_info_, info_)); EXPECT_TRUE(info_->texture_complete()); EXPECT_TRUE(info_->cube_complete()); - EXPECT_TRUE(info_->CanRender(&manager_)); + EXPECT_TRUE(info_->CanRender(&feature_info_)); EXPECT_FALSE(manager_.HaveUnrenderableTextures()); // Change a mip. - manager_.SetLevelInfo(info_, + manager_.SetLevelInfo(&feature_info_, info_, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 1, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE); EXPECT_FALSE(info_->npot()); EXPECT_FALSE(info_->texture_complete()); EXPECT_TRUE(info_->cube_complete()); - EXPECT_TRUE(info_->CanGenerateMipmaps(&manager_)); + EXPECT_TRUE(info_->CanGenerateMipmaps(&feature_info_)); // Set a level past the number of mips that would get generated. - manager_.SetLevelInfo(info_, + manager_.SetLevelInfo(&feature_info_, info_, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 3, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE); - EXPECT_TRUE(info_->CanGenerateMipmaps(&manager_)); + EXPECT_TRUE(info_->CanGenerateMipmaps(&feature_info_)); // Make mips. - EXPECT_TRUE(manager_.MarkMipmapsGenerated(info_)); + EXPECT_TRUE(manager_.MarkMipmapsGenerated(&feature_info_, info_)); EXPECT_FALSE(info_->texture_complete()); EXPECT_TRUE(info_->cube_complete()); } TEST_F(TextureInfoTest, GetLevelSize) { manager_.SetInfoTarget(info_, GL_TEXTURE_2D); - manager_.SetLevelInfo(info_, + manager_.SetLevelInfo(&feature_info_, info_, GL_TEXTURE_2D, 1, GL_RGBA, 4, 5, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE); GLsizei width = -1; GLsizei height = -1; @@ -428,13 +446,13 @@ TEST_F(TextureInfoTest, GetLevelSize) { EXPECT_TRUE(info_->GetLevelSize(GL_TEXTURE_2D, 1, &width, &height)); EXPECT_EQ(4, width); EXPECT_EQ(5, height); - manager_.RemoveTextureInfo(kClient1Id); + manager_.RemoveTextureInfo(&feature_info_, kClient1Id); EXPECT_FALSE(info_->GetLevelSize(GL_TEXTURE_2D, 1, &width, &height)); } TEST_F(TextureInfoTest, GetLevelType) { manager_.SetInfoTarget(info_, GL_TEXTURE_2D); - manager_.SetLevelInfo(info_, + manager_.SetLevelInfo(&feature_info_, info_, GL_TEXTURE_2D, 1, GL_RGBA, 4, 5, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE); GLenum type = -1; GLenum format = -1; @@ -446,13 +464,13 @@ TEST_F(TextureInfoTest, GetLevelType) { EXPECT_TRUE(info_->GetLevelType(GL_TEXTURE_2D, 1, &type, &format)); EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type); EXPECT_EQ(static_cast<GLenum>(GL_RGBA), format); - manager_.RemoveTextureInfo(kClient1Id); + manager_.RemoveTextureInfo(&feature_info_, kClient1Id); EXPECT_FALSE(info_->GetLevelType(GL_TEXTURE_2D, 1, &type, &format)); } TEST_F(TextureInfoTest, ValidForTexture) { manager_.SetInfoTarget(info_, GL_TEXTURE_2D); - manager_.SetLevelInfo(info_, + manager_.SetLevelInfo(&feature_info_, info_, GL_TEXTURE_2D, 1, GL_RGBA, 4, 5, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE); // Check bad face. EXPECT_FALSE(info_->ValidForTexture( @@ -491,70 +509,84 @@ TEST_F(TextureInfoTest, ValidForTexture) { // Check valid particial size. EXPECT_TRUE(info_->ValidForTexture( GL_TEXTURE_2D, 1, 1, 1, 2, 3, GL_RGBA, GL_UNSIGNED_BYTE)); - manager_.RemoveTextureInfo(kClient1Id); + manager_.RemoveTextureInfo(&feature_info_, kClient1Id); EXPECT_FALSE(info_->ValidForTexture( GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE)); } TEST_F(TextureInfoTest, FloatNotLinear) { - TextureManager manager( - false, false, false, kMaxTextureSize, kMaxCubeMapTextureSize); - manager.CreateTextureInfo(kClient1Id, kService1Id); + TextureManager manager(kMaxTextureSize, kMaxCubeMapTextureSize); + TestHelper::SetupFeatureInfoInitExpectations( + gl_.get(), "GL_OES_texture_float"); + FeatureInfo feature_info; + feature_info.Initialize(NULL); + manager.CreateTextureInfo(&feature_info, kClient1Id, kService1Id); TextureManager::TextureInfo* info = manager_.GetTextureInfo(kClient1Id); - ASSERT_TRUE(info_ != NULL); + ASSERT_TRUE(info != NULL); manager.SetInfoTarget(info, GL_TEXTURE_2D); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), info->target()); - manager.SetLevelInfo(info, + manager.SetLevelInfo(&feature_info, info, GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_FLOAT); EXPECT_FALSE(info->texture_complete()); - manager.SetParameter(info, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + manager.SetParameter(&feature_info, info, GL_TEXTURE_MAG_FILTER, GL_NEAREST); EXPECT_FALSE(info->texture_complete()); - manager.SetParameter(info, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + manager.SetParameter( + &feature_info, info, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); EXPECT_TRUE(info->texture_complete()); manager.Destroy(false); } TEST_F(TextureInfoTest, FloatLinear) { - TextureManager manager( - false, true, false, kMaxTextureSize, kMaxCubeMapTextureSize); - manager.CreateTextureInfo(kClient1Id, kService1Id); + TextureManager manager(kMaxTextureSize, kMaxCubeMapTextureSize); + TestHelper::SetupFeatureInfoInitExpectations( + gl_.get(), "GL_OES_texture_float GL_OES_texture_float_linear"); + FeatureInfo feature_info; + feature_info.Initialize(NULL); + manager.CreateTextureInfo(&feature_info, kClient1Id, kService1Id); TextureManager::TextureInfo* info = manager_.GetTextureInfo(kClient1Id); - ASSERT_TRUE(info_ != NULL); + ASSERT_TRUE(info != NULL); manager.SetInfoTarget(info, GL_TEXTURE_2D); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), info->target()); - manager.SetLevelInfo(info, + manager.SetLevelInfo(&feature_info, info, GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_FLOAT); EXPECT_TRUE(info->texture_complete()); manager.Destroy(false); } TEST_F(TextureInfoTest, HalfFloatNotLinear) { - TextureManager manager( - false, false, false, kMaxTextureSize, kMaxCubeMapTextureSize); - manager.CreateTextureInfo(kClient1Id, kService1Id); + TextureManager manager(kMaxTextureSize, kMaxCubeMapTextureSize); + TestHelper::SetupFeatureInfoInitExpectations( + gl_.get(), "GL_OES_texture_half_float"); + FeatureInfo feature_info; + feature_info.Initialize(NULL); + manager.CreateTextureInfo(&feature_info, kClient1Id, kService1Id); TextureManager::TextureInfo* info = manager_.GetTextureInfo(kClient1Id); - ASSERT_TRUE(info_ != NULL); + ASSERT_TRUE(info != NULL); manager.SetInfoTarget(info, GL_TEXTURE_2D); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), info->target()); - manager.SetLevelInfo(info, + manager.SetLevelInfo(&feature_info, info, GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_HALF_FLOAT_OES); EXPECT_FALSE(info->texture_complete()); - manager.SetParameter(info, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + manager.SetParameter(&feature_info, info, GL_TEXTURE_MAG_FILTER, GL_NEAREST); EXPECT_FALSE(info->texture_complete()); - manager.SetParameter(info, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + manager.SetParameter( + &feature_info, info, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); EXPECT_TRUE(info->texture_complete()); manager.Destroy(false); } TEST_F(TextureInfoTest, HalfFloatLinear) { - TextureManager manager( - false, false, true, kMaxTextureSize, kMaxCubeMapTextureSize); - manager.CreateTextureInfo(kClient1Id, kService1Id); + TextureManager manager(kMaxTextureSize, kMaxCubeMapTextureSize); + TestHelper::SetupFeatureInfoInitExpectations( + gl_.get(), "GL_OES_texture_half_float GL_OES_texture_half_float_linear"); + FeatureInfo feature_info; + feature_info.Initialize(NULL); + manager.CreateTextureInfo(&feature_info, kClient1Id, kService1Id); TextureManager::TextureInfo* info = manager_.GetTextureInfo(kClient1Id); - ASSERT_TRUE(info_ != NULL); + ASSERT_TRUE(info != NULL); manager.SetInfoTarget(info, GL_TEXTURE_2D); EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), info->target()); - manager.SetLevelInfo(info, + manager.SetLevelInfo(&feature_info, info, GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_HALF_FLOAT_OES); EXPECT_TRUE(info->texture_complete()); manager.Destroy(false); diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp index 8b6622a..6f1b4d7 100644 --- a/gpu/gpu.gyp +++ b/gpu/gpu.gyp @@ -149,6 +149,8 @@ 'command_buffer/service/common_decoder.h', 'command_buffer/service/context_group.h', 'command_buffer/service/context_group.cc', + 'command_buffer/service/feature_info.h', + 'command_buffer/service/feature_info.cc', 'command_buffer/service/gles2_cmd_decoder.h', 'command_buffer/service/gles2_cmd_decoder_autogen.h', 'command_buffer/service/gles2_cmd_decoder.cc', @@ -246,6 +248,7 @@ 'command_buffer/service/cmd_parser_test.cc', 'command_buffer/service/cmd_parser_test.cc', 'command_buffer/service/common_decoder_unittest.cc', + 'command_buffer/service/feature_info_unittest.cc', 'command_buffer/service/framebuffer_manager_unittest.cc', 'command_buffer/service/gpu_processor_unittest.cc', 'command_buffer/service/gles2_cmd_decoder_unittest_base.h', |