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 28 namespace WebKit { class WebGraphicsContext3D; } 29 30 namespace gfx { 31 class Rect; 32 class Vector2d; 33 } 34 35 namespace cc { 36 class 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). 40 class 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