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