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