diff options
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', |