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