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