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