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 <vector>
     12 
     13 #include "base/basictypes.h"
     14 #include "base/callback.h"
     15 #include "base/containers/hash_tables.h"
     16 #include "base/memory/scoped_ptr.h"
     17 #include "base/threading/thread_checker.h"
     18 #include "cc/base/cc_export.h"
     19 #include "cc/output/context_provider.h"
     20 #include "cc/output/output_surface.h"
     21 #include "cc/resources/texture_mailbox.h"
     22 #include "cc/resources/transferable_resource.h"
     23 #include "third_party/khronos/GLES2/gl2.h"
     24 #include "third_party/skia/include/core/SkBitmap.h"
     25 #include "third_party/skia/include/core/SkCanvas.h"
     26 #include "ui/gfx/size.h"
     27 
     28 namespace WebKit { class WebGraphicsContext3D; }
     29 
     30 namespace gfx {
     31 class Rect;
     32 class Vector2d;
     33 }
     34 
     35 namespace cc {
     36 class TextureUploader;
     37 
     38 // This class is not thread-safe and can only be called from the thread it was
     39 // created on (in practice, the impl thread).
     40 class CC_EXPORT ResourceProvider {
     41  public:
     42   typedef unsigned ResourceId;
     43   typedef std::vector<ResourceId> ResourceIdArray;
     44   typedef std::set<ResourceId> ResourceIdSet;
     45   typedef base::hash_map<ResourceId, ResourceId> ResourceIdMap;
     46   enum TextureUsageHint {
     47     TextureUsageAny,
     48     TextureUsageFramebuffer,
     49   };
     50   enum ResourceType {
     51     InvalidType = 0,
     52     GLTexture = 1,
     53     Bitmap,
     54   };
     55 
     56   static scoped_ptr<ResourceProvider> Create(OutputSurface* output_surface,
     57                                              int highp_threshold_min);
     58 
     59   virtual ~ResourceProvider();
     60 
     61   void InitializeSoftware();
     62   bool InitializeGL();
     63 
     64   void DidLoseOutputSurface() { lost_output_surface_ = true; }
     65 
     66   WebKit::WebGraphicsContext3D* GraphicsContext3D();
     67   int max_texture_size() const { return max_texture_size_; }
     68   GLenum best_texture_format() const { return best_texture_format_; }
     69   size_t num_resources() const { return resources_.size(); }
     70 
     71   // Checks whether a resource is in use by a consumer.
     72   bool InUseByConsumer(ResourceId id);
     73 
     74 
     75   // Producer interface.
     76 
     77   ResourceType default_resource_type() const { return default_resource_type_; }
     78   ResourceType GetResourceType(ResourceId id);
     79 
     80   // Creates a resource of the default resource type.
     81   ResourceId CreateResource(gfx::Size size,
     82                             GLenum format,
     83                             TextureUsageHint hint);
     84 
     85   // Creates a resource which is tagged as being managed for GPU memory
     86   // accounting purposes.
     87   ResourceId CreateManagedResource(gfx::Size size,
     88                                    GLenum format,
     89                                    TextureUsageHint hint);
     90 
     91   // You can also explicitly create a specific resource type.
     92   ResourceId CreateGLTexture(gfx::Size size,
     93                              GLenum format,
     94                              GLenum texture_pool,
     95                              TextureUsageHint hint);
     96 
     97   ResourceId CreateBitmap(gfx::Size size);
     98   // Wraps an external texture into a GL resource.
     99   ResourceId CreateResourceFromExternalTexture(
    100       unsigned texture_target,
    101       unsigned texture_id);
    102 
    103   // Wraps an external texture mailbox into a GL resource.
    104   ResourceId CreateResourceFromTextureMailbox(const TextureMailbox& mailbox);
    105 
    106   void DeleteResource(ResourceId id);
    107 
    108   // Update pixels from image, copying source_rect (in image) to dest_offset (in
    109   // the resource).
    110   void SetPixels(ResourceId id,
    111                  const uint8_t* image,
    112                  gfx::Rect image_rect,
    113                  gfx::Rect source_rect,
    114                  gfx::Vector2d dest_offset);
    115 
    116   // Check upload status.
    117   size_t NumBlockingUploads();
    118   void MarkPendingUploadsAsNonBlocking();
    119   double EstimatedUploadsPerSecond();
    120   void FlushUploads();
    121   void ReleaseCachedData();
    122 
    123   // Flush all context operations, kicking uploads and ensuring ordering with
    124   // respect to other contexts.
    125   void Flush();
    126 
    127   // Finish all context operations, causing any pending callbacks to be
    128   // scheduled.
    129   void Finish();
    130 
    131   // Only flush the command buffer if supported.
    132   // Returns true if the shallow flush occurred, false otherwise.
    133   bool ShallowFlushIfSupported();
    134 
    135   // Creates accounting for a child. Returns a child ID.
    136   int CreateChild();
    137 
    138   // Destroys accounting for the child, deleting all accounted resources.
    139   void DestroyChild(int child);
    140 
    141   // Gets the child->parent resource ID map.
    142   const ResourceIdMap& GetChildToParentMap(int child) const;
    143 
    144   // Prepares resources to be transfered to the parent, moving them to
    145   // mailboxes and serializing meta-data into TransferableResources.
    146   // Resources are not removed from the ResourceProvider, but are marked as
    147   // "in use".
    148   void PrepareSendToParent(const ResourceIdArray& resources,
    149                            TransferableResourceArray* transferable_resources);
    150 
    151   // Prepares resources to be transfered back to the child, moving them to
    152   // mailboxes and serializing meta-data into TransferableResources.
    153   // Resources are removed from the ResourceProvider. Note: the resource IDs
    154   // passed are in the parent namespace and will be translated to the child
    155   // namespace when returned.
    156   void PrepareSendToChild(int child,
    157                           const ResourceIdArray& resources,
    158                           TransferableResourceArray* transferable_resources);
    159 
    160   // Receives resources from a child, moving them from mailboxes. Resource IDs
    161   // passed are in the child namespace, and will be translated to the parent
    162   // namespace, added to the child->parent map.
    163   // NOTE: if the sync_point is set on any TransferableResource, this will
    164   // wait on it.
    165   void ReceiveFromChild(
    166       int child, const TransferableResourceArray& transferable_resources);
    167 
    168   // Receives resources from the parent, moving them from mailboxes. Resource
    169   // IDs passed are in the child namespace.
    170   // NOTE: if the sync_point is set on any TransferableResource, this will
    171   // wait on it.
    172   void ReceiveFromParent(
    173       const TransferableResourceArray& transferable_resources);
    174 
    175   // The following lock classes are part of the ResourceProvider API and are
    176   // needed to read and write the resource contents. The user must ensure
    177   // that they only use GL locks on GL resources, etc, and this is enforced
    178   // by assertions.
    179   class CC_EXPORT ScopedReadLockGL {
    180    public:
    181     ScopedReadLockGL(ResourceProvider* resource_provider,
    182                      ResourceProvider::ResourceId resource_id);
    183     virtual ~ScopedReadLockGL();
    184 
    185     unsigned texture_id() const { return texture_id_; }
    186 
    187    protected:
    188     ResourceProvider* resource_provider_;
    189     ResourceProvider::ResourceId resource_id_;
    190 
    191    private:
    192     unsigned texture_id_;
    193 
    194     DISALLOW_COPY_AND_ASSIGN(ScopedReadLockGL);
    195   };
    196 
    197   class CC_EXPORT ScopedSamplerGL : public ScopedReadLockGL {
    198    public:
    199     ScopedSamplerGL(ResourceProvider* resource_provider,
    200                     ResourceProvider::ResourceId resource_id,
    201                     GLenum target,
    202                     GLenum filter);
    203     ScopedSamplerGL(ResourceProvider* resource_provider,
    204                     ResourceProvider::ResourceId resource_id,
    205                     GLenum target,
    206                     GLenum unit,
    207                     GLenum filter);
    208     virtual ~ScopedSamplerGL();
    209 
    210    private:
    211     GLenum target_;
    212     GLenum unit_;
    213 
    214     DISALLOW_COPY_AND_ASSIGN(ScopedSamplerGL);
    215   };
    216 
    217   class CC_EXPORT ScopedWriteLockGL {
    218    public:
    219     ScopedWriteLockGL(ResourceProvider* resource_provider,
    220                       ResourceProvider::ResourceId resource_id);
    221     ~ScopedWriteLockGL();
    222 
    223     unsigned texture_id() const { return texture_id_; }
    224 
    225    private:
    226     ResourceProvider* resource_provider_;
    227     ResourceProvider::ResourceId resource_id_;
    228     unsigned texture_id_;
    229 
    230     DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockGL);
    231   };
    232 
    233   class CC_EXPORT ScopedReadLockSoftware {
    234    public:
    235     ScopedReadLockSoftware(ResourceProvider* resource_provider,
    236                            ResourceProvider::ResourceId resource_id);
    237     ~ScopedReadLockSoftware();
    238 
    239     const SkBitmap* sk_bitmap() const { return &sk_bitmap_; }
    240 
    241    private:
    242     ResourceProvider* resource_provider_;
    243     ResourceProvider::ResourceId resource_id_;
    244     SkBitmap sk_bitmap_;
    245 
    246     DISALLOW_COPY_AND_ASSIGN(ScopedReadLockSoftware);
    247   };
    248 
    249   class CC_EXPORT ScopedWriteLockSoftware {
    250    public:
    251     ScopedWriteLockSoftware(ResourceProvider* resource_provider,
    252                             ResourceProvider::ResourceId resource_id);
    253     ~ScopedWriteLockSoftware();
    254 
    255     SkCanvas* sk_canvas() { return sk_canvas_.get(); }
    256 
    257    private:
    258     ResourceProvider* resource_provider_;
    259     ResourceProvider::ResourceId resource_id_;
    260     SkBitmap sk_bitmap_;
    261     scoped_ptr<SkCanvas> sk_canvas_;
    262 
    263     DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockSoftware);
    264   };
    265 
    266   class Fence : public base::RefCounted<Fence> {
    267    public:
    268     Fence() {}
    269     virtual bool HasPassed() = 0;
    270 
    271    protected:
    272     friend class base::RefCounted<Fence>;
    273     virtual ~Fence() {}
    274 
    275    private:
    276     DISALLOW_COPY_AND_ASSIGN(Fence);
    277   };
    278 
    279   // Acquire pixel buffer for resource. The pixel buffer can be used to
    280   // set resource pixels without performing unnecessary copying.
    281   void AcquirePixelBuffer(ResourceId id);
    282   void ReleasePixelBuffer(ResourceId id);
    283 
    284   // Map/unmap the acquired pixel buffer.
    285   uint8_t* MapPixelBuffer(ResourceId id);
    286   void UnmapPixelBuffer(ResourceId id);
    287 
    288   // Asynchronously update pixels from acquired pixel buffer.
    289   void BeginSetPixels(ResourceId id);
    290   void ForceSetPixelsToComplete(ResourceId id);
    291   bool DidSetPixelsComplete(ResourceId id);
    292 
    293   // Acquire and release an image. The image allows direct
    294   // manipulation of texture memory.
    295   void AcquireImage(ResourceId id);
    296   void ReleaseImage(ResourceId id);
    297 
    298   // Maps the acquired image so that its pixels could be modified.
    299   // Unmap is called when all pixels are set.
    300   uint8_t* MapImage(ResourceId id);
    301   void UnmapImage(ResourceId id);
    302 
    303   // Returns the stride for the image.
    304   int GetImageStride(ResourceId id);
    305 
    306   // For tests only! This prevents detecting uninitialized reads.
    307   // Use SetPixels or LockForWrite to allocate implicitly.
    308   void AllocateForTesting(ResourceId id);
    309 
    310   // For tests only!
    311   void CreateForTesting(ResourceId id);
    312 
    313   // Sets the current read fence. If a resource is locked for read
    314   // and has read fences enabled, the resource will not allow writes
    315   // until this fence has passed.
    316   void SetReadLockFence(scoped_refptr<Fence> fence) {
    317     current_read_lock_fence_ = fence;
    318   }
    319   Fence* GetReadLockFence() { return current_read_lock_fence_.get(); }
    320 
    321   // Enable read lock fences for a specific resource.
    322   void EnableReadLockFences(ResourceProvider::ResourceId id, bool enable);
    323 
    324   // Indicates if we can currently lock this resource for write.
    325   bool CanLockForWrite(ResourceId id);
    326 
    327   cc::ContextProvider* offscreen_context_provider() {
    328     return offscreen_context_provider_.get();
    329   }
    330   void set_offscreen_context_provider(
    331       scoped_refptr<cc::ContextProvider> offscreen_context_provider) {
    332     offscreen_context_provider_ = offscreen_context_provider;
    333   }
    334   static GLint GetActiveTextureUnit(WebKit::WebGraphicsContext3D* context);
    335 
    336  private:
    337   struct Resource {
    338     Resource();
    339     ~Resource();
    340     Resource(unsigned texture_id,
    341              gfx::Size size,
    342              GLenum format,
    343              GLenum filter,
    344              GLenum texture_pool,
    345              TextureUsageHint hint);
    346     Resource(uint8_t* pixels, gfx::Size size, GLenum format, GLenum filter);
    347 
    348     unsigned gl_id;
    349     // Pixel buffer used for set pixels without unnecessary copying.
    350     unsigned gl_pixel_buffer_id;
    351     // Query used to determine when asynchronous set pixels complete.
    352     unsigned gl_upload_query_id;
    353     TextureMailbox mailbox;
    354     uint8_t* pixels;
    355     uint8_t* pixel_buffer;
    356     int lock_for_read_count;
    357     bool locked_for_write;
    358     bool external;
    359     bool exported;
    360     bool marked_for_deletion;
    361     bool pending_set_pixels;
    362     bool set_pixels_completion_forced;
    363     bool allocated;
    364     bool enable_read_lock_fences;
    365     scoped_refptr<Fence> read_lock_fence;
    366     gfx::Size size;
    367     GLenum format;
    368     // TODO(skyostil): Use a separate sampler object for filter state.
    369     GLenum filter;
    370     unsigned image_id;
    371     unsigned bound_image_id;
    372     bool dirty_image;
    373     GLenum texture_pool;
    374     TextureUsageHint hint;
    375     ResourceType type;
    376   };
    377   typedef base::hash_map<ResourceId, Resource> ResourceMap;
    378   struct Child {
    379     Child();
    380     ~Child();
    381 
    382     ResourceIdMap child_to_parent_map;
    383     ResourceIdMap parent_to_child_map;
    384   };
    385   typedef base::hash_map<int, Child> ChildMap;
    386 
    387   bool ReadLockFenceHasPassed(Resource* resource) {
    388     return !resource->read_lock_fence.get() ||
    389            resource->read_lock_fence->HasPassed();
    390   }
    391 
    392   explicit ResourceProvider(OutputSurface* output_surface,
    393                             int highp_threshold_min);
    394 
    395   void CleanUpGLIfNeeded();
    396 
    397   const Resource* LockForRead(ResourceId id);
    398   void UnlockForRead(ResourceId id);
    399   const Resource* LockForWrite(ResourceId id);
    400   void UnlockForWrite(ResourceId id);
    401   static void PopulateSkBitmapWithResource(SkBitmap* sk_bitmap,
    402                                            const Resource* resource);
    403 
    404   bool TransferResource(WebKit::WebGraphicsContext3D* context,
    405                         ResourceId id,
    406                         TransferableResource* resource);
    407   enum DeleteStyle {
    408     Normal,
    409     ForShutdown,
    410   };
    411   void DeleteResourceInternal(ResourceMap::iterator it, DeleteStyle style);
    412   void LazyCreate(Resource* resource);
    413   void LazyAllocate(Resource* resource);
    414 
    415   // Binds the given GL resource to a texture target for sampling using the
    416   // specified filter for both minification and magnification. The resource
    417   // must be locked for reading.
    418   void BindForSampling(ResourceProvider::ResourceId resource_id,
    419                        GLenum target,
    420                        GLenum unit,
    421                        GLenum filter);
    422 
    423   OutputSurface* output_surface_;
    424   bool lost_output_surface_;
    425   int highp_threshold_min_;
    426   ResourceId next_id_;
    427   ResourceMap resources_;
    428   int next_child_;
    429   ChildMap children_;
    430 
    431   ResourceType default_resource_type_;
    432   bool use_texture_storage_ext_;
    433   bool use_texture_usage_hint_;
    434   bool use_shallow_flush_;
    435   scoped_ptr<TextureUploader> texture_uploader_;
    436   int max_texture_size_;
    437   GLenum best_texture_format_;
    438 
    439   scoped_refptr<cc::ContextProvider> offscreen_context_provider_;
    440 
    441   base::ThreadChecker thread_checker_;
    442 
    443   scoped_refptr<Fence> current_read_lock_fence_;
    444 
    445   DISALLOW_COPY_AND_ASSIGN(ResourceProvider);
    446 };
    447 
    448 }  // namespace cc
    449 
    450 #endif  // CC_RESOURCES_RESOURCE_PROVIDER_H_
    451