Home | History | Annotate | Download | only in resources
      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 #ifndef CC_RESOURCES_RESOURCE_PROVIDER_H_
      6 #define CC_RESOURCES_RESOURCE_PROVIDER_H_
      7 
      8 #include <deque>
      9 #include <set>
     10 #include <string>
     11 #include <utility>
     12 #include <vector>
     13 
     14 #include "base/basictypes.h"
     15 #include "base/callback.h"
     16 #include "base/containers/hash_tables.h"
     17 #include "base/memory/linked_ptr.h"
     18 #include "base/memory/scoped_ptr.h"
     19 #include "base/threading/thread_checker.h"
     20 #include "cc/base/cc_export.h"
     21 #include "cc/output/context_provider.h"
     22 #include "cc/output/output_surface.h"
     23 #include "cc/resources/release_callback_impl.h"
     24 #include "cc/resources/resource_format.h"
     25 #include "cc/resources/return_callback.h"
     26 #include "cc/resources/shared_bitmap.h"
     27 #include "cc/resources/single_release_callback_impl.h"
     28 #include "cc/resources/texture_mailbox.h"
     29 #include "cc/resources/transferable_resource.h"
     30 #include "third_party/khronos/GLES2/gl2.h"
     31 #include "third_party/khronos/GLES2/gl2ext.h"
     32 #include "third_party/skia/include/core/SkBitmap.h"
     33 #include "third_party/skia/include/core/SkCanvas.h"
     34 #include "ui/gfx/size.h"
     35 
     36 class GrContext;
     37 
     38 namespace gpu {
     39 namespace gles {
     40 class GLES2Interface;
     41 }
     42 }
     43 
     44 namespace gfx {
     45 class Rect;
     46 class Vector2d;
     47 }
     48 
     49 namespace cc {
     50 class BlockingTaskRunner;
     51 class IdAllocator;
     52 class SharedBitmap;
     53 class SharedBitmapManager;
     54 class TextureUploader;
     55 
     56 // This class is not thread-safe and can only be called from the thread it was
     57 // created on (in practice, the impl thread).
     58 class CC_EXPORT ResourceProvider {
     59  public:
     60   typedef unsigned ResourceId;
     61   typedef std::vector<ResourceId> ResourceIdArray;
     62   typedef std::set<ResourceId> ResourceIdSet;
     63   typedef base::hash_map<ResourceId, ResourceId> ResourceIdMap;
     64   enum TextureHint {
     65     TextureHintDefault = 0x0,
     66     TextureHintImmutable = 0x1,
     67     TextureHintFramebuffer = 0x2,
     68     TextureHintImmutableFramebuffer =
     69         TextureHintImmutable | TextureHintFramebuffer
     70   };
     71   enum ResourceType {
     72     InvalidType = 0,
     73     GLTexture = 1,
     74     Bitmap,
     75   };
     76 
     77   static scoped_ptr<ResourceProvider> Create(
     78       OutputSurface* output_surface,
     79       SharedBitmapManager* shared_bitmap_manager,
     80       BlockingTaskRunner* blocking_main_thread_task_runner,
     81       int highp_threshold_min,
     82       bool use_rgba_4444_texture_format,
     83       size_t id_allocation_chunk_size,
     84       bool use_distance_field_text);
     85   virtual ~ResourceProvider();
     86 
     87   void InitializeSoftware();
     88   void InitializeGL();
     89 
     90   void DidLoseOutputSurface() { lost_output_surface_ = true; }
     91 
     92   int max_texture_size() const { return max_texture_size_; }
     93   ResourceFormat memory_efficient_texture_format() const {
     94     return use_rgba_4444_texture_format_ ? RGBA_4444 : best_texture_format_;
     95   }
     96   ResourceFormat best_texture_format() const { return best_texture_format_; }
     97   bool use_sync_query() const { return use_sync_query_; }
     98   size_t num_resources() const { return resources_.size(); }
     99 
    100   // Checks whether a resource is in use by a consumer.
    101   bool InUseByConsumer(ResourceId id);
    102 
    103   bool IsLost(ResourceId id);
    104   bool AllowOverlay(ResourceId id);
    105 
    106   // Producer interface.
    107 
    108   ResourceType default_resource_type() const { return default_resource_type_; }
    109   ResourceType GetResourceType(ResourceId id);
    110 
    111   // Creates a resource of the default resource type.
    112   ResourceId CreateResource(const gfx::Size& size,
    113                             GLint wrap_mode,
    114                             TextureHint hint,
    115                             ResourceFormat format);
    116 
    117   // Creates a resource which is tagged as being managed for GPU memory
    118   // accounting purposes.
    119   ResourceId CreateManagedResource(const gfx::Size& size,
    120                                    GLenum target,
    121                                    GLint wrap_mode,
    122                                    TextureHint hint,
    123                                    ResourceFormat format);
    124 
    125   // You can also explicitly create a specific resource type.
    126   ResourceId CreateGLTexture(const gfx::Size& size,
    127                              GLenum target,
    128                              GLenum texture_pool,
    129                              GLint wrap_mode,
    130                              TextureHint hint,
    131                              ResourceFormat format);
    132 
    133   ResourceId CreateBitmap(const gfx::Size& size, GLint wrap_mode);
    134   // Wraps an IOSurface into a GL resource.
    135   ResourceId CreateResourceFromIOSurface(const gfx::Size& size,
    136                                          unsigned io_surface_id);
    137 
    138   // Wraps an external texture mailbox into a GL resource.
    139   ResourceId CreateResourceFromTextureMailbox(
    140       const TextureMailbox& mailbox,
    141       scoped_ptr<SingleReleaseCallbackImpl> release_callback_impl);
    142 
    143   void DeleteResource(ResourceId id);
    144 
    145   // Update pixels from image, copying source_rect (in image) to dest_offset (in
    146   // the resource).
    147   void SetPixels(ResourceId id,
    148                  const uint8_t* image,
    149                  const gfx::Rect& image_rect,
    150                  const gfx::Rect& source_rect,
    151                  const gfx::Vector2d& dest_offset);
    152 
    153   // Check upload status.
    154   size_t NumBlockingUploads();
    155   void MarkPendingUploadsAsNonBlocking();
    156   size_t EstimatedUploadsPerTick();
    157   void FlushUploads();
    158   void ReleaseCachedData();
    159   base::TimeTicks EstimatedUploadCompletionTime(size_t uploads_per_tick);
    160 
    161   // Only flush the command buffer if supported.
    162   // Returns true if the shallow flush occurred, false otherwise.
    163   bool ShallowFlushIfSupported();
    164 
    165   // Creates accounting for a child. Returns a child ID.
    166   int CreateChild(const ReturnCallback& return_callback);
    167 
    168   // Destroys accounting for the child, deleting all accounted resources.
    169   void DestroyChild(int child);
    170 
    171   // Gets the child->parent resource ID map.
    172   const ResourceIdMap& GetChildToParentMap(int child) const;
    173 
    174   // Prepares resources to be transfered to the parent, moving them to
    175   // mailboxes and serializing meta-data into TransferableResources.
    176   // Resources are not removed from the ResourceProvider, but are marked as
    177   // "in use".
    178   void PrepareSendToParent(const ResourceIdArray& resources,
    179                            TransferableResourceArray* transferable_resources);
    180 
    181   // Receives resources from a child, moving them from mailboxes. Resource IDs
    182   // passed are in the child namespace, and will be translated to the parent
    183   // namespace, added to the child->parent map.
    184   // This adds the resources to the working set in the ResourceProvider without
    185   // declaring which resources are in use. Use DeclareUsedResourcesFromChild
    186   // after calling this method to do that. All calls to ReceiveFromChild should
    187   // be followed by a DeclareUsedResourcesFromChild.
    188   // NOTE: if the sync_point is set on any TransferableResource, this will
    189   // wait on it.
    190   void ReceiveFromChild(
    191       int child, const TransferableResourceArray& transferable_resources);
    192 
    193   // Once a set of resources have been received, they may or may not be used.
    194   // This declares what set of resources are currently in use from the child,
    195   // releasing any other resources back to the child.
    196   void DeclareUsedResourcesFromChild(
    197       int child,
    198       const ResourceIdArray& resources_from_child);
    199 
    200   // Receives resources from the parent, moving them from mailboxes. Resource
    201   // IDs passed are in the child namespace.
    202   // NOTE: if the sync_point is set on any TransferableResource, this will
    203   // wait on it.
    204   void ReceiveReturnsFromParent(
    205       const ReturnedResourceArray& transferable_resources);
    206 
    207   // The following lock classes are part of the ResourceProvider API and are
    208   // needed to read and write the resource contents. The user must ensure
    209   // that they only use GL locks on GL resources, etc, and this is enforced
    210   // by assertions.
    211   class CC_EXPORT ScopedReadLockGL {
    212    public:
    213     ScopedReadLockGL(ResourceProvider* resource_provider,
    214                      ResourceProvider::ResourceId resource_id);
    215     virtual ~ScopedReadLockGL();
    216 
    217     unsigned texture_id() const { return texture_id_; }
    218 
    219    protected:
    220     ResourceProvider* resource_provider_;
    221     ResourceProvider::ResourceId resource_id_;
    222 
    223    private:
    224     unsigned texture_id_;
    225 
    226     DISALLOW_COPY_AND_ASSIGN(ScopedReadLockGL);
    227   };
    228 
    229   class CC_EXPORT ScopedSamplerGL : public ScopedReadLockGL {
    230    public:
    231     ScopedSamplerGL(ResourceProvider* resource_provider,
    232                     ResourceProvider::ResourceId resource_id,
    233                     GLenum filter);
    234     ScopedSamplerGL(ResourceProvider* resource_provider,
    235                     ResourceProvider::ResourceId resource_id,
    236                     GLenum unit,
    237                     GLenum filter);
    238     virtual ~ScopedSamplerGL();
    239 
    240     GLenum target() const { return target_; }
    241 
    242    private:
    243     GLenum unit_;
    244     GLenum target_;
    245 
    246     DISALLOW_COPY_AND_ASSIGN(ScopedSamplerGL);
    247   };
    248 
    249   class CC_EXPORT ScopedWriteLockGL {
    250    public:
    251     ScopedWriteLockGL(ResourceProvider* resource_provider,
    252                       ResourceProvider::ResourceId resource_id);
    253     ~ScopedWriteLockGL();
    254 
    255     unsigned texture_id() const { return texture_id_; }
    256 
    257    private:
    258     ResourceProvider* resource_provider_;
    259     ResourceProvider::ResourceId resource_id_;
    260     unsigned texture_id_;
    261 
    262     DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockGL);
    263   };
    264 
    265   class CC_EXPORT ScopedReadLockSoftware {
    266    public:
    267     ScopedReadLockSoftware(ResourceProvider* resource_provider,
    268                            ResourceProvider::ResourceId resource_id);
    269     ~ScopedReadLockSoftware();
    270 
    271     const SkBitmap* sk_bitmap() const {
    272       DCHECK(valid());
    273       return &sk_bitmap_;
    274     }
    275     GLint wrap_mode() const { return wrap_mode_; }
    276 
    277     bool valid() const { return !!sk_bitmap_.getPixels(); }
    278 
    279    private:
    280     ResourceProvider* resource_provider_;
    281     ResourceProvider::ResourceId resource_id_;
    282     SkBitmap sk_bitmap_;
    283     GLint wrap_mode_;
    284 
    285     DISALLOW_COPY_AND_ASSIGN(ScopedReadLockSoftware);
    286   };
    287 
    288   class CC_EXPORT ScopedWriteLockSoftware {
    289    public:
    290     ScopedWriteLockSoftware(ResourceProvider* resource_provider,
    291                             ResourceProvider::ResourceId resource_id);
    292     ~ScopedWriteLockSoftware();
    293 
    294     SkCanvas* sk_canvas() { return sk_canvas_.get(); }
    295     bool valid() const { return !!sk_bitmap_.getPixels(); }
    296 
    297    private:
    298     ResourceProvider* resource_provider_;
    299     ResourceProvider::ResourceId resource_id_;
    300     SkBitmap sk_bitmap_;
    301     scoped_ptr<SkCanvas> sk_canvas_;
    302 
    303     DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockSoftware);
    304   };
    305 
    306   class Fence : public base::RefCounted<Fence> {
    307    public:
    308     Fence() {}
    309 
    310     virtual void Set() = 0;
    311     virtual bool HasPassed() = 0;
    312 
    313    protected:
    314     friend class base::RefCounted<Fence>;
    315     virtual ~Fence() {}
    316 
    317    private:
    318     DISALLOW_COPY_AND_ASSIGN(Fence);
    319   };
    320 
    321   // Acquire pixel buffer for resource. The pixel buffer can be used to
    322   // set resource pixels without performing unnecessary copying.
    323   void AcquirePixelBuffer(ResourceId resource);
    324   void ReleasePixelBuffer(ResourceId resource);
    325   // Map/unmap the acquired pixel buffer.
    326   uint8_t* MapPixelBuffer(ResourceId id, int* stride);
    327   void UnmapPixelBuffer(ResourceId id);
    328   // Asynchronously update pixels from acquired pixel buffer.
    329   void BeginSetPixels(ResourceId id);
    330   void ForceSetPixelsToComplete(ResourceId id);
    331   bool DidSetPixelsComplete(ResourceId id);
    332 
    333   // Acquire and release an image. The image allows direct
    334   // manipulation of texture memory.
    335   void AcquireImage(ResourceId id);
    336   void ReleaseImage(ResourceId id);
    337   // Maps the acquired image so that its pixels could be modified.
    338   // Unmap is called when all pixels are set.
    339   uint8_t* MapImage(ResourceId id, int* stride);
    340   void UnmapImage(ResourceId id);
    341 
    342   // Acquire and release a SkSurface.
    343   void AcquireSkSurface(ResourceId id);
    344   void ReleaseSkSurface(ResourceId id);
    345   // Lock/unlock resource for writing to SkSurface.
    346   SkSurface* LockForWriteToSkSurface(ResourceId id);
    347   void UnlockForWriteToSkSurface(ResourceId id);
    348 
    349   // For tests only! This prevents detecting uninitialized reads.
    350   // Use SetPixels or LockForWrite to allocate implicitly.
    351   void AllocateForTesting(ResourceId id);
    352 
    353   // For tests only!
    354   void CreateForTesting(ResourceId id);
    355 
    356   GLenum TargetForTesting(ResourceId id);
    357 
    358   // Sets the current read fence. If a resource is locked for read
    359   // and has read fences enabled, the resource will not allow writes
    360   // until this fence has passed.
    361   void SetReadLockFence(Fence* fence) { current_read_lock_fence_ = fence; }
    362 
    363   // Enable read lock fences for a specific resource.
    364   void EnableReadLockFences(ResourceId id);
    365 
    366   // Indicates if we can currently lock this resource for write.
    367   bool CanLockForWrite(ResourceId id);
    368 
    369   // Copy pixels from source to destination.
    370   void CopyResource(ResourceId source_id, ResourceId dest_id);
    371 
    372   void WaitSyncPointIfNeeded(ResourceId id);
    373 
    374   static GLint GetActiveTextureUnit(gpu::gles2::GLES2Interface* gl);
    375 
    376  private:
    377   struct Resource {
    378     enum Origin { Internal, External, Delegated };
    379 
    380     Resource();
    381     ~Resource();
    382     Resource(unsigned texture_id,
    383              const gfx::Size& size,
    384              Origin origin,
    385              GLenum target,
    386              GLenum filter,
    387              GLenum texture_pool,
    388              GLint wrap_mode,
    389              TextureHint hint,
    390              ResourceFormat format);
    391     Resource(uint8_t* pixels,
    392              SharedBitmap* bitmap,
    393              const gfx::Size& size,
    394              Origin origin,
    395              GLenum filter,
    396              GLint wrap_mode);
    397     Resource(const SharedBitmapId& bitmap_id,
    398              const gfx::Size& size,
    399              Origin origin,
    400              GLenum filter,
    401              GLint wrap_mode);
    402 
    403     int child_id;
    404     unsigned gl_id;
    405     // Pixel buffer used for set pixels without unnecessary copying.
    406     unsigned gl_pixel_buffer_id;
    407     // Query used to determine when asynchronous set pixels complete.
    408     unsigned gl_upload_query_id;
    409     // Query used to determine when read lock fence has passed.
    410     unsigned gl_read_lock_query_id;
    411     TextureMailbox mailbox;
    412     ReleaseCallbackImpl release_callback_impl;
    413     uint8_t* pixels;
    414     int lock_for_read_count;
    415     int imported_count;
    416     int exported_count;
    417     bool dirty_image : 1;
    418     bool locked_for_write : 1;
    419     bool lost : 1;
    420     bool marked_for_deletion : 1;
    421     bool pending_set_pixels : 1;
    422     bool set_pixels_completion_forced : 1;
    423     bool allocated : 1;
    424     bool read_lock_fences_enabled : 1;
    425     bool has_shared_bitmap_id : 1;
    426     bool allow_overlay : 1;
    427     scoped_refptr<Fence> read_lock_fence;
    428     gfx::Size size;
    429     Origin origin;
    430     GLenum target;
    431     // TODO(skyostil): Use a separate sampler object for filter state.
    432     GLenum original_filter;
    433     GLenum filter;
    434     unsigned image_id;
    435     unsigned bound_image_id;
    436     GLenum texture_pool;
    437     GLint wrap_mode;
    438     TextureHint hint;
    439     ResourceType type;
    440     ResourceFormat format;
    441     SharedBitmapId shared_bitmap_id;
    442     SharedBitmap* shared_bitmap;
    443     skia::RefPtr<SkSurface> sk_surface;
    444   };
    445   typedef base::hash_map<ResourceId, Resource> ResourceMap;
    446 
    447   static bool CompareResourceMapIteratorsByChildId(
    448       const std::pair<ReturnedResource, ResourceMap::iterator>& a,
    449       const std::pair<ReturnedResource, ResourceMap::iterator>& b);
    450 
    451   struct Child {
    452     Child();
    453     ~Child();
    454 
    455     ResourceIdMap child_to_parent_map;
    456     ResourceIdMap parent_to_child_map;
    457     ReturnCallback return_callback;
    458     ResourceIdSet in_use_resources;
    459     bool marked_for_deletion;
    460   };
    461   typedef base::hash_map<int, Child> ChildMap;
    462 
    463   bool ReadLockFenceHasPassed(const Resource* resource) {
    464     return !resource->read_lock_fence.get() ||
    465            resource->read_lock_fence->HasPassed();
    466   }
    467 
    468   ResourceProvider(OutputSurface* output_surface,
    469                    SharedBitmapManager* shared_bitmap_manager,
    470                    BlockingTaskRunner* blocking_main_thread_task_runner,
    471                    int highp_threshold_min,
    472                    bool use_rgba_4444_texture_format,
    473                    size_t id_allocation_chunk_size,
    474                    bool use_distance_field_text);
    475 
    476   void CleanUpGLIfNeeded();
    477 
    478   Resource* GetResource(ResourceId id);
    479   const Resource* LockForRead(ResourceId id);
    480   void UnlockForRead(ResourceId id);
    481   const Resource* LockForWrite(ResourceId id);
    482   void UnlockForWrite(ResourceId id);
    483   static void PopulateSkBitmapWithResource(SkBitmap* sk_bitmap,
    484                                            const Resource* resource);
    485 
    486   void TransferResource(gpu::gles2::GLES2Interface* gl,
    487                         ResourceId id,
    488                         TransferableResource* resource);
    489   enum DeleteStyle {
    490     Normal,
    491     ForShutdown,
    492   };
    493   void DeleteResourceInternal(ResourceMap::iterator it, DeleteStyle style);
    494   void DeleteAndReturnUnusedResourcesToChild(ChildMap::iterator child_it,
    495                                              DeleteStyle style,
    496                                              const ResourceIdArray& unused);
    497   void DestroyChildInternal(ChildMap::iterator it, DeleteStyle style);
    498   void LazyCreate(Resource* resource);
    499   void LazyAllocate(Resource* resource);
    500 
    501   void BindImageForSampling(Resource* resource);
    502   // Binds the given GL resource to a texture target for sampling using the
    503   // specified filter for both minification and magnification. Returns the
    504   // texture target used. The resource must be locked for reading.
    505   GLenum BindForSampling(ResourceId resource_id, GLenum unit, GLenum filter);
    506 
    507   // Returns NULL if the output_surface_ does not have a ContextProvider.
    508   gpu::gles2::GLES2Interface* ContextGL() const;
    509   class GrContext* GrContext() const;
    510 
    511   OutputSurface* output_surface_;
    512   SharedBitmapManager* shared_bitmap_manager_;
    513   BlockingTaskRunner* blocking_main_thread_task_runner_;
    514   bool lost_output_surface_;
    515   int highp_threshold_min_;
    516   ResourceId next_id_;
    517   ResourceMap resources_;
    518   int next_child_;
    519   ChildMap children_;
    520 
    521   ResourceType default_resource_type_;
    522   bool use_texture_storage_ext_;
    523   bool use_texture_format_bgra_;
    524   bool use_texture_usage_hint_;
    525   bool use_compressed_texture_etc1_;
    526   scoped_ptr<TextureUploader> texture_uploader_;
    527   int max_texture_size_;
    528   ResourceFormat best_texture_format_;
    529 
    530   base::ThreadChecker thread_checker_;
    531 
    532   scoped_refptr<Fence> current_read_lock_fence_;
    533   bool use_rgba_4444_texture_format_;
    534 
    535   const size_t id_allocation_chunk_size_;
    536   scoped_ptr<IdAllocator> texture_id_allocator_;
    537   scoped_ptr<IdAllocator> buffer_id_allocator_;
    538 
    539   bool use_sync_query_;
    540 
    541   bool use_distance_field_text_;
    542 
    543   DISALLOW_COPY_AND_ASSIGN(ResourceProvider);
    544 };
    545 
    546 
    547 // TODO(epenner): Move these format conversions to resource_format.h
    548 // once that builds on mac (npapi.h currently #includes OpenGL.h).
    549 inline unsigned BitsPerPixel(ResourceFormat format) {
    550   DCHECK_LE(format, RESOURCE_FORMAT_MAX);
    551   static const unsigned format_bits_per_pixel[RESOURCE_FORMAT_MAX + 1] = {
    552     32,  // RGBA_8888
    553     16,  // RGBA_4444
    554     32,  // BGRA_8888
    555     8,   // ALPHA_8
    556     8,   // LUMINANCE_8
    557     16,  // RGB_565,
    558     4    // ETC1
    559   };
    560   return format_bits_per_pixel[format];
    561 }
    562 
    563 inline GLenum GLDataType(ResourceFormat format) {
    564   DCHECK_LE(format, RESOURCE_FORMAT_MAX);
    565   static const unsigned format_gl_data_type[RESOURCE_FORMAT_MAX + 1] = {
    566     GL_UNSIGNED_BYTE,           // RGBA_8888
    567     GL_UNSIGNED_SHORT_4_4_4_4,  // RGBA_4444
    568     GL_UNSIGNED_BYTE,           // BGRA_8888
    569     GL_UNSIGNED_BYTE,           // ALPHA_8
    570     GL_UNSIGNED_BYTE,           // LUMINANCE_8
    571     GL_UNSIGNED_SHORT_5_6_5,    // RGB_565,
    572     GL_UNSIGNED_BYTE            // ETC1
    573   };
    574   return format_gl_data_type[format];
    575 }
    576 
    577 inline GLenum GLDataFormat(ResourceFormat format) {
    578   DCHECK_LE(format, RESOURCE_FORMAT_MAX);
    579   static const unsigned format_gl_data_format[RESOURCE_FORMAT_MAX + 1] = {
    580     GL_RGBA,           // RGBA_8888
    581     GL_RGBA,           // RGBA_4444
    582     GL_BGRA_EXT,       // BGRA_8888
    583     GL_ALPHA,          // ALPHA_8
    584     GL_LUMINANCE,      // LUMINANCE_8
    585     GL_RGB,            // RGB_565
    586     GL_ETC1_RGB8_OES   // ETC1
    587   };
    588   return format_gl_data_format[format];
    589 }
    590 
    591 inline GLenum GLInternalFormat(ResourceFormat format) {
    592   return GLDataFormat(format);
    593 }
    594 
    595 }  // namespace cc
    596 
    597 #endif  // CC_RESOURCES_RESOURCE_PROVIDER_H_
    598