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 34namespace gpu { 35namespace gles { 36class GLES2Interface; 37} 38} 39 40namespace gfx { 41class Rect; 42class Vector2d; 43} 44 45namespace cc { 46class IdAllocator; 47class SharedBitmap; 48class SharedBitmapManager; 49class 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). 53class 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 80 void DidLoseOutputSurface() { lost_output_surface_ = true; } 81 82 int max_texture_size() const { return max_texture_size_; } 83 ResourceFormat memory_efficient_texture_format() const { 84 return use_rgba_4444_texture_format_ ? RGBA_4444 : best_texture_format_; 85 } 86 ResourceFormat best_texture_format() const { return best_texture_format_; } 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 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 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 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 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 268 const SkBitmap* sk_bitmap() const { return &sk_bitmap_; } 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 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: 299 Fence() {} 300 virtual bool HasPassed() = 0; 301 302 protected: 303 friend class base::RefCounted<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. 351 void SetReadLockFence(scoped_refptr<Fence> fence) { 352 current_read_lock_fence_ = fence; 353 } 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 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). 515inline 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 528inline 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 541inline 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 554inline GLenum GLInternalFormat(ResourceFormat format) { 555 return GLDataFormat(format); 556} 557 558} // namespace cc 559 560#endif // CC_RESOURCES_RESOURCE_PROVIDER_H_ 561