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