// Copyright (c) 2012 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/texture_manager.h" #include #include "base/command_line.h" #include "base/memory/scoped_ptr.h" #include "gpu/command_buffer/service/error_state_mock.h" #include "gpu/command_buffer/service/feature_info.h" #include "gpu/command_buffer/service/framebuffer_manager.h" #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" #include "gpu/command_buffer/service/gpu_service_test.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/memory_tracking.h" #include "gpu/command_buffer/service/mocks.h" #include "gpu/command_buffer/service/test_helper.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gl/gl_image_stub.h" #include "ui/gl/gl_mock.h" #include "ui/gl/gl_switches.h" using ::testing::AtLeast; using ::testing::Pointee; using ::testing::Return; using ::testing::SetArgPointee; using ::testing::StrictMock; using ::testing::_; namespace gpu { namespace gles2 { class TextureTestHelper { public: static bool IsNPOT(const Texture* texture) { return texture->npot(); } static bool IsTextureComplete(const Texture* texture) { return texture->texture_complete(); } static bool IsCubeComplete(const Texture* texture) { return texture->cube_complete(); } }; class TextureManagerTest : public GpuServiceTest { public: static const GLint kMaxTextureSize = 16; static const GLint kMaxCubeMapTextureSize = 8; static const GLint kMaxRectangleTextureSize = 16; static const GLint kMaxExternalTextureSize = 16; static const GLint kMax3DTextureSize = 256; static const GLint kMax2dLevels = 5; static const GLint kMaxCubeMapLevels = 4; static const GLint kMaxExternalLevels = 1; static const bool kUseDefaultTextures = false; TextureManagerTest() { // Always run with this command line, but the ES3 features are not // enabled without FeatureInfo::EnableES3Validators(). base::CommandLine command_line(0, nullptr); command_line.AppendSwitch(switches::kEnableUnsafeES3APIs); feature_info_ = new FeatureInfo(command_line); } ~TextureManagerTest() override {} protected: void SetUp() override { GpuServiceTest::SetUp(); manager_.reset(new TextureManager(NULL, feature_info_.get(), kMaxTextureSize, kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, kUseDefaultTextures)); TestHelper::SetupTextureManagerInitExpectations( gl_.get(), false, "", kUseDefaultTextures); manager_->Initialize(); error_state_.reset(new ::testing::StrictMock()); } void TearDown() override { manager_->Destroy(false); manager_.reset(); GpuServiceTest::TearDown(); } void SetParameter( TextureRef* texture_ref, GLenum pname, GLint value, GLenum error) { TestHelper::SetTexParameteriWithExpectations( gl_.get(), error_state_.get(), manager_.get(), texture_ref, pname, value, error); } void SetupFeatureInfo(const char* gl_extensions, const char* gl_version, bool enable_es3) { TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion( gl_.get(), gl_extensions, "", gl_version); feature_info_->InitializeForTesting(); if (enable_es3) { EXPECT_CALL(*gl_, GetIntegerv(GL_MAX_COLOR_ATTACHMENTS, _)) .WillOnce(SetArgPointee<1>(8)) .RetiresOnSaturation(); EXPECT_CALL(*gl_, GetIntegerv(GL_MAX_DRAW_BUFFERS, _)) .WillOnce(SetArgPointee<1>(8)) .RetiresOnSaturation(); feature_info_->EnableES3Validators(); } } scoped_refptr feature_info_; scoped_ptr manager_; scoped_ptr error_state_; }; // GCC requires these declarations, but MSVC requires they not be present #ifndef COMPILER_MSVC const GLint TextureManagerTest::kMaxTextureSize; const GLint TextureManagerTest::kMaxCubeMapTextureSize; const GLint TextureManagerTest::kMaxRectangleTextureSize; const GLint TextureManagerTest::kMaxExternalTextureSize; const GLint TextureManagerTest::kMax2dLevels; const GLint TextureManagerTest::kMaxCubeMapLevels; const GLint TextureManagerTest::kMaxExternalLevels; #endif TEST_F(TextureManagerTest, Basic) { const GLuint kClient1Id = 1; const GLuint kService1Id = 11; const GLuint kClient2Id = 2; EXPECT_FALSE(manager_->HaveUnrenderableTextures()); EXPECT_FALSE(manager_->HaveUnsafeTextures()); EXPECT_FALSE(manager_->HaveUnclearedMips()); // Check we can create texture. manager_->CreateTexture(kClient1Id, kService1Id); // Check texture got created. scoped_refptr texture = manager_->GetTexture(kClient1Id); ASSERT_TRUE(texture.get() != NULL); EXPECT_EQ(kService1Id, texture->service_id()); EXPECT_EQ(kClient1Id, texture->client_id()); EXPECT_EQ(texture->texture(), manager_->GetTextureForServiceId( texture->service_id())); // Check we get nothing for a non-existent texture. EXPECT_TRUE(manager_->GetTexture(kClient2Id) == NULL); // Check trying to a remove non-existent textures does not crash. manager_->RemoveTexture(kClient2Id); // Check that it gets deleted when the last reference is released. EXPECT_CALL(*gl_, DeleteTextures(1, ::testing::Pointee(kService1Id))) .Times(1) .RetiresOnSaturation(); // Check we can't get the texture after we remove it. manager_->RemoveTexture(kClient1Id); EXPECT_TRUE(manager_->GetTexture(kClient1Id) == NULL); EXPECT_EQ(0u, texture->client_id()); } TEST_F(TextureManagerTest, SetParameter) { const GLuint kClient1Id = 1; const GLuint kService1Id = 11; // Check we can create texture. manager_->CreateTexture(kClient1Id, kService1Id); // Check texture got created. TextureRef* texture_ref = manager_->GetTexture(kClient1Id); ASSERT_TRUE(texture_ref != NULL); Texture* texture = texture_ref->texture(); manager_->SetTarget(texture_ref, GL_TEXTURE_2D); SetParameter(texture_ref, GL_TEXTURE_MIN_FILTER, GL_NEAREST, GL_NO_ERROR); EXPECT_EQ(static_cast(GL_NEAREST), texture->min_filter()); SetParameter(texture_ref, GL_TEXTURE_MAG_FILTER, GL_NEAREST, GL_NO_ERROR); EXPECT_EQ(static_cast(GL_NEAREST), texture->mag_filter()); SetParameter(texture_ref, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE, GL_NO_ERROR); EXPECT_EQ(static_cast(GL_CLAMP_TO_EDGE), texture->wrap_s()); SetParameter(texture_ref, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE, GL_NO_ERROR); EXPECT_EQ(static_cast(GL_CLAMP_TO_EDGE), texture->wrap_t()); SetParameter(texture_ref, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1, GL_NO_ERROR); SetParameter(texture_ref, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2, GL_NO_ERROR); SetParameter( texture_ref, GL_TEXTURE_MIN_FILTER, GL_CLAMP_TO_EDGE, GL_INVALID_ENUM); EXPECT_EQ(static_cast(GL_NEAREST), texture->min_filter()); SetParameter( texture_ref, GL_TEXTURE_MAG_FILTER, GL_CLAMP_TO_EDGE, GL_INVALID_ENUM); EXPECT_EQ(static_cast(GL_NEAREST), texture->min_filter()); SetParameter(texture_ref, GL_TEXTURE_WRAP_S, GL_NEAREST, GL_INVALID_ENUM); EXPECT_EQ(static_cast(GL_CLAMP_TO_EDGE), texture->wrap_s()); SetParameter(texture_ref, GL_TEXTURE_WRAP_T, GL_NEAREST, GL_INVALID_ENUM); EXPECT_EQ(static_cast(GL_CLAMP_TO_EDGE), texture->wrap_t()); SetParameter(texture_ref, GL_TEXTURE_MAX_ANISOTROPY_EXT, 0, GL_INVALID_VALUE); } TEST_F(TextureManagerTest, UseDefaultTexturesTrue) { bool use_default_textures = true; TestHelper::SetupTextureManagerInitExpectations(gl_.get(), false, "GL_ANGLE_texture_usage", use_default_textures); TextureManager manager(NULL, feature_info_.get(), kMaxTextureSize, kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, use_default_textures); manager.Initialize(); EXPECT_TRUE(manager.GetDefaultTextureInfo(GL_TEXTURE_2D) != NULL); EXPECT_TRUE(manager.GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP) != NULL); // TODO(vmiura): Test GL_TEXTURE_EXTERNAL_OES & GL_TEXTURE_RECTANGLE_ARB. manager.Destroy(false); } TEST_F(TextureManagerTest, UseDefaultTexturesFalse) { bool use_default_textures = false; TestHelper::SetupTextureManagerInitExpectations(gl_.get(), false, "GL_ANGLE_texture_usage", use_default_textures); TextureManager manager(NULL, feature_info_.get(), kMaxTextureSize, kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, use_default_textures); manager.Initialize(); EXPECT_TRUE(manager.GetDefaultTextureInfo(GL_TEXTURE_2D) == NULL); EXPECT_TRUE(manager.GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP) == NULL); // TODO(vmiura): Test GL_TEXTURE_EXTERNAL_OES & GL_TEXTURE_RECTANGLE_ARB. manager.Destroy(false); } TEST_F(TextureManagerTest, UseDefaultTexturesTrueES3) { bool use_default_textures = true; SetupFeatureInfo("", "OpenGL ES 3.0", true); TestHelper::SetupTextureManagerInitExpectations(gl_.get(), true, "", use_default_textures); TextureManager manager(NULL, feature_info_.get(), kMaxTextureSize, kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, use_default_textures); manager.Initialize(); EXPECT_TRUE(manager.GetDefaultTextureInfo(GL_TEXTURE_3D) != NULL); EXPECT_TRUE(manager.GetDefaultTextureInfo(GL_TEXTURE_2D_ARRAY) != NULL); manager.Destroy(false); } TEST_F(TextureManagerTest, UseDefaultTexturesFalseES3) { bool use_default_textures = false; SetupFeatureInfo("", "OpenGL ES 3.0", true); TestHelper::SetupTextureManagerInitExpectations(gl_.get(), true, "", use_default_textures); TextureManager manager(NULL, feature_info_.get(), kMaxTextureSize, kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, use_default_textures); manager.Initialize(); EXPECT_TRUE(manager.GetDefaultTextureInfo(GL_TEXTURE_3D) == NULL); EXPECT_TRUE(manager.GetDefaultTextureInfo(GL_TEXTURE_2D_ARRAY) == NULL); manager.Destroy(false); } TEST_F(TextureManagerTest, TextureUsageExt) { TestHelper::SetupTextureManagerInitExpectations( gl_.get(), false, "GL_ANGLE_texture_usage", kUseDefaultTextures); TextureManager manager(NULL, feature_info_.get(), kMaxTextureSize, kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, kUseDefaultTextures); manager.Initialize(); const GLuint kClient1Id = 1; const GLuint kService1Id = 11; // Check we can create texture. manager.CreateTexture(kClient1Id, kService1Id); // Check texture got created. TextureRef* texture_ref = manager.GetTexture(kClient1Id); ASSERT_TRUE(texture_ref != NULL); TestHelper::SetTexParameteriWithExpectations( gl_.get(), error_state_.get(), &manager, texture_ref, GL_TEXTURE_USAGE_ANGLE, GL_FRAMEBUFFER_ATTACHMENT_ANGLE, GL_NO_ERROR); EXPECT_EQ(static_cast(GL_FRAMEBUFFER_ATTACHMENT_ANGLE), texture_ref->texture()->usage()); manager.Destroy(false); } TEST_F(TextureManagerTest, Destroy) { const GLuint kClient1Id = 1; const GLuint kService1Id = 11; TestHelper::SetupTextureManagerInitExpectations( gl_.get(), false, "", kUseDefaultTextures); TextureManager manager(NULL, feature_info_.get(), kMaxTextureSize, kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, kUseDefaultTextures); manager.Initialize(); // Check we can create texture. manager.CreateTexture(kClient1Id, kService1Id); // Check texture got created. TextureRef* texture = manager.GetTexture(kClient1Id); ASSERT_TRUE(texture != NULL); EXPECT_CALL(*gl_, DeleteTextures(1, ::testing::Pointee(kService1Id))) .Times(1) .RetiresOnSaturation(); TestHelper::SetupTextureManagerDestructionExpectations( gl_.get(), false, "", kUseDefaultTextures); manager.Destroy(true); // Check that resources got freed. texture = manager.GetTexture(kClient1Id); ASSERT_TRUE(texture == NULL); } TEST_F(TextureManagerTest, MaxValues) { // Check we get the right values for the max sizes. EXPECT_EQ(kMax2dLevels, manager_->MaxLevelsForTarget(GL_TEXTURE_2D)); EXPECT_EQ(kMaxCubeMapLevels, manager_->MaxLevelsForTarget(GL_TEXTURE_CUBE_MAP)); EXPECT_EQ(kMaxCubeMapLevels, manager_->MaxLevelsForTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X)); EXPECT_EQ(kMaxCubeMapLevels, manager_->MaxLevelsForTarget(GL_TEXTURE_CUBE_MAP_NEGATIVE_X)); EXPECT_EQ(kMaxCubeMapLevels, manager_->MaxLevelsForTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_Y)); EXPECT_EQ(kMaxCubeMapLevels, manager_->MaxLevelsForTarget(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y)); EXPECT_EQ(kMaxCubeMapLevels, manager_->MaxLevelsForTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_Z)); EXPECT_EQ(kMaxCubeMapLevels, manager_->MaxLevelsForTarget(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)); EXPECT_EQ(kMaxExternalLevels, manager_->MaxLevelsForTarget(GL_TEXTURE_EXTERNAL_OES)); EXPECT_EQ(kMaxTextureSize, manager_->MaxSizeForTarget(GL_TEXTURE_2D)); EXPECT_EQ(kMaxCubeMapTextureSize, manager_->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP)); EXPECT_EQ(kMaxCubeMapTextureSize, manager_->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X)); EXPECT_EQ(kMaxCubeMapTextureSize, manager_->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP_NEGATIVE_X)); EXPECT_EQ(kMaxCubeMapTextureSize, manager_->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_Y)); EXPECT_EQ(kMaxCubeMapTextureSize, manager_->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y)); EXPECT_EQ(kMaxCubeMapTextureSize, manager_->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_Z)); EXPECT_EQ(kMaxCubeMapTextureSize, manager_->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)); EXPECT_EQ(kMaxRectangleTextureSize, manager_->MaxSizeForTarget(GL_TEXTURE_RECTANGLE_ARB)); EXPECT_EQ(kMaxExternalTextureSize, manager_->MaxSizeForTarget(GL_TEXTURE_EXTERNAL_OES)); } TEST_F(TextureManagerTest, ValidForTarget) { // check 2d EXPECT_TRUE(manager_->ValidForTarget( GL_TEXTURE_2D, 0, kMaxTextureSize, kMaxTextureSize, 1)); EXPECT_TRUE(manager_->ValidForTarget( GL_TEXTURE_2D, kMax2dLevels - 1, 1, 1, 1)); EXPECT_FALSE(manager_->ValidForTarget( GL_TEXTURE_2D, kMax2dLevels - 1, 1, 2, 1)); EXPECT_FALSE(manager_->ValidForTarget( GL_TEXTURE_2D, kMax2dLevels - 1, 2, 1, 1)); // check level out of range. EXPECT_FALSE(manager_->ValidForTarget( GL_TEXTURE_2D, kMax2dLevels, kMaxTextureSize, 1, 1)); // check has depth. EXPECT_FALSE(manager_->ValidForTarget( GL_TEXTURE_2D, kMax2dLevels, kMaxTextureSize, 1, 2)); // Check NPOT width on level 0 EXPECT_TRUE(manager_->ValidForTarget(GL_TEXTURE_2D, 0, 5, 2, 1)); // Check NPOT height on level 0 EXPECT_TRUE(manager_->ValidForTarget(GL_TEXTURE_2D, 0, 2, 5, 1)); // Check NPOT width on level 1 EXPECT_FALSE(manager_->ValidForTarget(GL_TEXTURE_2D, 1, 5, 2, 1)); // Check NPOT height on level 1 EXPECT_FALSE(manager_->ValidForTarget(GL_TEXTURE_2D, 1, 2, 5, 1)); // check cube EXPECT_TRUE(manager_->ValidForTarget( GL_TEXTURE_CUBE_MAP, 0, kMaxCubeMapTextureSize, kMaxCubeMapTextureSize, 1)); EXPECT_TRUE(manager_->ValidForTarget( GL_TEXTURE_CUBE_MAP, kMaxCubeMapLevels - 1, 1, 1, 1)); EXPECT_FALSE(manager_->ValidForTarget( GL_TEXTURE_CUBE_MAP, kMaxCubeMapLevels - 1, 2, 2, 1)); // check level out of range. EXPECT_FALSE(manager_->ValidForTarget( GL_TEXTURE_CUBE_MAP, kMaxCubeMapLevels, kMaxCubeMapTextureSize, 1, 1)); // check not square. EXPECT_FALSE(manager_->ValidForTarget( GL_TEXTURE_CUBE_MAP, kMaxCubeMapLevels, kMaxCubeMapTextureSize, 1, 1)); // check has depth. EXPECT_FALSE(manager_->ValidForTarget( GL_TEXTURE_CUBE_MAP, kMaxCubeMapLevels, kMaxCubeMapTextureSize, 1, 2)); for (GLint level = 0; level < kMax2dLevels; ++level) { EXPECT_TRUE(manager_->ValidForTarget( GL_TEXTURE_2D, level, kMaxTextureSize >> level, 1, 1)); EXPECT_TRUE(manager_->ValidForTarget( GL_TEXTURE_2D, level, 1, kMaxTextureSize >> level, 1)); EXPECT_FALSE(manager_->ValidForTarget( GL_TEXTURE_2D, level, (kMaxTextureSize >> level) + 1, 1, 1)); EXPECT_FALSE(manager_->ValidForTarget( GL_TEXTURE_2D, level, 1, (kMaxTextureSize >> level) + 1, 1)); } for (GLint level = 0; level < kMaxCubeMapLevels; ++level) { EXPECT_TRUE(manager_->ValidForTarget( GL_TEXTURE_CUBE_MAP, level, kMaxCubeMapTextureSize >> level, kMaxCubeMapTextureSize >> level, 1)); EXPECT_FALSE(manager_->ValidForTarget( GL_TEXTURE_CUBE_MAP, level, (kMaxCubeMapTextureSize >> level) * 2, (kMaxCubeMapTextureSize >> level) * 2, 1)); } } TEST_F(TextureManagerTest, ValidForTargetNPOT) { TestHelper::SetupFeatureInfoInitExpectations( gl_.get(), "GL_OES_texture_npot"); scoped_refptr feature_info(new FeatureInfo()); feature_info->InitializeForTesting(); TextureManager manager(NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, kUseDefaultTextures); // Check NPOT width on level 0 EXPECT_TRUE(manager.ValidForTarget(GL_TEXTURE_2D, 0, 5, 2, 1)); // Check NPOT height on level 0 EXPECT_TRUE(manager.ValidForTarget(GL_TEXTURE_2D, 0, 2, 5, 1)); // Check NPOT width on level 1 EXPECT_TRUE(manager.ValidForTarget(GL_TEXTURE_2D, 1, 5, 2, 1)); // Check NPOT height on level 1 EXPECT_TRUE(manager.ValidForTarget(GL_TEXTURE_2D, 1, 2, 5, 1)); manager.Destroy(false); } class TextureTestBase : public GpuServiceTest { public: static const GLint kMaxTextureSize = 16; static const GLint kMaxCubeMapTextureSize = 8; static const GLint kMaxRectangleTextureSize = 16; static const GLint kMax3DTextureSize = 256; static const GLint kMax2dLevels = 5; static const GLint kMaxCubeMapLevels = 4; static const GLuint kClient1Id = 1; static const GLuint kService1Id = 11; static const bool kUseDefaultTextures = false; TextureTestBase() : feature_info_(new FeatureInfo()) { } ~TextureTestBase() override { texture_ref_ = NULL; } protected: void SetUpBase(MemoryTracker* memory_tracker, const std::string& extensions) { GpuServiceTest::SetUp(); if (!extensions.empty()) { TestHelper::SetupFeatureInfoInitExpectations(gl_.get(), extensions.c_str()); feature_info_->InitializeForTesting(); } manager_.reset(new TextureManager(memory_tracker, feature_info_.get(), kMaxTextureSize, kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, kUseDefaultTextures)); decoder_.reset(new ::testing::StrictMock()); error_state_.reset(new ::testing::StrictMock()); manager_->CreateTexture(kClient1Id, kService1Id); texture_ref_ = manager_->GetTexture(kClient1Id); ASSERT_TRUE(texture_ref_.get() != NULL); } void TearDown() override { if (texture_ref_.get()) { // If it's not in the manager then setting texture_ref_ to NULL will // delete the texture. if (!texture_ref_->client_id()) { // Check that it gets deleted when the last reference is released. EXPECT_CALL(*gl_, DeleteTextures(1, ::testing::Pointee(texture_ref_->service_id()))) .Times(1) .RetiresOnSaturation(); } texture_ref_ = NULL; } manager_->Destroy(false); manager_.reset(); GpuServiceTest::TearDown(); } void SetParameter( TextureRef* texture_ref, GLenum pname, GLint value, GLenum error) { TestHelper::SetTexParameteriWithExpectations( gl_.get(), error_state_.get(), manager_.get(), texture_ref, pname, value, error); } scoped_ptr decoder_; scoped_ptr error_state_; scoped_refptr feature_info_; scoped_ptr manager_; scoped_refptr texture_ref_; }; class TextureTest : public TextureTestBase { protected: void SetUp() override { SetUpBase(NULL, std::string()); } }; class TextureMemoryTrackerTest : public TextureTestBase { protected: void SetUp() override { mock_memory_tracker_ = new StrictMock(); SetUpBase(mock_memory_tracker_.get(), std::string()); } scoped_refptr mock_memory_tracker_; }; #define EXPECT_MEMORY_ALLOCATION_CHANGE(old_size, new_size) \ EXPECT_CALL(*mock_memory_tracker_.get(), \ TrackMemoryAllocatedChange(old_size, new_size)) \ .Times(1).RetiresOnSaturation() TEST_F(TextureTest, Basic) { Texture* texture = texture_ref_->texture(); EXPECT_EQ(0u, texture->target()); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture)); EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_.get())); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_EQ(0, texture->num_uncleared_mips()); EXPECT_TRUE(manager_->CanRender(texture_ref_.get())); EXPECT_TRUE(texture->SafeToRenderFrom()); EXPECT_FALSE(texture->IsImmutable()); EXPECT_EQ(static_cast(GL_NEAREST_MIPMAP_LINEAR), texture->min_filter()); EXPECT_EQ(static_cast(GL_LINEAR), texture->mag_filter()); EXPECT_EQ(static_cast(GL_REPEAT), texture->wrap_s()); EXPECT_EQ(static_cast(GL_REPEAT), texture->wrap_t()); EXPECT_FALSE(manager_->HaveUnrenderableTextures()); EXPECT_FALSE(manager_->HaveUnsafeTextures()); EXPECT_EQ(0u, texture->estimated_size()); } TEST_F(TextureTest, SetTargetTexture2D) { Texture* texture = texture_ref_->texture(); manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture)); EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_.get())); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); EXPECT_TRUE(texture->SafeToRenderFrom()); EXPECT_FALSE(texture->IsImmutable()); } TEST_F(TextureTest, SetTargetTextureExternalOES) { Texture* texture = texture_ref_->texture(); manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_EXTERNAL_OES); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture)); EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_.get())); EXPECT_TRUE(TextureTestHelper::IsNPOT(texture)); EXPECT_TRUE(manager_->CanRender(texture_ref_.get())); EXPECT_TRUE(texture->SafeToRenderFrom()); EXPECT_TRUE(texture->IsImmutable()); } TEST_F(TextureTest, ZeroSizeCanNotRender) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(1, 1)); EXPECT_TRUE(manager_->CanRender(texture_ref_.get())); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); } TEST_F(TextureTest, EstimatedSize) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 8, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(8, 4)); EXPECT_EQ(8u * 4u * 4u, texture_ref_->texture()->estimated_size()); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 2, GL_RGBA, 8, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(8, 4)); EXPECT_EQ(8u * 4u * 4u * 2u, texture_ref_->texture()->estimated_size()); } TEST_F(TextureMemoryTrackerTest, EstimatedSize) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); EXPECT_MEMORY_ALLOCATION_CHANGE(0, 128); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 8, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(8, 4)); EXPECT_MEMORY_ALLOCATION_CHANGE(128, 0); EXPECT_MEMORY_ALLOCATION_CHANGE(0, 256); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 2, GL_RGBA, 8, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(8, 4)); // Add expectation for texture deletion. EXPECT_MEMORY_ALLOCATION_CHANGE(256, 0); EXPECT_MEMORY_ALLOCATION_CHANGE(0, 0); } TEST_F(TextureTest, POT2D) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); Texture* texture = texture_ref_->texture(); EXPECT_EQ(static_cast(GL_TEXTURE_2D), texture->target()); // Check Setting level 0 to POT manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); EXPECT_TRUE(texture->SafeToRenderFrom()); EXPECT_TRUE(manager_->HaveUnrenderableTextures()); // Set filters to something that will work with a single mip. SetParameter( texture_ref_.get(), GL_TEXTURE_MIN_FILTER, GL_LINEAR, GL_NO_ERROR); EXPECT_TRUE(manager_->CanRender(texture_ref_.get())); EXPECT_FALSE(manager_->HaveUnrenderableTextures()); // Set them back. SetParameter(texture_ref_.get(), GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR, GL_NO_ERROR); EXPECT_TRUE(manager_->HaveUnrenderableTextures()); EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_ref_.get())); // Make mips. EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_ref_.get())); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_TRUE(manager_->CanRender(texture_ref_.get())); EXPECT_FALSE(manager_->HaveUnrenderableTextures()); // Change a mip. manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_ref_.get())); EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); EXPECT_TRUE(manager_->HaveUnrenderableTextures()); // Set a level past the number of mips that would get generated. manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 3, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_ref_.get())); // Make mips. EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_ref_.get())); EXPECT_TRUE(manager_->CanRender(texture_ref_.get())); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_FALSE(manager_->HaveUnrenderableTextures()); } TEST_F(TextureMemoryTrackerTest, MarkMipmapsGenerated) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); EXPECT_MEMORY_ALLOCATION_CHANGE(0, 64); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); EXPECT_MEMORY_ALLOCATION_CHANGE(64, 0); EXPECT_MEMORY_ALLOCATION_CHANGE(0, 84); EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_ref_.get())); EXPECT_MEMORY_ALLOCATION_CHANGE(84, 0); EXPECT_MEMORY_ALLOCATION_CHANGE(0, 0); } TEST_F(TextureTest, UnusedMips) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); Texture* texture = texture_ref_->texture(); EXPECT_EQ(static_cast(GL_TEXTURE_2D), texture->target()); // Set level zero to large size. manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_ref_.get())); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_TRUE(manager_->CanRender(texture_ref_.get())); EXPECT_FALSE(manager_->HaveUnrenderableTextures()); // Set level zero to large smaller (levels unused mips) manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(2, 2)); EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_ref_.get())); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_TRUE(manager_->CanRender(texture_ref_.get())); EXPECT_FALSE(manager_->HaveUnrenderableTextures()); // Set an unused level to some size manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 4, GL_RGBA, 16, 16, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(16, 16)); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_TRUE(manager_->CanRender(texture_ref_.get())); EXPECT_FALSE(manager_->HaveUnrenderableTextures()); } TEST_F(TextureTest, NPOT2D) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); Texture* texture = texture_ref_->texture(); EXPECT_EQ(static_cast(GL_TEXTURE_2D), texture->target()); // Check Setting level 0 to NPOT manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 4, 5, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 5)); EXPECT_TRUE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_.get())); EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); EXPECT_TRUE(manager_->HaveUnrenderableTextures()); SetParameter( texture_ref_.get(), GL_TEXTURE_MIN_FILTER, GL_LINEAR, GL_NO_ERROR); EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); EXPECT_TRUE(manager_->HaveUnrenderableTextures()); SetParameter( texture_ref_.get(), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE, GL_NO_ERROR); EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); EXPECT_TRUE(manager_->HaveUnrenderableTextures()); SetParameter( texture_ref_.get(), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE, GL_NO_ERROR); EXPECT_TRUE(manager_->CanRender(texture_ref_.get())); EXPECT_FALSE(manager_->HaveUnrenderableTextures()); // Change it to POT. manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_ref_.get())); EXPECT_FALSE(manager_->HaveUnrenderableTextures()); } TEST_F(TextureTest, NPOT2DNPOTOK) { TestHelper::SetupFeatureInfoInitExpectations( gl_.get(), "GL_OES_texture_npot"); scoped_refptr feature_info(new FeatureInfo()); feature_info->InitializeForTesting(); TextureManager manager(NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, kUseDefaultTextures); manager.CreateTexture(kClient1Id, kService1Id); TextureRef* texture_ref = manager.GetTexture(kClient1Id); ASSERT_TRUE(texture_ref != NULL); Texture* texture = texture_ref->texture(); manager.SetTarget(texture_ref, GL_TEXTURE_2D); EXPECT_EQ(static_cast(GL_TEXTURE_2D), texture->target()); // Check Setting level 0 to NPOT manager.SetLevelInfo(texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, 4, 5, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 5)); EXPECT_TRUE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_TRUE(manager.CanGenerateMipmaps(texture_ref)); EXPECT_FALSE(manager.CanRender(texture_ref)); EXPECT_TRUE(manager.HaveUnrenderableTextures()); EXPECT_TRUE(manager.MarkMipmapsGenerated(texture_ref)); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_TRUE(manager.CanRender(texture_ref)); EXPECT_FALSE(manager.HaveUnrenderableTextures()); manager.Destroy(false); } TEST_F(TextureTest, POTCubeMap) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_CUBE_MAP); Texture* texture = texture_ref_->texture(); EXPECT_EQ(static_cast(GL_TEXTURE_CUBE_MAP), texture->target()); // Check Setting level 0 each face to POT manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture)); EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_.get())); EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); EXPECT_TRUE(manager_->HaveUnrenderableTextures()); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture)); EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_.get())); EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); EXPECT_TRUE(manager_->HaveUnrenderableTextures()); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture)); EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_.get())); EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); EXPECT_TRUE(manager_->HaveUnrenderableTextures()); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture)); EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_.get())); EXPECT_TRUE(manager_->HaveUnrenderableTextures()); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture)); EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_.get())); EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); EXPECT_TRUE(manager_->HaveUnrenderableTextures()); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_TRUE(TextureTestHelper::IsCubeComplete(texture)); EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_ref_.get())); EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); EXPECT_TRUE(manager_->HaveUnrenderableTextures()); // Make mips. EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_ref_.get())); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_TRUE(TextureTestHelper::IsCubeComplete(texture)); EXPECT_TRUE(manager_->CanRender(texture_ref_.get())); EXPECT_FALSE(manager_->HaveUnrenderableTextures()); // Change a mip. manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 1, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_TRUE(TextureTestHelper::IsCubeComplete(texture)); EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_ref_.get())); // Set a level past the number of mips that would get generated. manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 3, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_ref_.get())); // Make mips. EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_ref_.get())); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_TRUE(TextureTestHelper::IsCubeComplete(texture)); } TEST_F(TextureTest, POTCubeMapWithoutMipmap) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_CUBE_MAP); SetParameter( texture_ref_.get(), GL_TEXTURE_MIN_FILTER, GL_NEAREST, GL_NO_ERROR); SetParameter( texture_ref_.get(), GL_TEXTURE_MAG_FILTER, GL_NEAREST, GL_NO_ERROR); SetParameter( texture_ref_.get(), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE, GL_NO_ERROR); SetParameter( texture_ref_.get(), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE, GL_NO_ERROR); Texture* texture = texture_ref_->texture(); EXPECT_EQ(static_cast(GL_TEXTURE_CUBE_MAP), texture->target()); // Check Setting level 0 each face to POT manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture)); EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_.get())); EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); EXPECT_TRUE(manager_->HaveUnrenderableTextures()); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture)); EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_.get())); EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); EXPECT_TRUE(manager_->HaveUnrenderableTextures()); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture)); EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_.get())); EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); EXPECT_TRUE(manager_->HaveUnrenderableTextures()); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture)); EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_.get())); EXPECT_TRUE(manager_->HaveUnrenderableTextures()); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_FALSE(TextureTestHelper::IsCubeComplete(texture)); EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_ref_.get())); EXPECT_FALSE(manager_->CanRender(texture_ref_.get())); EXPECT_TRUE(manager_->HaveUnrenderableTextures()); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); EXPECT_FALSE(TextureTestHelper::IsNPOT(texture)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_TRUE(TextureTestHelper::IsCubeComplete(texture)); EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_ref_.get())); EXPECT_TRUE(manager_->CanRender(texture_ref_.get())); EXPECT_FALSE(manager_->HaveUnrenderableTextures()); } TEST_F(TextureTest, GetLevelSize) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_3D); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_3D, 1, GL_RGBA, 4, 5, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 5)); GLsizei width = -1; GLsizei height = -1; GLsizei depth = -1; Texture* texture = texture_ref_->texture(); EXPECT_FALSE( texture->GetLevelSize(GL_TEXTURE_3D, -1, &width, &height, &depth)); EXPECT_FALSE( texture->GetLevelSize(GL_TEXTURE_3D, 1000, &width, &height, &depth)); EXPECT_FALSE( texture->GetLevelSize(GL_TEXTURE_3D, 0, &width, &height, &depth)); EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_3D, 1, &width, &height, &depth)); EXPECT_EQ(4, width); EXPECT_EQ(5, height); EXPECT_EQ(6, depth); manager_->RemoveTexture(kClient1Id); EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_3D, 1, &width, &height, &depth)); EXPECT_EQ(4, width); EXPECT_EQ(5, height); EXPECT_EQ(6, depth); } TEST_F(TextureTest, GetLevelType) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 4, 5, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 5)); GLenum type = 0; GLenum format = 0; Texture* texture = texture_ref_->texture(); EXPECT_FALSE(texture->GetLevelType(GL_TEXTURE_2D, -1, &type, &format)); EXPECT_FALSE(texture->GetLevelType(GL_TEXTURE_2D, 1000, &type, &format)); EXPECT_FALSE(texture->GetLevelType(GL_TEXTURE_2D, 0, &type, &format)); EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 1, &type, &format)); EXPECT_EQ(static_cast(GL_UNSIGNED_BYTE), type); EXPECT_EQ(static_cast(GL_RGBA), format); manager_->RemoveTexture(kClient1Id); EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 1, &type, &format)); EXPECT_EQ(static_cast(GL_UNSIGNED_BYTE), type); EXPECT_EQ(static_cast(GL_RGBA), format); } TEST_F(TextureTest, ValidForTexture) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 4, 5, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 5)); // Check bad face. Texture* texture = texture_ref_->texture(); EXPECT_FALSE(texture->ValidForTexture( GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 1, 0, 0, 0, 4, 5, 6)); // Check bad level. EXPECT_FALSE(texture->ValidForTexture(GL_TEXTURE_2D, 0, 0, 0, 0, 4, 5, 6)); // Check bad xoffset. EXPECT_FALSE(texture->ValidForTexture(GL_TEXTURE_2D, 1, -1, 0, 0, 4, 5, 6)); // Check bad xoffset + width > width. EXPECT_FALSE(texture->ValidForTexture(GL_TEXTURE_2D, 1, 1, 0, 0, 4, 5, 6)); // Check bad yoffset. EXPECT_FALSE(texture->ValidForTexture(GL_TEXTURE_2D, 1, 0, -1, 0, 4, 5, 6)); // Check bad yoffset + height > height. EXPECT_FALSE(texture->ValidForTexture(GL_TEXTURE_2D, 1, 0, 1, 0, 4, 5, 6)); // Check bad zoffset. EXPECT_FALSE(texture->ValidForTexture(GL_TEXTURE_2D, 1, 0, 0, -1, 4, 5, 6)); // Check bad zoffset + depth > depth. EXPECT_FALSE(texture->ValidForTexture(GL_TEXTURE_2D, 1, 0, 0, 1, 4, 5, 6)); // Check bad width. EXPECT_FALSE(texture->ValidForTexture(GL_TEXTURE_2D, 1, 0, 0, 0, 5, 5, 6)); // Check bad height. EXPECT_FALSE(texture->ValidForTexture(GL_TEXTURE_2D, 1, 0, 0, 0, 4, 6, 6)); // Check bad depth. EXPECT_FALSE(texture->ValidForTexture(GL_TEXTURE_2D, 1, 0, 0, 0, 4, 5, 7)); // Check valid full size EXPECT_TRUE(texture->ValidForTexture(GL_TEXTURE_2D, 1, 0, 0, 0, 4, 5, 6)); // Check valid particial size. EXPECT_TRUE(texture->ValidForTexture(GL_TEXTURE_2D, 1, 1, 1, 1, 2, 3, 4)); manager_->RemoveTexture(kClient1Id); EXPECT_TRUE(texture->ValidForTexture(GL_TEXTURE_2D, 1, 0, 0, 0, 4, 5, 6)); } TEST_F(TextureTest, FloatNotLinear) { TestHelper::SetupFeatureInfoInitExpectations( gl_.get(), "GL_OES_texture_float"); scoped_refptr feature_info(new FeatureInfo()); feature_info->InitializeForTesting(); TextureManager manager(NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, kUseDefaultTextures); manager.CreateTexture(kClient1Id, kService1Id); TextureRef* texture_ref = manager.GetTexture(kClient1Id); ASSERT_TRUE(texture_ref != NULL); manager.SetTarget(texture_ref, GL_TEXTURE_2D); Texture* texture = texture_ref->texture(); EXPECT_EQ(static_cast(GL_TEXTURE_2D), texture->target()); manager.SetLevelInfo(texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_FLOAT, gfx::Rect(1, 1)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); TestHelper::SetTexParameteriWithExpectations( gl_.get(), error_state_.get(), &manager, texture_ref, GL_TEXTURE_MAG_FILTER, GL_NEAREST, GL_NO_ERROR); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); TestHelper::SetTexParameteriWithExpectations( gl_.get(), error_state_.get(), &manager, texture_ref, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST, GL_NO_ERROR); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); manager.Destroy(false); } TEST_F(TextureTest, FloatLinear) { TestHelper::SetupFeatureInfoInitExpectations( gl_.get(), "GL_OES_texture_float GL_OES_texture_float_linear"); scoped_refptr feature_info(new FeatureInfo()); feature_info->InitializeForTesting(); TextureManager manager(NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, kUseDefaultTextures); manager.CreateTexture(kClient1Id, kService1Id); TextureRef* texture_ref = manager.GetTexture(kClient1Id); ASSERT_TRUE(texture_ref != NULL); manager.SetTarget(texture_ref, GL_TEXTURE_2D); Texture* texture = texture_ref->texture(); EXPECT_EQ(static_cast(GL_TEXTURE_2D), texture->target()); manager.SetLevelInfo(texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_FLOAT, gfx::Rect(1, 1)); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); manager.Destroy(false); } TEST_F(TextureTest, HalfFloatNotLinear) { TestHelper::SetupFeatureInfoInitExpectations( gl_.get(), "GL_OES_texture_half_float"); scoped_refptr feature_info(new FeatureInfo()); feature_info->InitializeForTesting(); TextureManager manager(NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, kUseDefaultTextures); manager.CreateTexture(kClient1Id, kService1Id); TextureRef* texture_ref = manager.GetTexture(kClient1Id); ASSERT_TRUE(texture_ref != NULL); manager.SetTarget(texture_ref, GL_TEXTURE_2D); Texture* texture = texture_ref->texture(); EXPECT_EQ(static_cast(GL_TEXTURE_2D), texture->target()); manager.SetLevelInfo(texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_HALF_FLOAT_OES, gfx::Rect(1, 1)); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); TestHelper::SetTexParameteriWithExpectations( gl_.get(), error_state_.get(), &manager, texture_ref, GL_TEXTURE_MAG_FILTER, GL_NEAREST, GL_NO_ERROR); EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture)); TestHelper::SetTexParameteriWithExpectations( gl_.get(), error_state_.get(), &manager, texture_ref, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST, GL_NO_ERROR); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); manager.Destroy(false); } TEST_F(TextureTest, HalfFloatLinear) { TestHelper::SetupFeatureInfoInitExpectations( gl_.get(), "GL_OES_texture_half_float GL_OES_texture_half_float_linear"); scoped_refptr feature_info(new FeatureInfo()); feature_info->InitializeForTesting(); TextureManager manager(NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, kUseDefaultTextures); manager.CreateTexture(kClient1Id, kService1Id); TextureRef* texture_ref = manager.GetTexture(kClient1Id); ASSERT_TRUE(texture_ref != NULL); manager.SetTarget(texture_ref, GL_TEXTURE_2D); Texture* texture = texture_ref->texture(); EXPECT_EQ(static_cast(GL_TEXTURE_2D), texture->target()); manager.SetLevelInfo(texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_HALF_FLOAT_OES, gfx::Rect(1, 1)); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); manager.Destroy(false); } TEST_F(TextureTest, EGLImageExternal) { TestHelper::SetupFeatureInfoInitExpectations( gl_.get(), "GL_OES_EGL_image_external"); scoped_refptr feature_info(new FeatureInfo()); feature_info->InitializeForTesting(); TextureManager manager(NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, kUseDefaultTextures); manager.CreateTexture(kClient1Id, kService1Id); TextureRef* texture_ref = manager.GetTexture(kClient1Id); ASSERT_TRUE(texture_ref != NULL); manager.SetTarget(texture_ref, GL_TEXTURE_EXTERNAL_OES); Texture* texture = texture_ref->texture(); EXPECT_EQ(static_cast(GL_TEXTURE_EXTERNAL_OES), texture->target()); EXPECT_FALSE(manager.CanGenerateMipmaps(texture_ref)); manager.Destroy(false); } TEST_F(TextureTest, DepthTexture) { TestHelper::SetupFeatureInfoInitExpectations( gl_.get(), "GL_ANGLE_depth_texture"); scoped_refptr feature_info(new FeatureInfo()); feature_info->InitializeForTesting(); TextureManager manager(NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize, kMaxRectangleTextureSize, kMax3DTextureSize, kUseDefaultTextures); manager.CreateTexture(kClient1Id, kService1Id); TextureRef* texture_ref = manager.GetTexture(kClient1Id); ASSERT_TRUE(texture_ref != NULL); manager.SetTarget(texture_ref, GL_TEXTURE_2D); manager.SetLevelInfo(texture_ref, GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 4, 4, 1, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, gfx::Rect()); EXPECT_FALSE(manager.CanGenerateMipmaps(texture_ref)); manager.Destroy(false); } TEST_F(TextureTest, SafeUnsafe) { static const GLuint kClient2Id = 2; static const GLuint kService2Id = 12; static const GLuint kClient3Id = 3; static const GLuint kService3Id = 13; EXPECT_FALSE(manager_->HaveUnclearedMips()); Texture* texture = texture_ref_->texture(); EXPECT_EQ(0, texture->num_uncleared_mips()); manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); EXPECT_FALSE(texture->SafeToRenderFrom()); EXPECT_TRUE(manager_->HaveUnsafeTextures()); EXPECT_TRUE(manager_->HaveUnclearedMips()); EXPECT_EQ(1, texture->num_uncleared_mips()); manager_->SetLevelCleared(texture_ref_.get(), GL_TEXTURE_2D, 0, true); EXPECT_TRUE(texture->SafeToRenderFrom()); EXPECT_FALSE(manager_->HaveUnsafeTextures()); EXPECT_FALSE(manager_->HaveUnclearedMips()); EXPECT_EQ(0, texture->num_uncleared_mips()); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 8, 8, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); EXPECT_FALSE(texture->SafeToRenderFrom()); EXPECT_TRUE(manager_->HaveUnsafeTextures()); EXPECT_TRUE(manager_->HaveUnclearedMips()); EXPECT_EQ(1, texture->num_uncleared_mips()); manager_->SetLevelCleared(texture_ref_.get(), GL_TEXTURE_2D, 1, true); EXPECT_TRUE(texture->SafeToRenderFrom()); EXPECT_FALSE(manager_->HaveUnsafeTextures()); EXPECT_FALSE(manager_->HaveUnclearedMips()); EXPECT_EQ(0, texture->num_uncleared_mips()); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 8, 8, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); EXPECT_FALSE(texture->SafeToRenderFrom()); EXPECT_TRUE(manager_->HaveUnsafeTextures()); EXPECT_TRUE(manager_->HaveUnclearedMips()); EXPECT_EQ(2, texture->num_uncleared_mips()); manager_->SetLevelCleared(texture_ref_.get(), GL_TEXTURE_2D, 0, true); EXPECT_FALSE(texture->SafeToRenderFrom()); EXPECT_TRUE(manager_->HaveUnsafeTextures()); EXPECT_TRUE(manager_->HaveUnclearedMips()); EXPECT_EQ(1, texture->num_uncleared_mips()); manager_->SetLevelCleared(texture_ref_.get(), GL_TEXTURE_2D, 1, true); EXPECT_TRUE(texture->SafeToRenderFrom()); EXPECT_FALSE(manager_->HaveUnsafeTextures()); EXPECT_FALSE(manager_->HaveUnclearedMips()); EXPECT_EQ(0, texture->num_uncleared_mips()); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 8, 8, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); EXPECT_FALSE(texture->SafeToRenderFrom()); EXPECT_TRUE(manager_->HaveUnsafeTextures()); EXPECT_TRUE(manager_->HaveUnclearedMips()); EXPECT_EQ(1, texture->num_uncleared_mips()); manager_->MarkMipmapsGenerated(texture_ref_.get()); EXPECT_TRUE(texture->SafeToRenderFrom()); EXPECT_FALSE(manager_->HaveUnsafeTextures()); EXPECT_FALSE(manager_->HaveUnclearedMips()); EXPECT_EQ(0, texture->num_uncleared_mips()); manager_->CreateTexture(kClient2Id, kService2Id); scoped_refptr texture_ref2( manager_->GetTexture(kClient2Id)); ASSERT_TRUE(texture_ref2.get() != NULL); manager_->SetTarget(texture_ref2.get(), GL_TEXTURE_2D); EXPECT_FALSE(manager_->HaveUnsafeTextures()); EXPECT_FALSE(manager_->HaveUnclearedMips()); Texture* texture2 = texture_ref2->texture(); EXPECT_EQ(0, texture2->num_uncleared_mips()); manager_->SetLevelInfo(texture_ref2.get(), GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(8, 8)); EXPECT_FALSE(manager_->HaveUnsafeTextures()); EXPECT_FALSE(manager_->HaveUnclearedMips()); EXPECT_EQ(0, texture2->num_uncleared_mips()); manager_->SetLevelInfo(texture_ref2.get(), GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(1, 1)); EXPECT_TRUE(manager_->HaveUnsafeTextures()); EXPECT_TRUE(manager_->HaveUnclearedMips()); EXPECT_EQ(1, texture2->num_uncleared_mips()); manager_->CreateTexture(kClient3Id, kService3Id); scoped_refptr texture_ref3( manager_->GetTexture(kClient3Id)); ASSERT_TRUE(texture_ref3.get() != NULL); manager_->SetTarget(texture_ref3.get(), GL_TEXTURE_2D); manager_->SetLevelInfo(texture_ref3.get(), GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(2, 2)); EXPECT_TRUE(manager_->HaveUnsafeTextures()); EXPECT_TRUE(manager_->HaveUnclearedMips()); Texture* texture3 = texture_ref3->texture(); EXPECT_EQ(1, texture3->num_uncleared_mips()); manager_->SetLevelCleared(texture_ref2.get(), GL_TEXTURE_2D, 0, true); EXPECT_TRUE(manager_->HaveUnsafeTextures()); EXPECT_TRUE(manager_->HaveUnclearedMips()); EXPECT_EQ(0, texture2->num_uncleared_mips()); manager_->SetLevelCleared(texture_ref3.get(), GL_TEXTURE_2D, 0, true); EXPECT_FALSE(manager_->HaveUnsafeTextures()); EXPECT_FALSE(manager_->HaveUnclearedMips()); EXPECT_EQ(0, texture3->num_uncleared_mips()); manager_->SetLevelInfo(texture_ref2.get(), GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(1, 1, 1, 1)); manager_->SetLevelInfo(texture_ref3.get(), GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 4, 4, 4)); EXPECT_TRUE(manager_->HaveUnsafeTextures()); EXPECT_TRUE(manager_->HaveUnclearedMips()); EXPECT_EQ(1, texture2->num_uncleared_mips()); EXPECT_EQ(1, texture3->num_uncleared_mips()); manager_->RemoveTexture(kClient3Id); EXPECT_TRUE(manager_->HaveUnsafeTextures()); EXPECT_TRUE(manager_->HaveUnclearedMips()); manager_->RemoveTexture(kClient2Id); EXPECT_TRUE(manager_->HaveUnsafeTextures()); EXPECT_TRUE(manager_->HaveUnclearedMips()); EXPECT_CALL(*gl_, DeleteTextures(1, ::testing::Pointee(kService2Id))) .Times(1) .RetiresOnSaturation(); texture_ref2 = NULL; EXPECT_TRUE(manager_->HaveUnsafeTextures()); EXPECT_TRUE(manager_->HaveUnclearedMips()); EXPECT_CALL(*gl_, DeleteTextures(1, ::testing::Pointee(kService3Id))) .Times(1) .RetiresOnSaturation(); texture_ref3 = NULL; EXPECT_FALSE(manager_->HaveUnsafeTextures()); EXPECT_FALSE(manager_->HaveUnclearedMips()); } TEST_F(TextureTest, ClearTexture) { EXPECT_CALL(*decoder_, ClearLevel(_, _, _, _, _, _, _, _, _)) .WillRepeatedly(Return(true)); manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); Texture* texture = texture_ref_->texture(); EXPECT_FALSE(texture->SafeToRenderFrom()); EXPECT_TRUE(manager_->HaveUnsafeTextures()); EXPECT_TRUE(manager_->HaveUnclearedMips()); EXPECT_EQ(2, texture->num_uncleared_mips()); manager_->ClearRenderableLevels(decoder_.get(), texture_ref_.get()); EXPECT_TRUE(texture->SafeToRenderFrom()); EXPECT_FALSE(manager_->HaveUnsafeTextures()); EXPECT_FALSE(manager_->HaveUnclearedMips()); EXPECT_EQ(0, texture->num_uncleared_mips()); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(2, 2)); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 3)); EXPECT_FALSE(texture->SafeToRenderFrom()); EXPECT_TRUE(manager_->HaveUnsafeTextures()); EXPECT_TRUE(manager_->HaveUnclearedMips()); EXPECT_EQ(2, texture->num_uncleared_mips()); manager_->ClearTextureLevel( decoder_.get(), texture_ref_.get(), GL_TEXTURE_2D, 0); EXPECT_FALSE(texture->SafeToRenderFrom()); EXPECT_TRUE(manager_->HaveUnsafeTextures()); EXPECT_TRUE(manager_->HaveUnclearedMips()); EXPECT_EQ(1, texture->num_uncleared_mips()); manager_->ClearTextureLevel( decoder_.get(), texture_ref_.get(), GL_TEXTURE_2D, 1); EXPECT_TRUE(texture->SafeToRenderFrom()); EXPECT_FALSE(manager_->HaveUnsafeTextures()); EXPECT_FALSE(manager_->HaveUnclearedMips()); EXPECT_EQ(0, texture->num_uncleared_mips()); } TEST_F(TextureTest, UseDeletedTexture) { static const GLuint kClient2Id = 2; static const GLuint kService2Id = 12; // Make the default texture renderable manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); EXPECT_FALSE(manager_->HaveUnrenderableTextures()); // Make a new texture manager_->CreateTexture(kClient2Id, kService2Id); scoped_refptr texture_ref( manager_->GetTexture(kClient2Id)); manager_->SetTarget(texture_ref.get(), GL_TEXTURE_2D); EXPECT_FALSE(manager_->CanRender(texture_ref.get())); EXPECT_TRUE(manager_->HaveUnrenderableTextures()); // Remove it. manager_->RemoveTexture(kClient2Id); EXPECT_FALSE(manager_->CanRender(texture_ref.get())); EXPECT_TRUE(manager_->HaveUnrenderableTextures()); // Check that we can still manipulate it and it effects the manager. manager_->SetLevelInfo(texture_ref.get(), GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); EXPECT_TRUE(manager_->CanRender(texture_ref.get())); EXPECT_FALSE(manager_->HaveUnrenderableTextures()); EXPECT_CALL(*gl_, DeleteTextures(1, ::testing::Pointee(kService2Id))) .Times(1) .RetiresOnSaturation(); texture_ref = NULL; } TEST_F(TextureTest, GetLevelImage) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(2, 2)); Texture* texture = texture_ref_->texture(); EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 1) == NULL); // Set image. scoped_refptr image(new gl::GLImageStub); manager_->SetLevelImage(texture_ref_.get(), GL_TEXTURE_2D, 1, image.get(), Texture::BOUND); EXPECT_FALSE(texture->GetLevelImage(GL_TEXTURE_2D, 1) == NULL); // Remove it. manager_->SetLevelImage(texture_ref_.get(), GL_TEXTURE_2D, 1, nullptr, Texture::UNBOUND); EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 1) == NULL); manager_->SetLevelImage(texture_ref_.get(), GL_TEXTURE_2D, 1, image.get(), Texture::UNBOUND); // Image should be reset when SetLevelInfo is called. manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(2, 2)); EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 1) == NULL); } namespace { bool InSet(std::set* string_set, const std::string& str) { std::pair::iterator, bool> result = string_set->insert(str); return !result.second; } } // anonymous namespace TEST_F(TextureTest, AddToSignature) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(2, 2)); std::string signature1; std::string signature2; manager_->AddToSignature(texture_ref_.get(), GL_TEXTURE_2D, 1, &signature1); std::set string_set; EXPECT_FALSE(InSet(&string_set, signature1)); // check changing 1 thing makes a different signature. manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 4, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(4, 2)); manager_->AddToSignature(texture_ref_.get(), GL_TEXTURE_2D, 1, &signature2); EXPECT_FALSE(InSet(&string_set, signature2)); // check putting it back makes the same signature. manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(2, 2)); signature2.clear(); manager_->AddToSignature(texture_ref_.get(), GL_TEXTURE_2D, 1, &signature2); EXPECT_EQ(signature1, signature2); // Check setting cleared status does not change signature. manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); signature2.clear(); manager_->AddToSignature(texture_ref_.get(), GL_TEXTURE_2D, 1, &signature2); EXPECT_EQ(signature1, signature2); // Check changing other settings changes signature. manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 2, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); signature2.clear(); manager_->AddToSignature(texture_ref_.get(), GL_TEXTURE_2D, 1, &signature2); EXPECT_FALSE(InSet(&string_set, signature2)); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); signature2.clear(); manager_->AddToSignature(texture_ref_.get(), GL_TEXTURE_2D, 1, &signature2); EXPECT_FALSE(InSet(&string_set, signature2)); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); signature2.clear(); manager_->AddToSignature(texture_ref_.get(), GL_TEXTURE_2D, 1, &signature2); EXPECT_FALSE(InSet(&string_set, signature2)); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, gfx::Rect()); signature2.clear(); manager_->AddToSignature(texture_ref_.get(), GL_TEXTURE_2D, 1, &signature2); EXPECT_FALSE(InSet(&string_set, signature2)); manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_FLOAT, gfx::Rect()); signature2.clear(); manager_->AddToSignature(texture_ref_.get(), GL_TEXTURE_2D, 1, &signature2); EXPECT_FALSE(InSet(&string_set, signature2)); // put it back manager_->SetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); signature2.clear(); manager_->AddToSignature(texture_ref_.get(), GL_TEXTURE_2D, 1, &signature2); EXPECT_EQ(signature1, signature2); // check changing parameters changes signature. SetParameter( texture_ref_.get(), GL_TEXTURE_MIN_FILTER, GL_NEAREST, GL_NO_ERROR); signature2.clear(); manager_->AddToSignature(texture_ref_.get(), GL_TEXTURE_2D, 1, &signature2); EXPECT_FALSE(InSet(&string_set, signature2)); SetParameter(texture_ref_.get(), GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR, GL_NO_ERROR); SetParameter( texture_ref_.get(), GL_TEXTURE_MAG_FILTER, GL_NEAREST, GL_NO_ERROR); signature2.clear(); manager_->AddToSignature(texture_ref_.get(), GL_TEXTURE_2D, 1, &signature2); EXPECT_FALSE(InSet(&string_set, signature2)); SetParameter( texture_ref_.get(), GL_TEXTURE_MAG_FILTER, GL_LINEAR, GL_NO_ERROR); SetParameter( texture_ref_.get(), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE, GL_NO_ERROR); signature2.clear(); manager_->AddToSignature(texture_ref_.get(), GL_TEXTURE_2D, 1, &signature2); EXPECT_FALSE(InSet(&string_set, signature2)); SetParameter(texture_ref_.get(), GL_TEXTURE_WRAP_S, GL_REPEAT, GL_NO_ERROR); SetParameter( texture_ref_.get(), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE, GL_NO_ERROR); signature2.clear(); manager_->AddToSignature(texture_ref_.get(), GL_TEXTURE_2D, 1, &signature2); EXPECT_FALSE(InSet(&string_set, signature2)); // Check putting it back genenerates the same signature SetParameter(texture_ref_.get(), GL_TEXTURE_WRAP_T, GL_REPEAT, GL_NO_ERROR); signature2.clear(); manager_->AddToSignature(texture_ref_.get(), GL_TEXTURE_2D, 1, &signature2); EXPECT_EQ(signature1, signature2); // Check the set was acutally getting different signatures. EXPECT_EQ(11u, string_set.size()); } class ProduceConsumeTextureTest : public TextureTest, public ::testing::WithParamInterface { public: void SetUp() override { TextureTest::SetUpBase(NULL, "GL_OES_EGL_image_external"); manager_->CreateTexture(kClient2Id, kService2Id); texture2_ = manager_->GetTexture(kClient2Id); EXPECT_CALL(*decoder_.get(), GetErrorState()) .WillRepeatedly(Return(error_state_.get())); } void TearDown() override { if (texture2_.get()) { // If it's not in the manager then setting texture2_ to NULL will // delete the texture. if (!texture2_->client_id()) { // Check that it gets deleted when the last reference is released. EXPECT_CALL( *gl_, DeleteTextures(1, ::testing::Pointee(texture2_->service_id()))) .Times(1).RetiresOnSaturation(); } texture2_ = NULL; } TextureTest::TearDown(); } protected: struct LevelInfo { LevelInfo(GLenum target, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum type, const gfx::Rect& cleared_rect) : target(target), format(format), width(width), height(height), depth(depth), border(border), type(type), cleared_rect(cleared_rect) {} LevelInfo() : target(0), format(0), width(-1), height(-1), depth(1), border(0), type(0) {} bool operator==(const LevelInfo& other) const { return target == other.target && format == other.format && width == other.width && height == other.height && depth == other.depth && border == other.border && type == other.type && cleared_rect == other.cleared_rect; } GLenum target; GLenum format; GLsizei width; GLsizei height; GLsizei depth; GLint border; GLenum type; gfx::Rect cleared_rect; }; void SetLevelInfo(TextureRef* texture_ref, GLint level, const LevelInfo& info) { manager_->SetLevelInfo(texture_ref, info.target, level, info.format, info.width, info.height, info.depth, info.border, info.format, info.type, info.cleared_rect); } static LevelInfo GetLevelInfo(const TextureRef* texture_ref, GLint target, GLint level) { const Texture* texture = texture_ref->texture(); LevelInfo info; info.target = target; EXPECT_TRUE(texture->GetLevelSize(target, level, &info.width, &info.height, &info.depth)); EXPECT_TRUE(texture->GetLevelType(target, level, &info.type, &info.format)); info.cleared_rect = texture->GetLevelClearedRect(target, level); return info; } Texture* Produce(TextureRef* texture_ref) { Texture* texture = manager_->Produce(texture_ref); EXPECT_TRUE(texture != NULL); return texture; } void Consume(GLuint client_id, Texture* texture) { EXPECT_TRUE(manager_->Consume(client_id, texture)); } scoped_refptr texture2_; private: static const GLuint kClient2Id; static const GLuint kService2Id; }; const GLuint ProduceConsumeTextureTest::kClient2Id = 2; const GLuint ProduceConsumeTextureTest::kService2Id = 12; TEST_F(ProduceConsumeTextureTest, ProduceConsume2D) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D); Texture* texture = texture_ref_->texture(); EXPECT_EQ(static_cast(GL_TEXTURE_2D), texture->target()); LevelInfo level0(GL_TEXTURE_2D, GL_RGBA, 4, 4, 1, 0, GL_UNSIGNED_BYTE, gfx::Rect(4, 4)); SetLevelInfo(texture_ref_.get(), 0, level0); EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_ref_.get())); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); LevelInfo level1 = GetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 1); LevelInfo level2 = GetLevelInfo(texture_ref_.get(), GL_TEXTURE_2D, 2); Texture* produced_texture = Produce(texture_ref_.get()); EXPECT_EQ(produced_texture, texture); // Make this texture bigger with more levels, and make sure they get // clobbered correctly during Consume(). manager_->SetTarget(texture2_.get(), GL_TEXTURE_2D); SetLevelInfo(texture2_.get(), 0, LevelInfo(GL_TEXTURE_2D, GL_RGBA, 16, 16, 1, 0, GL_UNSIGNED_BYTE, gfx::Rect())); EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture2_.get())); texture = texture2_->texture(); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); EXPECT_EQ(1024U + 256U + 64U + 16U + 4U, texture->estimated_size()); GLuint client_id = texture2_->client_id(); manager_->RemoveTexture(client_id); Consume(client_id, produced_texture); scoped_refptr restored_texture = manager_->GetTexture(client_id); EXPECT_EQ(produced_texture, restored_texture->texture()); EXPECT_EQ(level0, GetLevelInfo(restored_texture.get(), GL_TEXTURE_2D, 0)); EXPECT_EQ(level1, GetLevelInfo(restored_texture.get(), GL_TEXTURE_2D, 1)); EXPECT_EQ(level2, GetLevelInfo(restored_texture.get(), GL_TEXTURE_2D, 2)); texture = restored_texture->texture(); EXPECT_EQ(64U + 16U + 4U, texture->estimated_size()); GLint w, h; EXPECT_FALSE(texture->GetLevelSize(GL_TEXTURE_2D, 3, &w, &h, nullptr)); // However the old texture ref still exists if it was referenced somewhere. EXPECT_EQ(1024U + 256U + 64U + 16U + 4U, texture2_->texture()->estimated_size()); } TEST_F(ProduceConsumeTextureTest, ProduceConsumeClearRectangle) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_RECTANGLE_ARB); Texture* texture = texture_ref_->texture(); EXPECT_EQ(static_cast(GL_TEXTURE_RECTANGLE_ARB), texture->target()); LevelInfo level0(GL_TEXTURE_RECTANGLE_ARB, GL_RGBA, 1, 1, 1, 0, GL_UNSIGNED_BYTE, gfx::Rect()); SetLevelInfo(texture_ref_.get(), 0, level0); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); Texture* produced_texture = Produce(texture_ref_.get()); EXPECT_EQ(produced_texture, texture); EXPECT_EQ(static_cast(GL_TEXTURE_RECTANGLE_ARB), produced_texture->target()); GLuint client_id = texture2_->client_id(); manager_->RemoveTexture(client_id); Consume(client_id, produced_texture); scoped_refptr restored_texture = manager_->GetTexture(client_id); EXPECT_EQ(produced_texture, restored_texture->texture()); // See if we can clear the previously uncleared level now. EXPECT_EQ(level0, GetLevelInfo(restored_texture.get(), GL_TEXTURE_RECTANGLE_ARB, 0)); EXPECT_CALL(*decoder_, ClearLevel(_, _, _, _, _, _, _, _, _)) .WillRepeatedly(Return(true)); EXPECT_TRUE(manager_->ClearTextureLevel( decoder_.get(), restored_texture.get(), GL_TEXTURE_RECTANGLE_ARB, 0)); } TEST_F(ProduceConsumeTextureTest, ProduceConsumeExternal) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_EXTERNAL_OES); Texture* texture = texture_ref_->texture(); EXPECT_EQ(static_cast(GL_TEXTURE_EXTERNAL_OES), texture->target()); LevelInfo level0(GL_TEXTURE_EXTERNAL_OES, GL_RGBA, 1, 1, 1, 0, GL_UNSIGNED_BYTE, gfx::Rect()); SetLevelInfo(texture_ref_.get(), 0, level0); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); Texture* produced_texture = Produce(texture_ref_.get()); EXPECT_EQ(produced_texture, texture); GLuint client_id = texture2_->client_id(); manager_->RemoveTexture(client_id); Consume(client_id, produced_texture); scoped_refptr restored_texture = manager_->GetTexture(client_id); EXPECT_EQ(produced_texture, restored_texture->texture()); EXPECT_EQ(level0, GetLevelInfo(restored_texture.get(), GL_TEXTURE_EXTERNAL_OES, 0)); } TEST_P(ProduceConsumeTextureTest, ProduceConsumeTextureWithImage) { GLenum target = GetParam(); manager_->SetTarget(texture_ref_.get(), target); Texture* texture = texture_ref_->texture(); EXPECT_EQ(static_cast(target), texture->target()); scoped_refptr image(new gl::GLImageStub); manager_->SetLevelInfo(texture_ref_.get(), target, 0, GL_RGBA, 0, 0, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); manager_->SetLevelImage(texture_ref_.get(), target, 0, image.get(), Texture::BOUND); GLuint service_id = texture->service_id(); Texture* produced_texture = Produce(texture_ref_.get()); GLuint client_id = texture2_->client_id(); manager_->RemoveTexture(client_id); Consume(client_id, produced_texture); scoped_refptr restored_texture = manager_->GetTexture(client_id); EXPECT_EQ(produced_texture, restored_texture->texture()); EXPECT_EQ(service_id, restored_texture->service_id()); EXPECT_EQ(image.get(), restored_texture->texture()->GetLevelImage(target, 0)); } static const GLenum kTextureTargets[] = {GL_TEXTURE_2D, GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_RECTANGLE_ARB, }; INSTANTIATE_TEST_CASE_P(Target, ProduceConsumeTextureTest, ::testing::ValuesIn(kTextureTargets)); TEST_F(ProduceConsumeTextureTest, ProduceConsumeCube) { manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_CUBE_MAP); Texture* texture = texture_ref_->texture(); EXPECT_EQ(static_cast(GL_TEXTURE_CUBE_MAP), texture->target()); LevelInfo face0(GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_RGBA, 1, 1, 1, 0, GL_UNSIGNED_BYTE, gfx::Rect(1, 1)); LevelInfo face5(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, GL_RGBA, 3, 3, 1, 0, GL_UNSIGNED_BYTE, gfx::Rect(1, 1)); SetLevelInfo(texture_ref_.get(), 0, face0); SetLevelInfo(texture_ref_.get(), 0, face5); EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture)); Texture* produced_texture = Produce(texture_ref_.get()); EXPECT_EQ(produced_texture, texture); GLuint client_id = texture2_->client_id(); manager_->RemoveTexture(client_id); Consume(client_id, produced_texture); scoped_refptr restored_texture = manager_->GetTexture(client_id); EXPECT_EQ(produced_texture, restored_texture->texture()); EXPECT_EQ( face0, GetLevelInfo(restored_texture.get(), GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)); EXPECT_EQ( face5, GetLevelInfo(restored_texture.get(), GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0)); } class CountingMemoryTracker : public MemoryTracker { public: CountingMemoryTracker() { current_size_ = 0; } void TrackMemoryAllocatedChange(size_t old_size, size_t new_size) override { current_size_ += new_size - old_size; } bool EnsureGPUMemoryAvailable(size_t size_needed) override { return true; } size_t GetSize() { return current_size_; } uint64_t ClientTracingId() const override { return 0; } int ClientId() const override { return 0; } uint64_t ShareGroupTracingGUID() const override { return 0; } private: ~CountingMemoryTracker() override {} size_t current_size_; DISALLOW_COPY_AND_ASSIGN(CountingMemoryTracker); }; class SharedTextureTest : public GpuServiceTest { public: static const bool kUseDefaultTextures = false; SharedTextureTest() : feature_info_(new FeatureInfo()) {} ~SharedTextureTest() override {} void SetUp() override { GpuServiceTest::SetUp(); memory_tracker1_ = new CountingMemoryTracker; texture_manager1_.reset( new TextureManager(memory_tracker1_.get(), feature_info_.get(), TextureManagerTest::kMaxTextureSize, TextureManagerTest::kMaxCubeMapTextureSize, TextureManagerTest::kMaxRectangleTextureSize, TextureManagerTest::kMax3DTextureSize, kUseDefaultTextures)); memory_tracker2_ = new CountingMemoryTracker; texture_manager2_.reset( new TextureManager(memory_tracker2_.get(), feature_info_.get(), TextureManagerTest::kMaxTextureSize, TextureManagerTest::kMaxCubeMapTextureSize, TextureManagerTest::kMaxRectangleTextureSize, TextureManagerTest::kMax3DTextureSize, kUseDefaultTextures)); TestHelper::SetupTextureManagerInitExpectations( gl_.get(), false, "", kUseDefaultTextures); texture_manager1_->Initialize(); TestHelper::SetupTextureManagerInitExpectations( gl_.get(), false, "", kUseDefaultTextures); texture_manager2_->Initialize(); } void TearDown() override { texture_manager2_->Destroy(false); texture_manager2_.reset(); texture_manager1_->Destroy(false); texture_manager1_.reset(); GpuServiceTest::TearDown(); } protected: scoped_refptr feature_info_; scoped_refptr memory_tracker1_; scoped_ptr texture_manager1_; scoped_refptr memory_tracker2_; scoped_ptr texture_manager2_; }; TEST_F(SharedTextureTest, DeleteTextures) { scoped_refptr ref1 = texture_manager1_->CreateTexture(10, 10); scoped_refptr ref2 = texture_manager2_->Consume(20, ref1->texture()); EXPECT_CALL(*gl_, DeleteTextures(1, _)) .Times(0); ref1 = NULL; texture_manager1_->RemoveTexture(10); testing::Mock::VerifyAndClearExpectations(gl_.get()); EXPECT_CALL(*gl_, DeleteTextures(1, _)) .Times(1) .RetiresOnSaturation(); ref2 = NULL; texture_manager2_->RemoveTexture(20); testing::Mock::VerifyAndClearExpectations(gl_.get()); } TEST_F(SharedTextureTest, TextureSafetyAccounting) { EXPECT_FALSE(texture_manager1_->HaveUnrenderableTextures()); EXPECT_FALSE(texture_manager1_->HaveUnsafeTextures()); EXPECT_FALSE(texture_manager1_->HaveUnclearedMips()); EXPECT_FALSE(texture_manager2_->HaveUnrenderableTextures()); EXPECT_FALSE(texture_manager2_->HaveUnsafeTextures()); EXPECT_FALSE(texture_manager2_->HaveUnclearedMips()); // Newly created texture is renderable. scoped_refptr ref1 = texture_manager1_->CreateTexture(10, 10); EXPECT_FALSE(texture_manager1_->HaveUnrenderableTextures()); EXPECT_FALSE(texture_manager1_->HaveUnsafeTextures()); EXPECT_FALSE(texture_manager1_->HaveUnclearedMips()); // Associate new texture ref to other texture manager, should account for it // too. scoped_refptr ref2 = texture_manager2_->Consume(20, ref1->texture()); EXPECT_FALSE(texture_manager2_->HaveUnrenderableTextures()); EXPECT_FALSE(texture_manager2_->HaveUnsafeTextures()); EXPECT_FALSE(texture_manager2_->HaveUnclearedMips()); // Make texture renderable but uncleared on one texture manager, should affect // other one. texture_manager1_->SetTarget(ref1.get(), GL_TEXTURE_2D); EXPECT_TRUE(texture_manager1_->HaveUnrenderableTextures()); EXPECT_FALSE(texture_manager1_->HaveUnsafeTextures()); EXPECT_FALSE(texture_manager1_->HaveUnclearedMips()); EXPECT_TRUE(texture_manager2_->HaveUnrenderableTextures()); EXPECT_FALSE(texture_manager2_->HaveUnsafeTextures()); EXPECT_FALSE(texture_manager2_->HaveUnclearedMips()); texture_manager1_->SetLevelInfo(ref1.get(), GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); EXPECT_FALSE(texture_manager1_->HaveUnrenderableTextures()); EXPECT_TRUE(texture_manager1_->HaveUnsafeTextures()); EXPECT_TRUE(texture_manager1_->HaveUnclearedMips()); EXPECT_FALSE(texture_manager2_->HaveUnrenderableTextures()); EXPECT_TRUE(texture_manager2_->HaveUnsafeTextures()); EXPECT_TRUE(texture_manager2_->HaveUnclearedMips()); // Make texture cleared on one texture manager, should affect other one. texture_manager1_->SetLevelCleared(ref1.get(), GL_TEXTURE_2D, 0, true); EXPECT_FALSE(texture_manager1_->HaveUnsafeTextures()); EXPECT_FALSE(texture_manager1_->HaveUnclearedMips()); EXPECT_FALSE(texture_manager2_->HaveUnsafeTextures()); EXPECT_FALSE(texture_manager2_->HaveUnclearedMips()); EXPECT_CALL(*gl_, DeleteTextures(1, _)) .Times(1) .RetiresOnSaturation(); texture_manager1_->RemoveTexture(10); texture_manager2_->RemoveTexture(20); } TEST_F(SharedTextureTest, FBOCompletenessCheck) { const GLenum kCompleteValue = GL_FRAMEBUFFER_COMPLETE; FramebufferManager framebuffer_manager1(1, 1, CONTEXT_TYPE_OPENGLES2, nullptr); texture_manager1_->set_framebuffer_manager(&framebuffer_manager1); FramebufferManager framebuffer_manager2(1, 1, CONTEXT_TYPE_OPENGLES2, nullptr); texture_manager2_->set_framebuffer_manager(&framebuffer_manager2); scoped_refptr ref1 = texture_manager1_->CreateTexture(10, 10); framebuffer_manager1.CreateFramebuffer(10, 10); scoped_refptr framebuffer1 = framebuffer_manager1.GetFramebuffer(10); framebuffer1->AttachTexture( GL_COLOR_ATTACHMENT0, ref1.get(), GL_TEXTURE_2D, 0, 0); EXPECT_FALSE(framebuffer_manager1.IsComplete(framebuffer1.get())); EXPECT_NE(kCompleteValue, framebuffer1->IsPossiblyComplete()); // Make FBO complete in manager 1. texture_manager1_->SetTarget(ref1.get(), GL_TEXTURE_2D); texture_manager1_->SetLevelInfo(ref1.get(), GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(1, 1)); EXPECT_EQ(kCompleteValue, framebuffer1->IsPossiblyComplete()); framebuffer_manager1.MarkAsComplete(framebuffer1.get()); EXPECT_TRUE(framebuffer_manager1.IsComplete(framebuffer1.get())); // Share texture with manager 2. scoped_refptr ref2 = texture_manager2_->Consume(20, ref1->texture()); framebuffer_manager2.CreateFramebuffer(20, 20); scoped_refptr framebuffer2 = framebuffer_manager2.GetFramebuffer(20); framebuffer2->AttachTexture( GL_COLOR_ATTACHMENT0, ref2.get(), GL_TEXTURE_2D, 0, 0); EXPECT_FALSE(framebuffer_manager2.IsComplete(framebuffer2.get())); EXPECT_EQ(kCompleteValue, framebuffer2->IsPossiblyComplete()); framebuffer_manager2.MarkAsComplete(framebuffer2.get()); EXPECT_TRUE(framebuffer_manager2.IsComplete(framebuffer2.get())); // Change level for texture, both FBOs should be marked incomplete texture_manager1_->SetLevelInfo(ref1.get(), GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(1, 1)); EXPECT_FALSE(framebuffer_manager1.IsComplete(framebuffer1.get())); EXPECT_EQ(kCompleteValue, framebuffer1->IsPossiblyComplete()); framebuffer_manager1.MarkAsComplete(framebuffer1.get()); EXPECT_TRUE(framebuffer_manager1.IsComplete(framebuffer1.get())); EXPECT_FALSE(framebuffer_manager2.IsComplete(framebuffer2.get())); EXPECT_EQ(kCompleteValue, framebuffer2->IsPossiblyComplete()); framebuffer_manager2.MarkAsComplete(framebuffer2.get()); EXPECT_TRUE(framebuffer_manager2.IsComplete(framebuffer2.get())); EXPECT_CALL(*gl_, DeleteFramebuffersEXT(1, _)) .Times(2) .RetiresOnSaturation(); framebuffer_manager1.RemoveFramebuffer(10); framebuffer_manager2.RemoveFramebuffer(20); EXPECT_CALL(*gl_, DeleteTextures(1, _)) .Times(1) .RetiresOnSaturation(); texture_manager1_->RemoveTexture(10); texture_manager2_->RemoveTexture(20); } TEST_F(SharedTextureTest, Memory) { size_t initial_memory1 = memory_tracker1_->GetSize(); size_t initial_memory2 = memory_tracker2_->GetSize(); // Newly created texture is unrenderable. scoped_refptr ref1 = texture_manager1_->CreateTexture(10, 10); texture_manager1_->SetTarget(ref1.get(), GL_TEXTURE_2D); texture_manager1_->SetLevelInfo(ref1.get(), GL_TEXTURE_2D, 0, GL_RGBA, 10, 10, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); EXPECT_LT(0u, ref1->texture()->estimated_size()); EXPECT_EQ(initial_memory1 + ref1->texture()->estimated_size(), memory_tracker1_->GetSize()); // Associate new texture ref to other texture manager, it doesn't account for // the texture memory, the first memory tracker still has it. scoped_refptr ref2 = texture_manager2_->Consume(20, ref1->texture()); EXPECT_EQ(initial_memory1 + ref1->texture()->estimated_size(), memory_tracker1_->GetSize()); EXPECT_EQ(initial_memory2, memory_tracker2_->GetSize()); // Delete the texture, memory should go to the remaining tracker. texture_manager1_->RemoveTexture(10); ref1 = NULL; EXPECT_EQ(initial_memory1, memory_tracker1_->GetSize()); EXPECT_EQ(initial_memory2 + ref2->texture()->estimated_size(), memory_tracker2_->GetSize()); EXPECT_CALL(*gl_, DeleteTextures(1, _)) .Times(1) .RetiresOnSaturation(); ref2 = NULL; texture_manager2_->RemoveTexture(20); EXPECT_EQ(initial_memory2, memory_tracker2_->GetSize()); } TEST_F(SharedTextureTest, Images) { scoped_refptr ref1 = texture_manager1_->CreateTexture(10, 10); scoped_refptr ref2 = texture_manager2_->Consume(20, ref1->texture()); texture_manager1_->SetTarget(ref1.get(), GL_TEXTURE_2D); texture_manager1_->SetLevelInfo(ref1.get(), GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(2, 2)); EXPECT_FALSE(ref1->texture()->HasImages()); EXPECT_FALSE(ref2->texture()->HasImages()); EXPECT_FALSE(texture_manager1_->HaveImages()); EXPECT_FALSE(texture_manager2_->HaveImages()); scoped_refptr image1(new gl::GLImageStub); texture_manager1_->SetLevelImage(ref1.get(), GL_TEXTURE_2D, 1, image1.get(), Texture::BOUND); EXPECT_TRUE(ref1->texture()->HasImages()); EXPECT_TRUE(ref2->texture()->HasImages()); EXPECT_TRUE(texture_manager1_->HaveImages()); EXPECT_TRUE(texture_manager2_->HaveImages()); scoped_refptr image2(new gl::GLImageStub); texture_manager1_->SetLevelImage(ref1.get(), GL_TEXTURE_2D, 1, image2.get(), Texture::BOUND); EXPECT_TRUE(ref1->texture()->HasImages()); EXPECT_TRUE(ref2->texture()->HasImages()); EXPECT_TRUE(texture_manager1_->HaveImages()); EXPECT_TRUE(texture_manager2_->HaveImages()); texture_manager1_->SetLevelInfo(ref1.get(), GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(2, 2)); EXPECT_FALSE(ref1->texture()->HasImages()); EXPECT_FALSE(ref2->texture()->HasImages()); EXPECT_FALSE(texture_manager1_->HaveImages()); EXPECT_FALSE(texture_manager1_->HaveImages()); EXPECT_CALL(*gl_, DeleteTextures(1, _)) .Times(1) .RetiresOnSaturation(); texture_manager1_->RemoveTexture(10); texture_manager2_->RemoveTexture(20); } class TextureFormatTypeValidationTest : public TextureManagerTest { public: TextureFormatTypeValidationTest() {} ~TextureFormatTypeValidationTest() override {} protected: void ExpectValid(GLenum format, GLenum type, GLenum internal_format) { EXPECT_TRUE(manager_->ValidateTextureParameters( error_state_.get(), "", format, type, internal_format, 0)); } void ExpectInvalid(GLenum format, GLenum type, GLenum internal_format) { EXPECT_CALL(*error_state_, SetGLError(_, _, _, _, _)) .Times(1) .RetiresOnSaturation(); EXPECT_FALSE(manager_->ValidateTextureParameters( error_state_.get(), "", format, type, internal_format, 0)); } void ExpectInvalidEnum(GLenum format, GLenum type, GLenum internal_format) { EXPECT_CALL(*error_state_, SetGLErrorInvalidEnum(_, _, _, _, _)) .Times(1) .RetiresOnSaturation(); EXPECT_FALSE(manager_->ValidateTextureParameters( error_state_.get(), "", format, type, internal_format, 0)); } }; TEST_F(TextureFormatTypeValidationTest, ES2Basic) { SetupFeatureInfo("", "OpenGL ES 2.0", false); ExpectValid(GL_ALPHA, GL_UNSIGNED_BYTE, GL_ALPHA); ExpectValid(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_RGB); ExpectValid(GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_RGBA); ExpectValid(GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_LUMINANCE); ExpectValid(GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_LUMINANCE_ALPHA); ExpectInvalid(GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_ALPHA); // float / half_float. ExpectInvalidEnum(GL_RGBA, GL_FLOAT, GL_RGBA); ExpectInvalidEnum(GL_RGBA, GL_HALF_FLOAT_OES, GL_RGBA); // GL_EXT_bgra ExpectInvalidEnum(GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_BGRA_EXT); // depth / stencil ExpectInvalidEnum(GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_DEPTH_COMPONENT); ExpectInvalidEnum(GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_DEPTH_STENCIL); // SRGB ExpectInvalidEnum(GL_SRGB_EXT, GL_UNSIGNED_BYTE, GL_SRGB_EXT); ExpectInvalidEnum(GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, GL_SRGB_ALPHA_EXT); // ES3 ExpectInvalidEnum(GL_RGB, GL_UNSIGNED_BYTE, GL_RGB8); } TEST_F(TextureFormatTypeValidationTest, ES2WithExtTextureFormatBGRA8888) { SetupFeatureInfo("GL_EXT_texture_format_BGRA8888", "OpenGL ES 2.0", false); ExpectValid(GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_BGRA_EXT); } TEST_F(TextureFormatTypeValidationTest, ES2WithAppleTextureFormatBGRA8888) { SetupFeatureInfo("GL_APPLE_texture_format_BGRA8888", "OpenGL ES 2.0", false); ExpectValid(GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_BGRA_EXT); } TEST_F(TextureFormatTypeValidationTest, ES2WithArbDepth) { SetupFeatureInfo("GL_ARB_depth_texture", "OpenGL ES 2.0", false); ExpectValid(GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_DEPTH_COMPONENT); ExpectValid(GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_DEPTH_COMPONENT); ExpectInvalidEnum(GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_DEPTH_STENCIL); } TEST_F(TextureFormatTypeValidationTest, ES2WithOesDepth) { SetupFeatureInfo("GL_OES_depth_texture", "OpenGL ES 2.0", false); ExpectValid(GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_DEPTH_COMPONENT); ExpectValid(GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_DEPTH_COMPONENT); ExpectInvalidEnum(GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_DEPTH_STENCIL); } TEST_F(TextureFormatTypeValidationTest, ES2WithAngleDepth) { SetupFeatureInfo("GL_ANGLE_depth_texture", "OpenGL ES 2.0", false); ExpectValid(GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_DEPTH_COMPONENT); ExpectValid(GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_DEPTH_COMPONENT); ExpectInvalidEnum(GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_DEPTH_STENCIL); } TEST_F(TextureFormatTypeValidationTest, ES2WithExtPackedDepthStencil) { SetupFeatureInfo( "GL_EXT_packed_depth_stencil GL_ARB_depth_texture", "OpenGL ES 2.0", false); ExpectValid(GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_DEPTH_COMPONENT); ExpectValid(GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_DEPTH_COMPONENT); ExpectValid(GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_DEPTH_STENCIL); } TEST_F(TextureFormatTypeValidationTest, ES2WithRGWithFloat) { SetupFeatureInfo( "GL_EXT_texture_rg GL_OES_texture_float GL_OES_texture_half_float", "OpenGL ES 2.0", false); ExpectValid(GL_RED_EXT, GL_HALF_FLOAT_OES, GL_RED_EXT); ExpectValid(GL_RG_EXT, GL_HALF_FLOAT_OES, GL_RG_EXT); ExpectValid(GL_RED_EXT, GL_UNSIGNED_BYTE, GL_RED_EXT); ExpectValid(GL_RG_EXT, GL_UNSIGNED_BYTE, GL_RG_EXT); ExpectInvalidEnum(GL_RED_EXT, GL_BYTE, GL_RED_EXT); ExpectInvalidEnum(GL_RG_EXT, GL_BYTE, GL_RG_EXT); ExpectInvalidEnum(GL_RED_EXT, GL_SHORT, GL_RED_EXT); ExpectInvalidEnum(GL_RG_EXT, GL_SHORT, GL_RG_EXT); } TEST_F(TextureFormatTypeValidationTest, ES2WithRGNoFloat) { SetupFeatureInfo("GL_ARB_texture_rg", "OpenGL ES 2.0", false); ExpectValid(GL_RED_EXT, GL_UNSIGNED_BYTE, GL_RED_EXT); ExpectValid(GL_RG_EXT, GL_UNSIGNED_BYTE, GL_RG_EXT); ExpectInvalidEnum(GL_RED_EXT, GL_HALF_FLOAT_OES, GL_RED_EXT); ExpectInvalidEnum(GL_RG_EXT, GL_HALF_FLOAT_OES, GL_RG_EXT); } TEST_F(TextureFormatTypeValidationTest, ES2OnTopOfES3) { SetupFeatureInfo("", "OpenGL ES 3.0", false); ExpectInvalidEnum(GL_RGB, GL_FLOAT, GL_RGB); ExpectInvalidEnum(GL_RGBA, GL_FLOAT, GL_RGBA); ExpectInvalidEnum(GL_LUMINANCE, GL_FLOAT, GL_LUMINANCE); ExpectInvalidEnum(GL_LUMINANCE_ALPHA, GL_FLOAT, GL_LUMINANCE_ALPHA); ExpectInvalidEnum(GL_ALPHA, GL_FLOAT, GL_ALPHA); ExpectInvalidEnum(GL_SRGB_EXT, GL_UNSIGNED_BYTE, GL_SRGB_EXT); ExpectInvalidEnum(GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, GL_SRGB_ALPHA_EXT); } TEST_F(TextureFormatTypeValidationTest, ES2WithOesTextureFloat) { SetupFeatureInfo("GL_OES_texture_float", "OpenGL ES 2.0", false); ExpectValid(GL_RGB, GL_FLOAT, GL_RGB); ExpectValid(GL_RGBA, GL_FLOAT, GL_RGBA); ExpectValid(GL_LUMINANCE, GL_FLOAT, GL_LUMINANCE); ExpectValid(GL_LUMINANCE_ALPHA, GL_FLOAT, GL_LUMINANCE_ALPHA); ExpectValid(GL_ALPHA, GL_FLOAT, GL_ALPHA); ExpectInvalidEnum(GL_RGB, GL_HALF_FLOAT_OES, GL_RGB); ExpectInvalidEnum(GL_RGBA, GL_HALF_FLOAT_OES, GL_RGBA); ExpectInvalidEnum(GL_LUMINANCE, GL_HALF_FLOAT_OES, GL_LUMINANCE); ExpectInvalidEnum(GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_LUMINANCE_ALPHA); ExpectInvalidEnum(GL_ALPHA, GL_HALF_FLOAT_OES, GL_ALPHA); } TEST_F(TextureFormatTypeValidationTest, ES2WithOesTextureFloatLinear) { SetupFeatureInfo( "GL_OES_texture_float GL_OES_texture_float_linear", "OpenGL ES 2.0", false); ExpectValid(GL_RGB, GL_FLOAT, GL_RGB); ExpectValid(GL_RGBA, GL_FLOAT, GL_RGBA); ExpectValid(GL_LUMINANCE, GL_FLOAT, GL_LUMINANCE); ExpectValid(GL_LUMINANCE_ALPHA, GL_FLOAT, GL_LUMINANCE_ALPHA); ExpectValid(GL_ALPHA, GL_FLOAT, GL_ALPHA); ExpectInvalidEnum(GL_RGB, GL_HALF_FLOAT_OES, GL_RGB); ExpectInvalidEnum(GL_RGBA, GL_HALF_FLOAT_OES, GL_RGBA); ExpectInvalidEnum(GL_LUMINANCE, GL_HALF_FLOAT_OES, GL_LUMINANCE); ExpectInvalidEnum(GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_LUMINANCE_ALPHA); ExpectInvalidEnum(GL_ALPHA, GL_HALF_FLOAT_OES, GL_ALPHA); } TEST_F(TextureFormatTypeValidationTest, ES2WithOesTextureHalfFloat) { SetupFeatureInfo("GL_OES_texture_half_float", "OpenGL ES 2.0", false); ExpectValid(GL_RGB, GL_HALF_FLOAT_OES, GL_RGB); ExpectValid(GL_RGBA, GL_HALF_FLOAT_OES, GL_RGBA); ExpectValid(GL_LUMINANCE, GL_HALF_FLOAT_OES, GL_LUMINANCE); ExpectValid(GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_LUMINANCE_ALPHA); ExpectValid(GL_ALPHA, GL_HALF_FLOAT_OES, GL_ALPHA); ExpectInvalidEnum(GL_RGB, GL_FLOAT, GL_RGB); ExpectInvalidEnum(GL_RGBA, GL_FLOAT, GL_RGBA); ExpectInvalidEnum(GL_LUMINANCE, GL_FLOAT, GL_LUMINANCE); ExpectInvalidEnum(GL_LUMINANCE_ALPHA, GL_FLOAT, GL_LUMINANCE_ALPHA); ExpectInvalidEnum(GL_ALPHA, GL_FLOAT, GL_ALPHA); } TEST_F(TextureFormatTypeValidationTest, ES2WithOesTextureHalfFloatLinear) { SetupFeatureInfo( "GL_OES_texture_half_float GL_OES_texture_half_float_linear", "OpenGL ES 2.0", false); ExpectValid(GL_RGB, GL_HALF_FLOAT_OES, GL_RGB); ExpectValid(GL_RGBA, GL_HALF_FLOAT_OES, GL_RGBA); ExpectValid(GL_LUMINANCE, GL_HALF_FLOAT_OES, GL_LUMINANCE); ExpectValid(GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_LUMINANCE_ALPHA); ExpectValid(GL_ALPHA, GL_HALF_FLOAT_OES, GL_ALPHA); ExpectInvalidEnum(GL_RGB, GL_FLOAT, GL_RGB); ExpectInvalidEnum(GL_RGBA, GL_FLOAT, GL_RGBA); ExpectInvalidEnum(GL_LUMINANCE, GL_FLOAT, GL_LUMINANCE); ExpectInvalidEnum(GL_LUMINANCE_ALPHA, GL_FLOAT, GL_LUMINANCE_ALPHA); ExpectInvalidEnum(GL_ALPHA, GL_FLOAT, GL_ALPHA); } TEST_F(TextureFormatTypeValidationTest, ES3Basic) { SetupFeatureInfo("", "OpenGL ES 3.0", true); ExpectValid(GL_ALPHA, GL_UNSIGNED_BYTE, GL_ALPHA); ExpectValid(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_RGB); ExpectValid(GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_RGBA); ExpectValid(GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_LUMINANCE); ExpectValid(GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_LUMINANCE_ALPHA); ExpectValid(GL_RG, GL_BYTE, GL_RG8_SNORM); ExpectValid(GL_RG_INTEGER, GL_UNSIGNED_INT, GL_RG32UI); ExpectValid(GL_RG_INTEGER, GL_SHORT, GL_RG16I); ExpectValid(GL_RGB, GL_UNSIGNED_BYTE, GL_SRGB8); ExpectValid(GL_RGBA, GL_HALF_FLOAT, GL_RGBA16F); ExpectValid(GL_RGBA, GL_FLOAT, GL_RGBA16F); ExpectValid(GL_RGBA, GL_FLOAT, GL_RGBA32F); ExpectValid(GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_DEPTH_COMPONENT16); ExpectValid(GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_DEPTH_COMPONENT24); ExpectValid(GL_DEPTH_COMPONENT, GL_FLOAT, GL_DEPTH_COMPONENT32F); ExpectValid(GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_DEPTH24_STENCIL8); ExpectValid(GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_DEPTH32F_STENCIL8); ExpectInvalid(GL_RGB_INTEGER, GL_INT, GL_RGBA8); } } // namespace gles2 } // namespace gpu