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