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