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