1// Copyright 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 "cc/resources/resource_provider.h"
6
7#include <algorithm>
8#include <map>
9
10#include "base/bind.h"
11#include "base/containers/hash_tables.h"
12#include "base/logging.h"
13#include "base/memory/ref_counted.h"
14#include "cc/base/scoped_ptr_deque.h"
15#include "cc/output/output_surface.h"
16#include "cc/resources/returned_resource.h"
17#include "cc/resources/shared_bitmap_manager.h"
18#include "cc/resources/single_release_callback.h"
19#include "cc/test/fake_output_surface.h"
20#include "cc/test/fake_output_surface_client.h"
21#include "cc/test/test_texture.h"
22#include "cc/test/test_web_graphics_context_3d.h"
23#include "gpu/GLES2/gl2extchromium.h"
24#include "testing/gmock/include/gmock/gmock.h"
25#include "testing/gtest/include/gtest/gtest.h"
26#include "third_party/khronos/GLES2/gl2.h"
27#include "third_party/khronos/GLES2/gl2ext.h"
28#include "ui/gfx/rect.h"
29
30using testing::Mock;
31using testing::NiceMock;
32using testing::Return;
33using testing::SetArgPointee;
34using testing::StrictMock;
35using testing::_;
36
37namespace cc {
38namespace {
39
40static void EmptyReleaseCallback(unsigned sync_point, bool lost_resource) {}
41
42static void SharedMemoryReleaseCallback(scoped_ptr<base::SharedMemory> memory,
43                                        unsigned sync_point,
44                                        bool lost_resource) {}
45
46static void ReleaseTextureMailbox(unsigned* release_sync_point,
47                                  bool* release_lost_resource,
48                                  unsigned sync_point,
49                                  bool lost_resource) {
50  *release_sync_point = sync_point;
51  *release_lost_resource = lost_resource;
52}
53
54static void ReleaseSharedMemoryCallback(
55    scoped_ptr<base::SharedMemory> shared_memory,
56    bool* release_called,
57    unsigned* release_sync_point,
58    bool* lost_resource_result,
59    unsigned sync_point,
60    bool lost_resource) {
61  *release_called = true;
62  *release_sync_point = sync_point;
63  *lost_resource_result = lost_resource;
64}
65
66static scoped_ptr<base::SharedMemory> CreateAndFillSharedMemory(
67    gfx::Size size,
68    uint32_t value) {
69  scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory);
70  CHECK(shared_memory->CreateAndMapAnonymous(4 * size.GetArea()));
71  uint32_t* pixels = reinterpret_cast<uint32_t*>(shared_memory->memory());
72  CHECK(pixels);
73  std::fill_n(pixels, size.GetArea(), value);
74  return shared_memory.Pass();
75}
76
77class TextureStateTrackingContext : public TestWebGraphicsContext3D {
78 public:
79  MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
80  MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param));
81  MOCK_METHOD1(waitSyncPoint, void(unsigned sync_point));
82  MOCK_METHOD0(insertSyncPoint, unsigned(void));
83  MOCK_METHOD2(produceTextureCHROMIUM,
84               void(GLenum target, const GLbyte* mailbox));
85  MOCK_METHOD2(consumeTextureCHROMIUM,
86               void(GLenum target, const GLbyte* mailbox));
87
88  // Force all textures to be consecutive numbers starting at "1",
89  // so we easily can test for them.
90  virtual GLuint NextTextureId() OVERRIDE {
91    base::AutoLock lock(namespace_->lock);
92    return namespace_->next_texture_id++;
93  }
94  virtual void RetireTextureId(GLuint) OVERRIDE {}
95};
96
97// Shared data between multiple ResourceProviderContext. This contains mailbox
98// contents as well as information about sync points.
99class ContextSharedData {
100 public:
101  static scoped_ptr<ContextSharedData> Create() {
102    return make_scoped_ptr(new ContextSharedData());
103  }
104
105  unsigned InsertSyncPoint() { return next_sync_point_++; }
106
107  void GenMailbox(GLbyte* mailbox) {
108    memset(mailbox, 0, sizeof(GLbyte[64]));
109    memcpy(mailbox, &next_mailbox_, sizeof(next_mailbox_));
110    ++next_mailbox_;
111  }
112
113  void ProduceTexture(const GLbyte* mailbox_name,
114                      unsigned sync_point,
115                      scoped_refptr<TestTexture> texture) {
116    unsigned mailbox = 0;
117    memcpy(&mailbox, mailbox_name, sizeof(mailbox));
118    ASSERT_TRUE(mailbox && mailbox < next_mailbox_);
119    textures_[mailbox] = texture;
120    ASSERT_LT(sync_point_for_mailbox_[mailbox], sync_point);
121    sync_point_for_mailbox_[mailbox] = sync_point;
122  }
123
124  scoped_refptr<TestTexture> ConsumeTexture(const GLbyte* mailbox_name,
125                                            unsigned sync_point) {
126    unsigned mailbox = 0;
127    memcpy(&mailbox, mailbox_name, sizeof(mailbox));
128    DCHECK(mailbox && mailbox < next_mailbox_);
129
130    // If the latest sync point the context has waited on is before the sync
131    // point for when the mailbox was set, pretend we never saw that
132    // ProduceTexture.
133    if (sync_point_for_mailbox_[mailbox] > sync_point) {
134      NOTREACHED();
135      return scoped_refptr<TestTexture>();
136    }
137    return textures_[mailbox];
138  }
139
140 private:
141  ContextSharedData() : next_sync_point_(1), next_mailbox_(1) {}
142
143  unsigned next_sync_point_;
144  unsigned next_mailbox_;
145  typedef base::hash_map<unsigned, scoped_refptr<TestTexture> > TextureMap;
146  TextureMap textures_;
147  base::hash_map<unsigned, unsigned> sync_point_for_mailbox_;
148};
149
150class ResourceProviderContext : public TestWebGraphicsContext3D {
151 public:
152  static scoped_ptr<ResourceProviderContext> Create(
153      ContextSharedData* shared_data) {
154    return make_scoped_ptr(new ResourceProviderContext(shared_data));
155  }
156
157  virtual unsigned insertSyncPoint() OVERRIDE {
158    unsigned sync_point = shared_data_->InsertSyncPoint();
159    // Commit the produceTextureCHROMIUM calls at this point, so that
160    // they're associated with the sync point.
161    for (PendingProduceTextureList::iterator it =
162             pending_produce_textures_.begin();
163         it != pending_produce_textures_.end();
164         ++it) {
165      shared_data_->ProduceTexture(
166          (*it)->mailbox, sync_point, (*it)->texture);
167    }
168    pending_produce_textures_.clear();
169    return sync_point;
170  }
171
172  virtual void waitSyncPoint(unsigned sync_point) OVERRIDE {
173    last_waited_sync_point_ = std::max(sync_point, last_waited_sync_point_);
174  }
175
176  virtual void texStorage2DEXT(GLenum target,
177                               GLint levels,
178                               GLuint internalformat,
179                               GLint width,
180                               GLint height) OVERRIDE {
181    CheckTextureIsBound(target);
182    ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
183    ASSERT_EQ(1, levels);
184    GLenum format = GL_RGBA;
185    switch (internalformat) {
186      case GL_RGBA8_OES:
187        break;
188      case GL_BGRA8_EXT:
189        format = GL_BGRA_EXT;
190        break;
191      default:
192        NOTREACHED();
193    }
194    AllocateTexture(gfx::Size(width, height), format);
195  }
196
197  virtual void texImage2D(GLenum target,
198                          GLint level,
199                          GLenum internalformat,
200                          GLsizei width,
201                          GLsizei height,
202                          GLint border,
203                          GLenum format,
204                          GLenum type,
205                          const void* pixels) OVERRIDE {
206    CheckTextureIsBound(target);
207    ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
208    ASSERT_FALSE(level);
209    ASSERT_EQ(internalformat, format);
210    ASSERT_FALSE(border);
211    ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type);
212    AllocateTexture(gfx::Size(width, height), format);
213    if (pixels)
214      SetPixels(0, 0, width, height, pixels);
215  }
216
217  virtual void texSubImage2D(GLenum target,
218                             GLint level,
219                             GLint xoffset,
220                             GLint yoffset,
221                             GLsizei width,
222                             GLsizei height,
223                             GLenum format,
224                             GLenum type,
225                             const void* pixels) OVERRIDE {
226    CheckTextureIsBound(target);
227    ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
228    ASSERT_FALSE(level);
229    ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type);
230    {
231      base::AutoLock lock_for_texture_access(namespace_->lock);
232      ASSERT_EQ(GLDataFormat(BoundTexture(target)->format), format);
233    }
234    ASSERT_TRUE(pixels);
235    SetPixels(xoffset, yoffset, width, height, pixels);
236  }
237
238  virtual void genMailboxCHROMIUM(GLbyte* mailbox) OVERRIDE {
239    return shared_data_->GenMailbox(mailbox);
240  }
241
242  virtual void produceTextureCHROMIUM(GLenum target,
243                                      const GLbyte* mailbox) OVERRIDE {
244    CheckTextureIsBound(target);
245
246    // Delay moving the texture into the mailbox until the next
247    // InsertSyncPoint, so that it is not visible to other contexts that
248    // haven't waited on that sync point.
249    scoped_ptr<PendingProduceTexture> pending(new PendingProduceTexture);
250    memcpy(pending->mailbox, mailbox, sizeof(pending->mailbox));
251    base::AutoLock lock_for_texture_access(namespace_->lock);
252    pending->texture = BoundTexture(target);
253    pending_produce_textures_.push_back(pending.Pass());
254  }
255
256  virtual void consumeTextureCHROMIUM(GLenum target,
257                                      const GLbyte* mailbox) OVERRIDE {
258    CheckTextureIsBound(target);
259    base::AutoLock lock_for_texture_access(namespace_->lock);
260    scoped_refptr<TestTexture> texture =
261        shared_data_->ConsumeTexture(mailbox, last_waited_sync_point_);
262    namespace_->textures.Replace(BoundTextureId(target), texture);
263  }
264
265  void GetPixels(gfx::Size size, ResourceFormat format, uint8_t* pixels) {
266    CheckTextureIsBound(GL_TEXTURE_2D);
267    base::AutoLock lock_for_texture_access(namespace_->lock);
268    scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
269    ASSERT_EQ(texture->size, size);
270    ASSERT_EQ(texture->format, format);
271    memcpy(pixels, texture->data.get(), TextureSizeBytes(size, format));
272  }
273
274 protected:
275  explicit ResourceProviderContext(ContextSharedData* shared_data)
276      : shared_data_(shared_data),
277        last_waited_sync_point_(0) {}
278
279 private:
280  void AllocateTexture(gfx::Size size, GLenum format) {
281    CheckTextureIsBound(GL_TEXTURE_2D);
282    ResourceFormat texture_format = RGBA_8888;
283    switch (format) {
284      case GL_RGBA:
285        texture_format = RGBA_8888;
286        break;
287      case GL_BGRA_EXT:
288        texture_format = BGRA_8888;
289        break;
290    }
291    base::AutoLock lock_for_texture_access(namespace_->lock);
292    BoundTexture(GL_TEXTURE_2D)->Reallocate(size, texture_format);
293  }
294
295  void SetPixels(int xoffset,
296                 int yoffset,
297                 int width,
298                 int height,
299                 const void* pixels) {
300    CheckTextureIsBound(GL_TEXTURE_2D);
301    base::AutoLock lock_for_texture_access(namespace_->lock);
302    scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
303    ASSERT_TRUE(texture->data.get());
304    ASSERT_TRUE(xoffset >= 0 && xoffset + width <= texture->size.width());
305    ASSERT_TRUE(yoffset >= 0 && yoffset + height <= texture->size.height());
306    ASSERT_TRUE(pixels);
307    size_t in_pitch = TextureSizeBytes(gfx::Size(width, 1), texture->format);
308    size_t out_pitch =
309        TextureSizeBytes(gfx::Size(texture->size.width(), 1), texture->format);
310    uint8_t* dest = texture->data.get() + yoffset * out_pitch +
311                    TextureSizeBytes(gfx::Size(xoffset, 1), texture->format);
312    const uint8_t* src = static_cast<const uint8_t*>(pixels);
313    for (int i = 0; i < height; ++i) {
314      memcpy(dest, src, in_pitch);
315      dest += out_pitch;
316      src += in_pitch;
317    }
318  }
319
320  struct PendingProduceTexture {
321    GLbyte mailbox[64];
322    scoped_refptr<TestTexture> texture;
323  };
324  typedef ScopedPtrDeque<PendingProduceTexture> PendingProduceTextureList;
325  ContextSharedData* shared_data_;
326  unsigned last_waited_sync_point_;
327  PendingProduceTextureList pending_produce_textures_;
328};
329
330void FreeSharedBitmap(SharedBitmap* shared_bitmap) {
331  delete shared_bitmap->memory();
332}
333
334void IgnoreSharedBitmap(SharedBitmap* shared_bitmap) {}
335
336class TestSharedBitmapManager : public SharedBitmapManager {
337 public:
338  TestSharedBitmapManager() : count_(0) {}
339  virtual ~TestSharedBitmapManager() {}
340
341  virtual scoped_ptr<SharedBitmap> AllocateSharedBitmap(gfx::Size size)
342      OVERRIDE {
343    scoped_ptr<base::SharedMemory> memory(new base::SharedMemory);
344    memory->CreateAndMapAnonymous(size.GetArea() * 4);
345    int8 name[64] = { 0 };
346    name[0] = count_++;
347    SharedBitmapId id;
348    id.SetName(name);
349    bitmap_map_[id] = memory.get();
350    return scoped_ptr<SharedBitmap>(
351        new SharedBitmap(memory.release(), id, base::Bind(&FreeSharedBitmap)));
352  }
353
354  virtual scoped_ptr<SharedBitmap> GetSharedBitmapFromId(
355      gfx::Size,
356      const SharedBitmapId& id) OVERRIDE {
357    if (bitmap_map_.find(id) == bitmap_map_.end())
358      return scoped_ptr<SharedBitmap>();
359    return scoped_ptr<SharedBitmap>(
360        new SharedBitmap(bitmap_map_[id], id, base::Bind(&IgnoreSharedBitmap)));
361  }
362
363  virtual scoped_ptr<SharedBitmap> GetBitmapForSharedMemory(
364      base::SharedMemory* memory) OVERRIDE {
365    int8 name[64] = { 0 };
366    name[0] = count_++;
367    SharedBitmapId id;
368    id.SetName(name);
369    bitmap_map_[id] = memory;
370    return scoped_ptr<SharedBitmap>(
371        new SharedBitmap(memory, id, base::Bind(&IgnoreSharedBitmap)));
372  }
373
374 private:
375  int count_;
376  std::map<SharedBitmapId, base::SharedMemory*> bitmap_map_;
377};
378
379void GetResourcePixels(ResourceProvider* resource_provider,
380                       ResourceProviderContext* context,
381                       ResourceProvider::ResourceId id,
382                       gfx::Size size,
383                       ResourceFormat format,
384                       uint8_t* pixels) {
385  switch (resource_provider->default_resource_type()) {
386    case ResourceProvider::GLTexture: {
387      ResourceProvider::ScopedReadLockGL lock_gl(resource_provider, id);
388      ASSERT_NE(0U, lock_gl.texture_id());
389      context->bindTexture(GL_TEXTURE_2D, lock_gl.texture_id());
390      context->GetPixels(size, format, pixels);
391      break;
392    }
393    case ResourceProvider::Bitmap: {
394      ResourceProvider::ScopedReadLockSoftware lock_software(resource_provider,
395                                                             id);
396      memcpy(pixels,
397             lock_software.sk_bitmap()->getPixels(),
398             lock_software.sk_bitmap()->getSize());
399      break;
400    }
401    case ResourceProvider::InvalidType:
402      NOTREACHED();
403      break;
404  }
405}
406
407class ResourceProviderTest
408    : public testing::TestWithParam<ResourceProvider::ResourceType> {
409 public:
410  ResourceProviderTest()
411      : shared_data_(ContextSharedData::Create()),
412        context3d_(NULL),
413        child_context_(NULL) {
414    switch (GetParam()) {
415      case ResourceProvider::GLTexture: {
416        scoped_ptr<ResourceProviderContext> context3d(
417            ResourceProviderContext::Create(shared_data_.get()));
418        context3d_ = context3d.get();
419
420        scoped_refptr<TestContextProvider> context_provider =
421            TestContextProvider::Create(
422                context3d.PassAs<TestWebGraphicsContext3D>());
423
424        output_surface_ = FakeOutputSurface::Create3d(context_provider);
425
426        scoped_ptr<ResourceProviderContext> child_context_owned =
427            ResourceProviderContext::Create(shared_data_.get());
428        child_context_ = child_context_owned.get();
429        child_output_surface_ = FakeOutputSurface::Create3d(
430            child_context_owned.PassAs<TestWebGraphicsContext3D>());
431        break;
432      }
433      case ResourceProvider::Bitmap:
434        output_surface_ = FakeOutputSurface::CreateSoftware(
435            make_scoped_ptr(new SoftwareOutputDevice));
436        child_output_surface_ = FakeOutputSurface::CreateSoftware(
437            make_scoped_ptr(new SoftwareOutputDevice));
438        break;
439      case ResourceProvider::InvalidType:
440        NOTREACHED();
441        break;
442    }
443    CHECK(output_surface_->BindToClient(&output_surface_client_));
444    CHECK(child_output_surface_->BindToClient(&child_output_surface_client_));
445
446    shared_bitmap_manager_.reset(new TestSharedBitmapManager());
447
448    resource_provider_ = ResourceProvider::Create(
449        output_surface_.get(), shared_bitmap_manager_.get(), 0, false, 1);
450    child_resource_provider_ = ResourceProvider::Create(
451        child_output_surface_.get(),
452        shared_bitmap_manager_.get(),
453        0,
454        false,
455        1);
456  }
457
458  static void CollectResources(ReturnedResourceArray* array,
459                               const ReturnedResourceArray& returned) {
460    array->insert(array->end(), returned.begin(), returned.end());
461  }
462
463  static ReturnCallback GetReturnCallback(ReturnedResourceArray* array) {
464    return base::Bind(&ResourceProviderTest::CollectResources, array);
465  }
466
467  static void SetResourceFilter(ResourceProvider* resource_provider,
468                                ResourceProvider::ResourceId id,
469                                GLenum filter) {
470    ResourceProvider::ScopedSamplerGL sampler(
471        resource_provider, id, GL_TEXTURE_2D, filter);
472  }
473
474  ResourceProviderContext* context() { return context3d_; }
475
476  ResourceProvider::ResourceId CreateChildMailbox(unsigned* release_sync_point,
477                                                  bool* lost_resource,
478                                                  bool* release_called,
479                                                  unsigned* sync_point) {
480    if (GetParam() == ResourceProvider::GLTexture) {
481      unsigned texture = child_context_->createTexture();
482      gpu::Mailbox gpu_mailbox;
483      child_context_->bindTexture(GL_TEXTURE_2D, texture);
484      child_context_->genMailboxCHROMIUM(gpu_mailbox.name);
485      child_context_->produceTextureCHROMIUM(GL_TEXTURE_2D, gpu_mailbox.name);
486      *sync_point = child_context_->insertSyncPoint();
487      EXPECT_LT(0u, *sync_point);
488
489      scoped_ptr<base::SharedMemory> shared_memory;
490      scoped_ptr<SingleReleaseCallback> callback =
491          SingleReleaseCallback::Create(base::Bind(ReleaseSharedMemoryCallback,
492                                                   base::Passed(&shared_memory),
493                                                   release_called,
494                                                   release_sync_point,
495                                                   lost_resource));
496      return child_resource_provider_->CreateResourceFromTextureMailbox(
497          TextureMailbox(gpu_mailbox, *sync_point), callback.Pass());
498    } else {
499      gfx::Size size(64, 64);
500      scoped_ptr<base::SharedMemory> shared_memory(
501          CreateAndFillSharedMemory(size, 0));
502
503      base::SharedMemory* shared_memory_ptr = shared_memory.get();
504      scoped_ptr<SingleReleaseCallback> callback =
505          SingleReleaseCallback::Create(base::Bind(ReleaseSharedMemoryCallback,
506                                                   base::Passed(&shared_memory),
507                                                   release_called,
508                                                   release_sync_point,
509                                                   lost_resource));
510      return child_resource_provider_->CreateResourceFromTextureMailbox(
511          TextureMailbox(shared_memory_ptr, size), callback.Pass());
512    }
513  }
514
515 protected:
516  scoped_ptr<ContextSharedData> shared_data_;
517  ResourceProviderContext* context3d_;
518  ResourceProviderContext* child_context_;
519  FakeOutputSurfaceClient output_surface_client_;
520  FakeOutputSurfaceClient child_output_surface_client_;
521  scoped_ptr<OutputSurface> output_surface_;
522  scoped_ptr<OutputSurface> child_output_surface_;
523  scoped_ptr<ResourceProvider> resource_provider_;
524  scoped_ptr<ResourceProvider> child_resource_provider_;
525  scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_;
526};
527
528void CheckCreateResource(ResourceProvider::ResourceType expected_default_type,
529                         ResourceProvider* resource_provider,
530                         ResourceProviderContext* context) {
531  DCHECK_EQ(expected_default_type, resource_provider->default_resource_type());
532
533  gfx::Size size(1, 1);
534  ResourceFormat format = RGBA_8888;
535  size_t pixel_size = TextureSizeBytes(size, format);
536  ASSERT_EQ(4U, pixel_size);
537
538  ResourceProvider::ResourceId id = resource_provider->CreateResource(
539      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
540  EXPECT_EQ(1, static_cast<int>(resource_provider->num_resources()));
541  if (expected_default_type == ResourceProvider::GLTexture)
542    EXPECT_EQ(0u, context->NumTextures());
543
544  uint8_t data[4] = { 1, 2, 3, 4 };
545  gfx::Rect rect(size);
546  resource_provider->SetPixels(id, data, rect, rect, gfx::Vector2d());
547  if (expected_default_type == ResourceProvider::GLTexture)
548    EXPECT_EQ(1u, context->NumTextures());
549
550  uint8_t result[4] = { 0 };
551  GetResourcePixels(resource_provider, context, id, size, format, result);
552  EXPECT_EQ(0, memcmp(data, result, pixel_size));
553
554  resource_provider->DeleteResource(id);
555  EXPECT_EQ(0, static_cast<int>(resource_provider->num_resources()));
556  if (expected_default_type == ResourceProvider::GLTexture)
557    EXPECT_EQ(0u, context->NumTextures());
558}
559
560TEST_P(ResourceProviderTest, Basic) {
561  CheckCreateResource(GetParam(), resource_provider_.get(), context());
562}
563
564TEST_P(ResourceProviderTest, Upload) {
565  gfx::Size size(2, 2);
566  ResourceFormat format = RGBA_8888;
567  size_t pixel_size = TextureSizeBytes(size, format);
568  ASSERT_EQ(16U, pixel_size);
569
570  ResourceProvider::ResourceId id = resource_provider_->CreateResource(
571      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
572
573  uint8_t image[16] = { 0 };
574  gfx::Rect image_rect(size);
575  resource_provider_->SetPixels(
576      id, image, image_rect, image_rect, gfx::Vector2d());
577
578  for (uint8_t i = 0; i < pixel_size; ++i)
579    image[i] = i;
580
581  uint8_t result[16] = { 0 };
582  {
583    gfx::Rect source_rect(0, 0, 1, 1);
584    gfx::Vector2d dest_offset(0, 0);
585    resource_provider_->SetPixels(
586        id, image, image_rect, source_rect, dest_offset);
587
588    uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
589    GetResourcePixels(
590        resource_provider_.get(), context(), id, size, format, result);
591    EXPECT_EQ(0, memcmp(expected, result, pixel_size));
592  }
593  {
594    gfx::Rect source_rect(0, 0, 1, 1);
595    gfx::Vector2d dest_offset(1, 1);
596    resource_provider_->SetPixels(
597        id, image, image_rect, source_rect, dest_offset);
598
599    uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
600    GetResourcePixels(
601        resource_provider_.get(), context(), id, size, format, result);
602    EXPECT_EQ(0, memcmp(expected, result, pixel_size));
603  }
604  {
605    gfx::Rect source_rect(1, 0, 1, 1);
606    gfx::Vector2d dest_offset(0, 1);
607    resource_provider_->SetPixels(
608        id, image, image_rect, source_rect, dest_offset);
609
610    uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3 };
611    GetResourcePixels(
612        resource_provider_.get(), context(), id, size, format, result);
613    EXPECT_EQ(0, memcmp(expected, result, pixel_size));
614  }
615  {
616    gfx::Rect offset_image_rect(gfx::Point(100, 100), size);
617    gfx::Rect source_rect(100, 100, 1, 1);
618    gfx::Vector2d dest_offset(1, 0);
619    resource_provider_->SetPixels(
620        id, image, offset_image_rect, source_rect, dest_offset);
621
622    uint8_t expected[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3 };
623    GetResourcePixels(
624        resource_provider_.get(), context(), id, size, format, result);
625    EXPECT_EQ(0, memcmp(expected, result, pixel_size));
626  }
627
628  resource_provider_->DeleteResource(id);
629}
630
631TEST_P(ResourceProviderTest, TransferGLResources) {
632  if (GetParam() != ResourceProvider::GLTexture)
633    return;
634  gfx::Size size(1, 1);
635  ResourceFormat format = RGBA_8888;
636  size_t pixel_size = TextureSizeBytes(size, format);
637  ASSERT_EQ(4U, pixel_size);
638
639  ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
640      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
641  uint8_t data1[4] = { 1, 2, 3, 4 };
642  gfx::Rect rect(size);
643  child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
644
645  ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
646      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
647  uint8_t data2[4] = { 5, 5, 5, 5 };
648  child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
649
650  GLuint external_texture_id = child_context_->createExternalTexture();
651  child_context_->bindTexture(GL_TEXTURE_EXTERNAL_OES, external_texture_id);
652
653  gpu::Mailbox external_mailbox;
654  child_context_->genMailboxCHROMIUM(external_mailbox.name);
655  child_context_->produceTextureCHROMIUM(GL_TEXTURE_EXTERNAL_OES,
656                                         external_mailbox.name);
657  const unsigned external_sync_point = child_context_->insertSyncPoint();
658  ResourceProvider::ResourceId id3 =
659      child_resource_provider_->CreateResourceFromTextureMailbox(
660          TextureMailbox(
661              external_mailbox, GL_TEXTURE_EXTERNAL_OES, external_sync_point),
662          SingleReleaseCallback::Create(base::Bind(&EmptyReleaseCallback)));
663
664  ReturnedResourceArray returned_to_child;
665  int child_id =
666      resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
667  {
668    // Transfer some resources to the parent.
669    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
670    resource_ids_to_transfer.push_back(id1);
671    resource_ids_to_transfer.push_back(id2);
672    resource_ids_to_transfer.push_back(id3);
673    TransferableResourceArray list;
674    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
675                                                  &list);
676    ASSERT_EQ(3u, list.size());
677    EXPECT_NE(0u, list[0].sync_point);
678    EXPECT_NE(0u, list[1].sync_point);
679    EXPECT_EQ(external_sync_point, list[2].sync_point);
680    EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].target);
681    EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[1].target);
682    EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), list[2].target);
683    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
684    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
685    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
686    resource_provider_->ReceiveFromChild(child_id, list);
687    resource_provider_->DeclareUsedResourcesFromChild(child_id,
688                                                      resource_ids_to_transfer);
689  }
690
691  EXPECT_EQ(3u, resource_provider_->num_resources());
692  ResourceProvider::ResourceIdMap resource_map =
693      resource_provider_->GetChildToParentMap(child_id);
694  ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
695  ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
696  ResourceProvider::ResourceId mapped_id3 = resource_map[id3];
697  EXPECT_NE(0u, mapped_id1);
698  EXPECT_NE(0u, mapped_id2);
699  EXPECT_NE(0u, mapped_id3);
700  EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
701  EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
702  EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
703
704  uint8_t result[4] = { 0 };
705  GetResourcePixels(
706      resource_provider_.get(), context(), mapped_id1, size, format, result);
707  EXPECT_EQ(0, memcmp(data1, result, pixel_size));
708
709  GetResourcePixels(
710      resource_provider_.get(), context(), mapped_id2, size, format, result);
711  EXPECT_EQ(0, memcmp(data2, result, pixel_size));
712
713  {
714    // Check that transfering again the same resource from the child to the
715    // parent works.
716    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
717    resource_ids_to_transfer.push_back(id1);
718    TransferableResourceArray list;
719    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
720                                                  &list);
721    EXPECT_EQ(1u, list.size());
722    EXPECT_EQ(id1, list[0].id);
723    EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].target);
724    ReturnedResourceArray returned;
725    TransferableResource::ReturnResources(list, &returned);
726    child_resource_provider_->ReceiveReturnsFromParent(returned);
727    // id1 was exported twice, we returned it only once, it should still be
728    // in-use.
729    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
730  }
731  {
732    EXPECT_EQ(0u, returned_to_child.size());
733
734    // Transfer resources back from the parent to the child. Set no resources as
735    // being in use.
736    ResourceProvider::ResourceIdArray no_resources;
737    resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
738
739    ASSERT_EQ(3u, returned_to_child.size());
740    EXPECT_NE(0u, returned_to_child[0].sync_point);
741    EXPECT_NE(0u, returned_to_child[1].sync_point);
742    EXPECT_NE(0u, returned_to_child[2].sync_point);
743    EXPECT_FALSE(returned_to_child[0].lost);
744    EXPECT_FALSE(returned_to_child[1].lost);
745    EXPECT_FALSE(returned_to_child[2].lost);
746    child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
747    returned_to_child.clear();
748  }
749  EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
750  EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
751  EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
752
753  {
754    ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
755                                            id1);
756    ASSERT_NE(0U, lock.texture_id());
757    child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
758    child_context_->GetPixels(size, format, result);
759    EXPECT_EQ(0, memcmp(data1, result, pixel_size));
760  }
761  {
762    ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
763                                            id2);
764    ASSERT_NE(0U, lock.texture_id());
765    child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
766    child_context_->GetPixels(size, format, result);
767    EXPECT_EQ(0, memcmp(data2, result, pixel_size));
768  }
769  {
770    // Transfer resources to the parent again.
771    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
772    resource_ids_to_transfer.push_back(id1);
773    resource_ids_to_transfer.push_back(id2);
774    resource_ids_to_transfer.push_back(id3);
775    TransferableResourceArray list;
776    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
777                                                  &list);
778    ASSERT_EQ(3u, list.size());
779    EXPECT_EQ(id1, list[0].id);
780    EXPECT_EQ(id2, list[1].id);
781    EXPECT_EQ(id3, list[2].id);
782    EXPECT_NE(0u, list[0].sync_point);
783    EXPECT_NE(0u, list[1].sync_point);
784    EXPECT_NE(0u, list[2].sync_point);
785    EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].target);
786    EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[1].target);
787    EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), list[2].target);
788    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
789    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
790    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
791    resource_provider_->ReceiveFromChild(child_id, list);
792    resource_provider_->DeclareUsedResourcesFromChild(child_id,
793                                                      resource_ids_to_transfer);
794  }
795
796  EXPECT_EQ(0u, returned_to_child.size());
797
798  EXPECT_EQ(3u, resource_provider_->num_resources());
799  resource_provider_->DestroyChild(child_id);
800  EXPECT_EQ(0u, resource_provider_->num_resources());
801
802  ASSERT_EQ(3u, returned_to_child.size());
803  EXPECT_NE(0u, returned_to_child[0].sync_point);
804  EXPECT_NE(0u, returned_to_child[1].sync_point);
805  EXPECT_NE(0u, returned_to_child[2].sync_point);
806  EXPECT_FALSE(returned_to_child[0].lost);
807  EXPECT_FALSE(returned_to_child[1].lost);
808  EXPECT_FALSE(returned_to_child[2].lost);
809}
810
811TEST_P(ResourceProviderTest, TransferSoftwareResources) {
812  if (GetParam() != ResourceProvider::Bitmap)
813    return;
814
815  gfx::Size size(1, 1);
816  ResourceFormat format = RGBA_8888;
817  size_t pixel_size = TextureSizeBytes(size, format);
818  ASSERT_EQ(4U, pixel_size);
819
820  ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
821      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
822  uint8_t data1[4] = { 1, 2, 3, 4 };
823  gfx::Rect rect(size);
824  child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
825
826  ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
827      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
828  uint8_t data2[4] = { 5, 5, 5, 5 };
829  child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
830
831  scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
832  shared_memory->CreateAndMapAnonymous(1);
833  base::SharedMemory* shared_memory_ptr = shared_memory.get();
834  ResourceProvider::ResourceId id3 =
835      child_resource_provider_->CreateResourceFromTextureMailbox(
836          TextureMailbox(shared_memory_ptr, gfx::Size(1, 1)),
837          SingleReleaseCallback::Create(base::Bind(
838              &SharedMemoryReleaseCallback, base::Passed(&shared_memory))));
839
840  ReturnedResourceArray returned_to_child;
841  int child_id =
842      resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
843  {
844    // Transfer some resources to the parent.
845    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
846    resource_ids_to_transfer.push_back(id1);
847    resource_ids_to_transfer.push_back(id2);
848    resource_ids_to_transfer.push_back(id3);
849    TransferableResourceArray list;
850    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
851                                                  &list);
852    ASSERT_EQ(3u, list.size());
853    EXPECT_EQ(0u, list[0].sync_point);
854    EXPECT_EQ(0u, list[1].sync_point);
855    EXPECT_EQ(0u, list[2].sync_point);
856    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
857    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
858    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
859    resource_provider_->ReceiveFromChild(child_id, list);
860    resource_provider_->DeclareUsedResourcesFromChild(child_id,
861                                                      resource_ids_to_transfer);
862  }
863
864  EXPECT_EQ(3u, resource_provider_->num_resources());
865  ResourceProvider::ResourceIdMap resource_map =
866      resource_provider_->GetChildToParentMap(child_id);
867  ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
868  ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
869  ResourceProvider::ResourceId mapped_id3 = resource_map[id3];
870  EXPECT_NE(0u, mapped_id1);
871  EXPECT_NE(0u, mapped_id2);
872  EXPECT_NE(0u, mapped_id3);
873  EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
874  EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
875  EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
876
877  uint8_t result[4] = { 0 };
878  GetResourcePixels(
879      resource_provider_.get(), context(), mapped_id1, size, format, result);
880  EXPECT_EQ(0, memcmp(data1, result, pixel_size));
881
882  GetResourcePixels(
883      resource_provider_.get(), context(), mapped_id2, size, format, result);
884  EXPECT_EQ(0, memcmp(data2, result, pixel_size));
885
886  {
887    // Check that transfering again the same resource from the child to the
888    // parent works.
889    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
890    resource_ids_to_transfer.push_back(id1);
891    TransferableResourceArray list;
892    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
893                                                  &list);
894    EXPECT_EQ(1u, list.size());
895    EXPECT_EQ(id1, list[0].id);
896    ReturnedResourceArray returned;
897    TransferableResource::ReturnResources(list, &returned);
898    child_resource_provider_->ReceiveReturnsFromParent(returned);
899    // id1 was exported twice, we returned it only once, it should still be
900    // in-use.
901    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
902  }
903  {
904    EXPECT_EQ(0u, returned_to_child.size());
905
906    // Transfer resources back from the parent to the child. Set no resources as
907    // being in use.
908    ResourceProvider::ResourceIdArray no_resources;
909    resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
910
911    ASSERT_EQ(3u, returned_to_child.size());
912    EXPECT_EQ(0u, returned_to_child[0].sync_point);
913    EXPECT_EQ(0u, returned_to_child[1].sync_point);
914    EXPECT_EQ(0u, returned_to_child[2].sync_point);
915    EXPECT_EQ(id1, returned_to_child[0].id);
916    EXPECT_EQ(id2, returned_to_child[1].id);
917    EXPECT_EQ(id3, returned_to_child[2].id);
918    EXPECT_FALSE(returned_to_child[0].lost);
919    EXPECT_FALSE(returned_to_child[1].lost);
920    EXPECT_FALSE(returned_to_child[2].lost);
921    child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
922    returned_to_child.clear();
923  }
924  EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
925  EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
926  EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
927
928  {
929    ResourceProvider::ScopedReadLockSoftware lock(
930        child_resource_provider_.get(), id1);
931    const SkBitmap* sk_bitmap = lock.sk_bitmap();
932    EXPECT_EQ(sk_bitmap->width(), size.width());
933    EXPECT_EQ(sk_bitmap->height(), size.height());
934    EXPECT_EQ(0, memcmp(data1, sk_bitmap->getPixels(), pixel_size));
935  }
936  {
937    ResourceProvider::ScopedReadLockSoftware lock(
938        child_resource_provider_.get(), id2);
939    const SkBitmap* sk_bitmap = lock.sk_bitmap();
940    EXPECT_EQ(sk_bitmap->width(), size.width());
941    EXPECT_EQ(sk_bitmap->height(), size.height());
942    EXPECT_EQ(0, memcmp(data2, sk_bitmap->getPixels(), pixel_size));
943  }
944  {
945    // Transfer resources to the parent again.
946    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
947    resource_ids_to_transfer.push_back(id1);
948    resource_ids_to_transfer.push_back(id2);
949    resource_ids_to_transfer.push_back(id3);
950    TransferableResourceArray list;
951    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
952                                                  &list);
953    ASSERT_EQ(3u, list.size());
954    EXPECT_EQ(id1, list[0].id);
955    EXPECT_EQ(id2, list[1].id);
956    EXPECT_EQ(id3, list[2].id);
957    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
958    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
959    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
960    resource_provider_->ReceiveFromChild(child_id, list);
961    resource_provider_->DeclareUsedResourcesFromChild(child_id,
962                                                      resource_ids_to_transfer);
963  }
964
965  EXPECT_EQ(0u, returned_to_child.size());
966
967  EXPECT_EQ(3u, resource_provider_->num_resources());
968  resource_provider_->DestroyChild(child_id);
969  EXPECT_EQ(0u, resource_provider_->num_resources());
970
971  ASSERT_EQ(3u, returned_to_child.size());
972  EXPECT_EQ(0u, returned_to_child[0].sync_point);
973  EXPECT_EQ(0u, returned_to_child[1].sync_point);
974  EXPECT_EQ(0u, returned_to_child[2].sync_point);
975  EXPECT_EQ(id1, returned_to_child[0].id);
976  EXPECT_EQ(id2, returned_to_child[1].id);
977  EXPECT_EQ(id3, returned_to_child[2].id);
978  EXPECT_FALSE(returned_to_child[0].lost);
979  EXPECT_FALSE(returned_to_child[1].lost);
980  EXPECT_FALSE(returned_to_child[2].lost);
981}
982
983TEST_P(ResourceProviderTest, TransferSoftwareToNonUber) {
984  // TODO(jbauman): Remove test when shared bitmap manager available
985  // everywhere.
986  if (GetParam() != ResourceProvider::Bitmap)
987    return;
988
989  scoped_ptr<FakeOutputSurface> parent_output_surface =
990      FakeOutputSurface::CreateSoftware(
991          make_scoped_ptr(new SoftwareOutputDevice));
992  FakeOutputSurfaceClient parent_output_surface_client;
993  CHECK(parent_output_surface->BindToClient(&parent_output_surface_client));
994
995  scoped_ptr<ResourceProvider> parent_resource_provider(
996      ResourceProvider::Create(parent_output_surface.get(),
997                               NULL,
998                               0,
999                               false,
1000                               1));
1001
1002  gfx::Size size(1, 1);
1003  ResourceFormat format = RGBA_8888;
1004  size_t pixel_size = TextureSizeBytes(size, format);
1005  ASSERT_EQ(4U, pixel_size);
1006
1007  ResourceProvider::ResourceId id1 = resource_provider_->CreateResource(
1008      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1009  uint8_t data1[4] = { 1, 2, 3, 4 };
1010  gfx::Rect rect(size);
1011  resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1012
1013  ReturnedResourceArray returned_to_child;
1014  int child_id = parent_resource_provider->CreateChild(
1015      GetReturnCallback(&returned_to_child));
1016  {
1017    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1018    resource_ids_to_transfer.push_back(id1);
1019    TransferableResourceArray list;
1020    resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1021    ASSERT_EQ(1u, list.size());
1022    EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1023    parent_resource_provider->ReceiveFromChild(child_id, list);
1024  }
1025
1026  EXPECT_EQ(0u, parent_resource_provider->num_resources());
1027  ASSERT_EQ(1u, returned_to_child.size());
1028  EXPECT_EQ(returned_to_child[0].id, id1);
1029  ResourceProvider::ResourceIdMap resource_map =
1030      parent_resource_provider->GetChildToParentMap(child_id);
1031  ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1032  EXPECT_EQ(0u, mapped_id1);
1033
1034  parent_resource_provider->DestroyChild(child_id);
1035  EXPECT_EQ(0u, parent_resource_provider->num_resources());
1036
1037  ASSERT_EQ(1u, returned_to_child.size());
1038  EXPECT_FALSE(returned_to_child[0].lost);
1039}
1040
1041TEST_P(ResourceProviderTest, TransferGLToSoftware) {
1042  if (GetParam() != ResourceProvider::Bitmap)
1043    return;
1044
1045  scoped_ptr<ResourceProviderContext> child_context_owned(
1046      ResourceProviderContext::Create(shared_data_.get()));
1047
1048  FakeOutputSurfaceClient child_output_surface_client;
1049  scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d(
1050      child_context_owned.PassAs<TestWebGraphicsContext3D>()));
1051  CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1052
1053  scoped_ptr<ResourceProvider> child_resource_provider(
1054      ResourceProvider::Create(child_output_surface.get(),
1055                               NULL,
1056                               0,
1057                               false,
1058                               1));
1059
1060  gfx::Size size(1, 1);
1061  ResourceFormat format = RGBA_8888;
1062  size_t pixel_size = TextureSizeBytes(size, format);
1063  ASSERT_EQ(4U, pixel_size);
1064
1065  ResourceProvider::ResourceId id1 = child_resource_provider->CreateResource(
1066      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1067  uint8_t data1[4] = { 1, 2, 3, 4 };
1068  gfx::Rect rect(size);
1069  child_resource_provider->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1070
1071  ReturnedResourceArray returned_to_child;
1072  int child_id =
1073      resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1074  {
1075    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1076    resource_ids_to_transfer.push_back(id1);
1077    TransferableResourceArray list;
1078    child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1079                                                 &list);
1080    ASSERT_EQ(1u, list.size());
1081    EXPECT_NE(0u, list[0].sync_point);
1082    EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].target);
1083    EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1));
1084    resource_provider_->ReceiveFromChild(child_id, list);
1085  }
1086
1087  EXPECT_EQ(0u, resource_provider_->num_resources());
1088  ASSERT_EQ(1u, returned_to_child.size());
1089  EXPECT_EQ(returned_to_child[0].id, id1);
1090  ResourceProvider::ResourceIdMap resource_map =
1091      resource_provider_->GetChildToParentMap(child_id);
1092  ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1093  EXPECT_EQ(0u, mapped_id1);
1094
1095  resource_provider_->DestroyChild(child_id);
1096  EXPECT_EQ(0u, resource_provider_->num_resources());
1097
1098  ASSERT_EQ(1u, returned_to_child.size());
1099  EXPECT_FALSE(returned_to_child[0].lost);
1100}
1101
1102TEST_P(ResourceProviderTest, TransferInvalidSoftware) {
1103  if (GetParam() != ResourceProvider::Bitmap)
1104    return;
1105
1106  gfx::Size size(1, 1);
1107  ResourceFormat format = RGBA_8888;
1108  size_t pixel_size = TextureSizeBytes(size, format);
1109  ASSERT_EQ(4U, pixel_size);
1110
1111  ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1112      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1113  uint8_t data1[4] = { 1, 2, 3, 4 };
1114  gfx::Rect rect(size);
1115  child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1116
1117  ReturnedResourceArray returned_to_child;
1118  int child_id =
1119      resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1120  {
1121    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1122    resource_ids_to_transfer.push_back(id1);
1123    TransferableResourceArray list;
1124    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1125                                                  &list);
1126    ASSERT_EQ(1u, list.size());
1127    // Make invalid.
1128    list[0].mailbox.name[1] = 5;
1129    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1130    resource_provider_->ReceiveFromChild(child_id, list);
1131  }
1132
1133  EXPECT_EQ(0u, resource_provider_->num_resources());
1134  ASSERT_EQ(1u, returned_to_child.size());
1135  EXPECT_EQ(returned_to_child[0].id, id1);
1136  ResourceProvider::ResourceIdMap resource_map =
1137      resource_provider_->GetChildToParentMap(child_id);
1138  ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1139  EXPECT_EQ(0u, mapped_id1);
1140
1141  resource_provider_->DestroyChild(child_id);
1142  EXPECT_EQ(0u, resource_provider_->num_resources());
1143
1144  ASSERT_EQ(1u, returned_to_child.size());
1145  EXPECT_FALSE(returned_to_child[0].lost);
1146}
1147
1148TEST_P(ResourceProviderTest, DeleteExportedResources) {
1149  gfx::Size size(1, 1);
1150  ResourceFormat format = RGBA_8888;
1151  size_t pixel_size = TextureSizeBytes(size, format);
1152  ASSERT_EQ(4U, pixel_size);
1153
1154  ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1155      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1156  uint8_t data1[4] = { 1, 2, 3, 4 };
1157  gfx::Rect rect(size);
1158  child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1159
1160  ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
1161      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1162  uint8_t data2[4] = {5, 5, 5, 5};
1163  child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
1164
1165  ReturnedResourceArray returned_to_child;
1166  int child_id =
1167      resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1168  {
1169    // Transfer some resources to the parent.
1170    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1171    resource_ids_to_transfer.push_back(id1);
1172    resource_ids_to_transfer.push_back(id2);
1173    TransferableResourceArray list;
1174    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1175                                                  &list);
1176    ASSERT_EQ(2u, list.size());
1177    if (GetParam() == ResourceProvider::GLTexture) {
1178      EXPECT_NE(0u, list[0].sync_point);
1179      EXPECT_NE(0u, list[1].sync_point);
1180    }
1181    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1182    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1183    resource_provider_->ReceiveFromChild(child_id, list);
1184    resource_provider_->DeclareUsedResourcesFromChild(child_id,
1185                                                      resource_ids_to_transfer);
1186  }
1187
1188  EXPECT_EQ(2u, resource_provider_->num_resources());
1189  ResourceProvider::ResourceIdMap resource_map =
1190      resource_provider_->GetChildToParentMap(child_id);
1191  ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1192  ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1193  EXPECT_NE(0u, mapped_id1);
1194  EXPECT_NE(0u, mapped_id2);
1195  EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1196  EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1197
1198  {
1199    // The parent transfers the resources to the grandparent.
1200    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1201    resource_ids_to_transfer.push_back(mapped_id1);
1202    resource_ids_to_transfer.push_back(mapped_id2);
1203    TransferableResourceArray list;
1204    resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1205
1206    ASSERT_EQ(2u, list.size());
1207    if (GetParam() == ResourceProvider::GLTexture) {
1208      EXPECT_NE(0u, list[0].sync_point);
1209      EXPECT_NE(0u, list[1].sync_point);
1210    }
1211    EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1212    EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1213
1214    // Release the resource in the parent. Set no resources as being in use. The
1215    // resources are exported so that can't be transferred back yet.
1216    ResourceProvider::ResourceIdArray no_resources;
1217    resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1218
1219    EXPECT_EQ(0u, returned_to_child.size());
1220    EXPECT_EQ(2u, resource_provider_->num_resources());
1221
1222    // Return the resources from the grandparent to the parent. They should be
1223    // returned to the child then.
1224    EXPECT_EQ(2u, list.size());
1225    EXPECT_EQ(mapped_id1, list[0].id);
1226    EXPECT_EQ(mapped_id2, list[1].id);
1227    ReturnedResourceArray returned;
1228    TransferableResource::ReturnResources(list, &returned);
1229    resource_provider_->ReceiveReturnsFromParent(returned);
1230
1231    EXPECT_EQ(0u, resource_provider_->num_resources());
1232    ASSERT_EQ(2u, returned_to_child.size());
1233    if (GetParam() == ResourceProvider::GLTexture) {
1234      EXPECT_NE(0u, returned_to_child[0].sync_point);
1235      EXPECT_NE(0u, returned_to_child[1].sync_point);
1236    }
1237    EXPECT_FALSE(returned_to_child[0].lost);
1238    EXPECT_FALSE(returned_to_child[1].lost);
1239  }
1240}
1241
1242TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) {
1243  gfx::Size size(1, 1);
1244  ResourceFormat format = RGBA_8888;
1245  size_t pixel_size = TextureSizeBytes(size, format);
1246  ASSERT_EQ(4U, pixel_size);
1247
1248  ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1249      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1250  uint8_t data1[4] = {1, 2, 3, 4};
1251  gfx::Rect rect(size);
1252  child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1253
1254  ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
1255      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1256  uint8_t data2[4] = {5, 5, 5, 5};
1257  child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
1258
1259  ReturnedResourceArray returned_to_child;
1260  int child_id =
1261      resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1262  {
1263    // Transfer some resources to the parent.
1264    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1265    resource_ids_to_transfer.push_back(id1);
1266    resource_ids_to_transfer.push_back(id2);
1267    TransferableResourceArray list;
1268    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1269                                                  &list);
1270    ASSERT_EQ(2u, list.size());
1271    if (GetParam() == ResourceProvider::GLTexture) {
1272      EXPECT_NE(0u, list[0].sync_point);
1273      EXPECT_NE(0u, list[1].sync_point);
1274    }
1275    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1276    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1277    resource_provider_->ReceiveFromChild(child_id, list);
1278    resource_provider_->DeclareUsedResourcesFromChild(child_id,
1279                                                      resource_ids_to_transfer);
1280  }
1281
1282  EXPECT_EQ(2u, resource_provider_->num_resources());
1283  ResourceProvider::ResourceIdMap resource_map =
1284      resource_provider_->GetChildToParentMap(child_id);
1285  ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1286  ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1287  EXPECT_NE(0u, mapped_id1);
1288  EXPECT_NE(0u, mapped_id2);
1289  EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1290  EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1291
1292  {
1293    // The parent transfers the resources to the grandparent.
1294    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1295    resource_ids_to_transfer.push_back(mapped_id1);
1296    resource_ids_to_transfer.push_back(mapped_id2);
1297    TransferableResourceArray list;
1298    resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1299
1300    ASSERT_EQ(2u, list.size());
1301    if (GetParam() == ResourceProvider::GLTexture) {
1302      EXPECT_NE(0u, list[0].sync_point);
1303      EXPECT_NE(0u, list[1].sync_point);
1304    }
1305    EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1306    EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1307
1308    // Release the resource in the parent. Set no resources as being in use. The
1309    // resources are exported so that can't be transferred back yet.
1310    ResourceProvider::ResourceIdArray no_resources;
1311    resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1312
1313    // Destroy the child, the resources should not be returned yet.
1314    EXPECT_EQ(0u, returned_to_child.size());
1315    EXPECT_EQ(2u, resource_provider_->num_resources());
1316
1317    resource_provider_->DestroyChild(child_id);
1318
1319    EXPECT_EQ(2u, resource_provider_->num_resources());
1320    ASSERT_EQ(0u, returned_to_child.size());
1321
1322    // Return a resource from the grandparent, it should be returned at this
1323    // point.
1324    EXPECT_EQ(2u, list.size());
1325    EXPECT_EQ(mapped_id1, list[0].id);
1326    EXPECT_EQ(mapped_id2, list[1].id);
1327    TransferableResourceArray return_list;
1328    return_list.push_back(list[1]);
1329    list.pop_back();
1330    ReturnedResourceArray returned;
1331    TransferableResource::ReturnResources(return_list, &returned);
1332    resource_provider_->ReceiveReturnsFromParent(returned);
1333
1334    EXPECT_EQ(1u, resource_provider_->num_resources());
1335    ASSERT_EQ(1u, returned_to_child.size());
1336    if (GetParam() == ResourceProvider::GLTexture) {
1337      EXPECT_NE(0u, returned_to_child[0].sync_point);
1338    }
1339    EXPECT_FALSE(returned_to_child[0].lost);
1340    returned_to_child.clear();
1341
1342    // Destroy the parent resource provider. The resource that's left should be
1343    // lost at this point, and returned.
1344    resource_provider_.reset();
1345    ASSERT_EQ(1u, returned_to_child.size());
1346    if (GetParam() == ResourceProvider::GLTexture) {
1347      EXPECT_NE(0u, returned_to_child[0].sync_point);
1348    }
1349    EXPECT_TRUE(returned_to_child[0].lost);
1350  }
1351}
1352
1353TEST_P(ResourceProviderTest, DeleteTransferredResources) {
1354  gfx::Size size(1, 1);
1355  ResourceFormat format = RGBA_8888;
1356  size_t pixel_size = TextureSizeBytes(size, format);
1357  ASSERT_EQ(4U, pixel_size);
1358
1359  ResourceProvider::ResourceId id = child_resource_provider_->CreateResource(
1360      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1361  uint8_t data[4] = { 1, 2, 3, 4 };
1362  gfx::Rect rect(size);
1363  child_resource_provider_->SetPixels(id, data, rect, rect, gfx::Vector2d());
1364
1365  ReturnedResourceArray returned_to_child;
1366  int child_id =
1367      resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1368  {
1369    // Transfer some resource to the parent.
1370    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1371    resource_ids_to_transfer.push_back(id);
1372    TransferableResourceArray list;
1373    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1374                                                  &list);
1375    ASSERT_EQ(1u, list.size());
1376    if (GetParam() == ResourceProvider::GLTexture)
1377      EXPECT_NE(0u, list[0].sync_point);
1378    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1379    resource_provider_->ReceiveFromChild(child_id, list);
1380    resource_provider_->DeclareUsedResourcesFromChild(child_id,
1381                                                      resource_ids_to_transfer);
1382  }
1383
1384  // Delete textures in the child, while they are transfered.
1385  child_resource_provider_->DeleteResource(id);
1386  EXPECT_EQ(1u, child_resource_provider_->num_resources());
1387  {
1388    EXPECT_EQ(0u, returned_to_child.size());
1389
1390    // Transfer resources back from the parent to the child. Set no resources as
1391    // being in use.
1392    ResourceProvider::ResourceIdArray no_resources;
1393    resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1394
1395    ASSERT_EQ(1u, returned_to_child.size());
1396    if (GetParam() == ResourceProvider::GLTexture)
1397      EXPECT_NE(0u, returned_to_child[0].sync_point);
1398    child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1399  }
1400  EXPECT_EQ(0u, child_resource_provider_->num_resources());
1401}
1402
1403class ResourceProviderTestTextureFilters : public ResourceProviderTest {
1404 public:
1405  static void RunTest(GLenum child_filter, GLenum parent_filter) {
1406    scoped_ptr<TextureStateTrackingContext> child_context_owned(
1407        new TextureStateTrackingContext);
1408    TextureStateTrackingContext* child_context = child_context_owned.get();
1409
1410    FakeOutputSurfaceClient child_output_surface_client;
1411    scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d(
1412        child_context_owned.PassAs<TestWebGraphicsContext3D>()));
1413    CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1414
1415    scoped_ptr<ResourceProvider> child_resource_provider(
1416        ResourceProvider::Create(child_output_surface.get(),
1417                                 NULL,
1418                                 0,
1419                                 false,
1420                                 1));
1421
1422    scoped_ptr<TextureStateTrackingContext> parent_context_owned(
1423        new TextureStateTrackingContext);
1424    TextureStateTrackingContext* parent_context = parent_context_owned.get();
1425
1426    FakeOutputSurfaceClient parent_output_surface_client;
1427    scoped_ptr<OutputSurface> parent_output_surface(FakeOutputSurface::Create3d(
1428        parent_context_owned.PassAs<TestWebGraphicsContext3D>()));
1429    CHECK(parent_output_surface->BindToClient(&parent_output_surface_client));
1430
1431    scoped_ptr<ResourceProvider> parent_resource_provider(
1432        ResourceProvider::Create(parent_output_surface.get(),
1433                                 NULL,
1434                                 0,
1435                                 false,
1436                                 1));
1437
1438    gfx::Size size(1, 1);
1439    ResourceFormat format = RGBA_8888;
1440    int child_texture_id = 1;
1441    int parent_texture_id = 2;
1442
1443    size_t pixel_size = TextureSizeBytes(size, format);
1444    ASSERT_EQ(4U, pixel_size);
1445
1446    ResourceProvider::ResourceId id = child_resource_provider->CreateResource(
1447        size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1448
1449    // The new texture is created with GL_LINEAR.
1450    EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id))
1451        .Times(2);  // Once to create and once to allocate.
1452    EXPECT_CALL(*child_context,
1453                texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
1454    EXPECT_CALL(*child_context,
1455                texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
1456    EXPECT_CALL(
1457        *child_context,
1458        texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
1459    EXPECT_CALL(
1460        *child_context,
1461        texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
1462    EXPECT_CALL(*child_context,
1463                texParameteri(GL_TEXTURE_2D,
1464                              GL_TEXTURE_POOL_CHROMIUM,
1465                              GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
1466    child_resource_provider->AllocateForTesting(id);
1467    Mock::VerifyAndClearExpectations(child_context);
1468
1469    uint8_t data[4] = { 1, 2, 3, 4 };
1470    gfx::Rect rect(size);
1471
1472    EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1473    child_resource_provider->SetPixels(id, data, rect, rect, gfx::Vector2d());
1474    Mock::VerifyAndClearExpectations(child_context);
1475
1476    // The texture is set to |child_filter| in the child.
1477    EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1478    if (child_filter != GL_LINEAR) {
1479      EXPECT_CALL(
1480          *child_context,
1481          texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1482      EXPECT_CALL(
1483          *child_context,
1484          texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1485    }
1486    SetResourceFilter(child_resource_provider.get(), id, child_filter);
1487    Mock::VerifyAndClearExpectations(child_context);
1488
1489    ReturnedResourceArray returned_to_child;
1490    int child_id = parent_resource_provider->CreateChild(
1491        GetReturnCallback(&returned_to_child));
1492    {
1493      // Transfer some resource to the parent.
1494      ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1495      resource_ids_to_transfer.push_back(id);
1496      TransferableResourceArray list;
1497
1498      EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1499      EXPECT_CALL(*child_context,
1500                  produceTextureCHROMIUM(GL_TEXTURE_2D, _));
1501      EXPECT_CALL(*child_context, insertSyncPoint());
1502      child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1503                                                   &list);
1504      Mock::VerifyAndClearExpectations(child_context);
1505
1506      ASSERT_EQ(1u, list.size());
1507      EXPECT_EQ(static_cast<unsigned>(child_filter), list[0].filter);
1508
1509      EXPECT_CALL(*parent_context,
1510                  bindTexture(GL_TEXTURE_2D, parent_texture_id));
1511      EXPECT_CALL(*parent_context, consumeTextureCHROMIUM(GL_TEXTURE_2D, _));
1512      parent_resource_provider->ReceiveFromChild(child_id, list);
1513      Mock::VerifyAndClearExpectations(parent_context);
1514
1515      parent_resource_provider->DeclareUsedResourcesFromChild(
1516          child_id, resource_ids_to_transfer);
1517      Mock::VerifyAndClearExpectations(parent_context);
1518    }
1519    ResourceProvider::ResourceIdMap resource_map =
1520        parent_resource_provider->GetChildToParentMap(child_id);
1521    ResourceProvider::ResourceId mapped_id = resource_map[id];
1522    EXPECT_NE(0u, mapped_id);
1523
1524    // The texture is set to |parent_filter| in the parent.
1525    EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1526    EXPECT_CALL(
1527        *parent_context,
1528        texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, parent_filter));
1529    EXPECT_CALL(
1530        *parent_context,
1531        texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, parent_filter));
1532    SetResourceFilter(parent_resource_provider.get(), mapped_id, parent_filter);
1533    Mock::VerifyAndClearExpectations(parent_context);
1534
1535    // The texture should be reset to |child_filter| in the parent when it is
1536    // returned, since that is how it was received.
1537    EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1538    EXPECT_CALL(
1539        *parent_context,
1540        texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1541    EXPECT_CALL(
1542        *parent_context,
1543        texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1544
1545    {
1546      EXPECT_EQ(0u, returned_to_child.size());
1547
1548      // Transfer resources back from the parent to the child. Set no resources
1549      // as being in use.
1550      ResourceProvider::ResourceIdArray no_resources;
1551      EXPECT_CALL(*parent_context, insertSyncPoint());
1552      parent_resource_provider->DeclareUsedResourcesFromChild(child_id,
1553                                                              no_resources);
1554      Mock::VerifyAndClearExpectations(parent_context);
1555
1556      ASSERT_EQ(1u, returned_to_child.size());
1557      child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
1558    }
1559
1560    // The child remembers the texture filter is set to |child_filter|.
1561    EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1562    SetResourceFilter(child_resource_provider.get(), id, child_filter);
1563    Mock::VerifyAndClearExpectations(child_context);
1564  }
1565};
1566
1567TEST_P(ResourceProviderTest, TextureFilters_ChildNearestParentLinear) {
1568  if (GetParam() != ResourceProvider::GLTexture)
1569    return;
1570  ResourceProviderTestTextureFilters::RunTest(GL_NEAREST, GL_LINEAR);
1571}
1572
1573TEST_P(ResourceProviderTest, TextureFilters_ChildLinearParentNearest) {
1574  if (GetParam() != ResourceProvider::GLTexture)
1575    return;
1576  ResourceProviderTestTextureFilters::RunTest(GL_LINEAR, GL_NEAREST);
1577}
1578
1579TEST_P(ResourceProviderTest, TransferMailboxResources) {
1580  // Other mailbox transfers tested elsewhere.
1581  if (GetParam() != ResourceProvider::GLTexture)
1582    return;
1583  unsigned texture = context()->createTexture();
1584  context()->bindTexture(GL_TEXTURE_2D, texture);
1585  uint8_t data[4] = { 1, 2, 3, 4 };
1586  context()->texImage2D(
1587      GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data);
1588  gpu::Mailbox mailbox;
1589  context()->genMailboxCHROMIUM(mailbox.name);
1590  context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1591  unsigned sync_point = context()->insertSyncPoint();
1592
1593  // All the logic below assumes that the sync points are all positive.
1594  EXPECT_LT(0u, sync_point);
1595
1596  unsigned release_sync_point = 0;
1597  bool lost_resource = false;
1598  ReleaseCallback callback =
1599      base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource);
1600  ResourceProvider::ResourceId resource =
1601      resource_provider_->CreateResourceFromTextureMailbox(
1602          TextureMailbox(mailbox, sync_point),
1603          SingleReleaseCallback::Create(callback));
1604  EXPECT_EQ(1u, context()->NumTextures());
1605  EXPECT_EQ(0u, release_sync_point);
1606  {
1607    // Transfer the resource, expect the sync points to be consistent.
1608    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1609    resource_ids_to_transfer.push_back(resource);
1610    TransferableResourceArray list;
1611    resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1612    ASSERT_EQ(1u, list.size());
1613    EXPECT_LE(sync_point, list[0].sync_point);
1614    EXPECT_EQ(0,
1615              memcmp(mailbox.name, list[0].mailbox.name, sizeof(mailbox.name)));
1616    EXPECT_EQ(0u, release_sync_point);
1617
1618    context()->waitSyncPoint(list[0].sync_point);
1619    unsigned other_texture = context()->createTexture();
1620    context()->bindTexture(GL_TEXTURE_2D, other_texture);
1621    context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1622    uint8_t test_data[4] = { 0 };
1623    context()->GetPixels(
1624        gfx::Size(1, 1), RGBA_8888, test_data);
1625    EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
1626    context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1627    context()->deleteTexture(other_texture);
1628    list[0].sync_point = context()->insertSyncPoint();
1629    EXPECT_LT(0u, list[0].sync_point);
1630
1631    // Receive the resource, then delete it, expect the sync points to be
1632    // consistent.
1633    ReturnedResourceArray returned;
1634    TransferableResource::ReturnResources(list, &returned);
1635    resource_provider_->ReceiveReturnsFromParent(returned);
1636    EXPECT_EQ(1u, context()->NumTextures());
1637    EXPECT_EQ(0u, release_sync_point);
1638
1639    resource_provider_->DeleteResource(resource);
1640    EXPECT_LE(list[0].sync_point, release_sync_point);
1641    EXPECT_FALSE(lost_resource);
1642  }
1643
1644  // We're going to do the same thing as above, but testing the case where we
1645  // delete the resource before we receive it back.
1646  sync_point = release_sync_point;
1647  EXPECT_LT(0u, sync_point);
1648  release_sync_point = 0;
1649  resource = resource_provider_->CreateResourceFromTextureMailbox(
1650      TextureMailbox(mailbox, sync_point),
1651      SingleReleaseCallback::Create(callback));
1652  EXPECT_EQ(1u, context()->NumTextures());
1653  EXPECT_EQ(0u, release_sync_point);
1654  {
1655    // Transfer the resource, expect the sync points to be consistent.
1656    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1657    resource_ids_to_transfer.push_back(resource);
1658    TransferableResourceArray list;
1659    resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1660    ASSERT_EQ(1u, list.size());
1661    EXPECT_LE(sync_point, list[0].sync_point);
1662    EXPECT_EQ(0,
1663              memcmp(mailbox.name, list[0].mailbox.name, sizeof(mailbox.name)));
1664    EXPECT_EQ(0u, release_sync_point);
1665
1666    context()->waitSyncPoint(list[0].sync_point);
1667    unsigned other_texture = context()->createTexture();
1668    context()->bindTexture(GL_TEXTURE_2D, other_texture);
1669    context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1670    uint8_t test_data[4] = { 0 };
1671    context()->GetPixels(
1672        gfx::Size(1, 1), RGBA_8888, test_data);
1673    EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
1674    context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1675    context()->deleteTexture(other_texture);
1676    list[0].sync_point = context()->insertSyncPoint();
1677    EXPECT_LT(0u, list[0].sync_point);
1678
1679    // Delete the resource, which shouldn't do anything.
1680    resource_provider_->DeleteResource(resource);
1681    EXPECT_EQ(1u, context()->NumTextures());
1682    EXPECT_EQ(0u, release_sync_point);
1683
1684    // Then receive the resource which should release the mailbox, expect the
1685    // sync points to be consistent.
1686    ReturnedResourceArray returned;
1687    TransferableResource::ReturnResources(list, &returned);
1688    resource_provider_->ReceiveReturnsFromParent(returned);
1689    EXPECT_LE(list[0].sync_point, release_sync_point);
1690    EXPECT_FALSE(lost_resource);
1691  }
1692
1693  context()->waitSyncPoint(release_sync_point);
1694  context()->bindTexture(GL_TEXTURE_2D, texture);
1695  context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1696  context()->deleteTexture(texture);
1697}
1698
1699TEST_P(ResourceProviderTest, LostResourceInParent) {
1700  gfx::Size size(1, 1);
1701  ResourceFormat format = RGBA_8888;
1702  ResourceProvider::ResourceId resource =
1703      child_resource_provider_->CreateResource(
1704          size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1705  child_resource_provider_->AllocateForTesting(resource);
1706  // Expect a GL resource to be lost.
1707  bool should_lose_resource = GetParam() == ResourceProvider::GLTexture;
1708
1709  ReturnedResourceArray returned_to_child;
1710  int child_id =
1711      resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1712  {
1713    // Transfer the resource to the parent.
1714    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1715    resource_ids_to_transfer.push_back(resource);
1716    TransferableResourceArray list;
1717    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1718                                                  &list);
1719    EXPECT_EQ(1u, list.size());
1720
1721    resource_provider_->ReceiveFromChild(child_id, list);
1722    resource_provider_->DeclareUsedResourcesFromChild(child_id,
1723                                                      resource_ids_to_transfer);
1724  }
1725
1726  // Lose the output surface in the parent.
1727  resource_provider_->DidLoseOutputSurface();
1728
1729  {
1730    EXPECT_EQ(0u, returned_to_child.size());
1731
1732    // Transfer resources back from the parent to the child. Set no resources as
1733    // being in use.
1734    ResourceProvider::ResourceIdArray no_resources;
1735    resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1736
1737    // Expect a GL resource to be lost.
1738    ASSERT_EQ(1u, returned_to_child.size());
1739    EXPECT_EQ(should_lose_resource, returned_to_child[0].lost);
1740    child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1741    returned_to_child.clear();
1742  }
1743
1744  // A GL resource should be lost.
1745  EXPECT_EQ(should_lose_resource, child_resource_provider_->IsLost(resource));
1746
1747  // Lost resources stay in use in the parent forever.
1748  EXPECT_EQ(should_lose_resource,
1749            child_resource_provider_->InUseByConsumer(resource));
1750}
1751
1752TEST_P(ResourceProviderTest, LostResourceInGrandParent) {
1753  gfx::Size size(1, 1);
1754  ResourceFormat format = RGBA_8888;
1755  ResourceProvider::ResourceId resource =
1756      child_resource_provider_->CreateResource(
1757          size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1758  child_resource_provider_->AllocateForTesting(resource);
1759
1760  ReturnedResourceArray returned_to_child;
1761  int child_id =
1762      resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1763  {
1764    // Transfer the resource to the parent.
1765    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1766    resource_ids_to_transfer.push_back(resource);
1767    TransferableResourceArray list;
1768    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1769                                                  &list);
1770    EXPECT_EQ(1u, list.size());
1771
1772    resource_provider_->ReceiveFromChild(child_id, list);
1773    resource_provider_->DeclareUsedResourcesFromChild(child_id,
1774                                                      resource_ids_to_transfer);
1775  }
1776
1777  {
1778    ResourceProvider::ResourceIdMap resource_map =
1779        resource_provider_->GetChildToParentMap(child_id);
1780    ResourceProvider::ResourceId parent_resource = resource_map[resource];
1781    EXPECT_NE(0u, parent_resource);
1782
1783    // Transfer to a grandparent.
1784    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1785    resource_ids_to_transfer.push_back(parent_resource);
1786    TransferableResourceArray list;
1787    resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1788
1789    // Receive back a lost resource from the grandparent.
1790    EXPECT_EQ(1u, list.size());
1791    EXPECT_EQ(parent_resource, list[0].id);
1792    ReturnedResourceArray returned;
1793    TransferableResource::ReturnResources(list, &returned);
1794    EXPECT_EQ(1u, returned.size());
1795    EXPECT_EQ(parent_resource, returned[0].id);
1796    returned[0].lost = true;
1797    resource_provider_->ReceiveReturnsFromParent(returned);
1798
1799    // The resource should be lost.
1800    EXPECT_TRUE(resource_provider_->IsLost(parent_resource));
1801
1802    // Lost resources stay in use in the parent forever.
1803    EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_resource));
1804  }
1805
1806  {
1807    EXPECT_EQ(0u, returned_to_child.size());
1808
1809    // Transfer resources back from the parent to the child. Set no resources as
1810    // being in use.
1811    ResourceProvider::ResourceIdArray no_resources;
1812    resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1813
1814    // Expect the resource to be lost.
1815    ASSERT_EQ(1u, returned_to_child.size());
1816    EXPECT_TRUE(returned_to_child[0].lost);
1817    child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1818    returned_to_child.clear();
1819  }
1820
1821  // The resource should be lost.
1822  EXPECT_TRUE(child_resource_provider_->IsLost(resource));
1823
1824  // Lost resources stay in use in the parent forever.
1825  EXPECT_TRUE(child_resource_provider_->InUseByConsumer(resource));
1826}
1827
1828TEST_P(ResourceProviderTest, LostMailboxInParent) {
1829  unsigned release_sync_point = 0;
1830  bool lost_resource = false;
1831  bool release_called = false;
1832  unsigned sync_point = 0;
1833  ResourceProvider::ResourceId resource = CreateChildMailbox(
1834      &release_sync_point, &lost_resource, &release_called, &sync_point);
1835
1836  ReturnedResourceArray returned_to_child;
1837  int child_id =
1838      resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1839  {
1840    // Transfer the resource to the parent.
1841    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1842    resource_ids_to_transfer.push_back(resource);
1843    TransferableResourceArray list;
1844    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1845                                                  &list);
1846    EXPECT_EQ(1u, list.size());
1847
1848    resource_provider_->ReceiveFromChild(child_id, list);
1849    resource_provider_->DeclareUsedResourcesFromChild(child_id,
1850                                                      resource_ids_to_transfer);
1851  }
1852
1853  // Lose the output surface in the parent.
1854  resource_provider_->DidLoseOutputSurface();
1855
1856  {
1857    EXPECT_EQ(0u, returned_to_child.size());
1858
1859    // Transfer resources back from the parent to the child. Set no resources as
1860    // being in use.
1861    ResourceProvider::ResourceIdArray no_resources;
1862    resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1863
1864    ASSERT_EQ(1u, returned_to_child.size());
1865    // Losing an output surface only loses hardware resources.
1866    EXPECT_EQ(returned_to_child[0].lost,
1867              GetParam() == ResourceProvider::GLTexture);
1868    child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1869    returned_to_child.clear();
1870  }
1871
1872  // Delete the resource in the child. Expect the resource to be lost if it's
1873  // a GL texture.
1874  child_resource_provider_->DeleteResource(resource);
1875  EXPECT_EQ(lost_resource, GetParam() == ResourceProvider::GLTexture);
1876}
1877
1878TEST_P(ResourceProviderTest, LostMailboxInGrandParent) {
1879  unsigned release_sync_point = 0;
1880  bool lost_resource = false;
1881  bool release_called = false;
1882  unsigned sync_point = 0;
1883  ResourceProvider::ResourceId resource = CreateChildMailbox(
1884      &release_sync_point, &lost_resource, &release_called, &sync_point);
1885
1886  ReturnedResourceArray returned_to_child;
1887  int child_id =
1888      resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1889  {
1890    // Transfer the resource to the parent.
1891    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1892    resource_ids_to_transfer.push_back(resource);
1893    TransferableResourceArray list;
1894    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1895                                                  &list);
1896    EXPECT_EQ(1u, list.size());
1897
1898    resource_provider_->ReceiveFromChild(child_id, list);
1899    resource_provider_->DeclareUsedResourcesFromChild(child_id,
1900                                                      resource_ids_to_transfer);
1901  }
1902
1903  {
1904    ResourceProvider::ResourceIdMap resource_map =
1905        resource_provider_->GetChildToParentMap(child_id);
1906    ResourceProvider::ResourceId parent_resource = resource_map[resource];
1907    EXPECT_NE(0u, parent_resource);
1908
1909    // Transfer to a grandparent.
1910    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1911    resource_ids_to_transfer.push_back(parent_resource);
1912    TransferableResourceArray list;
1913    resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1914
1915    // Receive back a lost resource from the grandparent.
1916    EXPECT_EQ(1u, list.size());
1917    EXPECT_EQ(parent_resource, list[0].id);
1918    ReturnedResourceArray returned;
1919    TransferableResource::ReturnResources(list, &returned);
1920    EXPECT_EQ(1u, returned.size());
1921    EXPECT_EQ(parent_resource, returned[0].id);
1922    returned[0].lost = true;
1923    resource_provider_->ReceiveReturnsFromParent(returned);
1924  }
1925
1926  {
1927    EXPECT_EQ(0u, returned_to_child.size());
1928
1929    // Transfer resources back from the parent to the child. Set no resources as
1930    // being in use.
1931    ResourceProvider::ResourceIdArray no_resources;
1932    resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1933
1934    // Expect the resource to be lost.
1935    ASSERT_EQ(1u, returned_to_child.size());
1936    EXPECT_TRUE(returned_to_child[0].lost);
1937    child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1938    returned_to_child.clear();
1939  }
1940
1941  // Delete the resource in the child. Expect the resource to be lost.
1942  child_resource_provider_->DeleteResource(resource);
1943  EXPECT_TRUE(lost_resource);
1944}
1945
1946TEST_P(ResourceProviderTest, Shutdown) {
1947  unsigned release_sync_point = 0;
1948  bool lost_resource = false;
1949  bool release_called = false;
1950  unsigned sync_point = 0;
1951  CreateChildMailbox(
1952      &release_sync_point, &lost_resource, &release_called, &sync_point);
1953
1954  EXPECT_EQ(0u, release_sync_point);
1955  EXPECT_FALSE(lost_resource);
1956
1957  child_resource_provider_.reset();
1958
1959  if (GetParam() == ResourceProvider::GLTexture) {
1960    EXPECT_LE(sync_point, release_sync_point);
1961  }
1962  EXPECT_TRUE(release_called);
1963  EXPECT_FALSE(lost_resource);
1964}
1965
1966TEST_P(ResourceProviderTest, ShutdownWithExportedResource) {
1967  unsigned release_sync_point = 0;
1968  bool lost_resource = false;
1969  bool release_called = false;
1970  unsigned sync_point = 0;
1971  ResourceProvider::ResourceId resource = CreateChildMailbox(
1972      &release_sync_point, &lost_resource, &release_called, &sync_point);
1973
1974  // Transfer the resource, so we can't release it properly on shutdown.
1975  ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1976  resource_ids_to_transfer.push_back(resource);
1977  TransferableResourceArray list;
1978  child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1979                                                &list);
1980
1981  EXPECT_EQ(0u, release_sync_point);
1982  EXPECT_FALSE(lost_resource);
1983
1984  child_resource_provider_.reset();
1985
1986  // Since the resource is in the parent, the child considers it lost.
1987  EXPECT_EQ(0u, release_sync_point);
1988  EXPECT_TRUE(lost_resource);
1989}
1990
1991TEST_P(ResourceProviderTest, LostContext) {
1992  // TextureMailbox callbacks only exist for GL textures for now.
1993  if (GetParam() != ResourceProvider::GLTexture)
1994    return;
1995  unsigned texture = context()->createTexture();
1996  context()->bindTexture(GL_TEXTURE_2D, texture);
1997  gpu::Mailbox mailbox;
1998  context()->genMailboxCHROMIUM(mailbox.name);
1999  context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
2000  unsigned sync_point = context()->insertSyncPoint();
2001
2002  EXPECT_LT(0u, sync_point);
2003
2004  unsigned release_sync_point = 0;
2005  bool lost_resource = false;
2006  scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
2007      base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource));
2008  resource_provider_->CreateResourceFromTextureMailbox(
2009      TextureMailbox(mailbox, sync_point),
2010      callback.Pass());
2011
2012  EXPECT_EQ(0u, release_sync_point);
2013  EXPECT_FALSE(lost_resource);
2014
2015  resource_provider_->DidLoseOutputSurface();
2016  resource_provider_.reset();
2017
2018  EXPECT_LE(sync_point, release_sync_point);
2019  EXPECT_TRUE(lost_resource);
2020}
2021
2022TEST_P(ResourceProviderTest, ScopedSampler) {
2023  // Sampling is only supported for GL textures.
2024  if (GetParam() != ResourceProvider::GLTexture)
2025    return;
2026
2027  scoped_ptr<TextureStateTrackingContext> context_owned(
2028      new TextureStateTrackingContext);
2029  TextureStateTrackingContext* context = context_owned.get();
2030
2031  FakeOutputSurfaceClient output_surface_client;
2032  scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2033      context_owned.PassAs<TestWebGraphicsContext3D>()));
2034  CHECK(output_surface->BindToClient(&output_surface_client));
2035
2036  scoped_ptr<ResourceProvider> resource_provider(
2037      ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2038
2039  gfx::Size size(1, 1);
2040  ResourceFormat format = RGBA_8888;
2041  int texture_id = 1;
2042
2043  ResourceProvider::ResourceId id = resource_provider->CreateResource(
2044      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2045
2046  // Check that the texture gets created with the right sampler settings.
2047  EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id))
2048      .Times(2);  // Once to create and once to allocate.
2049  EXPECT_CALL(*context,
2050              texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2051  EXPECT_CALL(*context,
2052              texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2053  EXPECT_CALL(
2054      *context,
2055      texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2056  EXPECT_CALL(
2057      *context,
2058      texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2059  EXPECT_CALL(*context,
2060              texParameteri(GL_TEXTURE_2D,
2061                            GL_TEXTURE_POOL_CHROMIUM,
2062                            GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2063
2064  resource_provider->AllocateForTesting(id);
2065  Mock::VerifyAndClearExpectations(context);
2066
2067  // Creating a sampler with the default filter should not change any texture
2068  // parameters.
2069  {
2070    EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2071    ResourceProvider::ScopedSamplerGL sampler(
2072        resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2073    Mock::VerifyAndClearExpectations(context);
2074  }
2075
2076  // Using a different filter should be reflected in the texture parameters.
2077  {
2078    EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2079    EXPECT_CALL(
2080        *context,
2081        texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
2082    EXPECT_CALL(
2083        *context,
2084        texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
2085    ResourceProvider::ScopedSamplerGL sampler(
2086        resource_provider.get(), id, GL_TEXTURE_2D, GL_NEAREST);
2087    Mock::VerifyAndClearExpectations(context);
2088  }
2089
2090  // Test resetting to the default filter.
2091  {
2092    EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2093    EXPECT_CALL(*context,
2094                texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2095    EXPECT_CALL(*context,
2096                texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2097    ResourceProvider::ScopedSamplerGL sampler(
2098        resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2099    Mock::VerifyAndClearExpectations(context);
2100  }
2101}
2102
2103TEST_P(ResourceProviderTest, ManagedResource) {
2104  // Sampling is only supported for GL textures.
2105  if (GetParam() != ResourceProvider::GLTexture)
2106    return;
2107
2108  scoped_ptr<TextureStateTrackingContext> context_owned(
2109      new TextureStateTrackingContext);
2110  TextureStateTrackingContext* context = context_owned.get();
2111
2112  FakeOutputSurfaceClient output_surface_client;
2113  scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2114      context_owned.PassAs<TestWebGraphicsContext3D>()));
2115  CHECK(output_surface->BindToClient(&output_surface_client));
2116
2117  scoped_ptr<ResourceProvider> resource_provider(
2118      ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2119
2120  gfx::Size size(1, 1);
2121  ResourceFormat format = RGBA_8888;
2122  int texture_id = 1;
2123
2124  // Check that the texture gets created with the right sampler settings.
2125  ResourceProvider::ResourceId id = resource_provider->CreateManagedResource(
2126      size,
2127      GL_TEXTURE_2D,
2128      GL_CLAMP_TO_EDGE,
2129      ResourceProvider::TextureUsageAny,
2130      format);
2131  EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2132  EXPECT_CALL(*context,
2133              texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2134  EXPECT_CALL(*context,
2135              texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2136  EXPECT_CALL(
2137      *context,
2138      texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2139  EXPECT_CALL(
2140      *context,
2141      texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2142  EXPECT_CALL(*context,
2143              texParameteri(GL_TEXTURE_2D,
2144                            GL_TEXTURE_POOL_CHROMIUM,
2145                            GL_TEXTURE_POOL_MANAGED_CHROMIUM));
2146  resource_provider->CreateForTesting(id);
2147  EXPECT_NE(0u, id);
2148
2149  Mock::VerifyAndClearExpectations(context);
2150}
2151
2152TEST_P(ResourceProviderTest, TextureWrapMode) {
2153  // Sampling is only supported for GL textures.
2154  if (GetParam() != ResourceProvider::GLTexture)
2155    return;
2156
2157  scoped_ptr<TextureStateTrackingContext> context_owned(
2158      new TextureStateTrackingContext);
2159  TextureStateTrackingContext* context = context_owned.get();
2160
2161  FakeOutputSurfaceClient output_surface_client;
2162  scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2163      context_owned.PassAs<TestWebGraphicsContext3D>()));
2164  CHECK(output_surface->BindToClient(&output_surface_client));
2165
2166  scoped_ptr<ResourceProvider> resource_provider(
2167      ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2168
2169  gfx::Size size(1, 1);
2170  ResourceFormat format = RGBA_8888;
2171  GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
2172
2173  for (int texture_id = 1; texture_id <= 2; ++texture_id) {
2174    GLint wrap_mode = texture_id == 1 ? GL_CLAMP_TO_EDGE : GL_REPEAT;
2175    // Check that the texture gets created with the right sampler settings.
2176    ResourceProvider::ResourceId id =
2177        resource_provider->CreateGLTexture(size,
2178                                           GL_TEXTURE_2D,
2179                                           texture_pool,
2180                                           wrap_mode,
2181                                           ResourceProvider::TextureUsageAny,
2182                                           format);
2183    EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2184    EXPECT_CALL(*context,
2185                texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2186    EXPECT_CALL(*context,
2187                texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2188    EXPECT_CALL(
2189        *context,
2190        texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode));
2191    EXPECT_CALL(
2192        *context,
2193        texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode));
2194    EXPECT_CALL(*context,
2195                texParameteri(GL_TEXTURE_2D,
2196                              GL_TEXTURE_POOL_CHROMIUM,
2197                              GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2198    resource_provider->CreateForTesting(id);
2199    EXPECT_NE(0u, id);
2200
2201    Mock::VerifyAndClearExpectations(context);
2202  }
2203}
2204
2205TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) {
2206  if (GetParam() != ResourceProvider::Bitmap)
2207    return;
2208
2209  gfx::Size size(64, 64);
2210  const uint32_t kBadBeef = 0xbadbeef;
2211  scoped_ptr<base::SharedMemory> shared_memory(
2212      CreateAndFillSharedMemory(size, kBadBeef));
2213
2214  FakeOutputSurfaceClient output_surface_client;
2215  scoped_ptr<OutputSurface> output_surface(
2216      FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2217          new SoftwareOutputDevice)));
2218  CHECK(output_surface->BindToClient(&output_surface_client));
2219
2220  scoped_ptr<ResourceProvider> resource_provider(
2221      ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2222
2223  scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
2224      base::Bind(&EmptyReleaseCallback));
2225  TextureMailbox mailbox(shared_memory.get(), size);
2226
2227  ResourceProvider::ResourceId id =
2228      resource_provider->CreateResourceFromTextureMailbox(
2229          mailbox, callback.Pass());
2230  EXPECT_NE(0u, id);
2231
2232  {
2233    ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id);
2234    const SkBitmap* sk_bitmap = lock.sk_bitmap();
2235    EXPECT_EQ(sk_bitmap->width(), size.width());
2236    EXPECT_EQ(sk_bitmap->height(), size.height());
2237    EXPECT_EQ(*sk_bitmap->getAddr32(16, 16), kBadBeef);
2238  }
2239}
2240
2241TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D) {
2242  // Mailboxing is only supported for GL textures.
2243  if (GetParam() != ResourceProvider::GLTexture)
2244    return;
2245
2246  scoped_ptr<TextureStateTrackingContext> context_owned(
2247      new TextureStateTrackingContext);
2248  TextureStateTrackingContext* context = context_owned.get();
2249
2250  FakeOutputSurfaceClient output_surface_client;
2251  scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2252      context_owned.PassAs<TestWebGraphicsContext3D>()));
2253  CHECK(output_surface->BindToClient(&output_surface_client));
2254
2255  scoped_ptr<ResourceProvider> resource_provider(
2256      ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2257
2258  unsigned texture_id = 1;
2259  unsigned sync_point = 30;
2260  unsigned target = GL_TEXTURE_2D;
2261
2262  EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2263  EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2264  EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2265  EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2266  EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2267
2268  gpu::Mailbox gpu_mailbox;
2269  memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2270  scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
2271      base::Bind(&EmptyReleaseCallback));
2272
2273  TextureMailbox mailbox(gpu_mailbox, sync_point);
2274
2275  ResourceProvider::ResourceId id =
2276      resource_provider->CreateResourceFromTextureMailbox(
2277          mailbox, callback.Pass());
2278  EXPECT_NE(0u, id);
2279
2280  Mock::VerifyAndClearExpectations(context);
2281
2282  {
2283    // Using the texture does a consume of the mailbox.
2284    EXPECT_CALL(*context, bindTexture(target, texture_id));
2285    EXPECT_CALL(*context, waitSyncPoint(sync_point));
2286    EXPECT_CALL(*context, consumeTextureCHROMIUM(target, _));
2287
2288    EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2289    EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2290
2291    ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id);
2292    Mock::VerifyAndClearExpectations(context);
2293
2294    // When done with it, a sync point should be inserted, but no produce is
2295    // necessary.
2296    EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2297    EXPECT_CALL(*context, insertSyncPoint());
2298    EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2299
2300    EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2301    EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2302  }
2303}
2304
2305TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) {
2306  // Mailboxing is only supported for GL textures.
2307  if (GetParam() != ResourceProvider::GLTexture)
2308    return;
2309
2310  scoped_ptr<TextureStateTrackingContext> context_owned(
2311      new TextureStateTrackingContext);
2312  TextureStateTrackingContext* context = context_owned.get();
2313
2314  FakeOutputSurfaceClient output_surface_client;
2315  scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2316      context_owned.PassAs<TestWebGraphicsContext3D>()));
2317  CHECK(output_surface->BindToClient(&output_surface_client));
2318
2319  scoped_ptr<ResourceProvider> resource_provider(
2320      ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2321
2322  unsigned texture_id = 1;
2323  unsigned sync_point = 30;
2324  unsigned target = GL_TEXTURE_EXTERNAL_OES;
2325
2326  EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2327  EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2328  EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2329  EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2330  EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2331
2332  gpu::Mailbox gpu_mailbox;
2333  memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2334  scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
2335      base::Bind(&EmptyReleaseCallback));
2336
2337  TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2338
2339  ResourceProvider::ResourceId id =
2340      resource_provider->CreateResourceFromTextureMailbox(
2341          mailbox, callback.Pass());
2342  EXPECT_NE(0u, id);
2343
2344  Mock::VerifyAndClearExpectations(context);
2345
2346  {
2347    // Using the texture does a consume of the mailbox.
2348    EXPECT_CALL(*context, bindTexture(target, texture_id));
2349    EXPECT_CALL(*context, waitSyncPoint(sync_point));
2350    EXPECT_CALL(*context, consumeTextureCHROMIUM(target, _));
2351
2352    EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2353    EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2354
2355    ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id);
2356    Mock::VerifyAndClearExpectations(context);
2357
2358    // When done with it, a sync point should be inserted, but no produce is
2359    // necessary.
2360    EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2361    EXPECT_CALL(*context, insertSyncPoint());
2362    EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2363
2364    EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2365    EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2366  }
2367}
2368
2369class AllocationTrackingContext3D : public TestWebGraphicsContext3D {
2370 public:
2371  MOCK_METHOD0(NextTextureId, GLuint());
2372  MOCK_METHOD1(RetireTextureId, void(GLuint id));
2373  MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
2374  MOCK_METHOD5(texStorage2DEXT,
2375               void(GLenum target,
2376                    GLint levels,
2377                    GLuint internalformat,
2378                    GLint width,
2379                    GLint height));
2380  MOCK_METHOD9(texImage2D,
2381               void(GLenum target,
2382                    GLint level,
2383                    GLenum internalformat,
2384                    GLsizei width,
2385                    GLsizei height,
2386                    GLint border,
2387                    GLenum format,
2388                    GLenum type,
2389                    const void* pixels));
2390  MOCK_METHOD9(texSubImage2D,
2391               void(GLenum target,
2392                    GLint level,
2393                    GLint xoffset,
2394                    GLint yoffset,
2395                    GLsizei width,
2396                    GLsizei height,
2397                    GLenum format,
2398                    GLenum type,
2399                    const void* pixels));
2400  MOCK_METHOD9(asyncTexImage2DCHROMIUM,
2401               void(GLenum target,
2402                    GLint level,
2403                    GLenum internalformat,
2404                    GLsizei width,
2405                    GLsizei height,
2406                    GLint border,
2407                    GLenum format,
2408                    GLenum type,
2409                    const void* pixels));
2410  MOCK_METHOD9(asyncTexSubImage2DCHROMIUM,
2411               void(GLenum target,
2412                    GLint level,
2413                    GLint xoffset,
2414                    GLint yoffset,
2415                    GLsizei width,
2416                    GLsizei height,
2417                    GLenum format,
2418                    GLenum type,
2419                    const void* pixels));
2420  MOCK_METHOD8(compressedTexImage2D,
2421               void(GLenum target,
2422                    GLint level,
2423                    GLenum internalformat,
2424                    GLsizei width,
2425                    GLsizei height,
2426                    GLint border,
2427                    GLsizei image_size,
2428                    const void* data));
2429  MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM, void(GLenum));
2430  MOCK_METHOD3(createImageCHROMIUM, GLuint(GLsizei, GLsizei, GLenum));
2431  MOCK_METHOD1(destroyImageCHROMIUM, void(GLuint));
2432  MOCK_METHOD2(mapImageCHROMIUM, void*(GLuint, GLenum));
2433  MOCK_METHOD3(getImageParameterivCHROMIUM, void(GLuint, GLenum, GLint*));
2434  MOCK_METHOD1(unmapImageCHROMIUM, void(GLuint));
2435  MOCK_METHOD2(bindTexImage2DCHROMIUM, void(GLenum, GLint));
2436  MOCK_METHOD2(releaseTexImage2DCHROMIUM, void(GLenum, GLint));
2437
2438  // We're mocking bindTexture, so we override
2439  // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
2440  // currently bound texture.
2441  virtual void texParameteri(GLenum target, GLenum pname, GLint param) {}
2442};
2443
2444TEST_P(ResourceProviderTest, TextureAllocation) {
2445  // Only for GL textures.
2446  if (GetParam() != ResourceProvider::GLTexture)
2447    return;
2448  scoped_ptr<AllocationTrackingContext3D> context_owned(
2449      new StrictMock<AllocationTrackingContext3D>);
2450  AllocationTrackingContext3D* context = context_owned.get();
2451
2452  FakeOutputSurfaceClient output_surface_client;
2453  scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2454      context_owned.PassAs<TestWebGraphicsContext3D>()));
2455  CHECK(output_surface->BindToClient(&output_surface_client));
2456
2457  scoped_ptr<ResourceProvider> resource_provider(
2458      ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2459
2460  gfx::Size size(2, 2);
2461  gfx::Vector2d offset(0, 0);
2462  gfx::Rect rect(0, 0, 2, 2);
2463  ResourceFormat format = RGBA_8888;
2464  ResourceProvider::ResourceId id = 0;
2465  uint8_t pixels[16] = { 0 };
2466  int texture_id = 123;
2467
2468  // Lazy allocation. Don't allocate when creating the resource.
2469  id = resource_provider->CreateResource(
2470      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2471
2472  EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2473  EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
2474  resource_provider->CreateForTesting(id);
2475
2476  EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2477  resource_provider->DeleteResource(id);
2478
2479  Mock::VerifyAndClearExpectations(context);
2480
2481  // Do allocate when we set the pixels.
2482  id = resource_provider->CreateResource(
2483      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2484
2485  EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2486  EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
2487  EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1);
2488  EXPECT_CALL(*context, texSubImage2D(_, _, _, _, 2, 2, _, _, _)).Times(1);
2489  resource_provider->SetPixels(id, pixels, rect, rect, offset);
2490
2491  EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2492  resource_provider->DeleteResource(id);
2493
2494  Mock::VerifyAndClearExpectations(context);
2495
2496  // Same for async version.
2497  id = resource_provider->CreateResource(
2498      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2499  resource_provider->AcquirePixelBuffer(id);
2500
2501  EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2502  EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
2503  EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
2504      .Times(1);
2505  resource_provider->BeginSetPixels(id);
2506  ASSERT_TRUE(resource_provider->DidSetPixelsComplete(id));
2507
2508  resource_provider->ReleasePixelBuffer(id);
2509
2510  EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2511  resource_provider->DeleteResource(id);
2512
2513  Mock::VerifyAndClearExpectations(context);
2514}
2515
2516TEST_P(ResourceProviderTest, TextureAllocationStorageUsageAny) {
2517  // Only for GL textures.
2518  if (GetParam() != ResourceProvider::GLTexture)
2519    return;
2520  scoped_ptr<AllocationTrackingContext3D> context_owned(
2521      new StrictMock<AllocationTrackingContext3D>);
2522  AllocationTrackingContext3D* context = context_owned.get();
2523  context->set_support_texture_storage(true);
2524
2525  FakeOutputSurfaceClient output_surface_client;
2526  scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2527      context_owned.PassAs<TestWebGraphicsContext3D>()));
2528  CHECK(output_surface->BindToClient(&output_surface_client));
2529
2530  scoped_ptr<ResourceProvider> resource_provider(
2531      ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2532
2533  gfx::Size size(2, 2);
2534  ResourceFormat format = RGBA_8888;
2535  ResourceProvider::ResourceId id = 0;
2536  int texture_id = 123;
2537
2538  // Lazy allocation. Don't allocate when creating the resource.
2539  id = resource_provider->CreateResource(
2540      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2541
2542  EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2543  EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
2544  EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2)).Times(1);
2545  resource_provider->AllocateForTesting(id);
2546
2547  EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2548  resource_provider->DeleteResource(id);
2549
2550  Mock::VerifyAndClearExpectations(context);
2551}
2552
2553TEST_P(ResourceProviderTest, TextureAllocationStorageUsageFramebuffer) {
2554  // Only for GL textures.
2555  if (GetParam() != ResourceProvider::GLTexture)
2556    return;
2557  scoped_ptr<AllocationTrackingContext3D> context_owned(
2558      new StrictMock<AllocationTrackingContext3D>);
2559  AllocationTrackingContext3D* context = context_owned.get();
2560  context->set_support_texture_storage(true);
2561
2562  FakeOutputSurfaceClient output_surface_client;
2563  scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2564      context_owned.PassAs<TestWebGraphicsContext3D>()));
2565  CHECK(output_surface->BindToClient(&output_surface_client));
2566
2567  scoped_ptr<ResourceProvider> resource_provider(
2568      ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2569
2570  gfx::Size size(2, 2);
2571  ResourceFormat format = RGBA_8888;
2572  ResourceProvider::ResourceId id = 0;
2573  int texture_id = 123;
2574
2575  // Lazy allocation. Don't allocate when creating the resource.
2576  id = resource_provider->CreateResource(
2577      size,
2578      GL_CLAMP_TO_EDGE,
2579      ResourceProvider::TextureUsageFramebuffer,
2580      format);
2581
2582  EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2583  EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
2584  EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1);
2585  resource_provider->AllocateForTesting(id);
2586
2587  EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2588  resource_provider->DeleteResource(id);
2589
2590  Mock::VerifyAndClearExpectations(context);
2591}
2592
2593TEST_P(ResourceProviderTest, PixelBuffer_GLTexture) {
2594  if (GetParam() != ResourceProvider::GLTexture)
2595    return;
2596  scoped_ptr<AllocationTrackingContext3D> context_owned(
2597      new StrictMock<AllocationTrackingContext3D>);
2598  AllocationTrackingContext3D* context = context_owned.get();
2599
2600  FakeOutputSurfaceClient output_surface_client;
2601  scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2602      context_owned.PassAs<TestWebGraphicsContext3D>()));
2603  CHECK(output_surface->BindToClient(&output_surface_client));
2604
2605  gfx::Size size(2, 2);
2606  ResourceFormat format = RGBA_8888;
2607  ResourceProvider::ResourceId id = 0;
2608  int texture_id = 123;
2609
2610  scoped_ptr<ResourceProvider> resource_provider(
2611      ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2612
2613  id = resource_provider->CreateResource(
2614      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2615  resource_provider->AcquirePixelBuffer(id);
2616
2617  EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2618  EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
2619  EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
2620      .Times(1);
2621  resource_provider->BeginSetPixels(id);
2622
2623  EXPECT_TRUE(resource_provider->DidSetPixelsComplete(id));
2624
2625  resource_provider->ReleasePixelBuffer(id);
2626
2627  EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2628  resource_provider->DeleteResource(id);
2629
2630  Mock::VerifyAndClearExpectations(context);
2631}
2632
2633TEST_P(ResourceProviderTest, PixelBuffer_Bitmap) {
2634  if (GetParam() != ResourceProvider::Bitmap)
2635    return;
2636  FakeOutputSurfaceClient output_surface_client;
2637  scoped_ptr<OutputSurface> output_surface(
2638      FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2639          new SoftwareOutputDevice)));
2640  CHECK(output_surface->BindToClient(&output_surface_client));
2641
2642  gfx::Size size(1, 1);
2643  ResourceFormat format = RGBA_8888;
2644  ResourceProvider::ResourceId id = 0;
2645  const uint32_t kBadBeef = 0xbadbeef;
2646
2647  scoped_ptr<ResourceProvider> resource_provider(
2648      ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2649
2650  id = resource_provider->CreateResource(
2651      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2652  resource_provider->AcquirePixelBuffer(id);
2653
2654  void* data = resource_provider->MapPixelBuffer(id);
2655  ASSERT_TRUE(!!data);
2656  memcpy(data, &kBadBeef, sizeof(kBadBeef));
2657  resource_provider->UnmapPixelBuffer(id);
2658
2659  resource_provider->BeginSetPixels(id);
2660  EXPECT_TRUE(resource_provider->DidSetPixelsComplete(id));
2661
2662  resource_provider->ReleasePixelBuffer(id);
2663
2664  {
2665    ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id);
2666    const SkBitmap* sk_bitmap = lock.sk_bitmap();
2667    EXPECT_EQ(sk_bitmap->width(), size.width());
2668    EXPECT_EQ(sk_bitmap->height(), size.height());
2669    EXPECT_EQ(*sk_bitmap->getAddr32(0, 0), kBadBeef);
2670  }
2671
2672  resource_provider->DeleteResource(id);
2673}
2674
2675TEST_P(ResourceProviderTest, ForcingAsyncUploadToComplete) {
2676  // Only for GL textures.
2677  if (GetParam() != ResourceProvider::GLTexture)
2678    return;
2679  scoped_ptr<AllocationTrackingContext3D> context_owned(
2680      new StrictMock<AllocationTrackingContext3D>);
2681  AllocationTrackingContext3D* context = context_owned.get();
2682
2683  FakeOutputSurfaceClient output_surface_client;
2684  scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2685      context_owned.PassAs<TestWebGraphicsContext3D>()));
2686  CHECK(output_surface->BindToClient(&output_surface_client));
2687
2688  gfx::Size size(2, 2);
2689  ResourceFormat format = RGBA_8888;
2690  ResourceProvider::ResourceId id = 0;
2691  int texture_id = 123;
2692
2693  scoped_ptr<ResourceProvider> resource_provider(
2694      ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2695
2696  id = resource_provider->CreateResource(
2697      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2698  resource_provider->AcquirePixelBuffer(id);
2699
2700  EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2701  EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
2702  EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
2703      .Times(1);
2704  resource_provider->BeginSetPixels(id);
2705
2706  EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
2707  EXPECT_CALL(*context, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D)).Times(1);
2708  EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, 0)).Times(1);
2709  resource_provider->ForceSetPixelsToComplete(id);
2710
2711  resource_provider->ReleasePixelBuffer(id);
2712
2713  EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2714  resource_provider->DeleteResource(id);
2715
2716  Mock::VerifyAndClearExpectations(context);
2717}
2718
2719TEST_P(ResourceProviderTest, PixelBufferLostContext) {
2720  scoped_ptr<AllocationTrackingContext3D> context_owned(
2721      new NiceMock<AllocationTrackingContext3D>);
2722  AllocationTrackingContext3D* context = context_owned.get();
2723
2724  FakeOutputSurfaceClient output_surface_client;
2725  scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2726      context_owned.PassAs<TestWebGraphicsContext3D>()));
2727  CHECK(output_surface->BindToClient(&output_surface_client));
2728
2729  gfx::Size size(2, 2);
2730  ResourceFormat format = RGBA_8888;
2731  ResourceProvider::ResourceId id = 0;
2732  int texture_id = 123;
2733
2734  scoped_ptr<ResourceProvider> resource_provider(
2735      ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2736
2737  EXPECT_CALL(*context, NextTextureId()).WillRepeatedly(Return(texture_id));
2738
2739  id = resource_provider->CreateResource(
2740      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2741  context->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
2742                               GL_INNOCENT_CONTEXT_RESET_ARB);
2743  resource_provider->AcquirePixelBuffer(id);
2744  uint8_t* buffer = resource_provider->MapPixelBuffer(id);
2745  EXPECT_TRUE(buffer == NULL);
2746  resource_provider->UnmapPixelBuffer(id);
2747  resource_provider->ReleasePixelBuffer(id);
2748  Mock::VerifyAndClearExpectations(context);
2749}
2750
2751TEST_P(ResourceProviderTest, Image_GLTexture) {
2752  // Only for GL textures.
2753  if (GetParam() != ResourceProvider::GLTexture)
2754    return;
2755  scoped_ptr<AllocationTrackingContext3D> context_owned(
2756      new StrictMock<AllocationTrackingContext3D>);
2757  AllocationTrackingContext3D* context = context_owned.get();
2758
2759  FakeOutputSurfaceClient output_surface_client;
2760  scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2761      context_owned.PassAs<TestWebGraphicsContext3D>()));
2762  CHECK(output_surface->BindToClient(&output_surface_client));
2763
2764  const int kWidth = 2;
2765  const int kHeight = 2;
2766  gfx::Size size(kWidth, kHeight);
2767  ResourceFormat format = RGBA_8888;
2768  ResourceProvider::ResourceId id = 0;
2769  const unsigned kTextureId = 123u;
2770  const unsigned kImageId = 234u;
2771
2772  scoped_ptr<ResourceProvider> resource_provider(
2773      ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2774
2775  id = resource_provider->CreateResource(
2776      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2777  EXPECT_CALL(*context, createImageCHROMIUM(kWidth, kHeight, GL_RGBA8_OES))
2778      .WillOnce(Return(kImageId))
2779      .RetiresOnSaturation();
2780  resource_provider->AcquireImage(id);
2781
2782  void* dummy_mapped_buffer_address = NULL;
2783  EXPECT_CALL(*context, mapImageCHROMIUM(kImageId, GL_READ_WRITE))
2784      .WillOnce(Return(dummy_mapped_buffer_address))
2785      .RetiresOnSaturation();
2786  resource_provider->MapImage(id);
2787
2788  const int kStride = 4;
2789  EXPECT_CALL(*context, getImageParameterivCHROMIUM(kImageId,
2790                                                    GL_IMAGE_ROWBYTES_CHROMIUM,
2791                                                    _))
2792      .WillOnce(SetArgPointee<2>(kStride))
2793      .RetiresOnSaturation();
2794  int stride = resource_provider->GetImageStride(id);
2795  EXPECT_EQ(kStride, stride);
2796
2797  EXPECT_CALL(*context, unmapImageCHROMIUM(kImageId))
2798      .Times(1)
2799      .RetiresOnSaturation();
2800  resource_provider->UnmapImage(id);
2801
2802  EXPECT_CALL(*context, NextTextureId())
2803      .WillOnce(Return(kTextureId))
2804      .RetiresOnSaturation();
2805  // Once in CreateTextureId and once in BindForSampling
2806  EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(2)
2807      .RetiresOnSaturation();
2808  EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
2809      .Times(1)
2810      .RetiresOnSaturation();
2811  {
2812    ResourceProvider::ScopedSamplerGL lock_gl(
2813        resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2814    EXPECT_EQ(kTextureId, lock_gl.texture_id());
2815  }
2816
2817  EXPECT_CALL(*context, mapImageCHROMIUM(kImageId, GL_READ_WRITE))
2818      .WillOnce(Return(dummy_mapped_buffer_address))
2819      .RetiresOnSaturation();
2820  resource_provider->MapImage(id);
2821
2822  EXPECT_CALL(*context, unmapImageCHROMIUM(kImageId))
2823      .Times(1)
2824      .RetiresOnSaturation();
2825  resource_provider->UnmapImage(id);
2826
2827  EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(1)
2828      .RetiresOnSaturation();
2829  EXPECT_CALL(*context, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
2830      .Times(1)
2831      .RetiresOnSaturation();
2832  EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
2833      .Times(1)
2834      .RetiresOnSaturation();
2835  EXPECT_CALL(*context, RetireTextureId(kTextureId))
2836      .Times(1)
2837      .RetiresOnSaturation();
2838  {
2839    ResourceProvider::ScopedSamplerGL lock_gl(
2840        resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2841    EXPECT_EQ(kTextureId, lock_gl.texture_id());
2842  }
2843
2844  EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
2845      .Times(1)
2846      .RetiresOnSaturation();
2847  resource_provider->ReleaseImage(id);
2848}
2849
2850TEST_P(ResourceProviderTest, Image_Bitmap) {
2851  if (GetParam() != ResourceProvider::Bitmap)
2852    return;
2853  FakeOutputSurfaceClient output_surface_client;
2854  scoped_ptr<OutputSurface> output_surface(
2855      FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2856          new SoftwareOutputDevice)));
2857  CHECK(output_surface->BindToClient(&output_surface_client));
2858
2859  gfx::Size size(1, 1);
2860  ResourceFormat format = RGBA_8888;
2861  ResourceProvider::ResourceId id = 0;
2862  const uint32_t kBadBeef = 0xbadbeef;
2863
2864  scoped_ptr<ResourceProvider> resource_provider(
2865      ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2866
2867  id = resource_provider->CreateResource(
2868      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2869  resource_provider->AcquireImage(id);
2870
2871  const int kStride = 0;
2872  int stride = resource_provider->GetImageStride(id);
2873  EXPECT_EQ(kStride, stride);
2874
2875  void* data = resource_provider->MapImage(id);
2876  ASSERT_TRUE(!!data);
2877  memcpy(data, &kBadBeef, sizeof(kBadBeef));
2878  resource_provider->UnmapImage(id);
2879
2880  {
2881    ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id);
2882    const SkBitmap* sk_bitmap = lock.sk_bitmap();
2883    EXPECT_EQ(sk_bitmap->width(), size.width());
2884    EXPECT_EQ(sk_bitmap->height(), size.height());
2885    EXPECT_EQ(*sk_bitmap->getAddr32(0, 0), kBadBeef);
2886  }
2887
2888  resource_provider->ReleaseImage(id);
2889  resource_provider->DeleteResource(id);
2890}
2891
2892void InitializeGLAndCheck(ContextSharedData* shared_data,
2893                          ResourceProvider* resource_provider,
2894                          FakeOutputSurface* output_surface) {
2895  scoped_ptr<ResourceProviderContext> context_owned =
2896      ResourceProviderContext::Create(shared_data);
2897  ResourceProviderContext* context = context_owned.get();
2898
2899  scoped_refptr<TestContextProvider> context_provider =
2900      TestContextProvider::Create(
2901          context_owned.PassAs<TestWebGraphicsContext3D>());
2902  output_surface->InitializeAndSetContext3d(context_provider, NULL);
2903  EXPECT_TRUE(resource_provider->InitializeGL());
2904
2905  CheckCreateResource(ResourceProvider::GLTexture, resource_provider, context);
2906}
2907
2908TEST(ResourceProviderTest, BasicInitializeGLSoftware) {
2909  scoped_ptr<ContextSharedData> shared_data = ContextSharedData::Create();
2910  FakeOutputSurfaceClient client;
2911  scoped_ptr<FakeOutputSurface> output_surface(
2912      FakeOutputSurface::CreateDeferredGL(
2913          scoped_ptr<SoftwareOutputDevice>(new SoftwareOutputDevice)));
2914  EXPECT_TRUE(output_surface->BindToClient(&client));
2915  scoped_ptr<ResourceProvider> resource_provider(
2916      ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
2917
2918  CheckCreateResource(ResourceProvider::Bitmap, resource_provider.get(), NULL);
2919
2920  InitializeGLAndCheck(shared_data.get(),
2921                       resource_provider.get(),
2922                       output_surface.get());
2923
2924  resource_provider->InitializeSoftware();
2925  output_surface->ReleaseGL();
2926  CheckCreateResource(ResourceProvider::Bitmap, resource_provider.get(), NULL);
2927
2928  InitializeGLAndCheck(shared_data.get(),
2929                       resource_provider.get(),
2930                       output_surface.get());
2931}
2932
2933TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) {
2934  if (GetParam() != ResourceProvider::GLTexture)
2935    return;
2936
2937  scoped_ptr<AllocationTrackingContext3D> context_owned(
2938      new AllocationTrackingContext3D);
2939  AllocationTrackingContext3D* context = context_owned.get();
2940  context_owned->set_support_compressed_texture_etc1(true);
2941
2942  FakeOutputSurfaceClient output_surface_client;
2943  scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2944      context_owned.PassAs<TestWebGraphicsContext3D>()));
2945  CHECK(output_surface->BindToClient(&output_surface_client));
2946
2947  gfx::Size size(4, 4);
2948  scoped_ptr<ResourceProvider> resource_provider(
2949      ResourceProvider::Create(output_surface.get(),
2950                               shared_bitmap_manager_.get(),
2951                               0,
2952                               false,
2953                               1));
2954  int texture_id = 123;
2955
2956  ResourceProvider::ResourceId id = resource_provider->CreateResource(
2957      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, ETC1);
2958  EXPECT_NE(0u, id);
2959  EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2960  EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
2961  resource_provider->AllocateForTesting(id);
2962
2963  EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2964  resource_provider->DeleteResource(id);
2965}
2966
2967TEST_P(ResourceProviderTest, CompressedTextureETC1SetPixels) {
2968  if (GetParam() != ResourceProvider::GLTexture)
2969    return;
2970
2971  scoped_ptr<AllocationTrackingContext3D> context_owned(
2972      new AllocationTrackingContext3D);
2973  AllocationTrackingContext3D* context = context_owned.get();
2974  context_owned->set_support_compressed_texture_etc1(true);
2975
2976  FakeOutputSurfaceClient output_surface_client;
2977  scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2978      context_owned.PassAs<TestWebGraphicsContext3D>()));
2979  CHECK(output_surface->BindToClient(&output_surface_client));
2980
2981  gfx::Size size(4, 4);
2982  scoped_ptr<ResourceProvider> resource_provider(
2983      ResourceProvider::Create(output_surface.get(),
2984                               shared_bitmap_manager_.get(),
2985                               0,
2986                               false,
2987                               1));
2988  int texture_id = 123;
2989  uint8_t pixels[8];
2990
2991  ResourceProvider::ResourceId id = resource_provider->CreateResource(
2992      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, ETC1);
2993  EXPECT_NE(0u, id);
2994  EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2995  EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
2996  EXPECT_CALL(*context,
2997              compressedTexImage2D(
2998                  _, 0, _, size.width(), size.height(), _, _, _)).Times(1);
2999  resource_provider->SetPixels(
3000      id, pixels, gfx::Rect(size), gfx::Rect(size), gfx::Vector2d(0, 0));
3001
3002  EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3003  resource_provider->DeleteResource(id);
3004}
3005
3006INSTANTIATE_TEST_CASE_P(
3007    ResourceProviderTests,
3008    ResourceProviderTest,
3009    ::testing::Values(ResourceProvider::GLTexture, ResourceProvider::Bitmap));
3010
3011class TextureIdAllocationTrackingContext : public TestWebGraphicsContext3D {
3012 public:
3013  virtual GLuint NextTextureId() OVERRIDE {
3014    base::AutoLock lock(namespace_->lock);
3015    return namespace_->next_texture_id++;
3016  }
3017  virtual void RetireTextureId(GLuint) OVERRIDE {}
3018  GLuint PeekTextureId() {
3019    base::AutoLock lock(namespace_->lock);
3020    return namespace_->next_texture_id;
3021  }
3022};
3023
3024TEST(ResourceProviderTest, TextureAllocationChunkSize) {
3025  scoped_ptr<TextureIdAllocationTrackingContext> context_owned(
3026      new TextureIdAllocationTrackingContext);
3027  TextureIdAllocationTrackingContext* context = context_owned.get();
3028
3029  FakeOutputSurfaceClient output_surface_client;
3030  scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3031      context_owned.PassAs<TestWebGraphicsContext3D>()));
3032  CHECK(output_surface->BindToClient(&output_surface_client));
3033
3034  gfx::Size size(1, 1);
3035  ResourceFormat format = RGBA_8888;
3036
3037  {
3038    size_t kTextureAllocationChunkSize = 1;
3039    scoped_ptr<ResourceProvider> resource_provider(
3040        ResourceProvider::Create(output_surface.get(),
3041                                 NULL,
3042                                 0,
3043                                 false,
3044                                 kTextureAllocationChunkSize));
3045
3046    ResourceProvider::ResourceId id = resource_provider->CreateResource(
3047        size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
3048    resource_provider->AllocateForTesting(id);
3049    Mock::VerifyAndClearExpectations(context);
3050
3051    DCHECK_EQ(2u, context->PeekTextureId());
3052    resource_provider->DeleteResource(id);
3053  }
3054
3055  {
3056    size_t kTextureAllocationChunkSize = 8;
3057    scoped_ptr<ResourceProvider> resource_provider(
3058        ResourceProvider::Create(output_surface.get(),
3059                                 NULL,
3060                                 0,
3061                                 false,
3062                                 kTextureAllocationChunkSize));
3063
3064    ResourceProvider::ResourceId id = resource_provider->CreateResource(
3065        size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
3066    resource_provider->AllocateForTesting(id);
3067    Mock::VerifyAndClearExpectations(context);
3068
3069    DCHECK_EQ(10u, context->PeekTextureId());
3070    resource_provider->DeleteResource(id);
3071  }
3072}
3073
3074}  // namespace
3075}  // namespace cc
3076