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 <limits>
      9 
     10 #include "base/containers/hash_tables.h"
     11 #include "base/debug/trace_event.h"
     12 #include "base/stl_util.h"
     13 #include "base/strings/string_split.h"
     14 #include "base/strings/string_util.h"
     15 #include "cc/base/util.h"
     16 #include "cc/output/gl_renderer.h"  // For the GLC() macro.
     17 #include "cc/resources/platform_color.h"
     18 #include "cc/resources/returned_resource.h"
     19 #include "cc/resources/shared_bitmap_manager.h"
     20 #include "cc/resources/transferable_resource.h"
     21 #include "cc/scheduler/texture_uploader.h"
     22 #include "gpu/GLES2/gl2extchromium.h"
     23 #include "gpu/command_buffer/client/gles2_interface.h"
     24 #include "third_party/khronos/GLES2/gl2.h"
     25 #include "third_party/khronos/GLES2/gl2ext.h"
     26 #include "ui/gfx/frame_time.h"
     27 #include "ui/gfx/rect.h"
     28 #include "ui/gfx/vector2d.h"
     29 
     30 using gpu::gles2::GLES2Interface;
     31 
     32 namespace cc {
     33 
     34 class IdAllocator {
     35  public:
     36   virtual ~IdAllocator() {}
     37 
     38   virtual GLuint NextId() = 0;
     39 
     40  protected:
     41   IdAllocator(GLES2Interface* gl, size_t id_allocation_chunk_size)
     42       : gl_(gl),
     43         id_allocation_chunk_size_(id_allocation_chunk_size),
     44         ids_(new GLuint[id_allocation_chunk_size]),
     45         next_id_index_(id_allocation_chunk_size) {
     46     DCHECK(id_allocation_chunk_size_);
     47   }
     48 
     49   GLES2Interface* gl_;
     50   const size_t id_allocation_chunk_size_;
     51   scoped_ptr<GLuint[]> ids_;
     52   size_t next_id_index_;
     53 };
     54 
     55 namespace {
     56 
     57 // Measured in seconds.
     58 const double kSoftwareUploadTickRate = 0.000250;
     59 const double kTextureUploadTickRate = 0.004;
     60 
     61 GLenum TextureToStorageFormat(ResourceFormat format) {
     62   GLenum storage_format = GL_RGBA8_OES;
     63   switch (format) {
     64     case RGBA_8888:
     65       break;
     66     case BGRA_8888:
     67       storage_format = GL_BGRA8_EXT;
     68       break;
     69     case RGBA_4444:
     70     case LUMINANCE_8:
     71     case RGB_565:
     72     case ETC1:
     73       NOTREACHED();
     74       break;
     75   }
     76 
     77   return storage_format;
     78 }
     79 
     80 bool IsFormatSupportedForStorage(ResourceFormat format) {
     81   switch (format) {
     82     case RGBA_8888:
     83     case BGRA_8888:
     84       return true;
     85     case RGBA_4444:
     86     case LUMINANCE_8:
     87     case RGB_565:
     88     case ETC1:
     89       return false;
     90   }
     91   return false;
     92 }
     93 
     94 class ScopedSetActiveTexture {
     95  public:
     96   ScopedSetActiveTexture(GLES2Interface* gl, GLenum unit)
     97       : gl_(gl), unit_(unit) {
     98     DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(gl_));
     99 
    100     if (unit_ != GL_TEXTURE0)
    101       GLC(gl_, gl_->ActiveTexture(unit_));
    102   }
    103 
    104   ~ScopedSetActiveTexture() {
    105     // Active unit being GL_TEXTURE0 is effectively the ground state.
    106     if (unit_ != GL_TEXTURE0)
    107       GLC(gl_, gl_->ActiveTexture(GL_TEXTURE0));
    108   }
    109 
    110  private:
    111   GLES2Interface* gl_;
    112   GLenum unit_;
    113 };
    114 
    115 class TextureIdAllocator : public IdAllocator {
    116  public:
    117   TextureIdAllocator(GLES2Interface* gl,
    118                      size_t texture_id_allocation_chunk_size)
    119       : IdAllocator(gl, texture_id_allocation_chunk_size) {}
    120   virtual ~TextureIdAllocator() {
    121     gl_->DeleteTextures(id_allocation_chunk_size_ - next_id_index_,
    122                         ids_.get() + next_id_index_);
    123   }
    124 
    125   // Overridden from IdAllocator:
    126   virtual GLuint NextId() OVERRIDE {
    127     if (next_id_index_ == id_allocation_chunk_size_) {
    128       gl_->GenTextures(id_allocation_chunk_size_, ids_.get());
    129       next_id_index_ = 0;
    130     }
    131 
    132     return ids_[next_id_index_++];
    133   }
    134 
    135  private:
    136   DISALLOW_COPY_AND_ASSIGN(TextureIdAllocator);
    137 };
    138 
    139 class BufferIdAllocator : public IdAllocator {
    140  public:
    141   BufferIdAllocator(GLES2Interface* gl, size_t buffer_id_allocation_chunk_size)
    142       : IdAllocator(gl, buffer_id_allocation_chunk_size) {}
    143   virtual ~BufferIdAllocator() {
    144     gl_->DeleteBuffers(id_allocation_chunk_size_ - next_id_index_,
    145                        ids_.get() + next_id_index_);
    146   }
    147 
    148   // Overridden from IdAllocator:
    149   virtual GLuint NextId() OVERRIDE {
    150     if (next_id_index_ == id_allocation_chunk_size_) {
    151       gl_->GenBuffers(id_allocation_chunk_size_, ids_.get());
    152       next_id_index_ = 0;
    153     }
    154 
    155     return ids_[next_id_index_++];
    156   }
    157 
    158  private:
    159   DISALLOW_COPY_AND_ASSIGN(BufferIdAllocator);
    160 };
    161 
    162 }  // namespace
    163 
    164 ResourceProvider::Resource::Resource()
    165     : child_id(0),
    166       gl_id(0),
    167       gl_pixel_buffer_id(0),
    168       gl_upload_query_id(0),
    169       pixels(NULL),
    170       pixel_buffer(NULL),
    171       lock_for_read_count(0),
    172       imported_count(0),
    173       exported_count(0),
    174       locked_for_write(false),
    175       external(false),
    176       marked_for_deletion(false),
    177       pending_set_pixels(false),
    178       set_pixels_completion_forced(false),
    179       allocated(false),
    180       enable_read_lock_fences(false),
    181       read_lock_fence(NULL),
    182       size(),
    183       target(0),
    184       original_filter(0),
    185       filter(0),
    186       image_id(0),
    187       bound_image_id(0),
    188       dirty_image(false),
    189       texture_pool(0),
    190       wrap_mode(0),
    191       lost(false),
    192       hint(TextureUsageAny),
    193       type(static_cast<ResourceType>(0)),
    194       format(RGBA_8888),
    195       shared_bitmap(NULL) {}
    196 
    197 ResourceProvider::Resource::~Resource() {}
    198 
    199 ResourceProvider::Resource::Resource(GLuint texture_id,
    200                                      gfx::Size size,
    201                                      GLenum target,
    202                                      GLenum filter,
    203                                      GLenum texture_pool,
    204                                      GLint wrap_mode,
    205                                      TextureUsageHint hint,
    206                                      ResourceFormat format)
    207     : child_id(0),
    208       gl_id(texture_id),
    209       gl_pixel_buffer_id(0),
    210       gl_upload_query_id(0),
    211       pixels(NULL),
    212       pixel_buffer(NULL),
    213       lock_for_read_count(0),
    214       imported_count(0),
    215       exported_count(0),
    216       locked_for_write(false),
    217       external(false),
    218       marked_for_deletion(false),
    219       pending_set_pixels(false),
    220       set_pixels_completion_forced(false),
    221       allocated(false),
    222       enable_read_lock_fences(false),
    223       read_lock_fence(NULL),
    224       size(size),
    225       target(target),
    226       original_filter(filter),
    227       filter(filter),
    228       image_id(0),
    229       bound_image_id(0),
    230       dirty_image(false),
    231       texture_pool(texture_pool),
    232       wrap_mode(wrap_mode),
    233       lost(false),
    234       hint(hint),
    235       type(GLTexture),
    236       format(format),
    237       shared_bitmap(NULL) {
    238   DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
    239 }
    240 
    241 ResourceProvider::Resource::Resource(uint8_t* pixels,
    242                                      SharedBitmap* bitmap,
    243                                      gfx::Size size,
    244                                      GLenum filter,
    245                                      GLint wrap_mode)
    246     : child_id(0),
    247       gl_id(0),
    248       gl_pixel_buffer_id(0),
    249       gl_upload_query_id(0),
    250       pixels(pixels),
    251       pixel_buffer(NULL),
    252       lock_for_read_count(0),
    253       imported_count(0),
    254       exported_count(0),
    255       locked_for_write(false),
    256       external(false),
    257       marked_for_deletion(false),
    258       pending_set_pixels(false),
    259       set_pixels_completion_forced(false),
    260       allocated(false),
    261       enable_read_lock_fences(false),
    262       read_lock_fence(NULL),
    263       size(size),
    264       target(0),
    265       original_filter(filter),
    266       filter(filter),
    267       image_id(0),
    268       bound_image_id(0),
    269       dirty_image(false),
    270       texture_pool(0),
    271       wrap_mode(wrap_mode),
    272       lost(false),
    273       hint(TextureUsageAny),
    274       type(Bitmap),
    275       format(RGBA_8888),
    276       shared_bitmap(bitmap) {
    277   DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
    278 }
    279 
    280 ResourceProvider::Child::Child() : marked_for_deletion(false) {}
    281 
    282 ResourceProvider::Child::~Child() {}
    283 
    284 scoped_ptr<ResourceProvider> ResourceProvider::Create(
    285     OutputSurface* output_surface,
    286     SharedBitmapManager* shared_bitmap_manager,
    287     int highp_threshold_min,
    288     bool use_rgba_4444_texture_format,
    289     size_t id_allocation_chunk_size) {
    290   scoped_ptr<ResourceProvider> resource_provider(
    291       new ResourceProvider(output_surface,
    292                            shared_bitmap_manager,
    293                            highp_threshold_min,
    294                            use_rgba_4444_texture_format,
    295                            id_allocation_chunk_size));
    296 
    297   bool success = false;
    298   if (resource_provider->ContextGL()) {
    299     success = resource_provider->InitializeGL();
    300   } else {
    301     resource_provider->InitializeSoftware();
    302     success = true;
    303   }
    304 
    305   if (!success)
    306     return scoped_ptr<ResourceProvider>();
    307 
    308   DCHECK_NE(InvalidType, resource_provider->default_resource_type());
    309   return resource_provider.Pass();
    310 }
    311 
    312 ResourceProvider::~ResourceProvider() {
    313   while (!children_.empty())
    314     DestroyChildInternal(children_.begin(), ForShutdown);
    315   while (!resources_.empty())
    316     DeleteResourceInternal(resources_.begin(), ForShutdown);
    317 
    318   CleanUpGLIfNeeded();
    319 }
    320 
    321 bool ResourceProvider::InUseByConsumer(ResourceId id) {
    322   Resource* resource = GetResource(id);
    323   return resource->lock_for_read_count > 0 || resource->exported_count > 0 ||
    324          resource->lost;
    325 }
    326 
    327 bool ResourceProvider::IsLost(ResourceId id) {
    328   Resource* resource = GetResource(id);
    329   return resource->lost;
    330 }
    331 
    332 ResourceProvider::ResourceId ResourceProvider::CreateResource(
    333     gfx::Size size,
    334     GLint wrap_mode,
    335     TextureUsageHint hint,
    336     ResourceFormat format) {
    337   DCHECK(!size.IsEmpty());
    338   switch (default_resource_type_) {
    339     case GLTexture:
    340       return CreateGLTexture(size,
    341                              GL_TEXTURE_2D,
    342                              GL_TEXTURE_POOL_UNMANAGED_CHROMIUM,
    343                              wrap_mode,
    344                              hint,
    345                              format);
    346     case Bitmap:
    347       DCHECK_EQ(RGBA_8888, format);
    348       return CreateBitmap(size, wrap_mode);
    349     case InvalidType:
    350       break;
    351   }
    352 
    353   LOG(FATAL) << "Invalid default resource type.";
    354   return 0;
    355 }
    356 
    357 ResourceProvider::ResourceId ResourceProvider::CreateManagedResource(
    358     gfx::Size size,
    359     GLenum target,
    360     GLint wrap_mode,
    361     TextureUsageHint hint,
    362     ResourceFormat format) {
    363   DCHECK(!size.IsEmpty());
    364   switch (default_resource_type_) {
    365     case GLTexture:
    366       return CreateGLTexture(size,
    367                              target,
    368                              GL_TEXTURE_POOL_MANAGED_CHROMIUM,
    369                              wrap_mode,
    370                              hint,
    371                              format);
    372     case Bitmap:
    373       DCHECK_EQ(RGBA_8888, format);
    374       return CreateBitmap(size, wrap_mode);
    375     case InvalidType:
    376       break;
    377   }
    378 
    379   LOG(FATAL) << "Invalid default resource type.";
    380   return 0;
    381 }
    382 
    383 ResourceProvider::ResourceId ResourceProvider::CreateGLTexture(
    384     gfx::Size size,
    385     GLenum target,
    386     GLenum texture_pool,
    387     GLint wrap_mode,
    388     TextureUsageHint hint,
    389     ResourceFormat format) {
    390   DCHECK_LE(size.width(), max_texture_size_);
    391   DCHECK_LE(size.height(), max_texture_size_);
    392   DCHECK(thread_checker_.CalledOnValidThread());
    393 
    394   ResourceId id = next_id_++;
    395   Resource resource(
    396       0, size, target, GL_LINEAR, texture_pool, wrap_mode, hint, format);
    397   resource.allocated = false;
    398   resources_[id] = resource;
    399   return id;
    400 }
    401 
    402 ResourceProvider::ResourceId ResourceProvider::CreateBitmap(
    403     gfx::Size size, GLint wrap_mode) {
    404   DCHECK(thread_checker_.CalledOnValidThread());
    405 
    406   scoped_ptr<SharedBitmap> bitmap;
    407   if (shared_bitmap_manager_)
    408     bitmap = shared_bitmap_manager_->AllocateSharedBitmap(size);
    409 
    410   uint8_t* pixels;
    411   if (bitmap)
    412     pixels = bitmap->pixels();
    413   else
    414     pixels = new uint8_t[4 * size.GetArea()];
    415 
    416   ResourceId id = next_id_++;
    417   Resource resource(
    418       pixels, bitmap.release(), size, GL_LINEAR, wrap_mode);
    419   resource.allocated = true;
    420   resources_[id] = resource;
    421   return id;
    422 }
    423 
    424 ResourceProvider::ResourceId
    425 ResourceProvider::CreateResourceFromExternalTexture(
    426     GLuint texture_target,
    427     GLuint texture_id) {
    428   DCHECK(thread_checker_.CalledOnValidThread());
    429 
    430   GLES2Interface* gl = ContextGL();
    431   DCHECK(gl);
    432   GLC(gl, gl->BindTexture(texture_target, texture_id));
    433   GLC(gl, gl->TexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
    434   GLC(gl, gl->TexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
    435   GLC(gl,
    436       gl->TexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
    437   GLC(gl,
    438       gl->TexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
    439 
    440   ResourceId id = next_id_++;
    441   Resource resource(texture_id,
    442                     gfx::Size(),
    443                     texture_target,
    444                     GL_LINEAR,
    445                     0,
    446                     GL_CLAMP_TO_EDGE,
    447                     TextureUsageAny,
    448                     RGBA_8888);
    449   resource.external = true;
    450   resource.allocated = true;
    451   resources_[id] = resource;
    452   return id;
    453 }
    454 
    455 ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox(
    456     const TextureMailbox& mailbox,
    457     scoped_ptr<SingleReleaseCallback> release_callback) {
    458   DCHECK(thread_checker_.CalledOnValidThread());
    459   // Just store the information. Mailbox will be consumed in LockForRead().
    460   ResourceId id = next_id_++;
    461   DCHECK(mailbox.IsValid());
    462   Resource& resource = resources_[id];
    463   if (mailbox.IsTexture()) {
    464     resource = Resource(0,
    465                         gfx::Size(),
    466                         mailbox.target(),
    467                         GL_LINEAR,
    468                         0,
    469                         GL_CLAMP_TO_EDGE,
    470                         TextureUsageAny,
    471                         RGBA_8888);
    472   } else {
    473     DCHECK(mailbox.IsSharedMemory());
    474     base::SharedMemory* shared_memory = mailbox.shared_memory();
    475     DCHECK(shared_memory->memory());
    476     uint8_t* pixels = reinterpret_cast<uint8_t*>(shared_memory->memory());
    477     scoped_ptr<SharedBitmap> shared_bitmap;
    478     if (shared_bitmap_manager_) {
    479       shared_bitmap =
    480           shared_bitmap_manager_->GetBitmapForSharedMemory(shared_memory);
    481     }
    482     resource = Resource(pixels,
    483                         shared_bitmap.release(),
    484                         mailbox.shared_memory_size(),
    485                         GL_LINEAR,
    486                         GL_CLAMP_TO_EDGE);
    487   }
    488   resource.external = true;
    489   resource.allocated = true;
    490   resource.mailbox = mailbox;
    491   resource.release_callback =
    492       base::Bind(&SingleReleaseCallback::Run,
    493                  base::Owned(release_callback.release()));
    494   return id;
    495 }
    496 
    497 void ResourceProvider::DeleteResource(ResourceId id) {
    498   DCHECK(thread_checker_.CalledOnValidThread());
    499   ResourceMap::iterator it = resources_.find(id);
    500   CHECK(it != resources_.end());
    501   Resource* resource = &it->second;
    502   DCHECK(!resource->lock_for_read_count);
    503   DCHECK(!resource->marked_for_deletion);
    504   DCHECK_EQ(resource->imported_count, 0);
    505   DCHECK(resource->pending_set_pixels || !resource->locked_for_write);
    506 
    507   if (resource->exported_count > 0) {
    508     resource->marked_for_deletion = true;
    509     return;
    510   } else {
    511     DeleteResourceInternal(it, Normal);
    512   }
    513 }
    514 
    515 void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it,
    516                                               DeleteStyle style) {
    517   TRACE_EVENT0("cc", "ResourceProvider::DeleteResourceInternal");
    518   Resource* resource = &it->second;
    519   bool lost_resource = resource->lost;
    520 
    521   DCHECK(resource->exported_count == 0 || style != Normal);
    522   if (style == ForShutdown && resource->exported_count > 0)
    523     lost_resource = true;
    524 
    525   if (resource->image_id) {
    526     GLES2Interface* gl = ContextGL();
    527     DCHECK(gl);
    528     GLC(gl, gl->DestroyImageCHROMIUM(resource->image_id));
    529   }
    530 
    531   if (resource->gl_id && !resource->external) {
    532     GLES2Interface* gl = ContextGL();
    533     DCHECK(gl);
    534     GLC(gl, gl->DeleteTextures(1, &resource->gl_id));
    535   }
    536   if (resource->gl_upload_query_id) {
    537     GLES2Interface* gl = ContextGL();
    538     DCHECK(gl);
    539     GLC(gl, gl->DeleteQueriesEXT(1, &resource->gl_upload_query_id));
    540   }
    541   if (resource->gl_pixel_buffer_id) {
    542     GLES2Interface* gl = ContextGL();
    543     DCHECK(gl);
    544     GLC(gl, gl->DeleteBuffers(1, &resource->gl_pixel_buffer_id));
    545   }
    546   if (resource->mailbox.IsValid() && resource->external) {
    547     GLuint sync_point = resource->mailbox.sync_point();
    548     if (resource->mailbox.IsTexture()) {
    549       lost_resource |= lost_output_surface_;
    550       GLES2Interface* gl = ContextGL();
    551       DCHECK(gl);
    552       if (resource->gl_id)
    553         GLC(gl, gl->DeleteTextures(1, &resource->gl_id));
    554       if (!lost_resource && resource->gl_id)
    555         sync_point = gl->InsertSyncPointCHROMIUM();
    556     } else {
    557       DCHECK(resource->mailbox.IsSharedMemory());
    558       base::SharedMemory* shared_memory = resource->mailbox.shared_memory();
    559       if (resource->pixels && shared_memory) {
    560         DCHECK(shared_memory->memory() == resource->pixels);
    561         resource->pixels = NULL;
    562         delete resource->shared_bitmap;
    563         resource->shared_bitmap = NULL;
    564       }
    565     }
    566     resource->release_callback.Run(sync_point, lost_resource);
    567   }
    568   if (resource->shared_bitmap) {
    569     delete resource->shared_bitmap;
    570     resource->pixels = NULL;
    571   }
    572   if (resource->pixels)
    573     delete[] resource->pixels;
    574   if (resource->pixel_buffer)
    575     delete[] resource->pixel_buffer;
    576 
    577   resources_.erase(it);
    578 }
    579 
    580 ResourceProvider::ResourceType ResourceProvider::GetResourceType(
    581     ResourceId id) {
    582   return GetResource(id)->type;
    583 }
    584 
    585 void ResourceProvider::SetPixels(ResourceId id,
    586                                  const uint8_t* image,
    587                                  gfx::Rect image_rect,
    588                                  gfx::Rect source_rect,
    589                                  gfx::Vector2d dest_offset) {
    590   Resource* resource = GetResource(id);
    591   DCHECK(!resource->locked_for_write);
    592   DCHECK(!resource->lock_for_read_count);
    593   DCHECK(!resource->external);
    594   DCHECK_EQ(resource->exported_count, 0);
    595   DCHECK(ReadLockFenceHasPassed(resource));
    596   LazyAllocate(resource);
    597 
    598   if (resource->gl_id) {
    599     DCHECK(!resource->pending_set_pixels);
    600     DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
    601     GLES2Interface* gl = ContextGL();
    602     DCHECK(gl);
    603     DCHECK(texture_uploader_.get());
    604     gl->BindTexture(GL_TEXTURE_2D, resource->gl_id);
    605     texture_uploader_->Upload(image,
    606                               image_rect,
    607                               source_rect,
    608                               dest_offset,
    609                               resource->format,
    610                               resource->size);
    611   }
    612 
    613   if (resource->pixels) {
    614     DCHECK(resource->allocated);
    615     DCHECK_EQ(RGBA_8888, resource->format);
    616     SkBitmap src_full;
    617     src_full.setConfig(
    618         SkBitmap::kARGB_8888_Config, image_rect.width(), image_rect.height());
    619     src_full.setPixels(const_cast<uint8_t*>(image));
    620     SkBitmap src_subset;
    621     SkIRect sk_source_rect = SkIRect::MakeXYWH(source_rect.x(),
    622                                                source_rect.y(),
    623                                                source_rect.width(),
    624                                                source_rect.height());
    625     sk_source_rect.offset(-image_rect.x(), -image_rect.y());
    626     src_full.extractSubset(&src_subset, sk_source_rect);
    627 
    628     ScopedWriteLockSoftware lock(this, id);
    629     SkCanvas* dest = lock.sk_canvas();
    630     dest->writePixels(src_subset, dest_offset.x(), dest_offset.y());
    631   }
    632 }
    633 
    634 size_t ResourceProvider::NumBlockingUploads() {
    635   if (!texture_uploader_)
    636     return 0;
    637 
    638   return texture_uploader_->NumBlockingUploads();
    639 }
    640 
    641 void ResourceProvider::MarkPendingUploadsAsNonBlocking() {
    642   if (!texture_uploader_)
    643     return;
    644 
    645   texture_uploader_->MarkPendingUploadsAsNonBlocking();
    646 }
    647 
    648 size_t ResourceProvider::EstimatedUploadsPerTick() {
    649   if (!texture_uploader_)
    650     return 1u;
    651 
    652   double textures_per_second = texture_uploader_->EstimatedTexturesPerSecond();
    653   size_t textures_per_tick = floor(
    654       kTextureUploadTickRate * textures_per_second);
    655   return textures_per_tick ? textures_per_tick : 1u;
    656 }
    657 
    658 void ResourceProvider::FlushUploads() {
    659   if (!texture_uploader_)
    660     return;
    661 
    662   texture_uploader_->Flush();
    663 }
    664 
    665 void ResourceProvider::ReleaseCachedData() {
    666   if (!texture_uploader_)
    667     return;
    668 
    669   texture_uploader_->ReleaseCachedQueries();
    670 }
    671 
    672 base::TimeTicks ResourceProvider::EstimatedUploadCompletionTime(
    673     size_t uploads_per_tick) {
    674   if (lost_output_surface_)
    675     return base::TimeTicks();
    676 
    677   // Software resource uploads happen on impl thread, so don't bother batching
    678   // them up and trying to wait for them to complete.
    679   if (!texture_uploader_) {
    680     return gfx::FrameTime::Now() + base::TimeDelta::FromMicroseconds(
    681         base::Time::kMicrosecondsPerSecond * kSoftwareUploadTickRate);
    682   }
    683 
    684   base::TimeDelta upload_one_texture_time =
    685       base::TimeDelta::FromMicroseconds(
    686           base::Time::kMicrosecondsPerSecond * kTextureUploadTickRate) /
    687       uploads_per_tick;
    688 
    689   size_t total_uploads = NumBlockingUploads() + uploads_per_tick;
    690   return gfx::FrameTime::Now() + upload_one_texture_time * total_uploads;
    691 }
    692 
    693 void ResourceProvider::Flush() {
    694   DCHECK(thread_checker_.CalledOnValidThread());
    695   GLES2Interface* gl = ContextGL();
    696   if (gl)
    697     gl->Flush();
    698 }
    699 
    700 void ResourceProvider::Finish() {
    701   DCHECK(thread_checker_.CalledOnValidThread());
    702   GLES2Interface* gl = ContextGL();
    703   if (gl)
    704     gl->Finish();
    705 }
    706 
    707 bool ResourceProvider::ShallowFlushIfSupported() {
    708   DCHECK(thread_checker_.CalledOnValidThread());
    709   GLES2Interface* gl = ContextGL();
    710   if (!gl)
    711     return false;
    712 
    713   gl->ShallowFlushCHROMIUM();
    714   return true;
    715 }
    716 
    717 ResourceProvider::Resource* ResourceProvider::GetResource(ResourceId id) {
    718   DCHECK(thread_checker_.CalledOnValidThread());
    719   ResourceMap::iterator it = resources_.find(id);
    720   CHECK(it != resources_.end());
    721   return &it->second;
    722 }
    723 
    724 const ResourceProvider::Resource* ResourceProvider::LockForRead(ResourceId id) {
    725   Resource* resource = GetResource(id);
    726   DCHECK(!resource->locked_for_write ||
    727          resource->set_pixels_completion_forced) <<
    728       "locked for write: " << resource->locked_for_write <<
    729       " pixels completion forced: " << resource->set_pixels_completion_forced;
    730   DCHECK_EQ(resource->exported_count, 0);
    731   // Uninitialized! Call SetPixels or LockForWrite first.
    732   DCHECK(resource->allocated);
    733 
    734   LazyCreate(resource);
    735 
    736   if (resource->external) {
    737     if (!resource->gl_id && resource->mailbox.IsTexture()) {
    738       GLES2Interface* gl = ContextGL();
    739       DCHECK(gl);
    740       if (resource->mailbox.sync_point()) {
    741         GLC(gl, gl->WaitSyncPointCHROMIUM(resource->mailbox.sync_point()));
    742         resource->mailbox.ResetSyncPoint();
    743       }
    744       resource->gl_id = texture_id_allocator_->NextId();
    745       GLC(gl, gl->BindTexture(resource->target, resource->gl_id));
    746       GLC(gl,
    747           gl->ConsumeTextureCHROMIUM(resource->target,
    748                                      resource->mailbox.data()));
    749     }
    750   }
    751 
    752   resource->lock_for_read_count++;
    753   if (resource->enable_read_lock_fences)
    754     resource->read_lock_fence = current_read_lock_fence_;
    755 
    756   return resource;
    757 }
    758 
    759 void ResourceProvider::UnlockForRead(ResourceId id) {
    760   Resource* resource = GetResource(id);
    761   DCHECK_GT(resource->lock_for_read_count, 0);
    762   DCHECK_EQ(resource->exported_count, 0);
    763   resource->lock_for_read_count--;
    764 }
    765 
    766 const ResourceProvider::Resource* ResourceProvider::LockForWrite(
    767     ResourceId id) {
    768   Resource* resource = GetResource(id);
    769   DCHECK(!resource->locked_for_write);
    770   DCHECK(!resource->lock_for_read_count);
    771   DCHECK_EQ(resource->exported_count, 0);
    772   DCHECK(!resource->external);
    773   DCHECK(!resource->lost);
    774   DCHECK(ReadLockFenceHasPassed(resource));
    775   LazyAllocate(resource);
    776 
    777   resource->locked_for_write = true;
    778   return resource;
    779 }
    780 
    781 bool ResourceProvider::CanLockForWrite(ResourceId id) {
    782   Resource* resource = GetResource(id);
    783   return !resource->locked_for_write && !resource->lock_for_read_count &&
    784          !resource->exported_count && !resource->external && !resource->lost &&
    785          ReadLockFenceHasPassed(resource);
    786 }
    787 
    788 void ResourceProvider::UnlockForWrite(ResourceId id) {
    789   Resource* resource = GetResource(id);
    790   DCHECK(resource->locked_for_write);
    791   DCHECK_EQ(resource->exported_count, 0);
    792   DCHECK(!resource->external);
    793   resource->locked_for_write = false;
    794 }
    795 
    796 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL(
    797     ResourceProvider* resource_provider,
    798     ResourceProvider::ResourceId resource_id)
    799     : resource_provider_(resource_provider),
    800       resource_id_(resource_id),
    801       texture_id_(resource_provider->LockForRead(resource_id)->gl_id) {
    802   DCHECK(texture_id_);
    803 }
    804 
    805 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() {
    806   resource_provider_->UnlockForRead(resource_id_);
    807 }
    808 
    809 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
    810     ResourceProvider* resource_provider,
    811     ResourceProvider::ResourceId resource_id,
    812     GLenum filter)
    813     : ScopedReadLockGL(resource_provider, resource_id),
    814       unit_(GL_TEXTURE0),
    815       target_(resource_provider->BindForSampling(resource_id, unit_, filter)) {
    816 }
    817 
    818 ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
    819     ResourceProvider* resource_provider,
    820     ResourceProvider::ResourceId resource_id,
    821     GLenum unit,
    822     GLenum filter)
    823     : ScopedReadLockGL(resource_provider, resource_id),
    824       unit_(unit),
    825       target_(resource_provider->BindForSampling(resource_id, unit_, filter)) {
    826 }
    827 
    828 ResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() {
    829 }
    830 
    831 ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
    832     ResourceProvider* resource_provider,
    833     ResourceProvider::ResourceId resource_id)
    834     : resource_provider_(resource_provider),
    835       resource_id_(resource_id),
    836       texture_id_(resource_provider->LockForWrite(resource_id)->gl_id) {
    837   DCHECK(texture_id_);
    838 }
    839 
    840 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {
    841   resource_provider_->UnlockForWrite(resource_id_);
    842 }
    843 
    844 void ResourceProvider::PopulateSkBitmapWithResource(
    845     SkBitmap* sk_bitmap, const Resource* resource) {
    846   DCHECK(resource->pixels);
    847   DCHECK_EQ(RGBA_8888, resource->format);
    848   sk_bitmap->setConfig(SkBitmap::kARGB_8888_Config,
    849                        resource->size.width(),
    850                        resource->size.height());
    851   sk_bitmap->setPixels(resource->pixels);
    852 }
    853 
    854 ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(
    855     ResourceProvider* resource_provider,
    856     ResourceProvider::ResourceId resource_id)
    857     : resource_provider_(resource_provider),
    858       resource_id_(resource_id) {
    859   const Resource* resource = resource_provider->LockForRead(resource_id);
    860   wrap_mode_ = resource->wrap_mode;
    861   ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_, resource);
    862 }
    863 
    864 ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() {
    865   resource_provider_->UnlockForRead(resource_id_);
    866 }
    867 
    868 ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(
    869     ResourceProvider* resource_provider,
    870     ResourceProvider::ResourceId resource_id)
    871     : resource_provider_(resource_provider),
    872       resource_id_(resource_id) {
    873   ResourceProvider::PopulateSkBitmapWithResource(
    874       &sk_bitmap_, resource_provider->LockForWrite(resource_id));
    875   sk_canvas_.reset(new SkCanvas(sk_bitmap_));
    876 }
    877 
    878 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() {
    879   resource_provider_->UnlockForWrite(resource_id_);
    880 }
    881 
    882 ResourceProvider::ResourceProvider(OutputSurface* output_surface,
    883                                    SharedBitmapManager* shared_bitmap_manager,
    884                                    int highp_threshold_min,
    885                                    bool use_rgba_4444_texture_format,
    886                                    size_t id_allocation_chunk_size)
    887     : output_surface_(output_surface),
    888       shared_bitmap_manager_(shared_bitmap_manager),
    889       lost_output_surface_(false),
    890       highp_threshold_min_(highp_threshold_min),
    891       next_id_(1),
    892       next_child_(1),
    893       default_resource_type_(InvalidType),
    894       use_texture_storage_ext_(false),
    895       use_texture_usage_hint_(false),
    896       use_compressed_texture_etc1_(false),
    897       max_texture_size_(0),
    898       best_texture_format_(RGBA_8888),
    899       use_rgba_4444_texture_format_(use_rgba_4444_texture_format),
    900       id_allocation_chunk_size_(id_allocation_chunk_size) {
    901   DCHECK(output_surface_->HasClient());
    902   DCHECK(id_allocation_chunk_size_);
    903 }
    904 
    905 void ResourceProvider::InitializeSoftware() {
    906   DCHECK(thread_checker_.CalledOnValidThread());
    907   DCHECK_NE(Bitmap, default_resource_type_);
    908 
    909   CleanUpGLIfNeeded();
    910 
    911   default_resource_type_ = Bitmap;
    912   // Pick an arbitrary limit here similar to what hardware might.
    913   max_texture_size_ = 16 * 1024;
    914   best_texture_format_ = RGBA_8888;
    915 }
    916 
    917 bool ResourceProvider::InitializeGL() {
    918   DCHECK(thread_checker_.CalledOnValidThread());
    919   DCHECK(!texture_uploader_);
    920   DCHECK_NE(GLTexture, default_resource_type_);
    921   DCHECK(!texture_id_allocator_);
    922   DCHECK(!buffer_id_allocator_);
    923 
    924   default_resource_type_ = GLTexture;
    925 
    926   const ContextProvider::Capabilities& caps =
    927       output_surface_->context_provider()->ContextCapabilities();
    928 
    929   bool use_bgra = caps.texture_format_bgra8888;
    930   use_texture_storage_ext_ = caps.texture_storage;
    931   use_texture_usage_hint_ = caps.texture_usage;
    932   use_compressed_texture_etc1_ = caps.texture_format_etc1;
    933 
    934   GLES2Interface* gl = ContextGL();
    935   DCHECK(gl);
    936 
    937   texture_uploader_ = TextureUploader::Create(gl);
    938   max_texture_size_ = 0;  // Context expects cleared value.
    939   GLC(gl, gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size_));
    940   best_texture_format_ = PlatformColor::BestTextureFormat(use_bgra);
    941 
    942   texture_id_allocator_.reset(
    943       new TextureIdAllocator(gl, id_allocation_chunk_size_));
    944   buffer_id_allocator_.reset(
    945       new BufferIdAllocator(gl, id_allocation_chunk_size_));
    946 
    947   return true;
    948 }
    949 
    950 void ResourceProvider::CleanUpGLIfNeeded() {
    951   GLES2Interface* gl = ContextGL();
    952   if (default_resource_type_ != GLTexture) {
    953     // We are not in GL mode, but double check before returning.
    954     DCHECK(!gl);
    955     DCHECK(!texture_uploader_);
    956     return;
    957   }
    958 
    959   DCHECK(gl);
    960   texture_uploader_.reset();
    961   texture_id_allocator_.reset();
    962   buffer_id_allocator_.reset();
    963   Finish();
    964 }
    965 
    966 int ResourceProvider::CreateChild(const ReturnCallback& return_callback) {
    967   DCHECK(thread_checker_.CalledOnValidThread());
    968 
    969   Child child_info;
    970   child_info.return_callback = return_callback;
    971 
    972   int child = next_child_++;
    973   children_[child] = child_info;
    974   return child;
    975 }
    976 
    977 void ResourceProvider::DestroyChild(int child_id) {
    978   ChildMap::iterator it = children_.find(child_id);
    979   DCHECK(it != children_.end());
    980   DestroyChildInternal(it, Normal);
    981 }
    982 
    983 void ResourceProvider::DestroyChildInternal(ChildMap::iterator it,
    984                                             DeleteStyle style) {
    985   DCHECK(thread_checker_.CalledOnValidThread());
    986 
    987   Child& child = it->second;
    988   DCHECK(style == ForShutdown || !child.marked_for_deletion);
    989 
    990   ResourceIdArray resources_for_child;
    991 
    992   for (ResourceIdMap::iterator child_it = child.child_to_parent_map.begin();
    993        child_it != child.child_to_parent_map.end();
    994        ++child_it) {
    995     ResourceId id = child_it->second;
    996     resources_for_child.push_back(id);
    997   }
    998 
    999   // If the child is going away, don't consider any resources in use.
   1000   child.in_use_resources.clear();
   1001   child.marked_for_deletion = true;
   1002 
   1003   DeleteAndReturnUnusedResourcesToChild(it, style, resources_for_child);
   1004 }
   1005 
   1006 const ResourceProvider::ResourceIdMap& ResourceProvider::GetChildToParentMap(
   1007     int child) const {
   1008   DCHECK(thread_checker_.CalledOnValidThread());
   1009   ChildMap::const_iterator it = children_.find(child);
   1010   DCHECK(it != children_.end());
   1011   DCHECK(!it->second.marked_for_deletion);
   1012   return it->second.child_to_parent_map;
   1013 }
   1014 
   1015 void ResourceProvider::PrepareSendToParent(const ResourceIdArray& resources,
   1016                                            TransferableResourceArray* list) {
   1017   DCHECK(thread_checker_.CalledOnValidThread());
   1018   GLES2Interface* gl = ContextGL();
   1019   bool need_sync_point = false;
   1020   for (ResourceIdArray::const_iterator it = resources.begin();
   1021        it != resources.end();
   1022        ++it) {
   1023     TransferableResource resource;
   1024     TransferResource(gl, *it, &resource);
   1025     if (!resource.sync_point && !resource.is_software)
   1026       need_sync_point = true;
   1027     ++resources_.find(*it)->second.exported_count;
   1028     list->push_back(resource);
   1029   }
   1030   if (need_sync_point) {
   1031     GLuint sync_point = gl->InsertSyncPointCHROMIUM();
   1032     for (TransferableResourceArray::iterator it = list->begin();
   1033          it != list->end();
   1034          ++it) {
   1035       if (!it->sync_point)
   1036         it->sync_point = sync_point;
   1037     }
   1038   }
   1039 }
   1040 
   1041 void ResourceProvider::ReceiveFromChild(
   1042     int child, const TransferableResourceArray& resources) {
   1043   DCHECK(thread_checker_.CalledOnValidThread());
   1044   GLES2Interface* gl = ContextGL();
   1045   Child& child_info = children_.find(child)->second;
   1046   DCHECK(!child_info.marked_for_deletion);
   1047   for (TransferableResourceArray::const_iterator it = resources.begin();
   1048        it != resources.end();
   1049        ++it) {
   1050     ResourceIdMap::iterator resource_in_map_it =
   1051         child_info.child_to_parent_map.find(it->id);
   1052     if (resource_in_map_it != child_info.child_to_parent_map.end()) {
   1053       resources_[resource_in_map_it->second].imported_count++;
   1054       continue;
   1055     }
   1056 
   1057     scoped_ptr<SharedBitmap> bitmap;
   1058     uint8_t* pixels = NULL;
   1059     if (it->is_software) {
   1060       if (shared_bitmap_manager_)
   1061         bitmap = shared_bitmap_manager_->GetSharedBitmapFromId(it->size,
   1062                                                                it->mailbox);
   1063       if (bitmap)
   1064         pixels = bitmap->pixels();
   1065     }
   1066 
   1067     if ((!it->is_software && !gl) || (it->is_software && !pixels)) {
   1068       TRACE_EVENT0("cc", "ResourceProvider::ReceiveFromChild dropping invalid");
   1069       ReturnedResourceArray to_return;
   1070       to_return.push_back(it->ToReturnedResource());
   1071       child_info.return_callback.Run(to_return);
   1072       continue;
   1073     }
   1074 
   1075     ResourceId local_id = next_id_++;
   1076     Resource& resource = resources_[local_id];
   1077     if (it->is_software) {
   1078       resource = Resource(
   1079           pixels, bitmap.release(), it->size, GL_LINEAR, GL_CLAMP_TO_EDGE);
   1080     } else {
   1081       GLuint texture_id;
   1082       // NOTE: If the parent is a browser and the child a renderer, the parent
   1083       // is not supposed to have its context wait, because that could induce
   1084       // deadlocks and/or security issues. The caller is responsible for
   1085       // waiting asynchronously, and resetting sync_point before calling this.
   1086       // However if the parent is a renderer (e.g. browser tag), it may be ok
   1087       // (and is simpler) to wait.
   1088       if (it->sync_point)
   1089         GLC(gl, gl->WaitSyncPointCHROMIUM(it->sync_point));
   1090       texture_id = texture_id_allocator_->NextId();
   1091       GLC(gl, gl->BindTexture(it->target, texture_id));
   1092       GLC(gl, gl->ConsumeTextureCHROMIUM(it->target, it->mailbox.name));
   1093       resource = Resource(texture_id,
   1094                           it->size,
   1095                           it->target,
   1096                           it->filter,
   1097                           0,
   1098                           GL_CLAMP_TO_EDGE,
   1099                           TextureUsageAny,
   1100                           it->format);
   1101       resource.mailbox.SetName(it->mailbox);
   1102     }
   1103     resource.child_id = child;
   1104     // Don't allocate a texture for a child.
   1105     resource.allocated = true;
   1106     resource.imported_count = 1;
   1107     child_info.parent_to_child_map[local_id] = it->id;
   1108     child_info.child_to_parent_map[it->id] = local_id;
   1109   }
   1110 }
   1111 
   1112 void ResourceProvider::DeclareUsedResourcesFromChild(
   1113     int child,
   1114     const ResourceIdArray& resources_from_child) {
   1115   DCHECK(thread_checker_.CalledOnValidThread());
   1116 
   1117   ChildMap::iterator child_it = children_.find(child);
   1118   DCHECK(child_it != children_.end());
   1119   Child& child_info = child_it->second;
   1120   DCHECK(!child_info.marked_for_deletion);
   1121   child_info.in_use_resources.clear();
   1122 
   1123   for (size_t i = 0; i < resources_from_child.size(); ++i) {
   1124     ResourceIdMap::iterator it =
   1125         child_info.child_to_parent_map.find(resources_from_child[i]);
   1126     DCHECK(it != child_info.child_to_parent_map.end());
   1127 
   1128     ResourceId local_id = it->second;
   1129     child_info.in_use_resources.insert(local_id);
   1130   }
   1131 
   1132   ResourceIdArray unused;
   1133   for (ResourceIdMap::iterator it = child_info.child_to_parent_map.begin();
   1134        it != child_info.child_to_parent_map.end();
   1135        ++it) {
   1136     ResourceId local_id = it->second;
   1137     bool resource_is_in_use = child_info.in_use_resources.count(local_id) > 0;
   1138     if (!resource_is_in_use)
   1139       unused.push_back(local_id);
   1140   }
   1141   DeleteAndReturnUnusedResourcesToChild(child_it, Normal, unused);
   1142 }
   1143 
   1144 // static
   1145 bool ResourceProvider::CompareResourceMapIteratorsByChildId(
   1146     const std::pair<ReturnedResource, ResourceMap::iterator>& a,
   1147     const std::pair<ReturnedResource, ResourceMap::iterator>& b) {
   1148   const ResourceMap::iterator& a_it = a.second;
   1149   const ResourceMap::iterator& b_it = b.second;
   1150   const Resource& a_resource = a_it->second;
   1151   const Resource& b_resource = b_it->second;
   1152   return a_resource.child_id < b_resource.child_id;
   1153 }
   1154 
   1155 void ResourceProvider::ReceiveReturnsFromParent(
   1156     const ReturnedResourceArray& resources) {
   1157   DCHECK(thread_checker_.CalledOnValidThread());
   1158   GLES2Interface* gl = ContextGL();
   1159 
   1160   int child_id = 0;
   1161   ResourceIdArray resources_for_child;
   1162 
   1163   std::vector<std::pair<ReturnedResource, ResourceMap::iterator> >
   1164       sorted_resources;
   1165 
   1166   for (ReturnedResourceArray::const_iterator it = resources.begin();
   1167        it != resources.end();
   1168        ++it) {
   1169     ResourceId local_id = it->id;
   1170     ResourceMap::iterator map_iterator = resources_.find(local_id);
   1171 
   1172     // Resource was already lost (e.g. it belonged to a child that was
   1173     // destroyed).
   1174     if (map_iterator == resources_.end())
   1175       continue;
   1176 
   1177     sorted_resources.push_back(
   1178         std::pair<ReturnedResource, ResourceMap::iterator>(*it, map_iterator));
   1179   }
   1180 
   1181   std::sort(sorted_resources.begin(),
   1182             sorted_resources.end(),
   1183             CompareResourceMapIteratorsByChildId);
   1184 
   1185   ChildMap::iterator child_it = children_.end();
   1186   for (size_t i = 0; i < sorted_resources.size(); ++i) {
   1187     ReturnedResource& returned = sorted_resources[i].first;
   1188     ResourceMap::iterator& map_iterator = sorted_resources[i].second;
   1189     ResourceId local_id = map_iterator->first;
   1190     Resource* resource = &map_iterator->second;
   1191 
   1192     CHECK_GE(resource->exported_count, returned.count);
   1193     resource->exported_count -= returned.count;
   1194     resource->lost |= returned.lost;
   1195     if (resource->exported_count)
   1196       continue;
   1197 
   1198     if (resource->gl_id) {
   1199       if (returned.sync_point)
   1200         GLC(gl, gl->WaitSyncPointCHROMIUM(returned.sync_point));
   1201     } else if (!resource->shared_bitmap) {
   1202       resource->mailbox =
   1203           TextureMailbox(resource->mailbox.name(), returned.sync_point);
   1204     }
   1205 
   1206     if (!resource->marked_for_deletion)
   1207       continue;
   1208 
   1209     if (!resource->child_id) {
   1210       // The resource belongs to this ResourceProvider, so it can be destroyed.
   1211       DeleteResourceInternal(map_iterator, Normal);
   1212       continue;
   1213     }
   1214 
   1215     // Delete the resource and return it to the child it came from one.
   1216     if (resource->child_id != child_id) {
   1217       if (child_id) {
   1218         DCHECK_NE(resources_for_child.size(), 0u);
   1219         DCHECK(child_it != children_.end());
   1220         DeleteAndReturnUnusedResourcesToChild(
   1221             child_it, Normal, resources_for_child);
   1222         resources_for_child.clear();
   1223       }
   1224 
   1225       child_it = children_.find(resource->child_id);
   1226       DCHECK(child_it != children_.end());
   1227       child_id = resource->child_id;
   1228     }
   1229     resources_for_child.push_back(local_id);
   1230   }
   1231 
   1232   if (child_id) {
   1233     DCHECK_NE(resources_for_child.size(), 0u);
   1234     DCHECK(child_it != children_.end());
   1235     DeleteAndReturnUnusedResourcesToChild(
   1236         child_it, Normal, resources_for_child);
   1237   }
   1238 }
   1239 
   1240 void ResourceProvider::TransferResource(GLES2Interface* gl,
   1241                                         ResourceId id,
   1242                                         TransferableResource* resource) {
   1243   Resource* source = GetResource(id);
   1244   DCHECK(!source->locked_for_write);
   1245   DCHECK(!source->lock_for_read_count);
   1246   DCHECK(!source->external || (source->external && source->mailbox.IsValid()));
   1247   DCHECK(source->allocated);
   1248   DCHECK_EQ(source->wrap_mode, GL_CLAMP_TO_EDGE);
   1249   resource->id = id;
   1250   resource->format = source->format;
   1251   resource->target = source->target;
   1252   resource->filter = source->filter;
   1253   resource->size = source->size;
   1254 
   1255   if (source->shared_bitmap) {
   1256     resource->mailbox = source->shared_bitmap->id();
   1257     resource->is_software = true;
   1258   } else if (!source->mailbox.IsValid()) {
   1259     // This is a resource allocated by the compositor, we need to produce it.
   1260     // Don't set a sync point, the caller will do it.
   1261     DCHECK(source->gl_id);
   1262     GLC(gl, gl->BindTexture(resource->target, source->gl_id));
   1263     GLC(gl, gl->GenMailboxCHROMIUM(resource->mailbox.name));
   1264     GLC(gl,
   1265         gl->ProduceTextureCHROMIUM(resource->target, resource->mailbox.name));
   1266     source->mailbox.SetName(resource->mailbox);
   1267   } else {
   1268     DCHECK(source->mailbox.IsTexture());
   1269     // This is either an external resource, or a compositor resource that we
   1270     // already exported. Make sure to forward the sync point that we were given.
   1271     resource->mailbox = source->mailbox.name();
   1272     resource->sync_point = source->mailbox.sync_point();
   1273     source->mailbox.ResetSyncPoint();
   1274   }
   1275 }
   1276 
   1277 void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
   1278     ChildMap::iterator child_it,
   1279     DeleteStyle style,
   1280     const ResourceIdArray& unused) {
   1281   DCHECK(thread_checker_.CalledOnValidThread());
   1282   DCHECK(child_it != children_.end());
   1283   Child* child_info = &child_it->second;
   1284 
   1285   if (unused.empty() && !child_info->marked_for_deletion)
   1286     return;
   1287 
   1288   ReturnedResourceArray to_return;
   1289 
   1290   GLES2Interface* gl = ContextGL();
   1291   bool need_sync_point = false;
   1292   for (size_t i = 0; i < unused.size(); ++i) {
   1293     ResourceId local_id = unused[i];
   1294 
   1295     ResourceMap::iterator it = resources_.find(local_id);
   1296     CHECK(it != resources_.end());
   1297     Resource& resource = it->second;
   1298 
   1299     DCHECK(!resource.locked_for_write);
   1300     DCHECK(!resource.lock_for_read_count);
   1301     DCHECK_EQ(0u, child_info->in_use_resources.count(local_id));
   1302     DCHECK(child_info->parent_to_child_map.count(local_id));
   1303 
   1304     ResourceId child_id = child_info->parent_to_child_map[local_id];
   1305     DCHECK(child_info->child_to_parent_map.count(child_id));
   1306 
   1307     bool is_lost =
   1308         resource.lost || (!resource.shared_bitmap && lost_output_surface_);
   1309     if (resource.exported_count > 0) {
   1310       if (style != ForShutdown) {
   1311         // Defer this until we receive the resource back from the parent.
   1312         resource.marked_for_deletion = true;
   1313         continue;
   1314       }
   1315 
   1316       // We still have an exported_count, so we'll have to lose it.
   1317       is_lost = true;
   1318     }
   1319 
   1320     if (gl && resource.filter != resource.original_filter) {
   1321       DCHECK(resource.target);
   1322       DCHECK(resource.gl_id);
   1323 
   1324       GLC(gl, gl->BindTexture(resource.target, resource.gl_id));
   1325       GLC(gl,
   1326           gl->TexParameteri(resource.target,
   1327                             GL_TEXTURE_MIN_FILTER,
   1328                             resource.original_filter));
   1329       GLC(gl,
   1330           gl->TexParameteri(resource.target,
   1331                             GL_TEXTURE_MAG_FILTER,
   1332                             resource.original_filter));
   1333     }
   1334 
   1335     ReturnedResource returned;
   1336     returned.id = child_id;
   1337     returned.sync_point = resource.mailbox.sync_point();
   1338     if (!returned.sync_point && !resource.shared_bitmap)
   1339       need_sync_point = true;
   1340     returned.count = resource.imported_count;
   1341     returned.lost = is_lost;
   1342     to_return.push_back(returned);
   1343 
   1344     child_info->parent_to_child_map.erase(local_id);
   1345     child_info->child_to_parent_map.erase(child_id);
   1346     resource.imported_count = 0;
   1347     DeleteResourceInternal(it, style);
   1348   }
   1349   if (need_sync_point) {
   1350     DCHECK(gl);
   1351     GLuint sync_point = gl->InsertSyncPointCHROMIUM();
   1352     for (size_t i = 0; i < to_return.size(); ++i) {
   1353       if (!to_return[i].sync_point)
   1354         to_return[i].sync_point = sync_point;
   1355     }
   1356   }
   1357 
   1358   if (!to_return.empty())
   1359     child_info->return_callback.Run(to_return);
   1360 
   1361   if (child_info->marked_for_deletion &&
   1362       child_info->parent_to_child_map.empty()) {
   1363     DCHECK(child_info->child_to_parent_map.empty());
   1364     children_.erase(child_it);
   1365   }
   1366 }
   1367 
   1368 void ResourceProvider::AcquirePixelBuffer(ResourceId id) {
   1369   Resource* resource = GetResource(id);
   1370   DCHECK(!resource->external);
   1371   DCHECK_EQ(resource->exported_count, 0);
   1372   DCHECK(!resource->image_id);
   1373   DCHECK_NE(ETC1, resource->format);
   1374 
   1375   if (resource->type == GLTexture) {
   1376     GLES2Interface* gl = ContextGL();
   1377     DCHECK(gl);
   1378     if (!resource->gl_pixel_buffer_id)
   1379       resource->gl_pixel_buffer_id = buffer_id_allocator_->NextId();
   1380     gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
   1381                    resource->gl_pixel_buffer_id);
   1382     unsigned bytes_per_pixel = BitsPerPixel(resource->format) / 8;
   1383     gl->BufferData(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
   1384                    resource->size.height() *
   1385                        RoundUp(bytes_per_pixel * resource->size.width(), 4u),
   1386                    NULL,
   1387                    GL_DYNAMIC_DRAW);
   1388     gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
   1389   }
   1390 
   1391   if (resource->pixels) {
   1392     if (resource->pixel_buffer)
   1393       return;
   1394 
   1395     resource->pixel_buffer = new uint8_t[4 * resource->size.GetArea()];
   1396   }
   1397 }
   1398 
   1399 void ResourceProvider::ReleasePixelBuffer(ResourceId id) {
   1400   Resource* resource = GetResource(id);
   1401   DCHECK(!resource->external);
   1402   DCHECK_EQ(resource->exported_count, 0);
   1403   DCHECK(!resource->image_id);
   1404 
   1405   // The pixel buffer can be released while there is a pending "set pixels"
   1406   // if completion has been forced. Any shared memory associated with this
   1407   // pixel buffer will not be freed until the waitAsyncTexImage2DCHROMIUM
   1408   // command has been processed on the service side. It is also safe to
   1409   // reuse any query id associated with this resource before they complete
   1410   // as each new query has a unique submit count.
   1411   if (resource->pending_set_pixels) {
   1412     DCHECK(resource->set_pixels_completion_forced);
   1413     resource->pending_set_pixels = false;
   1414     UnlockForWrite(id);
   1415   }
   1416 
   1417   if (resource->type == GLTexture) {
   1418     if (!resource->gl_pixel_buffer_id)
   1419       return;
   1420     GLES2Interface* gl = ContextGL();
   1421     DCHECK(gl);
   1422     gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
   1423                    resource->gl_pixel_buffer_id);
   1424     gl->BufferData(
   1425         GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0, NULL, GL_DYNAMIC_DRAW);
   1426     gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
   1427   }
   1428 
   1429   if (resource->pixels) {
   1430     if (!resource->pixel_buffer)
   1431       return;
   1432     delete[] resource->pixel_buffer;
   1433     resource->pixel_buffer = NULL;
   1434   }
   1435 }
   1436 
   1437 uint8_t* ResourceProvider::MapPixelBuffer(ResourceId id) {
   1438   Resource* resource = GetResource(id);
   1439   DCHECK(!resource->external);
   1440   DCHECK_EQ(resource->exported_count, 0);
   1441   DCHECK(!resource->image_id);
   1442 
   1443   if (resource->type == GLTexture) {
   1444     GLES2Interface* gl = ContextGL();
   1445     DCHECK(gl);
   1446     DCHECK(resource->gl_pixel_buffer_id);
   1447     gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
   1448                    resource->gl_pixel_buffer_id);
   1449     uint8_t* image = static_cast<uint8_t*>(gl->MapBufferCHROMIUM(
   1450         GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, GL_WRITE_ONLY));
   1451     gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
   1452     // Buffer is required to be 4-byte aligned.
   1453     CHECK(!(reinterpret_cast<intptr_t>(image) & 3));
   1454     return image;
   1455   }
   1456 
   1457   if (resource->pixels)
   1458     return resource->pixel_buffer;
   1459 
   1460   return NULL;
   1461 }
   1462 
   1463 void ResourceProvider::UnmapPixelBuffer(ResourceId id) {
   1464   Resource* resource = GetResource(id);
   1465   DCHECK(!resource->external);
   1466   DCHECK_EQ(resource->exported_count, 0);
   1467   DCHECK(!resource->image_id);
   1468 
   1469   if (resource->type == GLTexture) {
   1470     GLES2Interface* gl = ContextGL();
   1471     DCHECK(gl);
   1472     DCHECK(resource->gl_pixel_buffer_id);
   1473     gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
   1474                    resource->gl_pixel_buffer_id);
   1475     gl->UnmapBufferCHROMIUM(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM);
   1476     gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
   1477   }
   1478 }
   1479 
   1480 GLenum ResourceProvider::BindForSampling(
   1481     ResourceProvider::ResourceId resource_id,
   1482     GLenum unit,
   1483     GLenum filter) {
   1484   DCHECK(thread_checker_.CalledOnValidThread());
   1485   GLES2Interface* gl = ContextGL();
   1486   ResourceMap::iterator it = resources_.find(resource_id);
   1487   DCHECK(it != resources_.end());
   1488   Resource* resource = &it->second;
   1489   DCHECK(resource->lock_for_read_count);
   1490   DCHECK(!resource->locked_for_write || resource->set_pixels_completion_forced);
   1491 
   1492   ScopedSetActiveTexture scoped_active_tex(gl, unit);
   1493   GLenum target = resource->target;
   1494   GLC(gl, gl->BindTexture(target, resource->gl_id));
   1495   if (filter != resource->filter) {
   1496     GLC(gl, gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, filter));
   1497     GLC(gl, gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, filter));
   1498     resource->filter = filter;
   1499   }
   1500 
   1501   if (resource->image_id && resource->dirty_image) {
   1502     // Release image currently bound to texture.
   1503     if (resource->bound_image_id)
   1504       gl->ReleaseTexImage2DCHROMIUM(target, resource->bound_image_id);
   1505     gl->BindTexImage2DCHROMIUM(target, resource->image_id);
   1506     resource->bound_image_id = resource->image_id;
   1507     resource->dirty_image = false;
   1508   }
   1509 
   1510   return target;
   1511 }
   1512 
   1513 void ResourceProvider::BeginSetPixels(ResourceId id) {
   1514   Resource* resource = GetResource(id);
   1515   DCHECK(!resource->pending_set_pixels);
   1516 
   1517   LazyCreate(resource);
   1518   DCHECK(resource->gl_id || resource->allocated);
   1519   DCHECK(ReadLockFenceHasPassed(resource));
   1520   DCHECK(!resource->image_id);
   1521 
   1522   bool allocate = !resource->allocated;
   1523   resource->allocated = true;
   1524   LockForWrite(id);
   1525 
   1526   if (resource->gl_id) {
   1527     GLES2Interface* gl = ContextGL();
   1528     DCHECK(gl);
   1529     DCHECK(resource->gl_pixel_buffer_id);
   1530     DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
   1531     gl->BindTexture(GL_TEXTURE_2D, resource->gl_id);
   1532     gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
   1533                    resource->gl_pixel_buffer_id);
   1534     if (!resource->gl_upload_query_id)
   1535       gl->GenQueriesEXT(1, &resource->gl_upload_query_id);
   1536     gl->BeginQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM,
   1537                       resource->gl_upload_query_id);
   1538     if (allocate) {
   1539       gl->AsyncTexImage2DCHROMIUM(GL_TEXTURE_2D,
   1540                                   0, /* level */
   1541                                   GLInternalFormat(resource->format),
   1542                                   resource->size.width(),
   1543                                   resource->size.height(),
   1544                                   0, /* border */
   1545                                   GLDataFormat(resource->format),
   1546                                   GLDataType(resource->format),
   1547                                   NULL);
   1548     } else {
   1549       gl->AsyncTexSubImage2DCHROMIUM(GL_TEXTURE_2D,
   1550                                      0, /* level */
   1551                                      0, /* x */
   1552                                      0, /* y */
   1553                                      resource->size.width(),
   1554                                      resource->size.height(),
   1555                                      GLDataFormat(resource->format),
   1556                                      GLDataType(resource->format),
   1557                                      NULL);
   1558     }
   1559     gl->EndQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM);
   1560     gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
   1561   }
   1562 
   1563   if (resource->pixels) {
   1564     DCHECK(!resource->mailbox.IsValid());
   1565     DCHECK(resource->pixel_buffer);
   1566     DCHECK_EQ(RGBA_8888, resource->format);
   1567 
   1568     std::swap(resource->pixels, resource->pixel_buffer);
   1569     delete[] resource->pixel_buffer;
   1570     resource->pixel_buffer = NULL;
   1571   }
   1572 
   1573   resource->pending_set_pixels = true;
   1574   resource->set_pixels_completion_forced = false;
   1575 }
   1576 
   1577 void ResourceProvider::ForceSetPixelsToComplete(ResourceId id) {
   1578   Resource* resource = GetResource(id);
   1579   DCHECK(resource->locked_for_write);
   1580   DCHECK(resource->pending_set_pixels);
   1581   DCHECK(!resource->set_pixels_completion_forced);
   1582 
   1583   if (resource->gl_id) {
   1584     GLES2Interface* gl = ContextGL();
   1585     GLC(gl, gl->BindTexture(GL_TEXTURE_2D, resource->gl_id));
   1586     GLC(gl, gl->WaitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D));
   1587     GLC(gl, gl->BindTexture(GL_TEXTURE_2D, 0));
   1588   }
   1589 
   1590   resource->set_pixels_completion_forced = true;
   1591 }
   1592 
   1593 bool ResourceProvider::DidSetPixelsComplete(ResourceId id) {
   1594   Resource* resource = GetResource(id);
   1595   DCHECK(resource->locked_for_write);
   1596   DCHECK(resource->pending_set_pixels);
   1597 
   1598   if (resource->gl_id) {
   1599     GLES2Interface* gl = ContextGL();
   1600     DCHECK(gl);
   1601     DCHECK(resource->gl_upload_query_id);
   1602     GLuint complete = 1;
   1603     gl->GetQueryObjectuivEXT(
   1604         resource->gl_upload_query_id, GL_QUERY_RESULT_AVAILABLE_EXT, &complete);
   1605     if (!complete)
   1606       return false;
   1607   }
   1608 
   1609   resource->pending_set_pixels = false;
   1610   UnlockForWrite(id);
   1611 
   1612   return true;
   1613 }
   1614 
   1615 void ResourceProvider::CreateForTesting(ResourceId id) {
   1616   LazyCreate(GetResource(id));
   1617 }
   1618 
   1619 GLenum ResourceProvider::TargetForTesting(ResourceId id) {
   1620   Resource* resource = GetResource(id);
   1621   return resource->target;
   1622 }
   1623 
   1624 void ResourceProvider::LazyCreate(Resource* resource) {
   1625   if (resource->type != GLTexture || resource->gl_id != 0)
   1626     return;
   1627 
   1628   // Early out for resources that don't require texture creation.
   1629   if (resource->texture_pool == 0)
   1630     return;
   1631 
   1632   resource->gl_id = texture_id_allocator_->NextId();
   1633 
   1634   GLES2Interface* gl = ContextGL();
   1635   DCHECK(gl);
   1636 
   1637   // Create and set texture properties. Allocation is delayed until needed.
   1638   GLC(gl, gl->BindTexture(resource->target, resource->gl_id));
   1639   GLC(gl,
   1640       gl->TexParameteri(resource->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
   1641   GLC(gl,
   1642       gl->TexParameteri(resource->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
   1643   GLC(gl,
   1644       gl->TexParameteri(
   1645           resource->target, GL_TEXTURE_WRAP_S, resource->wrap_mode));
   1646   GLC(gl,
   1647       gl->TexParameteri(
   1648           resource->target, GL_TEXTURE_WRAP_T, resource->wrap_mode));
   1649   GLC(gl,
   1650       gl->TexParameteri(
   1651           resource->target, GL_TEXTURE_POOL_CHROMIUM, resource->texture_pool));
   1652   if (use_texture_usage_hint_ && resource->hint == TextureUsageFramebuffer) {
   1653     GLC(gl,
   1654         gl->TexParameteri(resource->target,
   1655                           GL_TEXTURE_USAGE_ANGLE,
   1656                           GL_FRAMEBUFFER_ATTACHMENT_ANGLE));
   1657   }
   1658 }
   1659 
   1660 void ResourceProvider::AllocateForTesting(ResourceId id) {
   1661   LazyAllocate(GetResource(id));
   1662 }
   1663 
   1664 void ResourceProvider::LazyAllocate(Resource* resource) {
   1665   DCHECK(resource);
   1666   LazyCreate(resource);
   1667 
   1668   DCHECK(resource->gl_id || resource->allocated);
   1669   if (resource->allocated || !resource->gl_id)
   1670     return;
   1671   resource->allocated = true;
   1672   GLES2Interface* gl = ContextGL();
   1673   gfx::Size& size = resource->size;
   1674   DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D));
   1675   ResourceFormat format = resource->format;
   1676   GLC(gl, gl->BindTexture(GL_TEXTURE_2D, resource->gl_id));
   1677   if (use_texture_storage_ext_ && IsFormatSupportedForStorage(format) &&
   1678       resource->hint != TextureUsageFramebuffer) {
   1679     GLenum storage_format = TextureToStorageFormat(format);
   1680     GLC(gl,
   1681         gl->TexStorage2DEXT(
   1682             GL_TEXTURE_2D, 1, storage_format, size.width(), size.height()));
   1683   } else {
   1684     // ETC1 does not support preallocation.
   1685     if (format != ETC1) {
   1686       GLC(gl,
   1687           gl->TexImage2D(GL_TEXTURE_2D,
   1688                          0,
   1689                          GLInternalFormat(format),
   1690                          size.width(),
   1691                          size.height(),
   1692                          0,
   1693                          GLDataFormat(format),
   1694                          GLDataType(format),
   1695                          NULL));
   1696     }
   1697   }
   1698 }
   1699 
   1700 void ResourceProvider::EnableReadLockFences(ResourceProvider::ResourceId id,
   1701                                             bool enable) {
   1702   Resource* resource = GetResource(id);
   1703   resource->enable_read_lock_fences = enable;
   1704 }
   1705 
   1706 void ResourceProvider::AcquireImage(ResourceId id) {
   1707   Resource* resource = GetResource(id);
   1708   DCHECK(!resource->external);
   1709   DCHECK_EQ(resource->exported_count, 0);
   1710 
   1711   if (resource->type != GLTexture)
   1712     return;
   1713 
   1714   if (resource->image_id)
   1715     return;
   1716 
   1717   resource->allocated = true;
   1718   GLES2Interface* gl = ContextGL();
   1719   DCHECK(gl);
   1720   resource->image_id =
   1721       gl->CreateImageCHROMIUM(resource->size.width(),
   1722                               resource->size.height(),
   1723                               TextureToStorageFormat(resource->format));
   1724   DCHECK(resource->image_id);
   1725 }
   1726 
   1727 void ResourceProvider::ReleaseImage(ResourceId id) {
   1728   Resource* resource = GetResource(id);
   1729   DCHECK(!resource->external);
   1730   DCHECK_EQ(resource->exported_count, 0);
   1731 
   1732   if (!resource->image_id)
   1733     return;
   1734 
   1735   GLES2Interface* gl = ContextGL();
   1736   DCHECK(gl);
   1737   gl->DestroyImageCHROMIUM(resource->image_id);
   1738   resource->image_id = 0;
   1739   resource->bound_image_id = 0;
   1740   resource->dirty_image = false;
   1741   resource->allocated = false;
   1742 }
   1743 
   1744 uint8_t* ResourceProvider::MapImage(ResourceId id) {
   1745   Resource* resource = GetResource(id);
   1746   DCHECK(ReadLockFenceHasPassed(resource));
   1747   DCHECK(!resource->external);
   1748   DCHECK_EQ(resource->exported_count, 0);
   1749 
   1750   if (resource->image_id) {
   1751     GLES2Interface* gl = ContextGL();
   1752     DCHECK(gl);
   1753     return static_cast<uint8_t*>(
   1754         gl->MapImageCHROMIUM(resource->image_id, GL_READ_WRITE));
   1755   }
   1756 
   1757   if (resource->pixels)
   1758     return resource->pixels;
   1759 
   1760   return NULL;
   1761 }
   1762 
   1763 void ResourceProvider::UnmapImage(ResourceId id) {
   1764   Resource* resource = GetResource(id);
   1765   DCHECK(!resource->external);
   1766   DCHECK_EQ(resource->exported_count, 0);
   1767 
   1768   if (resource->image_id) {
   1769     GLES2Interface* gl = ContextGL();
   1770     DCHECK(gl);
   1771     gl->UnmapImageCHROMIUM(resource->image_id);
   1772     resource->dirty_image = true;
   1773   }
   1774 }
   1775 
   1776 int ResourceProvider::GetImageStride(ResourceId id) {
   1777   Resource* resource = GetResource(id);
   1778   DCHECK(!resource->external);
   1779   DCHECK_EQ(resource->exported_count, 0);
   1780 
   1781   int stride = 0;
   1782 
   1783   if (resource->image_id) {
   1784     GLES2Interface* gl = ContextGL();
   1785     DCHECK(gl);
   1786     gl->GetImageParameterivCHROMIUM(
   1787         resource->image_id, GL_IMAGE_ROWBYTES_CHROMIUM, &stride);
   1788   }
   1789 
   1790   return stride;
   1791 }
   1792 
   1793 base::SharedMemory* ResourceProvider::GetSharedMemory(ResourceId id) {
   1794   Resource* resource = GetResource(id);
   1795   DCHECK(!resource->external);
   1796   DCHECK_EQ(resource->exported_count, 0);
   1797 
   1798   if (!resource->shared_bitmap)
   1799     return NULL;
   1800   return resource->shared_bitmap->memory();
   1801 }
   1802 
   1803 GLint ResourceProvider::GetActiveTextureUnit(GLES2Interface* gl) {
   1804   GLint active_unit = 0;
   1805   gl->GetIntegerv(GL_ACTIVE_TEXTURE, &active_unit);
   1806   return active_unit;
   1807 }
   1808 
   1809 GLES2Interface* ResourceProvider::ContextGL() const {
   1810   ContextProvider* context_provider = output_surface_->context_provider();
   1811   return context_provider ? context_provider->ContextGL() : NULL;
   1812 }
   1813 
   1814 }  // namespace cc
   1815