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