summaryrefslogtreecommitdiff
path: root/chromium/gpu/command_buffer/service/texture_manager_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/gpu/command_buffer/service/texture_manager_unittest.cc')
-rw-r--r--chromium/gpu/command_buffer/service/texture_manager_unittest.cc2353
1 files changed, 2353 insertions, 0 deletions
diff --git a/chromium/gpu/command_buffer/service/texture_manager_unittest.cc b/chromium/gpu/command_buffer/service/texture_manager_unittest.cc
new file mode 100644
index 00000000000..402cc8d0eff
--- /dev/null
+++ b/chromium/gpu/command_buffer/service/texture_manager_unittest.cc
@@ -0,0 +1,2353 @@
+// 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 "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/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_mock.h"
+
+using ::testing::AtLeast;
+using ::testing::Pointee;
+using ::testing::Return;
+using ::testing::SetArgumentPointee;
+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 testing::Test {
+ public:
+ static const GLint kMaxTextureSize = 16;
+ static const GLint kMaxCubeMapTextureSize = 8;
+ static const GLint kMaxExternalTextureSize = 16;
+ static const GLint kMax2dLevels = 5;
+ static const GLint kMaxCubeMapLevels = 4;
+ static const GLint kMaxExternalLevels = 1;
+
+ TextureManagerTest()
+ : feature_info_(new FeatureInfo()) {
+ }
+
+ virtual ~TextureManagerTest() {
+ }
+
+ protected:
+ virtual void SetUp() {
+ gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>());
+ ::gfx::GLInterface::SetGLInterface(gl_.get());
+
+ manager_.reset(new TextureManager(
+ NULL, feature_info_.get(),
+ kMaxTextureSize, kMaxCubeMapTextureSize));
+ TestHelper::SetupTextureManagerInitExpectations(gl_.get(), "");
+ manager_->Initialize();
+ error_state_.reset(new ::testing::StrictMock<gles2::MockErrorState>());
+ }
+
+ virtual void TearDown() {
+ manager_->Destroy(false);
+ manager_.reset();
+ ::gfx::GLInterface::SetGLInterface(NULL);
+ gl_.reset();
+ }
+
+ void SetParameter(
+ TextureRef* texture_ref, GLenum pname, GLint value, GLenum error) {
+ TestHelper::SetTexParameterWithExpectations(
+ gl_.get(), error_state_.get(), manager_.get(),
+ texture_ref, pname, value, error);
+ }
+
+ // Use StrictMock to make 100% sure we know how GL will be called.
+ scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_;
+ scoped_refptr<FeatureInfo> feature_info_;
+ scoped_ptr<TextureManager> manager_;
+ scoped_ptr<MockErrorState> 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::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<TextureRef> 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<GLenum>(GL_NEAREST), texture->min_filter());
+ SetParameter(texture_ref, GL_TEXTURE_MAG_FILTER, GL_NEAREST, GL_NO_ERROR);
+ EXPECT_EQ(static_cast<GLenum>(GL_NEAREST), texture->mag_filter());
+ SetParameter(texture_ref, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE, GL_NO_ERROR);
+ EXPECT_EQ(static_cast<GLenum>(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<GLenum>(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<GLenum>(GL_NEAREST), texture->min_filter());
+ SetParameter(
+ texture_ref, GL_TEXTURE_MAG_FILTER, GL_CLAMP_TO_EDGE, GL_INVALID_ENUM);
+ EXPECT_EQ(static_cast<GLenum>(GL_NEAREST), texture->min_filter());
+ SetParameter(texture_ref, GL_TEXTURE_WRAP_S, GL_NEAREST, GL_INVALID_ENUM);
+ EXPECT_EQ(static_cast<GLenum>(GL_CLAMP_TO_EDGE), texture->wrap_s());
+ SetParameter(texture_ref, GL_TEXTURE_WRAP_T, GL_NEAREST, GL_INVALID_ENUM);
+ EXPECT_EQ(static_cast<GLenum>(GL_CLAMP_TO_EDGE), texture->wrap_t());
+ SetParameter(texture_ref, GL_TEXTURE_MAX_ANISOTROPY_EXT, 0, GL_INVALID_VALUE);
+}
+
+TEST_F(TextureManagerTest, TextureUsageExt) {
+ TestHelper::SetupTextureManagerInitExpectations(gl_.get(),
+ "GL_ANGLE_texture_usage");
+ TextureManager manager(
+ NULL, feature_info_.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
+ 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::SetTexParameterWithExpectations(
+ gl_.get(), error_state_.get(), &manager, texture_ref,
+ GL_TEXTURE_USAGE_ANGLE, GL_FRAMEBUFFER_ATTACHMENT_ANGLE,GL_NO_ERROR);
+ EXPECT_EQ(static_cast<GLenum>(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(), "");
+ TextureManager manager(
+ NULL, feature_info_.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
+ 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(), "");
+ 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(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<FeatureInfo> feature_info(new FeatureInfo());
+ feature_info->Initialize(NULL);
+ TextureManager manager(
+ NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
+ // 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 testing::Test {
+ public:
+ static const GLint kMaxTextureSize = 16;
+ static const GLint kMaxCubeMapTextureSize = 8;
+ static const GLint kMax2dLevels = 5;
+ static const GLint kMaxCubeMapLevels = 4;
+ static const GLuint kClient1Id = 1;
+ static const GLuint kService1Id = 11;
+
+ TextureTestBase()
+ : feature_info_(new FeatureInfo()) {
+ }
+ virtual ~TextureTestBase() {
+ texture_ref_ = NULL;
+ }
+
+ protected:
+ void SetUpBase(MemoryTracker* memory_tracker, std::string extensions) {
+ gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>());
+ ::gfx::GLInterface::SetGLInterface(gl_.get());
+
+ if (!extensions.empty()) {
+ TestHelper::SetupFeatureInfoInitExpectations(gl_.get(),
+ extensions.c_str());
+ feature_info_->Initialize(NULL);
+ }
+
+ manager_.reset(new TextureManager(
+ memory_tracker, feature_info_.get(),
+ kMaxTextureSize, kMaxCubeMapTextureSize));
+ decoder_.reset(new ::testing::StrictMock<gles2::MockGLES2Decoder>());
+ error_state_.reset(new ::testing::StrictMock<gles2::MockErrorState>());
+ manager_->CreateTexture(kClient1Id, kService1Id);
+ texture_ref_ = manager_->GetTexture(kClient1Id);
+ ASSERT_TRUE(texture_ref_.get() != NULL);
+ }
+
+ virtual void TearDown() {
+ 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();
+ ::gfx::GLInterface::SetGLInterface(NULL);
+ gl_.reset();
+ }
+
+ void SetParameter(
+ TextureRef* texture_ref, GLenum pname, GLint value, GLenum error) {
+ TestHelper::SetTexParameterWithExpectations(
+ gl_.get(), error_state_.get(), manager_.get(),
+ texture_ref, pname, value, error);
+ }
+
+ scoped_ptr<MockGLES2Decoder> decoder_;
+ scoped_ptr<MockErrorState> error_state_;
+ // Use StrictMock to make 100% sure we know how GL will be called.
+ scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_;
+ scoped_refptr<FeatureInfo> feature_info_;
+ scoped_ptr<TextureManager> manager_;
+ scoped_refptr<TextureRef> texture_ref_;
+};
+
+class TextureTest : public TextureTestBase {
+ protected:
+ virtual void SetUp() {
+ SetUpBase(NULL, std::string());
+ }
+};
+
+class TextureMemoryTrackerTest : public TextureTestBase {
+ protected:
+ virtual void SetUp() {
+ mock_memory_tracker_ = new StrictMock<MockMemoryTracker>();
+ SetUpBase(mock_memory_tracker_.get(), std::string());
+ }
+
+ scoped_refptr<MockMemoryTracker> mock_memory_tracker_;
+};
+
+#define EXPECT_MEMORY_ALLOCATION_CHANGE(old_size, new_size, pool) \
+ EXPECT_CALL(*mock_memory_tracker_.get(), \
+ TrackMemoryAllocatedChange(old_size, new_size, pool)) \
+ .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<GLenum>(GL_NEAREST_MIPMAP_LINEAR),
+ texture->min_filter());
+ EXPECT_EQ(static_cast<GLenum>(GL_LINEAR), texture->mag_filter());
+ EXPECT_EQ(static_cast<GLenum>(GL_REPEAT), texture->wrap_s());
+ EXPECT_EQ(static_cast<GLenum>(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_FALSE(manager_->CanRender(texture_ref_.get()));
+ EXPECT_TRUE(texture->SafeToRenderFrom());
+ EXPECT_TRUE(texture->IsImmutable());
+ manager_->SetStreamTexture(texture_ref_.get(), true);
+ EXPECT_TRUE(manager_->CanRender(texture_ref_.get()));
+}
+
+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,
+ true);
+ 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,
+ true);
+ 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,
+ true);
+ 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,
+ true);
+ 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, MemoryTracker::kUnmanaged);
+ manager_->SetLevelInfo(texture_ref_.get(),
+ GL_TEXTURE_2D,
+ 0,
+ GL_RGBA,
+ 8,
+ 4,
+ 1,
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ true);
+ EXPECT_MEMORY_ALLOCATION_CHANGE(128, 0, MemoryTracker::kUnmanaged);
+ EXPECT_MEMORY_ALLOCATION_CHANGE(0, 256, MemoryTracker::kUnmanaged);
+ manager_->SetLevelInfo(texture_ref_.get(),
+ GL_TEXTURE_2D,
+ 2,
+ GL_RGBA,
+ 8,
+ 4,
+ 1,
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ true);
+ // Add expectation for texture deletion.
+ EXPECT_MEMORY_ALLOCATION_CHANGE(256, 0, MemoryTracker::kUnmanaged);
+ EXPECT_MEMORY_ALLOCATION_CHANGE(0, 0, MemoryTracker::kUnmanaged);
+}
+
+TEST_F(TextureMemoryTrackerTest, SetParameterPool) {
+ manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D);
+ EXPECT_MEMORY_ALLOCATION_CHANGE(0, 128, MemoryTracker::kUnmanaged);
+ manager_->SetLevelInfo(texture_ref_.get(),
+ GL_TEXTURE_2D,
+ 0,
+ GL_RGBA,
+ 8,
+ 4,
+ 1,
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ true);
+ EXPECT_MEMORY_ALLOCATION_CHANGE(128, 0, MemoryTracker::kUnmanaged);
+ EXPECT_MEMORY_ALLOCATION_CHANGE(0, 128, MemoryTracker::kManaged);
+ SetParameter(texture_ref_.get(),
+ GL_TEXTURE_POOL_CHROMIUM,
+ GL_TEXTURE_POOL_MANAGED_CHROMIUM,
+ GL_NO_ERROR);
+ // Add expectation for texture deletion.
+ EXPECT_MEMORY_ALLOCATION_CHANGE(128, 0, MemoryTracker::kManaged);
+ EXPECT_MEMORY_ALLOCATION_CHANGE(0, 0, MemoryTracker::kUnmanaged);
+ EXPECT_MEMORY_ALLOCATION_CHANGE(0, 0, MemoryTracker::kManaged);
+}
+
+TEST_F(TextureTest, POT2D) {
+ manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D);
+ Texture* texture = texture_ref_->texture();
+ EXPECT_EQ(static_cast<GLenum>(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,
+ true);
+ EXPECT_FALSE(TextureTestHelper::IsNPOT(texture));
+ EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture));
+ EXPECT_FALSE(manager_->CanRender(texture_ref_.get()));
+ EXPECT_EQ(0, texture->num_uncleared_mips());
+ 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,
+ true);
+ 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,
+ true);
+ 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, MemoryTracker::kUnmanaged);
+ manager_->SetLevelInfo(texture_ref_.get(),
+ GL_TEXTURE_2D,
+ 0,
+ GL_RGBA,
+ 4,
+ 4,
+ 1,
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ true);
+ EXPECT_MEMORY_ALLOCATION_CHANGE(64, 0, MemoryTracker::kUnmanaged);
+ EXPECT_MEMORY_ALLOCATION_CHANGE(0, 84, MemoryTracker::kUnmanaged);
+ EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_ref_.get()));
+ EXPECT_MEMORY_ALLOCATION_CHANGE(84, 0, MemoryTracker::kUnmanaged);
+ EXPECT_MEMORY_ALLOCATION_CHANGE(0, 0, MemoryTracker::kUnmanaged);
+}
+
+TEST_F(TextureTest, UnusedMips) {
+ manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_2D);
+ Texture* texture = texture_ref_->texture();
+ EXPECT_EQ(static_cast<GLenum>(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,
+ true);
+ 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,
+ true);
+ 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,
+ true);
+ 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<GLenum>(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,
+ true);
+ 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,
+ true);
+ 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<FeatureInfo> feature_info(new FeatureInfo());
+ feature_info->Initialize(NULL);
+ TextureManager manager(
+ NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
+ 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<GLenum>(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, true);
+ 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<GLenum>(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,
+ true);
+ 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,
+ true);
+ 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,
+ true);
+ 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,
+ true);
+ 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,
+ true);
+ 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,
+ true);
+ 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,
+ true);
+ 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,
+ true);
+ 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, GetLevelSize) {
+ 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,
+ true);
+ GLsizei width = -1;
+ GLsizei height = -1;
+ Texture* texture = texture_ref_->texture();
+ EXPECT_FALSE(texture->GetLevelSize(GL_TEXTURE_2D, -1, &width, &height));
+ EXPECT_FALSE(texture->GetLevelSize(GL_TEXTURE_2D, 1000, &width, &height));
+ EXPECT_FALSE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height));
+ EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 1, &width, &height));
+ EXPECT_EQ(4, width);
+ EXPECT_EQ(5, height);
+ manager_->RemoveTexture(kClient1Id);
+ EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 1, &width, &height));
+ EXPECT_EQ(4, width);
+ EXPECT_EQ(5, height);
+}
+
+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,
+ true);
+ GLenum type = -1;
+ GLenum format = -1;
+ 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<GLenum>(GL_UNSIGNED_BYTE), type);
+ EXPECT_EQ(static_cast<GLenum>(GL_RGBA), format);
+ manager_->RemoveTexture(kClient1Id);
+ EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 1, &type, &format));
+ EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type);
+ EXPECT_EQ(static_cast<GLenum>(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,
+ 1,
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ true);
+ // Check bad face.
+ Texture* texture = texture_ref_->texture();
+ EXPECT_FALSE(texture->ValidForTexture(
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
+ 1, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
+ // Check bad level.
+ EXPECT_FALSE(texture->ValidForTexture(
+ GL_TEXTURE_2D, 0, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
+ // Check bad xoffset.
+ EXPECT_FALSE(texture->ValidForTexture(
+ GL_TEXTURE_2D, 1, -1, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
+ // Check bad xoffset + width > width.
+ EXPECT_FALSE(texture->ValidForTexture(
+ GL_TEXTURE_2D, 1, 1, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
+ // Check bad yoffset.
+ EXPECT_FALSE(texture->ValidForTexture(
+ GL_TEXTURE_2D, 1, 0, -1, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
+ // Check bad yoffset + height > height.
+ EXPECT_FALSE(texture->ValidForTexture(
+ GL_TEXTURE_2D, 1, 0, 1, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
+ // Check bad width.
+ EXPECT_FALSE(texture->ValidForTexture(
+ GL_TEXTURE_2D, 1, 0, 0, 5, 5, GL_RGBA, GL_UNSIGNED_BYTE));
+ // Check bad height.
+ EXPECT_FALSE(texture->ValidForTexture(
+ GL_TEXTURE_2D, 1, 0, 0, 4, 6, GL_RGBA, GL_UNSIGNED_BYTE));
+ // Check bad format.
+ EXPECT_FALSE(texture->ValidForTexture(
+ GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_RGB, GL_UNSIGNED_BYTE));
+ // Check bad type.
+ EXPECT_FALSE(texture->ValidForTexture(
+ GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4));
+ // Check valid full size
+ EXPECT_TRUE(texture->ValidForTexture(
+ GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
+ // Check valid particial size.
+ EXPECT_TRUE(texture->ValidForTexture(
+ GL_TEXTURE_2D, 1, 1, 1, 2, 3, GL_RGBA, GL_UNSIGNED_BYTE));
+ manager_->RemoveTexture(kClient1Id);
+ EXPECT_TRUE(texture->ValidForTexture(
+ GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
+}
+
+TEST_F(TextureTest, FloatNotLinear) {
+ TestHelper::SetupFeatureInfoInitExpectations(
+ gl_.get(), "GL_OES_texture_float");
+ scoped_refptr<FeatureInfo> feature_info(new FeatureInfo());
+ feature_info->Initialize(NULL);
+ TextureManager manager(
+ NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
+ 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<GLenum>(GL_TEXTURE_2D), texture->target());
+ manager.SetLevelInfo(texture_ref,
+ GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_FLOAT, true);
+ EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture));
+ TestHelper::SetTexParameterWithExpectations(
+ gl_.get(), error_state_.get(), &manager,
+ texture_ref, GL_TEXTURE_MAG_FILTER, GL_NEAREST, GL_NO_ERROR);
+ EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture));
+ TestHelper::SetTexParameterWithExpectations(
+ 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<FeatureInfo> feature_info(new FeatureInfo());
+ feature_info->Initialize(NULL);
+ TextureManager manager(
+ NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
+ 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<GLenum>(GL_TEXTURE_2D), texture->target());
+ manager.SetLevelInfo(texture_ref,
+ GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_FLOAT, true);
+ EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture));
+ manager.Destroy(false);
+}
+
+TEST_F(TextureTest, HalfFloatNotLinear) {
+ TestHelper::SetupFeatureInfoInitExpectations(
+ gl_.get(), "GL_OES_texture_half_float");
+ scoped_refptr<FeatureInfo> feature_info(new FeatureInfo());
+ feature_info->Initialize(NULL);
+ TextureManager manager(
+ NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
+ 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<GLenum>(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, true);
+ EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture));
+ TestHelper::SetTexParameterWithExpectations(
+ gl_.get(), error_state_.get(), &manager,
+ texture_ref, GL_TEXTURE_MAG_FILTER, GL_NEAREST, GL_NO_ERROR);
+ EXPECT_FALSE(TextureTestHelper::IsTextureComplete(texture));
+ TestHelper::SetTexParameterWithExpectations(
+ 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<FeatureInfo> feature_info(new FeatureInfo());
+ feature_info->Initialize(NULL);
+ TextureManager manager(
+ NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
+ 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<GLenum>(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, true);
+ EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture));
+ manager.Destroy(false);
+}
+
+TEST_F(TextureTest, EGLImageExternal) {
+ TestHelper::SetupFeatureInfoInitExpectations(
+ gl_.get(), "GL_OES_EGL_image_external");
+ scoped_refptr<FeatureInfo> feature_info(new FeatureInfo());
+ feature_info->Initialize(NULL);
+ TextureManager manager(
+ NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
+ 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<GLenum>(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<FeatureInfo> feature_info(new FeatureInfo());
+ feature_info->Initialize(NULL);
+ TextureManager manager(
+ NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
+ 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, false);
+ 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,
+ false);
+ 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,
+ false);
+ 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,
+ false);
+ manager_->SetLevelInfo(texture_ref_.get(),
+ GL_TEXTURE_2D,
+ 1,
+ GL_RGBA,
+ 8,
+ 8,
+ 1,
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ false);
+ 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,
+ false);
+ 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<TextureRef> 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,
+ true);
+ 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,
+ false);
+ EXPECT_TRUE(manager_->HaveUnsafeTextures());
+ EXPECT_TRUE(manager_->HaveUnclearedMips());
+ EXPECT_EQ(1, texture2->num_uncleared_mips());
+
+ manager_->CreateTexture(kClient3Id, kService3Id);
+ scoped_refptr<TextureRef> 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,
+ false);
+ 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,
+ false);
+ manager_->SetLevelInfo(texture_ref3.get(),
+ GL_TEXTURE_2D,
+ 0,
+ GL_RGBA,
+ 8,
+ 8,
+ 1,
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ false);
+ 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,
+ false);
+ manager_->SetLevelInfo(texture_ref_.get(),
+ GL_TEXTURE_2D,
+ 1,
+ GL_RGBA,
+ 4,
+ 4,
+ 1,
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ false);
+ 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,
+ false);
+ manager_->SetLevelInfo(texture_ref_.get(),
+ GL_TEXTURE_2D,
+ 1,
+ GL_RGBA,
+ 4,
+ 4,
+ 1,
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ false);
+ 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,
+ false);
+ EXPECT_FALSE(manager_->HaveUnrenderableTextures());
+ // Make a new texture
+ manager_->CreateTexture(kClient2Id, kService2Id);
+ scoped_refptr<TextureRef> 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,
+ false);
+ 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,
+ true);
+ Texture* texture = texture_ref_->texture();
+ EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 1) == NULL);
+ // Set image.
+ manager_->SetLevelImage(texture_ref_.get(),
+ GL_TEXTURE_2D,
+ 1,
+ gfx::GLImage::CreateGLImage(0).get());
+ EXPECT_FALSE(texture->GetLevelImage(GL_TEXTURE_2D, 1) == NULL);
+ // Remove it.
+ manager_->SetLevelImage(texture_ref_.get(), GL_TEXTURE_2D, 1, NULL);
+ EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 1) == NULL);
+ manager_->SetLevelImage(texture_ref_.get(),
+ GL_TEXTURE_2D,
+ 1,
+ gfx::GLImage::CreateGLImage(0).get());
+ // 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,
+ true);
+ EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 1) == NULL);
+}
+
+namespace {
+
+bool InSet(std::set<std::string>* string_set, const std::string& str) {
+ std::pair<std::set<std::string>::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,
+ true);
+ std::string signature1;
+ std::string signature2;
+ manager_->AddToSignature(texture_ref_.get(), GL_TEXTURE_2D, 1, &signature1);
+
+ std::set<std::string> 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,
+ true);
+ 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,
+ true);
+ 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,
+ false);
+ 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,
+ false);
+ 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,
+ false);
+ 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,
+ false);
+ 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,
+ false);
+ 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,
+ false);
+ 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,
+ false);
+ 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:
+ virtual void SetUp() {
+ 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()));
+ }
+
+ virtual void TearDown() {
+ 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,
+ bool cleared)
+ : target(target),
+ format(format),
+ width(width),
+ height(height),
+ depth(depth),
+ border(border),
+ type(type),
+ cleared(cleared) {}
+
+ LevelInfo()
+ : target(0),
+ format(0),
+ width(-1),
+ height(-1),
+ depth(1),
+ border(0),
+ type(0),
+ cleared(false) {}
+
+ 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 == other.cleared;
+ }
+
+ GLenum target;
+ GLenum format;
+ GLsizei width;
+ GLsizei height;
+ GLsizei depth;
+ GLint border;
+ GLenum type;
+ bool cleared;
+ };
+
+ 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);
+ }
+
+ 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));
+ EXPECT_TRUE(texture->GetLevelType(target, level, &info.type,
+ &info.format));
+ info.cleared = texture->IsLevelCleared(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<TextureRef> 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<GLenum>(GL_TEXTURE_2D), texture->target());
+ LevelInfo level0(
+ GL_TEXTURE_2D, GL_RGBA, 4, 4, 1, 0, GL_UNSIGNED_BYTE, true);
+ 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, false));
+ 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<TextureRef> 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));
+
+ // 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<GLenum>(GL_TEXTURE_RECTANGLE_ARB), texture->target());
+ LevelInfo level0(
+ GL_TEXTURE_RECTANGLE_ARB, GL_RGBA, 1, 1, 1, 0, GL_UNSIGNED_BYTE, false);
+ 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<GLenum>(GL_TEXTURE_RECTANGLE_ARB),
+ produced_texture->target());
+
+ GLuint client_id = texture2_->client_id();
+ manager_->RemoveTexture(client_id);
+ Consume(client_id, produced_texture);
+ scoped_refptr<TextureRef> 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, ProduceConsumeStreamTexture) {
+ manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_EXTERNAL_OES);
+ Texture* texture = texture_ref_->texture();
+ EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), texture->target());
+ manager_->SetStreamTexture(texture_ref_.get(), true);
+ GLuint service_id = texture->service_id();
+ Texture* produced_texture = Produce(texture_ref_.get());
+ EXPECT_TRUE(texture->IsStreamTexture());
+
+ GLuint client_id = texture2_->client_id();
+ manager_->RemoveTexture(client_id);
+ Consume(client_id, produced_texture);
+ scoped_refptr<TextureRef> restored_texture = manager_->GetTexture(client_id);
+ EXPECT_EQ(produced_texture, restored_texture->texture());
+ EXPECT_TRUE(restored_texture->texture()->IsStreamTexture());
+ EXPECT_TRUE(restored_texture->texture()->IsImmutable());
+ EXPECT_EQ(service_id, restored_texture->service_id());
+}
+
+TEST_F(ProduceConsumeTextureTest, ProduceConsumeCube) {
+ manager_->SetTarget(texture_ref_.get(), GL_TEXTURE_CUBE_MAP);
+ Texture* texture = texture_ref_->texture();
+ EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP), texture->target());
+ LevelInfo face0(GL_TEXTURE_CUBE_MAP_POSITIVE_X,
+ GL_RGBA,
+ 1,
+ 1,
+ 1,
+ 0,
+ GL_UNSIGNED_BYTE,
+ true);
+ LevelInfo face5(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
+ GL_RGBA,
+ 3,
+ 3,
+ 1,
+ 0,
+ GL_UNSIGNED_BYTE,
+ true);
+ 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<TextureRef> 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] = 0;
+ current_size_[1] = 0;
+ }
+
+ virtual void TrackMemoryAllocatedChange(size_t old_size,
+ size_t new_size,
+ Pool pool) OVERRIDE {
+ DCHECK_LT(static_cast<size_t>(pool), arraysize(current_size_));
+ current_size_[pool] += new_size - old_size;
+ }
+
+ virtual bool EnsureGPUMemoryAvailable(size_t size_needed) OVERRIDE {
+ return true;
+ }
+
+ size_t GetSize(Pool pool) {
+ DCHECK_LT(static_cast<size_t>(pool), arraysize(current_size_));
+ return current_size_[pool];
+ }
+
+ private:
+ virtual ~CountingMemoryTracker() {}
+
+ size_t current_size_[2];
+ DISALLOW_COPY_AND_ASSIGN(CountingMemoryTracker);
+};
+
+class SharedTextureTest : public testing::Test {
+ public:
+ SharedTextureTest()
+ : feature_info_(new FeatureInfo()) {
+ }
+
+ virtual ~SharedTextureTest() {
+ }
+
+ virtual void SetUp() {
+ gl_.reset(new ::gfx::MockGLInterface());
+ ::gfx::GLInterface::SetGLInterface(gl_.get());
+
+ memory_tracker1_ = new CountingMemoryTracker;
+ texture_manager1_.reset(
+ new TextureManager(memory_tracker1_.get(),
+ feature_info_.get(),
+ TextureManagerTest::kMaxTextureSize,
+ TextureManagerTest::kMaxCubeMapTextureSize));
+ memory_tracker2_ = new CountingMemoryTracker;
+ texture_manager2_.reset(
+ new TextureManager(memory_tracker2_.get(),
+ feature_info_.get(),
+ TextureManagerTest::kMaxTextureSize,
+ TextureManagerTest::kMaxCubeMapTextureSize));
+ TestHelper::SetupTextureManagerInitExpectations(gl_.get(), "");
+ texture_manager1_->Initialize();
+ TestHelper::SetupTextureManagerInitExpectations(gl_.get(), "");
+ texture_manager2_->Initialize();
+ }
+
+ virtual void TearDown() {
+ texture_manager2_->Destroy(false);
+ texture_manager2_.reset();
+ texture_manager1_->Destroy(false);
+ texture_manager1_.reset();
+ ::gfx::GLInterface::SetGLInterface(NULL);
+ gl_.reset();
+ }
+
+ protected:
+ scoped_ptr< ::gfx::MockGLInterface > gl_;
+ scoped_refptr<FeatureInfo> feature_info_;
+ scoped_refptr<CountingMemoryTracker> memory_tracker1_;
+ scoped_ptr<TextureManager> texture_manager1_;
+ scoped_refptr<CountingMemoryTracker> memory_tracker2_;
+ scoped_ptr<TextureManager> texture_manager2_;
+};
+
+TEST_F(SharedTextureTest, DeleteTextures) {
+ scoped_refptr<TextureRef> ref1 = texture_manager1_->CreateTexture(10, 10);
+ scoped_refptr<TextureRef> 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<TextureRef> 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<TextureRef> 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,
+ false);
+ 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);
+ texture_manager1_->set_framebuffer_manager(&framebuffer_manager1);
+ FramebufferManager framebuffer_manager2(1, 1);
+ texture_manager2_->set_framebuffer_manager(&framebuffer_manager2);
+
+ scoped_refptr<TextureRef> ref1 = texture_manager1_->CreateTexture(10, 10);
+ framebuffer_manager1.CreateFramebuffer(10, 10);
+ scoped_refptr<Framebuffer> 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,
+ true);
+ EXPECT_EQ(kCompleteValue, framebuffer1->IsPossiblyComplete());
+ framebuffer_manager1.MarkAsComplete(framebuffer1.get());
+ EXPECT_TRUE(framebuffer_manager1.IsComplete(framebuffer1.get()));
+
+ // Share texture with manager 2.
+ scoped_refptr<TextureRef> ref2 =
+ texture_manager2_->Consume(20, ref1->texture());
+ framebuffer_manager2.CreateFramebuffer(20, 20);
+ scoped_refptr<Framebuffer> 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,
+ true);
+ 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(MemoryTracker::kUnmanaged);
+ size_t initial_memory2 = memory_tracker2_->GetSize(MemoryTracker::kUnmanaged);
+
+ // Newly created texture is unrenderable.
+ scoped_refptr<TextureRef> 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,
+ false);
+
+ EXPECT_LT(0u, ref1->texture()->estimated_size());
+ EXPECT_EQ(initial_memory1 + ref1->texture()->estimated_size(),
+ memory_tracker1_->GetSize(MemoryTracker::kUnmanaged));
+
+ // 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<TextureRef> ref2 =
+ texture_manager2_->Consume(20, ref1->texture());
+ EXPECT_EQ(initial_memory1 + ref1->texture()->estimated_size(),
+ memory_tracker1_->GetSize(MemoryTracker::kUnmanaged));
+ EXPECT_EQ(initial_memory2,
+ memory_tracker2_->GetSize(MemoryTracker::kUnmanaged));
+
+ // Delete the texture, memory should go to the remaining tracker.
+ texture_manager1_->RemoveTexture(10);
+ ref1 = NULL;
+ EXPECT_EQ(initial_memory1,
+ memory_tracker1_->GetSize(MemoryTracker::kUnmanaged));
+ EXPECT_EQ(initial_memory2 + ref2->texture()->estimated_size(),
+ memory_tracker2_->GetSize(MemoryTracker::kUnmanaged));
+
+ EXPECT_CALL(*gl_, DeleteTextures(1, _))
+ .Times(1)
+ .RetiresOnSaturation();
+ ref2 = NULL;
+ texture_manager2_->RemoveTexture(20);
+ EXPECT_EQ(initial_memory2,
+ memory_tracker2_->GetSize(MemoryTracker::kUnmanaged));
+}
+
+} // namespace gles2
+} // namespace gpu