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
28namespace WebKit { class WebGraphicsContext3D; }
29
30namespace gfx {
31class Rect;
32class Vector2d;
33}
34
35namespace cc {
36class 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).
40class 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    GLenum texture_pool;
372    TextureUsageHint hint;
373    ResourceType type;
374  };
375  typedef base::hash_map<ResourceId, Resource> ResourceMap;
376  struct Child {
377    Child();
378    ~Child();
379
380    ResourceIdMap child_to_parent_map;
381    ResourceIdMap parent_to_child_map;
382  };
383  typedef base::hash_map<int, Child> ChildMap;
384
385  bool ReadLockFenceHasPassed(Resource* resource) {
386    return !resource->read_lock_fence.get() ||
387           resource->read_lock_fence->HasPassed();
388  }
389
390  explicit ResourceProvider(OutputSurface* output_surface,
391                            int highp_threshold_min);
392
393  void CleanUpGLIfNeeded();
394
395  const Resource* LockForRead(ResourceId id);
396  void UnlockForRead(ResourceId id);
397  const Resource* LockForWrite(ResourceId id);
398  void UnlockForWrite(ResourceId id);
399  static void PopulateSkBitmapWithResource(SkBitmap* sk_bitmap,
400                                           const Resource* resource);
401
402  bool TransferResource(WebKit::WebGraphicsContext3D* context,
403                        ResourceId id,
404                        TransferableResource* resource);
405  enum DeleteStyle {
406    Normal,
407    ForShutdown,
408  };
409  void DeleteResourceInternal(ResourceMap::iterator it, DeleteStyle style);
410  void LazyCreate(Resource* resource);
411  void LazyAllocate(Resource* resource);
412
413  // Binds the given GL resource to a texture target for sampling using the
414  // specified filter for both minification and magnification. The resource
415  // must be locked for reading.
416  void BindForSampling(ResourceProvider::ResourceId resource_id,
417                       GLenum target,
418                       GLenum unit,
419                       GLenum filter);
420  void UnbindForSampling(ResourceProvider::ResourceId resource_id,
421                         GLenum target,
422                         GLenum unit);
423
424  OutputSurface* output_surface_;
425  bool lost_output_surface_;
426  int highp_threshold_min_;
427  ResourceId next_id_;
428  ResourceMap resources_;
429  int next_child_;
430  ChildMap children_;
431
432  ResourceType default_resource_type_;
433  bool use_texture_storage_ext_;
434  bool use_texture_usage_hint_;
435  bool use_shallow_flush_;
436  scoped_ptr<TextureUploader> texture_uploader_;
437  int max_texture_size_;
438  GLenum best_texture_format_;
439
440  scoped_refptr<cc::ContextProvider> offscreen_context_provider_;
441
442  base::ThreadChecker thread_checker_;
443
444  scoped_refptr<Fence> current_read_lock_fence_;
445
446  DISALLOW_COPY_AND_ASSIGN(ResourceProvider);
447};
448
449}  // namespace cc
450
451#endif  // CC_RESOURCES_RESOURCE_PROVIDER_H_
452