• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
DidLoseOutputSurface()80   void DidLoseOutputSurface() { lost_output_surface_ = true; }
81 
max_texture_size()82   int max_texture_size() const { return max_texture_size_; }
memory_efficient_texture_format()83   ResourceFormat memory_efficient_texture_format() const {
84     return use_rgba_4444_texture_format_ ? RGBA_4444 : best_texture_format_;
85   }
best_texture_format()86   ResourceFormat best_texture_format() const { return best_texture_format_; }
num_resources()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 
default_resource_type()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 
texture_id()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 
target()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 
texture_id()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 
sk_bitmap()268     const SkBitmap* sk_bitmap() const { return &sk_bitmap_; }
wrap_mode()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 
sk_canvas()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:
Fence()299     Fence() {}
300     virtual bool HasPassed() = 0;
301 
302    protected:
303     friend class base::RefCounted<Fence>;
~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.
SetReadLockFence(scoped_refptr<Fence> fence)351   void SetReadLockFence(scoped_refptr<Fence> fence) {
352     current_read_lock_fence_ = fence;
353   }
GetReadLockFence()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 
ReadLockFenceHasPassed(Resource * resource)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).
BitsPerPixel(ResourceFormat format)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 
GLDataType(ResourceFormat format)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 
GLDataFormat(ResourceFormat format)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 
GLInternalFormat(ResourceFormat format)554 inline GLenum GLInternalFormat(ResourceFormat format) {
555   return GLDataFormat(format);
556 }
557 
558 }  // namespace cc
559 
560 #endif  // CC_RESOURCES_RESOURCE_PROVIDER_H_
561