texture_manager_unittest.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "gpu/command_buffer/service/texture_manager.h"
6
7#include "base/memory/scoped_ptr.h"
8#include "gpu/command_buffer/service/feature_info.h"
9#include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h"
10#include "gpu/command_buffer/service/memory_tracking.h"
11#include "gpu/command_buffer/service/mocks.h"
12#include "gpu/command_buffer/service/test_helper.h"
13#include "gpu/command_buffer/service/texture_definition.h"
14#include "testing/gtest/include/gtest/gtest.h"
15#include "ui/gl/gl_mock.h"
16
17using ::testing::AtLeast;
18using ::testing::Pointee;
19using ::testing::Return;
20using ::testing::SetArgumentPointee;
21using ::testing::StrictMock;
22using ::testing::_;
23
24namespace gpu {
25namespace gles2 {
26
27class TextureManagerTest : public testing::Test {
28 public:
29  static const GLint kMaxTextureSize = 16;
30  static const GLint kMaxCubeMapTextureSize = 8;
31  static const GLint kMaxExternalTextureSize = 16;
32  static const GLint kMax2dLevels = 5;
33  static const GLint kMaxCubeMapLevels = 4;
34  static const GLint kMaxExternalLevels = 1;
35
36  TextureManagerTest()
37      : feature_info_(new FeatureInfo()) {
38  }
39
40  virtual ~TextureManagerTest() {
41  }
42
43 protected:
44  virtual void SetUp() {
45    gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>());
46    ::gfx::GLInterface::SetGLInterface(gl_.get());
47
48    manager_.reset(new TextureManager(
49        NULL, feature_info_.get(),
50        kMaxTextureSize, kMaxCubeMapTextureSize));
51    TestHelper::SetupTextureManagerInitExpectations(gl_.get(), "");
52    manager_->Initialize();
53    decoder_.reset(new ::testing::StrictMock<gles2::MockGLES2Decoder>());
54  }
55
56  virtual void TearDown() {
57    manager_->Destroy(false);
58    manager_.reset();
59    ::gfx::GLInterface::SetGLInterface(NULL);
60    gl_.reset();
61  }
62
63  void SetParameter(
64      Texture* texture, GLenum pname, GLint value, GLenum error) {
65    TestHelper::SetTexParameterWithExpectations(
66        gl_.get(), decoder_.get(), manager_.get(),
67        texture, pname, value, error);
68  }
69
70  // Use StrictMock to make 100% sure we know how GL will be called.
71  scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_;
72  scoped_refptr<FeatureInfo> feature_info_;
73  scoped_ptr<TextureManager> manager_;
74  scoped_ptr<MockGLES2Decoder> decoder_;
75};
76
77// GCC requires these declarations, but MSVC requires they not be present
78#ifndef COMPILER_MSVC
79const GLint TextureManagerTest::kMaxTextureSize;
80const GLint TextureManagerTest::kMaxCubeMapTextureSize;
81const GLint TextureManagerTest::kMaxExternalTextureSize;
82const GLint TextureManagerTest::kMax2dLevels;
83const GLint TextureManagerTest::kMaxCubeMapLevels;
84const GLint TextureManagerTest::kMaxExternalLevels;
85#endif
86
87TEST_F(TextureManagerTest, Basic) {
88  const GLuint kClient1Id = 1;
89  const GLuint kService1Id = 11;
90  const GLuint kClient2Id = 2;
91  EXPECT_FALSE(manager_->HaveUnrenderableTextures());
92  EXPECT_FALSE(manager_->HaveUnsafeTextures());
93  EXPECT_FALSE(manager_->HaveUnclearedMips());
94  // Check we can create texture.
95  manager_->CreateTexture(kClient1Id, kService1Id);
96  // Check texture got created.
97  Texture* texture = manager_->GetTexture(kClient1Id);
98  ASSERT_TRUE(texture != NULL);
99  EXPECT_EQ(kService1Id, texture->service_id());
100  GLuint client_id = 0;
101  EXPECT_TRUE(manager_->GetClientId(texture->service_id(), &client_id));
102  EXPECT_EQ(kClient1Id, client_id);
103  // Check we get nothing for a non-existent texture.
104  EXPECT_TRUE(manager_->GetTexture(kClient2Id) == NULL);
105  // Check trying to a remove non-existent textures does not crash.
106  manager_->RemoveTexture(kClient2Id);
107  // Check that it gets deleted when the last reference is released.
108  EXPECT_CALL(*gl_, DeleteTextures(1, ::testing::Pointee(kService1Id)))
109      .Times(1)
110      .RetiresOnSaturation();
111  // Check we can't get the texture after we remove it.
112  manager_->RemoveTexture(kClient1Id);
113  EXPECT_TRUE(manager_->GetTexture(kClient1Id) == NULL);
114}
115
116TEST_F(TextureManagerTest, SetParameter) {
117  const GLuint kClient1Id = 1;
118  const GLuint kService1Id = 11;
119  // Check we can create texture.
120  manager_->CreateTexture(kClient1Id, kService1Id);
121  // Check texture got created.
122  Texture* texture = manager_->GetTexture(kClient1Id);
123  manager_->SetTarget(texture, GL_TEXTURE_2D);
124  ASSERT_TRUE(texture != NULL);
125  SetParameter(texture, GL_TEXTURE_MIN_FILTER, GL_NEAREST, GL_NO_ERROR);
126  EXPECT_EQ(static_cast<GLenum>(GL_NEAREST), texture->min_filter());
127  SetParameter(texture, GL_TEXTURE_MAG_FILTER, GL_NEAREST, GL_NO_ERROR);
128  EXPECT_EQ(static_cast<GLenum>(GL_NEAREST), texture->mag_filter());
129  SetParameter(texture, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE, GL_NO_ERROR);
130  EXPECT_EQ(static_cast<GLenum>(GL_CLAMP_TO_EDGE), texture->wrap_s());
131  SetParameter(texture, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE, GL_NO_ERROR);
132  EXPECT_EQ(static_cast<GLenum>(GL_CLAMP_TO_EDGE), texture->wrap_t());
133  SetParameter(texture, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1, GL_NO_ERROR);
134  SetParameter(texture, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2, GL_NO_ERROR);
135  SetParameter(
136      texture, GL_TEXTURE_MIN_FILTER, GL_CLAMP_TO_EDGE, GL_INVALID_ENUM);
137  EXPECT_EQ(static_cast<GLenum>(GL_NEAREST), texture->min_filter());
138  SetParameter(
139      texture, GL_TEXTURE_MAG_FILTER, GL_CLAMP_TO_EDGE, GL_INVALID_ENUM);
140  EXPECT_EQ(static_cast<GLenum>(GL_NEAREST), texture->min_filter());
141  SetParameter(texture, GL_TEXTURE_WRAP_S, GL_NEAREST, GL_INVALID_ENUM);
142  EXPECT_EQ(static_cast<GLenum>(GL_CLAMP_TO_EDGE), texture->wrap_s());
143  SetParameter(texture, GL_TEXTURE_WRAP_T, GL_NEAREST, GL_INVALID_ENUM);
144  EXPECT_EQ(static_cast<GLenum>(GL_CLAMP_TO_EDGE), texture->wrap_t());
145  SetParameter(texture, GL_TEXTURE_MAX_ANISOTROPY_EXT, 0, GL_INVALID_VALUE);
146}
147
148TEST_F(TextureManagerTest, TextureUsageExt) {
149  TestHelper::SetupTextureManagerInitExpectations(gl_.get(),
150                                                  "GL_ANGLE_texture_usage");
151  TextureManager manager(
152      NULL, feature_info_.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
153  manager.Initialize();
154  const GLuint kClient1Id = 1;
155  const GLuint kService1Id = 11;
156  // Check we can create texture.
157  manager.CreateTexture(kClient1Id, kService1Id);
158  // Check texture got created.
159  Texture* texture = manager.GetTexture(kClient1Id);
160  ASSERT_TRUE(texture != NULL);
161  TestHelper::SetTexParameterWithExpectations(
162      gl_.get(), decoder_.get(), &manager, texture,
163      GL_TEXTURE_USAGE_ANGLE, GL_FRAMEBUFFER_ATTACHMENT_ANGLE,GL_NO_ERROR);
164  EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_ATTACHMENT_ANGLE),
165            texture->usage());
166  manager.Destroy(false);
167}
168
169TEST_F(TextureManagerTest, Destroy) {
170  const GLuint kClient1Id = 1;
171  const GLuint kService1Id = 11;
172  TestHelper::SetupTextureManagerInitExpectations(gl_.get(), "");
173  TextureManager manager(
174      NULL, feature_info_.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
175  manager.Initialize();
176  // Check we can create texture.
177  manager.CreateTexture(kClient1Id, kService1Id);
178  // Check texture got created.
179  Texture* texture = manager.GetTexture(kClient1Id);
180  ASSERT_TRUE(texture != NULL);
181  EXPECT_CALL(*gl_, DeleteTextures(1, ::testing::Pointee(kService1Id)))
182      .Times(1)
183      .RetiresOnSaturation();
184  TestHelper::SetupTextureManagerDestructionExpectations(gl_.get(), "");
185  manager.Destroy(true);
186  // Check that resources got freed.
187  texture = manager.GetTexture(kClient1Id);
188  ASSERT_TRUE(texture == NULL);
189}
190
191TEST_F(TextureManagerTest, DestroyUnowned) {
192  const GLuint kClient1Id = 1;
193  const GLuint kService1Id = 11;
194  TestHelper::SetupTextureManagerInitExpectations(gl_.get(), "");
195  TextureManager manager(
196      NULL, feature_info_.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
197  manager.Initialize();
198  // Check we can create texture.
199  Texture* created_texture =
200      manager.CreateTexture(kClient1Id, kService1Id);
201  created_texture->SetNotOwned();
202
203  // Check texture got created.
204  Texture* texture = manager.GetTexture(kClient1Id);
205  ASSERT_TRUE(texture != NULL);
206
207  // Check that it is not freed if it is not owned.
208  TestHelper::SetupTextureManagerDestructionExpectations(gl_.get(), "");
209  manager.Destroy(true);
210  texture = manager.GetTexture(kClient1Id);
211  ASSERT_TRUE(texture == NULL);
212}
213
214TEST_F(TextureManagerTest, MaxValues) {
215  // Check we get the right values for the max sizes.
216  EXPECT_EQ(kMax2dLevels, manager_->MaxLevelsForTarget(GL_TEXTURE_2D));
217  EXPECT_EQ(kMaxCubeMapLevels,
218            manager_->MaxLevelsForTarget(GL_TEXTURE_CUBE_MAP));
219  EXPECT_EQ(kMaxCubeMapLevels,
220            manager_->MaxLevelsForTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X));
221  EXPECT_EQ(kMaxCubeMapLevels,
222            manager_->MaxLevelsForTarget(GL_TEXTURE_CUBE_MAP_NEGATIVE_X));
223  EXPECT_EQ(kMaxCubeMapLevels,
224            manager_->MaxLevelsForTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_Y));
225  EXPECT_EQ(kMaxCubeMapLevels,
226            manager_->MaxLevelsForTarget(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y));
227  EXPECT_EQ(kMaxCubeMapLevels,
228            manager_->MaxLevelsForTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_Z));
229  EXPECT_EQ(kMaxCubeMapLevels,
230            manager_->MaxLevelsForTarget(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z));
231  EXPECT_EQ(kMaxExternalLevels,
232            manager_->MaxLevelsForTarget(GL_TEXTURE_EXTERNAL_OES));
233  EXPECT_EQ(kMaxTextureSize, manager_->MaxSizeForTarget(GL_TEXTURE_2D));
234  EXPECT_EQ(kMaxCubeMapTextureSize,
235            manager_->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP));
236  EXPECT_EQ(kMaxCubeMapTextureSize,
237            manager_->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X));
238  EXPECT_EQ(kMaxCubeMapTextureSize,
239            manager_->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP_NEGATIVE_X));
240  EXPECT_EQ(kMaxCubeMapTextureSize,
241            manager_->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_Y));
242  EXPECT_EQ(kMaxCubeMapTextureSize,
243            manager_->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y));
244  EXPECT_EQ(kMaxCubeMapTextureSize,
245            manager_->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_Z));
246  EXPECT_EQ(kMaxCubeMapTextureSize,
247            manager_->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z));
248  EXPECT_EQ(kMaxExternalTextureSize,
249            manager_->MaxSizeForTarget(GL_TEXTURE_EXTERNAL_OES));
250}
251
252TEST_F(TextureManagerTest, ValidForTarget) {
253  // check 2d
254  EXPECT_TRUE(manager_->ValidForTarget(
255      GL_TEXTURE_2D, 0, kMaxTextureSize, kMaxTextureSize, 1));
256  EXPECT_TRUE(manager_->ValidForTarget(
257      GL_TEXTURE_2D, kMax2dLevels - 1, 1, 1, 1));
258  EXPECT_FALSE(manager_->ValidForTarget(
259      GL_TEXTURE_2D, kMax2dLevels - 1, 1, 2, 1));
260  EXPECT_FALSE(manager_->ValidForTarget(
261      GL_TEXTURE_2D, kMax2dLevels - 1, 2, 1, 1));
262  // check level out of range.
263  EXPECT_FALSE(manager_->ValidForTarget(
264      GL_TEXTURE_2D, kMax2dLevels, kMaxTextureSize, 1, 1));
265  // check has depth.
266  EXPECT_FALSE(manager_->ValidForTarget(
267      GL_TEXTURE_2D, kMax2dLevels, kMaxTextureSize, 1, 2));
268  // Check NPOT width on level 0
269  EXPECT_TRUE(manager_->ValidForTarget(GL_TEXTURE_2D, 0, 5, 2, 1));
270  // Check NPOT height on level 0
271  EXPECT_TRUE(manager_->ValidForTarget(GL_TEXTURE_2D, 0, 2, 5, 1));
272  // Check NPOT width on level 1
273  EXPECT_FALSE(manager_->ValidForTarget(GL_TEXTURE_2D, 1, 5, 2, 1));
274  // Check NPOT height on level 1
275  EXPECT_FALSE(manager_->ValidForTarget(GL_TEXTURE_2D, 1, 2, 5, 1));
276
277  // check cube
278  EXPECT_TRUE(manager_->ValidForTarget(
279      GL_TEXTURE_CUBE_MAP, 0,
280      kMaxCubeMapTextureSize, kMaxCubeMapTextureSize, 1));
281  EXPECT_TRUE(manager_->ValidForTarget(
282      GL_TEXTURE_CUBE_MAP, kMaxCubeMapLevels - 1, 1, 1, 1));
283  EXPECT_FALSE(manager_->ValidForTarget(
284      GL_TEXTURE_CUBE_MAP, kMaxCubeMapLevels - 1, 2, 2, 1));
285  // check level out of range.
286  EXPECT_FALSE(manager_->ValidForTarget(
287      GL_TEXTURE_CUBE_MAP, kMaxCubeMapLevels,
288      kMaxCubeMapTextureSize, 1, 1));
289  // check not square.
290  EXPECT_FALSE(manager_->ValidForTarget(
291      GL_TEXTURE_CUBE_MAP, kMaxCubeMapLevels,
292      kMaxCubeMapTextureSize, 1, 1));
293  // check has depth.
294  EXPECT_FALSE(manager_->ValidForTarget(
295      GL_TEXTURE_CUBE_MAP, kMaxCubeMapLevels,
296      kMaxCubeMapTextureSize, 1, 2));
297
298  for (GLint level = 0; level < kMax2dLevels; ++level) {
299    EXPECT_TRUE(manager_->ValidForTarget(
300        GL_TEXTURE_2D, level, kMaxTextureSize >> level, 1, 1));
301    EXPECT_TRUE(manager_->ValidForTarget(
302        GL_TEXTURE_2D, level, 1, kMaxTextureSize >> level, 1));
303    EXPECT_FALSE(manager_->ValidForTarget(
304        GL_TEXTURE_2D, level, (kMaxTextureSize >> level) + 1, 1, 1));
305    EXPECT_FALSE(manager_->ValidForTarget(
306        GL_TEXTURE_2D, level, 1, (kMaxTextureSize >> level) + 1, 1));
307  }
308
309  for (GLint level = 0; level < kMaxCubeMapLevels; ++level) {
310    EXPECT_TRUE(manager_->ValidForTarget(
311        GL_TEXTURE_CUBE_MAP, level,
312        kMaxCubeMapTextureSize >> level,
313        kMaxCubeMapTextureSize >> level,
314        1));
315    EXPECT_FALSE(manager_->ValidForTarget(
316        GL_TEXTURE_CUBE_MAP, level,
317        (kMaxCubeMapTextureSize >> level) * 2,
318        (kMaxCubeMapTextureSize >> level) * 2,
319        1));
320  }
321}
322
323TEST_F(TextureManagerTest, ValidForTargetNPOT) {
324  TestHelper::SetupFeatureInfoInitExpectations(
325      gl_.get(), "GL_OES_texture_npot");
326  scoped_refptr<FeatureInfo> feature_info(new FeatureInfo());
327  feature_info->Initialize(NULL);
328  TextureManager manager(
329     NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
330  // Check NPOT width on level 0
331  EXPECT_TRUE(manager.ValidForTarget(GL_TEXTURE_2D, 0, 5, 2, 1));
332  // Check NPOT height on level 0
333  EXPECT_TRUE(manager.ValidForTarget(GL_TEXTURE_2D, 0, 2, 5, 1));
334  // Check NPOT width on level 1
335  EXPECT_TRUE(manager.ValidForTarget(GL_TEXTURE_2D, 1, 5, 2, 1));
336  // Check NPOT height on level 1
337  EXPECT_TRUE(manager.ValidForTarget(GL_TEXTURE_2D, 1, 2, 5, 1));
338  manager.Destroy(false);
339}
340
341class TextureTestBase : public testing::Test {
342 public:
343  static const GLint kMaxTextureSize = 16;
344  static const GLint kMaxCubeMapTextureSize = 8;
345  static const GLint kMax2dLevels = 5;
346  static const GLint kMaxCubeMapLevels = 4;
347  static const GLuint kClient1Id = 1;
348  static const GLuint kService1Id = 11;
349
350  TextureTestBase()
351      : feature_info_(new FeatureInfo()) {
352  }
353  virtual ~TextureTestBase() {
354    texture_ = NULL;
355  }
356
357 protected:
358  void SetUpBase(MemoryTracker* memory_tracker) {
359    gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>());
360    ::gfx::GLInterface::SetGLInterface(gl_.get());
361    manager_.reset(new TextureManager(
362        memory_tracker, feature_info_.get(),
363        kMaxTextureSize, kMaxCubeMapTextureSize));
364    decoder_.reset(new ::testing::StrictMock<gles2::MockGLES2Decoder>());
365    manager_->CreateTexture(kClient1Id, kService1Id);
366    texture_ = manager_->GetTexture(kClient1Id);
367    ASSERT_TRUE(texture_.get() != NULL);
368  }
369
370  virtual void TearDown() {
371    if (texture_.get()) {
372      GLuint client_id = 0;
373      // If it's not in the manager then setting texture_ to NULL will
374      // delete the texture.
375      if (!manager_->GetClientId(texture_->service_id(), &client_id)) {
376        // Check that it gets deleted when the last reference is released.
377        EXPECT_CALL(*gl_,
378            DeleteTextures(1, ::testing::Pointee(texture_->service_id())))
379            .Times(1)
380            .RetiresOnSaturation();
381      }
382      texture_ = NULL;
383    }
384    manager_->Destroy(false);
385    manager_.reset();
386    ::gfx::GLInterface::SetGLInterface(NULL);
387    gl_.reset();
388  }
389
390  void SetParameter(
391      Texture* texture, GLenum pname, GLint value, GLenum error) {
392    TestHelper::SetTexParameterWithExpectations(
393        gl_.get(), decoder_.get(), manager_.get(),
394        texture, pname, value, error);
395  }
396
397  // Use StrictMock to make 100% sure we know how GL will be called.
398  scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_;
399  scoped_refptr<FeatureInfo> feature_info_;
400  scoped_ptr<TextureManager> manager_;
401  scoped_ptr<MockGLES2Decoder> decoder_;
402  scoped_refptr<Texture> texture_;
403};
404
405class TextureTest : public TextureTestBase {
406 protected:
407  virtual void SetUp() {
408    SetUpBase(NULL);
409  }
410};
411
412class TextureMemoryTrackerTest : public TextureTestBase {
413 protected:
414  virtual void SetUp() {
415    mock_memory_tracker_ = new StrictMock<MockMemoryTracker>();
416    SetUpBase(mock_memory_tracker_.get());
417  }
418
419  scoped_refptr<MockMemoryTracker> mock_memory_tracker_;
420};
421
422#define EXPECT_MEMORY_ALLOCATION_CHANGE(old_size, new_size, pool) \
423    EXPECT_CALL(*mock_memory_tracker_, \
424                TrackMemoryAllocatedChange(old_size, new_size, pool)) \
425        .Times(1) \
426        .RetiresOnSaturation() \
427
428TEST_F(TextureTest, Basic) {
429  EXPECT_EQ(0u, texture_->target());
430  EXPECT_FALSE(texture_->texture_complete());
431  EXPECT_FALSE(texture_->cube_complete());
432  EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_));
433  EXPECT_FALSE(texture_->npot());
434  EXPECT_EQ(0, texture_->num_uncleared_mips());
435  EXPECT_FALSE(manager_->CanRender(texture_));
436  EXPECT_TRUE(texture_->SafeToRenderFrom());
437  EXPECT_FALSE(texture_->IsImmutable());
438  EXPECT_EQ(static_cast<GLenum>(GL_NEAREST_MIPMAP_LINEAR),
439            texture_->min_filter());
440  EXPECT_EQ(static_cast<GLenum>(GL_LINEAR), texture_->mag_filter());
441  EXPECT_EQ(static_cast<GLenum>(GL_REPEAT), texture_->wrap_s());
442  EXPECT_EQ(static_cast<GLenum>(GL_REPEAT), texture_->wrap_t());
443  EXPECT_TRUE(manager_->HaveUnrenderableTextures());
444  EXPECT_FALSE(manager_->HaveUnsafeTextures());
445  EXPECT_EQ(0u, texture_->estimated_size());
446}
447
448TEST_F(TextureTest, EstimatedSize) {
449  manager_->SetTarget(texture_, GL_TEXTURE_2D);
450  manager_->SetLevelInfo(texture_,
451      GL_TEXTURE_2D, 0, GL_RGBA, 8, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
452  EXPECT_EQ(8u * 4u * 4u, texture_->estimated_size());
453  manager_->SetLevelInfo(texture_,
454      GL_TEXTURE_2D, 2, GL_RGBA, 8, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
455  EXPECT_EQ(8u * 4u * 4u * 2u, texture_->estimated_size());
456}
457
458TEST_F(TextureMemoryTrackerTest, EstimatedSize) {
459  manager_->SetTarget(texture_, GL_TEXTURE_2D);
460  EXPECT_MEMORY_ALLOCATION_CHANGE(0, 128, MemoryTracker::kUnmanaged);
461  manager_->SetLevelInfo(texture_,
462      GL_TEXTURE_2D, 0, GL_RGBA, 8, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
463  EXPECT_MEMORY_ALLOCATION_CHANGE(128, 0, MemoryTracker::kUnmanaged);
464  EXPECT_MEMORY_ALLOCATION_CHANGE(0, 256, MemoryTracker::kUnmanaged);
465  manager_->SetLevelInfo(texture_,
466      GL_TEXTURE_2D, 2, GL_RGBA, 8, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
467  // Add expectation for texture deletion.
468  EXPECT_MEMORY_ALLOCATION_CHANGE(256, 0, MemoryTracker::kUnmanaged);
469  EXPECT_MEMORY_ALLOCATION_CHANGE(0, 0, MemoryTracker::kUnmanaged);
470}
471
472TEST_F(TextureMemoryTrackerTest, SetParameterPool) {
473  manager_->SetTarget(texture_, GL_TEXTURE_2D);
474  EXPECT_MEMORY_ALLOCATION_CHANGE(0, 128, MemoryTracker::kUnmanaged);
475  manager_->SetLevelInfo(texture_,
476      GL_TEXTURE_2D, 0, GL_RGBA, 8, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
477  EXPECT_MEMORY_ALLOCATION_CHANGE(128, 0, MemoryTracker::kUnmanaged);
478  EXPECT_MEMORY_ALLOCATION_CHANGE(0, 128, MemoryTracker::kManaged);
479  SetParameter(
480      texture_, GL_TEXTURE_POOL_CHROMIUM, GL_TEXTURE_POOL_MANAGED_CHROMIUM,
481      GL_NO_ERROR);
482  // Add expectation for texture deletion.
483  EXPECT_MEMORY_ALLOCATION_CHANGE(128, 0, MemoryTracker::kManaged);
484  EXPECT_MEMORY_ALLOCATION_CHANGE(0, 0, MemoryTracker::kUnmanaged);
485  EXPECT_MEMORY_ALLOCATION_CHANGE(0, 0, MemoryTracker::kManaged);
486}
487
488TEST_F(TextureTest, POT2D) {
489  manager_->SetTarget(texture_, GL_TEXTURE_2D);
490  EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture_->target());
491  // Check Setting level 0 to POT
492  manager_->SetLevelInfo(texture_,
493      GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
494  EXPECT_FALSE(texture_->npot());
495  EXPECT_FALSE(texture_->texture_complete());
496  EXPECT_FALSE(manager_->CanRender(texture_));
497  EXPECT_EQ(0, texture_->num_uncleared_mips());
498  EXPECT_TRUE(manager_->HaveUnrenderableTextures());
499  // Set filters to something that will work with a single mip.
500  SetParameter(texture_, GL_TEXTURE_MIN_FILTER, GL_LINEAR, GL_NO_ERROR);
501  EXPECT_TRUE(manager_->CanRender(texture_));
502  EXPECT_FALSE(manager_->HaveUnrenderableTextures());
503  // Set them back.
504  SetParameter(
505      texture_, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR, GL_NO_ERROR);
506  EXPECT_TRUE(manager_->HaveUnrenderableTextures());
507
508  EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_));
509  // Make mips.
510  EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_));
511  EXPECT_TRUE(texture_->texture_complete());
512  EXPECT_TRUE(manager_->CanRender(texture_));
513  EXPECT_FALSE(manager_->HaveUnrenderableTextures());
514  // Change a mip.
515  manager_->SetLevelInfo(texture_,
516      GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
517  EXPECT_FALSE(texture_->npot());
518  EXPECT_FALSE(texture_->texture_complete());
519  EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_));
520  EXPECT_FALSE(manager_->CanRender(texture_));
521  EXPECT_TRUE(manager_->HaveUnrenderableTextures());
522  // Set a level past the number of mips that would get generated.
523  manager_->SetLevelInfo(texture_,
524      GL_TEXTURE_2D, 3, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
525  EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_));
526  // Make mips.
527  EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_));
528  EXPECT_TRUE(manager_->CanRender(texture_));
529  EXPECT_TRUE(texture_->texture_complete());
530  EXPECT_FALSE(manager_->HaveUnrenderableTextures());
531}
532
533TEST_F(TextureMemoryTrackerTest, MarkMipmapsGenerated) {
534  manager_->SetTarget(texture_, GL_TEXTURE_2D);
535  EXPECT_MEMORY_ALLOCATION_CHANGE(0, 64, MemoryTracker::kUnmanaged);
536  manager_->SetLevelInfo(texture_,
537      GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
538  EXPECT_MEMORY_ALLOCATION_CHANGE(64, 0, MemoryTracker::kUnmanaged);
539  EXPECT_MEMORY_ALLOCATION_CHANGE(0, 84, MemoryTracker::kUnmanaged);
540  EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_));
541  EXPECT_MEMORY_ALLOCATION_CHANGE(84, 0, MemoryTracker::kUnmanaged);
542  EXPECT_MEMORY_ALLOCATION_CHANGE(0, 0, MemoryTracker::kUnmanaged);
543}
544
545TEST_F(TextureTest, UnusedMips) {
546  manager_->SetTarget(texture_, GL_TEXTURE_2D);
547  EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture_->target());
548  // Set level zero to large size.
549  manager_->SetLevelInfo(texture_,
550      GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
551  EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_));
552  EXPECT_FALSE(texture_->npot());
553  EXPECT_TRUE(texture_->texture_complete());
554  EXPECT_TRUE(manager_->CanRender(texture_));
555  EXPECT_FALSE(manager_->HaveUnrenderableTextures());
556  // Set level zero to large smaller (levels unused mips)
557  manager_->SetLevelInfo(texture_,
558      GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
559  EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_));
560  EXPECT_FALSE(texture_->npot());
561  EXPECT_TRUE(texture_->texture_complete());
562  EXPECT_TRUE(manager_->CanRender(texture_));
563  EXPECT_FALSE(manager_->HaveUnrenderableTextures());
564  // Set an unused level to some size
565  manager_->SetLevelInfo(texture_,
566      GL_TEXTURE_2D, 4, GL_RGBA, 16, 16, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
567  EXPECT_FALSE(texture_->npot());
568  EXPECT_TRUE(texture_->texture_complete());
569  EXPECT_TRUE(manager_->CanRender(texture_));
570  EXPECT_FALSE(manager_->HaveUnrenderableTextures());
571}
572
573TEST_F(TextureTest, NPOT2D) {
574  manager_->SetTarget(texture_, GL_TEXTURE_2D);
575  EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture_->target());
576  // Check Setting level 0 to NPOT
577  manager_->SetLevelInfo(texture_,
578      GL_TEXTURE_2D, 0, GL_RGBA, 4, 5, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
579  EXPECT_TRUE(texture_->npot());
580  EXPECT_FALSE(texture_->texture_complete());
581  EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_));
582  EXPECT_FALSE(manager_->CanRender(texture_));
583  EXPECT_TRUE(manager_->HaveUnrenderableTextures());
584  SetParameter(texture_, GL_TEXTURE_MIN_FILTER, GL_LINEAR, GL_NO_ERROR);
585  EXPECT_FALSE(manager_->CanRender(texture_));
586  EXPECT_TRUE(manager_->HaveUnrenderableTextures());
587  SetParameter(texture_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE, GL_NO_ERROR);
588  EXPECT_FALSE(manager_->CanRender(texture_));
589  EXPECT_TRUE(manager_->HaveUnrenderableTextures());
590  SetParameter(texture_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE, GL_NO_ERROR);
591  EXPECT_TRUE(manager_->CanRender(texture_));
592  EXPECT_FALSE(manager_->HaveUnrenderableTextures());
593  // Change it to POT.
594  manager_->SetLevelInfo(texture_,
595      GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
596  EXPECT_FALSE(texture_->npot());
597  EXPECT_FALSE(texture_->texture_complete());
598  EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_));
599  EXPECT_FALSE(manager_->HaveUnrenderableTextures());
600}
601
602TEST_F(TextureTest, NPOT2DNPOTOK) {
603  TestHelper::SetupFeatureInfoInitExpectations(
604      gl_.get(), "GL_OES_texture_npot");
605  scoped_refptr<FeatureInfo> feature_info(new FeatureInfo());
606  feature_info->Initialize(NULL);
607  TextureManager manager(
608      NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
609  manager.CreateTexture(kClient1Id, kService1Id);
610  Texture* texture = manager.GetTexture(kClient1Id);
611  ASSERT_TRUE(texture != NULL);
612
613  manager.SetTarget(texture, GL_TEXTURE_2D);
614  EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture->target());
615  // Check Setting level 0 to NPOT
616  manager.SetLevelInfo(texture,
617      GL_TEXTURE_2D, 0, GL_RGBA, 4, 5, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
618  EXPECT_TRUE(texture->npot());
619  EXPECT_FALSE(texture->texture_complete());
620  EXPECT_TRUE(manager.CanGenerateMipmaps(texture));
621  EXPECT_FALSE(manager.CanRender(texture));
622  EXPECT_TRUE(manager.HaveUnrenderableTextures());
623  EXPECT_TRUE(manager.MarkMipmapsGenerated(texture));
624  EXPECT_TRUE(texture->texture_complete());
625  EXPECT_TRUE(manager.CanRender(texture));
626  EXPECT_FALSE(manager.HaveUnrenderableTextures());
627  manager.Destroy(false);
628}
629
630TEST_F(TextureTest, POTCubeMap) {
631  manager_->SetTarget(texture_, GL_TEXTURE_CUBE_MAP);
632  EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP), texture_->target());
633  // Check Setting level 0 each face to POT
634  manager_->SetLevelInfo(texture_,
635      GL_TEXTURE_CUBE_MAP_POSITIVE_X,
636      0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
637  EXPECT_FALSE(texture_->npot());
638  EXPECT_FALSE(texture_->texture_complete());
639  EXPECT_FALSE(texture_->cube_complete());
640  EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_));
641  EXPECT_FALSE(manager_->CanRender(texture_));
642  EXPECT_TRUE(manager_->HaveUnrenderableTextures());
643  manager_->SetLevelInfo(texture_,
644      GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
645      0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
646  EXPECT_FALSE(texture_->npot());
647  EXPECT_FALSE(texture_->texture_complete());
648  EXPECT_FALSE(texture_->cube_complete());
649  EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_));
650  EXPECT_FALSE(manager_->CanRender(texture_));
651  EXPECT_TRUE(manager_->HaveUnrenderableTextures());
652  manager_->SetLevelInfo(texture_,
653      GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
654      0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
655  EXPECT_FALSE(texture_->npot());
656  EXPECT_FALSE(texture_->texture_complete());
657  EXPECT_FALSE(texture_->cube_complete());
658  EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_));
659  EXPECT_FALSE(manager_->CanRender(texture_));
660  EXPECT_TRUE(manager_->HaveUnrenderableTextures());
661  manager_->SetLevelInfo(texture_,
662      GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
663      0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
664  EXPECT_FALSE(texture_->npot());
665  EXPECT_FALSE(texture_->texture_complete());
666  EXPECT_FALSE(texture_->cube_complete());
667  EXPECT_FALSE(manager_->CanRender(texture_));
668  EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_));
669  EXPECT_TRUE(manager_->HaveUnrenderableTextures());
670  manager_->SetLevelInfo(texture_,
671      GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
672      0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
673  EXPECT_FALSE(texture_->npot());
674  EXPECT_FALSE(texture_->texture_complete());
675  EXPECT_FALSE(texture_->cube_complete());
676  EXPECT_FALSE(manager_->CanGenerateMipmaps(texture_));
677  EXPECT_FALSE(manager_->CanRender(texture_));
678  EXPECT_TRUE(manager_->HaveUnrenderableTextures());
679  manager_->SetLevelInfo(texture_,
680      GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
681      0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
682  EXPECT_FALSE(texture_->npot());
683  EXPECT_FALSE(texture_->texture_complete());
684  EXPECT_TRUE(texture_->cube_complete());
685  EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_));
686  EXPECT_FALSE(manager_->CanRender(texture_));
687  EXPECT_TRUE(manager_->HaveUnrenderableTextures());
688
689  // Make mips.
690  EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_));
691  EXPECT_TRUE(texture_->texture_complete());
692  EXPECT_TRUE(texture_->cube_complete());
693  EXPECT_TRUE(manager_->CanRender(texture_));
694  EXPECT_FALSE(manager_->HaveUnrenderableTextures());
695
696  // Change a mip.
697  manager_->SetLevelInfo(texture_,
698      GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
699      1, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
700  EXPECT_FALSE(texture_->npot());
701  EXPECT_FALSE(texture_->texture_complete());
702  EXPECT_TRUE(texture_->cube_complete());
703  EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_));
704  // Set a level past the number of mips that would get generated.
705  manager_->SetLevelInfo(texture_,
706      GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
707      3, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
708  EXPECT_TRUE(manager_->CanGenerateMipmaps(texture_));
709  // Make mips.
710  EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_));
711  EXPECT_TRUE(texture_->texture_complete());
712  EXPECT_TRUE(texture_->cube_complete());
713}
714
715TEST_F(TextureTest, GetLevelSize) {
716  manager_->SetTarget(texture_, GL_TEXTURE_2D);
717  manager_->SetLevelInfo(texture_,
718      GL_TEXTURE_2D, 1, GL_RGBA, 4, 5, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
719  GLsizei width = -1;
720  GLsizei height = -1;
721  EXPECT_FALSE(texture_->GetLevelSize(GL_TEXTURE_2D, -1, &width, &height));
722  EXPECT_FALSE(texture_->GetLevelSize(GL_TEXTURE_2D, 1000, &width, &height));
723  EXPECT_FALSE(texture_->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height));
724  EXPECT_TRUE(texture_->GetLevelSize(GL_TEXTURE_2D, 1, &width, &height));
725  EXPECT_EQ(4, width);
726  EXPECT_EQ(5, height);
727  manager_->RemoveTexture(kClient1Id);
728  EXPECT_TRUE(texture_->GetLevelSize(GL_TEXTURE_2D, 1, &width, &height));
729  EXPECT_EQ(4, width);
730  EXPECT_EQ(5, height);
731}
732
733TEST_F(TextureTest, GetLevelType) {
734  manager_->SetTarget(texture_, GL_TEXTURE_2D);
735  manager_->SetLevelInfo(texture_,
736      GL_TEXTURE_2D, 1, GL_RGBA, 4, 5, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
737  GLenum type = -1;
738  GLenum format = -1;
739  EXPECT_FALSE(texture_->GetLevelType(GL_TEXTURE_2D, -1, &type, &format));
740  EXPECT_FALSE(texture_->GetLevelType(GL_TEXTURE_2D, 1000, &type, &format));
741  EXPECT_FALSE(texture_->GetLevelType(GL_TEXTURE_2D, 0, &type, &format));
742  EXPECT_TRUE(texture_->GetLevelType(GL_TEXTURE_2D, 1, &type, &format));
743  EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type);
744  EXPECT_EQ(static_cast<GLenum>(GL_RGBA), format);
745  manager_->RemoveTexture(kClient1Id);
746  EXPECT_TRUE(texture_->GetLevelType(GL_TEXTURE_2D, 1, &type, &format));
747  EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type);
748  EXPECT_EQ(static_cast<GLenum>(GL_RGBA), format);
749}
750
751TEST_F(TextureTest, ValidForTexture) {
752  manager_->SetTarget(texture_, GL_TEXTURE_2D);
753  manager_->SetLevelInfo(texture_,
754      GL_TEXTURE_2D, 1, GL_RGBA, 4, 5, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
755  // Check bad face.
756  EXPECT_FALSE(texture_->ValidForTexture(
757      GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
758      1, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
759  // Check bad level.
760  EXPECT_FALSE(texture_->ValidForTexture(
761      GL_TEXTURE_2D, 0, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
762  // Check bad xoffset.
763  EXPECT_FALSE(texture_->ValidForTexture(
764      GL_TEXTURE_2D, 1, -1, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
765  // Check bad xoffset + width > width.
766  EXPECT_FALSE(texture_->ValidForTexture(
767      GL_TEXTURE_2D, 1, 1, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
768  // Check bad yoffset.
769  EXPECT_FALSE(texture_->ValidForTexture(
770      GL_TEXTURE_2D, 1, 0, -1, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
771  // Check bad yoffset + height > height.
772  EXPECT_FALSE(texture_->ValidForTexture(
773      GL_TEXTURE_2D, 1, 0, 1, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
774  // Check bad width.
775  EXPECT_FALSE(texture_->ValidForTexture(
776      GL_TEXTURE_2D, 1, 0, 0, 5, 5, GL_RGBA, GL_UNSIGNED_BYTE));
777  // Check bad height.
778  EXPECT_FALSE(texture_->ValidForTexture(
779      GL_TEXTURE_2D, 1, 0, 0, 4, 6, GL_RGBA, GL_UNSIGNED_BYTE));
780  // Check bad format.
781  EXPECT_FALSE(texture_->ValidForTexture(
782      GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_RGB, GL_UNSIGNED_BYTE));
783  // Check bad type.
784  EXPECT_FALSE(texture_->ValidForTexture(
785      GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4));
786  // Check valid full size
787  EXPECT_TRUE(texture_->ValidForTexture(
788      GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
789  // Check valid particial size.
790  EXPECT_TRUE(texture_->ValidForTexture(
791      GL_TEXTURE_2D, 1, 1, 1, 2, 3, GL_RGBA, GL_UNSIGNED_BYTE));
792  manager_->RemoveTexture(kClient1Id);
793  EXPECT_TRUE(texture_->ValidForTexture(
794      GL_TEXTURE_2D, 1, 0, 0, 4, 5, GL_RGBA, GL_UNSIGNED_BYTE));
795}
796
797TEST_F(TextureTest, FloatNotLinear) {
798  TestHelper::SetupFeatureInfoInitExpectations(
799      gl_.get(), "GL_OES_texture_float");
800  scoped_refptr<FeatureInfo> feature_info(new FeatureInfo());
801  feature_info->Initialize(NULL);
802  TextureManager manager(
803      NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
804  manager.CreateTexture(kClient1Id, kService1Id);
805  Texture* texture = manager.GetTexture(kClient1Id);
806  ASSERT_TRUE(texture != NULL);
807  manager.SetTarget(texture, GL_TEXTURE_2D);
808  EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture->target());
809  manager.SetLevelInfo(texture,
810      GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_FLOAT, true);
811  EXPECT_FALSE(texture->texture_complete());
812  TestHelper::SetTexParameterWithExpectations(
813      gl_.get(), decoder_.get(), &manager,
814      texture, GL_TEXTURE_MAG_FILTER, GL_NEAREST, GL_NO_ERROR);
815  EXPECT_FALSE(texture->texture_complete());
816  TestHelper::SetTexParameterWithExpectations(
817      gl_.get(), decoder_.get(), &manager,
818      texture, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST, GL_NO_ERROR);
819  EXPECT_TRUE(texture->texture_complete());
820  manager.Destroy(false);
821}
822
823TEST_F(TextureTest, FloatLinear) {
824  TestHelper::SetupFeatureInfoInitExpectations(
825      gl_.get(), "GL_OES_texture_float GL_OES_texture_float_linear");
826  scoped_refptr<FeatureInfo> feature_info(new FeatureInfo());
827  feature_info->Initialize(NULL);
828  TextureManager manager(
829      NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
830  manager.CreateTexture(kClient1Id, kService1Id);
831  Texture* texture = manager.GetTexture(kClient1Id);
832  ASSERT_TRUE(texture != NULL);
833  manager.SetTarget(texture, GL_TEXTURE_2D);
834  EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture->target());
835  manager.SetLevelInfo(texture,
836      GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_FLOAT, true);
837  EXPECT_TRUE(texture->texture_complete());
838  manager.Destroy(false);
839}
840
841TEST_F(TextureTest, HalfFloatNotLinear) {
842  TestHelper::SetupFeatureInfoInitExpectations(
843      gl_.get(), "GL_OES_texture_half_float");
844  scoped_refptr<FeatureInfo> feature_info(new FeatureInfo());
845  feature_info->Initialize(NULL);
846  TextureManager manager(
847      NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
848  manager.CreateTexture(kClient1Id, kService1Id);
849  Texture* texture = manager.GetTexture(kClient1Id);
850  ASSERT_TRUE(texture != NULL);
851  manager.SetTarget(texture, GL_TEXTURE_2D);
852  EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture->target());
853  manager.SetLevelInfo(texture,
854      GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_HALF_FLOAT_OES, true);
855  EXPECT_FALSE(texture->texture_complete());
856  TestHelper::SetTexParameterWithExpectations(
857      gl_.get(), decoder_.get(), &manager,
858      texture, GL_TEXTURE_MAG_FILTER, GL_NEAREST, GL_NO_ERROR);
859  EXPECT_FALSE(texture->texture_complete());
860  TestHelper::SetTexParameterWithExpectations(
861      gl_.get(), decoder_.get(), &manager,
862      texture, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST, GL_NO_ERROR);
863  EXPECT_TRUE(texture->texture_complete());
864  manager.Destroy(false);
865}
866
867TEST_F(TextureTest, HalfFloatLinear) {
868  TestHelper::SetupFeatureInfoInitExpectations(
869      gl_.get(), "GL_OES_texture_half_float GL_OES_texture_half_float_linear");
870  scoped_refptr<FeatureInfo> feature_info(new FeatureInfo());
871  feature_info->Initialize(NULL);
872  TextureManager manager(
873      NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
874  manager.CreateTexture(kClient1Id, kService1Id);
875  Texture* texture = manager.GetTexture(kClient1Id);
876  ASSERT_TRUE(texture != NULL);
877  manager.SetTarget(texture, GL_TEXTURE_2D);
878  EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture->target());
879  manager.SetLevelInfo(texture,
880      GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_HALF_FLOAT_OES, true);
881  EXPECT_TRUE(texture->texture_complete());
882  manager.Destroy(false);
883}
884
885TEST_F(TextureTest, EGLImageExternal) {
886  TestHelper::SetupFeatureInfoInitExpectations(
887      gl_.get(), "GL_OES_EGL_image_external");
888  scoped_refptr<FeatureInfo> feature_info(new FeatureInfo());
889  feature_info->Initialize(NULL);
890  TextureManager manager(
891      NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
892  manager.CreateTexture(kClient1Id, kService1Id);
893  Texture* texture = manager.GetTexture(kClient1Id);
894  ASSERT_TRUE(texture != NULL);
895  manager.SetTarget(texture, GL_TEXTURE_EXTERNAL_OES);
896  EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), texture->target());
897  EXPECT_FALSE(manager.CanGenerateMipmaps(texture));
898  manager.Destroy(false);
899}
900
901TEST_F(TextureTest, DepthTexture) {
902  TestHelper::SetupFeatureInfoInitExpectations(
903      gl_.get(), "GL_ANGLE_depth_texture");
904  scoped_refptr<FeatureInfo> feature_info(new FeatureInfo());
905  feature_info->Initialize(NULL);
906  TextureManager manager(
907      NULL, feature_info.get(), kMaxTextureSize, kMaxCubeMapTextureSize);
908  manager.CreateTexture(kClient1Id, kService1Id);
909  Texture* texture = manager.GetTexture(kClient1Id);
910  ASSERT_TRUE(texture != NULL);
911  manager.SetTarget(texture, GL_TEXTURE_2D);
912  manager.SetLevelInfo(
913      texture, GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 4, 4, 1, 0,
914      GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, false);
915  EXPECT_FALSE(manager.CanGenerateMipmaps(texture));
916  manager.Destroy(false);
917}
918
919TEST_F(TextureTest, SafeUnsafe) {
920  static const GLuint kClient2Id = 2;
921  static const GLuint kService2Id = 12;
922  static const GLuint kClient3Id = 3;
923  static const GLuint kService3Id = 13;
924  EXPECT_FALSE(manager_->HaveUnclearedMips());
925  EXPECT_EQ(0, texture_->num_uncleared_mips());
926  manager_->SetTarget(texture_, GL_TEXTURE_2D);
927  manager_->SetLevelInfo(texture_,
928      GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
929  EXPECT_FALSE(texture_->SafeToRenderFrom());
930  EXPECT_TRUE(manager_->HaveUnsafeTextures());
931  EXPECT_TRUE(manager_->HaveUnclearedMips());
932  EXPECT_EQ(1, texture_->num_uncleared_mips());
933  manager_->SetLevelCleared(texture_, GL_TEXTURE_2D, 0, true);
934  EXPECT_TRUE(texture_->SafeToRenderFrom());
935  EXPECT_FALSE(manager_->HaveUnsafeTextures());
936  EXPECT_FALSE(manager_->HaveUnclearedMips());
937  EXPECT_EQ(0, texture_->num_uncleared_mips());
938  manager_->SetLevelInfo(texture_,
939      GL_TEXTURE_2D, 1, GL_RGBA, 8, 8, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
940  EXPECT_FALSE(texture_->SafeToRenderFrom());
941  EXPECT_TRUE(manager_->HaveUnsafeTextures());
942  EXPECT_TRUE(manager_->HaveUnclearedMips());
943  EXPECT_EQ(1, texture_->num_uncleared_mips());
944  manager_->SetLevelCleared(texture_, GL_TEXTURE_2D, 1, true);
945  EXPECT_TRUE(texture_->SafeToRenderFrom());
946  EXPECT_FALSE(manager_->HaveUnsafeTextures());
947  EXPECT_FALSE(manager_->HaveUnclearedMips());
948  EXPECT_EQ(0, texture_->num_uncleared_mips());
949  manager_->SetLevelInfo(texture_,
950      GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
951  manager_->SetLevelInfo(texture_,
952      GL_TEXTURE_2D, 1, GL_RGBA, 8, 8, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
953  EXPECT_FALSE(texture_->SafeToRenderFrom());
954  EXPECT_TRUE(manager_->HaveUnsafeTextures());
955  EXPECT_TRUE(manager_->HaveUnclearedMips());
956  EXPECT_EQ(2, texture_->num_uncleared_mips());
957  manager_->SetLevelCleared(texture_, GL_TEXTURE_2D, 0, true);
958  EXPECT_FALSE(texture_->SafeToRenderFrom());
959  EXPECT_TRUE(manager_->HaveUnsafeTextures());
960  EXPECT_TRUE(manager_->HaveUnclearedMips());
961  EXPECT_EQ(1, texture_->num_uncleared_mips());
962  manager_->SetLevelCleared(texture_, GL_TEXTURE_2D, 1, true);
963  EXPECT_TRUE(texture_->SafeToRenderFrom());
964  EXPECT_FALSE(manager_->HaveUnsafeTextures());
965  EXPECT_FALSE(manager_->HaveUnclearedMips());
966  EXPECT_EQ(0, texture_->num_uncleared_mips());
967  manager_->SetLevelInfo(texture_,
968      GL_TEXTURE_2D, 1, GL_RGBA, 8, 8, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
969  EXPECT_FALSE(texture_->SafeToRenderFrom());
970  EXPECT_TRUE(manager_->HaveUnsafeTextures());
971  EXPECT_TRUE(manager_->HaveUnclearedMips());
972  EXPECT_EQ(1, texture_->num_uncleared_mips());
973  manager_->MarkMipmapsGenerated(texture_);
974  EXPECT_TRUE(texture_->SafeToRenderFrom());
975  EXPECT_FALSE(manager_->HaveUnsafeTextures());
976  EXPECT_FALSE(manager_->HaveUnclearedMips());
977  EXPECT_EQ(0, texture_->num_uncleared_mips());
978
979  manager_->CreateTexture(kClient2Id, kService2Id);
980  scoped_refptr<Texture> texture2(
981      manager_->GetTexture(kClient2Id));
982  ASSERT_TRUE(texture2.get() != NULL);
983  manager_->SetTarget(texture2, GL_TEXTURE_2D);
984  EXPECT_FALSE(manager_->HaveUnsafeTextures());
985  EXPECT_FALSE(manager_->HaveUnclearedMips());
986  EXPECT_EQ(0, texture2->num_uncleared_mips());
987  manager_->SetLevelInfo(texture2,
988      GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
989  EXPECT_FALSE(manager_->HaveUnsafeTextures());
990  EXPECT_FALSE(manager_->HaveUnclearedMips());
991  EXPECT_EQ(0, texture2->num_uncleared_mips());
992  manager_->SetLevelInfo(texture2,
993      GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
994  EXPECT_TRUE(manager_->HaveUnsafeTextures());
995  EXPECT_TRUE(manager_->HaveUnclearedMips());
996  EXPECT_EQ(1, texture2->num_uncleared_mips());
997
998  manager_->CreateTexture(kClient3Id, kService3Id);
999  scoped_refptr<Texture> texture3(
1000      manager_->GetTexture(kClient3Id));
1001  ASSERT_TRUE(texture3.get() != NULL);
1002  manager_->SetTarget(texture3, GL_TEXTURE_2D);
1003  manager_->SetLevelInfo(texture3,
1004      GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
1005  EXPECT_TRUE(manager_->HaveUnsafeTextures());
1006  EXPECT_TRUE(manager_->HaveUnclearedMips());
1007  EXPECT_EQ(1, texture3->num_uncleared_mips());
1008  manager_->SetLevelCleared(texture2, GL_TEXTURE_2D, 0, true);
1009  EXPECT_TRUE(manager_->HaveUnsafeTextures());
1010  EXPECT_TRUE(manager_->HaveUnclearedMips());
1011  EXPECT_EQ(0, texture2->num_uncleared_mips());
1012  manager_->SetLevelCleared(texture3, GL_TEXTURE_2D, 0, true);
1013  EXPECT_FALSE(manager_->HaveUnsafeTextures());
1014  EXPECT_FALSE(manager_->HaveUnclearedMips());
1015  EXPECT_EQ(0, texture3->num_uncleared_mips());
1016
1017  manager_->SetLevelInfo(texture2,
1018      GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
1019  manager_->SetLevelInfo(texture3,
1020      GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
1021  EXPECT_TRUE(manager_->HaveUnsafeTextures());
1022  EXPECT_TRUE(manager_->HaveUnclearedMips());
1023  EXPECT_EQ(1, texture2->num_uncleared_mips());
1024  EXPECT_EQ(1, texture3->num_uncleared_mips());
1025  manager_->RemoveTexture(kClient3Id);
1026  EXPECT_TRUE(manager_->HaveUnsafeTextures());
1027  EXPECT_TRUE(manager_->HaveUnclearedMips());
1028  manager_->RemoveTexture(kClient2Id);
1029  EXPECT_TRUE(manager_->HaveUnsafeTextures());
1030  EXPECT_TRUE(manager_->HaveUnclearedMips());
1031  EXPECT_CALL(*gl_, DeleteTextures(1, ::testing::Pointee(kService2Id)))
1032      .Times(1)
1033      .RetiresOnSaturation();
1034  texture2 = NULL;
1035  EXPECT_TRUE(manager_->HaveUnsafeTextures());
1036  EXPECT_TRUE(manager_->HaveUnclearedMips());
1037  EXPECT_CALL(*gl_, DeleteTextures(1, ::testing::Pointee(kService3Id)))
1038      .Times(1)
1039      .RetiresOnSaturation();
1040  texture3 = NULL;
1041  EXPECT_FALSE(manager_->HaveUnsafeTextures());
1042  EXPECT_FALSE(manager_->HaveUnclearedMips());
1043}
1044
1045TEST_F(TextureTest, ClearTexture) {
1046  EXPECT_CALL(*decoder_, ClearLevel(_, _, _, _, _, _, _, _, _))
1047      .WillRepeatedly(Return(true));
1048  manager_->SetTarget(texture_, GL_TEXTURE_2D);
1049  manager_->SetLevelInfo(texture_,
1050      GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
1051  manager_->SetLevelInfo(texture_,
1052      GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
1053  EXPECT_FALSE(texture_->SafeToRenderFrom());
1054  EXPECT_TRUE(manager_->HaveUnsafeTextures());
1055  EXPECT_TRUE(manager_->HaveUnclearedMips());
1056  EXPECT_EQ(2, texture_->num_uncleared_mips());
1057  manager_->ClearRenderableLevels(decoder_.get(), texture_);
1058  EXPECT_TRUE(texture_->SafeToRenderFrom());
1059  EXPECT_FALSE(manager_->HaveUnsafeTextures());
1060  EXPECT_FALSE(manager_->HaveUnclearedMips());
1061  EXPECT_EQ(0, texture_->num_uncleared_mips());
1062  manager_->SetLevelInfo(texture_,
1063      GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
1064  manager_->SetLevelInfo(texture_,
1065      GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
1066  EXPECT_FALSE(texture_->SafeToRenderFrom());
1067  EXPECT_TRUE(manager_->HaveUnsafeTextures());
1068  EXPECT_TRUE(manager_->HaveUnclearedMips());
1069  EXPECT_EQ(2, texture_->num_uncleared_mips());
1070  manager_->ClearTextureLevel(decoder_.get(), texture_, GL_TEXTURE_2D, 0);
1071  EXPECT_FALSE(texture_->SafeToRenderFrom());
1072  EXPECT_TRUE(manager_->HaveUnsafeTextures());
1073  EXPECT_TRUE(manager_->HaveUnclearedMips());
1074  EXPECT_EQ(1, texture_->num_uncleared_mips());
1075  manager_->ClearTextureLevel(decoder_.get(), texture_, GL_TEXTURE_2D, 1);
1076  EXPECT_TRUE(texture_->SafeToRenderFrom());
1077  EXPECT_FALSE(manager_->HaveUnsafeTextures());
1078  EXPECT_FALSE(manager_->HaveUnclearedMips());
1079  EXPECT_EQ(0, texture_->num_uncleared_mips());
1080}
1081
1082TEST_F(TextureTest, UseDeletedTexture) {
1083  static const GLuint kClient2Id = 2;
1084  static const GLuint kService2Id = 12;
1085  // Make the default texture renderable
1086  manager_->SetTarget(texture_, GL_TEXTURE_2D);
1087  manager_->SetLevelInfo(texture_,
1088      GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
1089  EXPECT_FALSE(manager_->HaveUnrenderableTextures());
1090  // Make a new texture
1091  manager_->CreateTexture(kClient2Id, kService2Id);
1092  scoped_refptr<Texture> texture(
1093      manager_->GetTexture(kClient2Id));
1094  manager_->SetTarget(texture, GL_TEXTURE_2D);
1095  EXPECT_FALSE(manager_->CanRender(texture));
1096  EXPECT_TRUE(manager_->HaveUnrenderableTextures());
1097  // Remove it.
1098  manager_->RemoveTexture(kClient2Id);
1099  EXPECT_FALSE(manager_->CanRender(texture));
1100  EXPECT_TRUE(manager_->HaveUnrenderableTextures());
1101  // Check that we can still manipulate it and it effects the manager.
1102  manager_->SetLevelInfo(texture,
1103      GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
1104  EXPECT_TRUE(manager_->CanRender(texture));
1105  EXPECT_FALSE(manager_->HaveUnrenderableTextures());
1106  EXPECT_CALL(*gl_, DeleteTextures(1, ::testing::Pointee(kService2Id)))
1107      .Times(1)
1108      .RetiresOnSaturation();
1109  texture = NULL;
1110}
1111
1112TEST_F(TextureTest, GetLevelImage) {
1113  manager_->SetTarget(texture_, GL_TEXTURE_2D);
1114  manager_->SetLevelInfo(texture_,
1115      GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
1116  EXPECT_TRUE(texture_->GetLevelImage(GL_TEXTURE_2D, 1) == NULL);
1117  // Set image.
1118  manager_->SetLevelImage(texture_,
1119      GL_TEXTURE_2D, 1, gfx::GLImage::CreateGLImage(0));
1120  EXPECT_FALSE(texture_->GetLevelImage(GL_TEXTURE_2D, 1) == NULL);
1121  // Remove it.
1122  manager_->SetLevelImage(texture_, GL_TEXTURE_2D, 1, NULL);
1123  EXPECT_TRUE(texture_->GetLevelImage(GL_TEXTURE_2D, 1) == NULL);
1124  manager_->SetLevelImage(texture_,
1125      GL_TEXTURE_2D, 1, gfx::GLImage::CreateGLImage(0));
1126  // Image should be reset when SetLevelInfo is called.
1127  manager_->SetLevelInfo(texture_,
1128      GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
1129  EXPECT_TRUE(texture_->GetLevelImage(GL_TEXTURE_2D, 1) == NULL);
1130}
1131
1132namespace {
1133
1134bool InSet(std::set<std::string>* string_set, const std::string& str) {
1135  std::pair<std::set<std::string>::iterator, bool> result =
1136      string_set->insert(str);
1137  return !result.second;
1138}
1139
1140}  // anonymous namespace
1141
1142TEST_F(TextureTest, AddToSignature) {
1143  manager_->SetTarget(texture_, GL_TEXTURE_2D);
1144  manager_->SetLevelInfo(texture_,
1145      GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
1146  std::string signature1;
1147  std::string signature2;
1148  manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature1);
1149
1150  std::set<std::string> string_set;
1151  EXPECT_FALSE(InSet(&string_set, signature1));
1152
1153  // check changing 1 thing makes a different signature.
1154  manager_->SetLevelInfo(texture_,
1155      GL_TEXTURE_2D, 1, GL_RGBA, 4, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
1156  manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature2);
1157  EXPECT_FALSE(InSet(&string_set, signature2));
1158
1159  // check putting it back makes the same signature.
1160  manager_->SetLevelInfo(texture_,
1161      GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true);
1162  signature2.clear();
1163  manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature2);
1164  EXPECT_EQ(signature1, signature2);
1165
1166  // Check setting cleared status does not change signature.
1167  manager_->SetLevelInfo(texture_,
1168      GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
1169  signature2.clear();
1170  manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature2);
1171  EXPECT_EQ(signature1, signature2);
1172
1173  // Check changing other settings changes signature.
1174  manager_->SetLevelInfo(texture_,
1175      GL_TEXTURE_2D, 1, GL_RGBA, 2, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
1176  signature2.clear();
1177  manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature2);
1178  EXPECT_FALSE(InSet(&string_set, signature2));
1179
1180  manager_->SetLevelInfo(texture_,
1181      GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, false);
1182  signature2.clear();
1183  manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature2);
1184  EXPECT_FALSE(InSet(&string_set, signature2));
1185
1186  manager_->SetLevelInfo(texture_,
1187      GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, false);
1188  signature2.clear();
1189  manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature2);
1190  EXPECT_FALSE(InSet(&string_set, signature2));
1191
1192  manager_->SetLevelInfo(texture_,
1193      GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, false);
1194  signature2.clear();
1195  manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature2);
1196  EXPECT_FALSE(InSet(&string_set, signature2));
1197
1198  manager_->SetLevelInfo(texture_,
1199      GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_FLOAT,
1200      false);
1201  signature2.clear();
1202  manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature2);
1203  EXPECT_FALSE(InSet(&string_set, signature2));
1204
1205  // put it back
1206  manager_->SetLevelInfo(texture_,
1207      GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1208      false);
1209  signature2.clear();
1210  manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature2);
1211  EXPECT_EQ(signature1, signature2);
1212
1213  // check changing parameters changes signature.
1214  SetParameter(texture_, GL_TEXTURE_MIN_FILTER, GL_NEAREST, GL_NO_ERROR);
1215  signature2.clear();
1216  manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature2);
1217  EXPECT_FALSE(InSet(&string_set, signature2));
1218
1219  SetParameter(
1220      texture_, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR, GL_NO_ERROR);
1221  SetParameter(texture_, GL_TEXTURE_MAG_FILTER, GL_NEAREST, GL_NO_ERROR);
1222  signature2.clear();
1223  manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature2);
1224  EXPECT_FALSE(InSet(&string_set, signature2));
1225
1226  SetParameter(texture_, GL_TEXTURE_MAG_FILTER, GL_LINEAR, GL_NO_ERROR);
1227  SetParameter(texture_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE, GL_NO_ERROR);
1228  signature2.clear();
1229  manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature2);
1230  EXPECT_FALSE(InSet(&string_set, signature2));
1231
1232  SetParameter(texture_, GL_TEXTURE_WRAP_S, GL_REPEAT, GL_NO_ERROR);
1233  SetParameter(texture_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE, GL_NO_ERROR);
1234  signature2.clear();
1235  manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature2);
1236  EXPECT_FALSE(InSet(&string_set, signature2));
1237
1238  // Check putting it back genenerates the same signature
1239  SetParameter(texture_, GL_TEXTURE_WRAP_T, GL_REPEAT, GL_NO_ERROR);
1240  signature2.clear();
1241  manager_->AddToSignature(texture_, GL_TEXTURE_2D, 1, &signature2);
1242  EXPECT_EQ(signature1, signature2);
1243
1244  // Check the set was acutally getting different signatures.
1245  EXPECT_EQ(11u, string_set.size());
1246}
1247
1248class SaveRestoreTextureTest : public TextureTest {
1249 public:
1250  virtual void SetUp() {
1251    TextureTest::SetUp();
1252    manager_->CreateTexture(kClient2Id, kService2Id);
1253    texture2_ = manager_->GetTexture(kClient2Id);
1254  }
1255
1256  virtual void TearDown() {
1257    if (texture2_.get()) {
1258      GLuint client_id = 0;
1259      // If it's not in the manager then setting texture2_ to NULL will
1260      // delete the texture.
1261      if (!manager_->GetClientId(texture2_->service_id(), &client_id)) {
1262        // Check that it gets deleted when the last reference is released.
1263        EXPECT_CALL(
1264            *gl_,
1265            DeleteTextures(1, ::testing::Pointee(texture2_->service_id())))
1266            .Times(1).RetiresOnSaturation();
1267      }
1268      texture2_ = NULL;
1269    }
1270    TextureTest::TearDown();
1271  }
1272
1273 protected:
1274  struct LevelInfo {
1275    LevelInfo(GLenum target,
1276              GLenum format,
1277              GLsizei width,
1278              GLsizei height,
1279              GLsizei depth,
1280              GLint border,
1281              GLenum type,
1282              bool cleared)
1283        : target(target),
1284          format(format),
1285          width(width),
1286          height(height),
1287          depth(depth),
1288          border(border),
1289          type(type),
1290          cleared(cleared) {}
1291
1292    LevelInfo()
1293        : target(0),
1294          format(0),
1295          width(-1),
1296          height(-1),
1297          depth(1),
1298          border(0),
1299          type(0),
1300          cleared(false) {}
1301
1302    bool operator==(const LevelInfo& other) const {
1303      return target == other.target && format == other.format &&
1304             width == other.width && height == other.height &&
1305             depth == other.depth && border == other.border &&
1306             type == other.type && cleared == other.cleared;
1307    }
1308
1309    GLenum target;
1310    GLenum format;
1311    GLsizei width;
1312    GLsizei height;
1313    GLsizei depth;
1314    GLint border;
1315    GLenum type;
1316    bool cleared;
1317  };
1318
1319  void SetLevelInfo(Texture* texture, GLint level, const LevelInfo& info) {
1320    manager_->SetLevelInfo(texture,
1321                           info.target,
1322                           level,
1323                           info.format,
1324                           info.width,
1325                           info.height,
1326                           info.depth,
1327                           info.border,
1328                           info.format,
1329                           info.type,
1330                           info.cleared);
1331  }
1332
1333  static LevelInfo GetLevelInfo(const Texture* texture,
1334                                GLint target,
1335                                GLint level) {
1336    LevelInfo info;
1337    info.target = target;
1338    EXPECT_TRUE(texture->GetLevelSize(target, level, &info.width,
1339                                      &info.height));
1340    EXPECT_TRUE(texture->GetLevelType(target, level, &info.type,
1341                                      &info.format));
1342    info.cleared = texture->IsLevelCleared(target, level);
1343    return info;
1344  }
1345
1346  TextureDefinition* Save(Texture* texture) {
1347    EXPECT_CALL(*gl_, GenTextures(_, _))
1348        .WillOnce(SetArgumentPointee<1>(kService2Id));
1349    TextureDefinition* definition = manager_->Save(texture);
1350    EXPECT_TRUE(definition != NULL);
1351    return definition;
1352  }
1353
1354  void Restore(Texture* texture, TextureDefinition* definition) {
1355    EXPECT_CALL(*gl_, DeleteTextures(1, Pointee(texture->service_id())))
1356        .Times(1).RetiresOnSaturation();
1357    EXPECT_CALL(*gl_,
1358                BindTexture(definition->target(), definition->service_id()))
1359        .Times(1).RetiresOnSaturation();
1360    EXPECT_CALL(*gl_, TexParameteri(_, _, _)).Times(AtLeast(1));
1361
1362    EXPECT_TRUE(
1363        manager_->Restore("TextureTest", decoder_.get(), texture, definition));
1364  }
1365
1366  scoped_refptr<Texture> texture2_;
1367
1368 private:
1369  static const GLuint kEmptyTextureServiceId;
1370  static const GLuint kClient2Id;
1371  static const GLuint kService2Id;
1372};
1373
1374const GLuint SaveRestoreTextureTest::kClient2Id = 2;
1375const GLuint SaveRestoreTextureTest::kService2Id = 12;
1376const GLuint SaveRestoreTextureTest::kEmptyTextureServiceId = 13;
1377
1378TEST_F(SaveRestoreTextureTest, SaveRestore2D) {
1379  manager_->SetTarget(texture_, GL_TEXTURE_2D);
1380  EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), texture_->target());
1381  LevelInfo level0(
1382      GL_TEXTURE_2D, GL_RGBA, 4, 4, 1, 0, GL_UNSIGNED_BYTE, true);
1383  SetLevelInfo(texture_, 0, level0);
1384  EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture_));
1385  EXPECT_TRUE(texture_->texture_complete());
1386  LevelInfo level1 = GetLevelInfo(texture_.get(), GL_TEXTURE_2D, 1);
1387  LevelInfo level2 = GetLevelInfo(texture_.get(), GL_TEXTURE_2D, 2);
1388  scoped_ptr<TextureDefinition> definition(Save(texture_));
1389  const TextureDefinition::LevelInfos& infos = definition->level_infos();
1390  EXPECT_EQ(1U, infos.size());
1391  EXPECT_EQ(3U, infos[0].size());
1392
1393  // Make this texture bigger with more levels, and make sure they get
1394  // clobbered correctly during Restore().
1395  manager_->SetTarget(texture2_, GL_TEXTURE_2D);
1396  SetLevelInfo(
1397      texture2_,
1398      0,
1399      LevelInfo(GL_TEXTURE_2D, GL_RGBA, 16, 16, 1, 0, GL_UNSIGNED_BYTE, false));
1400  EXPECT_TRUE(manager_->MarkMipmapsGenerated(texture2_));
1401  EXPECT_TRUE(texture2_->texture_complete());
1402  EXPECT_EQ(1024U + 256U + 64U + 16U + 4U, texture2_->estimated_size());
1403  Restore(texture2_, definition.release());
1404  EXPECT_EQ(level0, GetLevelInfo(texture2_.get(), GL_TEXTURE_2D, 0));
1405  EXPECT_EQ(level1, GetLevelInfo(texture2_.get(), GL_TEXTURE_2D, 1));
1406  EXPECT_EQ(level2, GetLevelInfo(texture2_.get(), GL_TEXTURE_2D, 2));
1407  EXPECT_EQ(64U + 16U + 4U, texture2_->estimated_size());
1408  GLint w, h;
1409  EXPECT_TRUE(texture2_->GetLevelSize(GL_TEXTURE_2D, 3, &w, &h));
1410  EXPECT_EQ(0, w);
1411  EXPECT_EQ(0, h);
1412}
1413
1414TEST_F(SaveRestoreTextureTest, SaveRestoreClearRectangle) {
1415  manager_->SetTarget(texture_, GL_TEXTURE_RECTANGLE_ARB);
1416  EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_RECTANGLE_ARB), texture_->target());
1417  LevelInfo level0(
1418      GL_TEXTURE_RECTANGLE_ARB, GL_RGBA, 1, 1, 1, 0, GL_UNSIGNED_BYTE, false);
1419  SetLevelInfo(texture_, 0, level0);
1420  EXPECT_TRUE(texture_->texture_complete());
1421  scoped_ptr<TextureDefinition> definition(Save(texture_));
1422  const TextureDefinition::LevelInfos& infos = definition->level_infos();
1423  EXPECT_EQ(1U, infos.size());
1424  EXPECT_EQ(1U, infos[0].size());
1425  EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_RECTANGLE_ARB), infos[0][0].target);
1426  manager_->SetTarget(texture2_, GL_TEXTURE_RECTANGLE_ARB);
1427  Restore(texture2_, definition.release());
1428
1429  // See if we can clear the previously uncleared level now.
1430  EXPECT_EQ(level0, GetLevelInfo(texture2_.get(), GL_TEXTURE_RECTANGLE_ARB, 0));
1431  EXPECT_CALL(*decoder_, ClearLevel(_, _, _, _, _, _, _, _, _))
1432      .WillRepeatedly(Return(true));
1433  EXPECT_TRUE(manager_->ClearTextureLevel(
1434      decoder_.get(), texture2_, GL_TEXTURE_RECTANGLE_ARB, 0));
1435}
1436
1437TEST_F(SaveRestoreTextureTest, SaveRestoreCube) {
1438  manager_->SetTarget(texture_, GL_TEXTURE_CUBE_MAP);
1439  EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP), texture_->target());
1440  LevelInfo face0(GL_TEXTURE_CUBE_MAP_POSITIVE_X,
1441                  GL_RGBA,
1442                  1,
1443                  1,
1444                  1,
1445                  0,
1446                  GL_UNSIGNED_BYTE,
1447                  true);
1448  LevelInfo face5(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
1449                  GL_RGBA,
1450                  3,
1451                  3,
1452                  1,
1453                  0,
1454                  GL_UNSIGNED_BYTE,
1455                  true);
1456  SetLevelInfo(texture_, 0, face0);
1457  SetLevelInfo(texture_, 0, face5);
1458  EXPECT_TRUE(texture_->texture_complete());
1459  scoped_ptr<TextureDefinition> definition(Save(texture_));
1460  const TextureDefinition::LevelInfos& infos = definition->level_infos();
1461  EXPECT_EQ(6U, infos.size());
1462  EXPECT_EQ(1U, infos[0].size());
1463  manager_->SetTarget(texture2_, GL_TEXTURE_CUBE_MAP);
1464  Restore(texture2_, definition.release());
1465  EXPECT_EQ(face0,
1466            GetLevelInfo(texture2_.get(), GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0));
1467  EXPECT_EQ(face5,
1468            GetLevelInfo(texture2_.get(), GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0));
1469}
1470
1471}  // namespace gles2
1472}  // namespace gpu
1473
1474
1475