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