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