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#include "cc/resources/resource_provider.h" 6 7#include <algorithm> 8#include <limits> 9 10#include "base/containers/hash_tables.h" 11#include "base/debug/trace_event.h" 12#include "base/stl_util.h" 13#include "base/strings/string_split.h" 14#include "base/strings/string_util.h" 15#include "cc/base/util.h" 16#include "cc/output/gl_renderer.h" // For the GLC() macro. 17#include "cc/resources/platform_color.h" 18#include "cc/resources/returned_resource.h" 19#include "cc/resources/shared_bitmap_manager.h" 20#include "cc/resources/texture_uploader.h" 21#include "cc/resources/transferable_resource.h" 22#include "gpu/GLES2/gl2extchromium.h" 23#include "gpu/command_buffer/client/gles2_interface.h" 24#include "third_party/khronos/GLES2/gl2.h" 25#include "third_party/khronos/GLES2/gl2ext.h" 26#include "third_party/skia/include/core/SkSurface.h" 27#include "third_party/skia/include/gpu/GrContext.h" 28#include "ui/gfx/frame_time.h" 29#include "ui/gfx/rect.h" 30#include "ui/gfx/vector2d.h" 31 32using gpu::gles2::GLES2Interface; 33 34namespace cc { 35 36class IdAllocator { 37 public: 38 virtual ~IdAllocator() {} 39 40 virtual GLuint NextId() = 0; 41 42 protected: 43 IdAllocator(GLES2Interface* gl, size_t id_allocation_chunk_size) 44 : gl_(gl), 45 id_allocation_chunk_size_(id_allocation_chunk_size), 46 ids_(new GLuint[id_allocation_chunk_size]), 47 next_id_index_(id_allocation_chunk_size) { 48 DCHECK(id_allocation_chunk_size_); 49 } 50 51 GLES2Interface* gl_; 52 const size_t id_allocation_chunk_size_; 53 scoped_ptr<GLuint[]> ids_; 54 size_t next_id_index_; 55}; 56 57namespace { 58 59// Measured in seconds. 60const double kSoftwareUploadTickRate = 0.000250; 61const double kTextureUploadTickRate = 0.004; 62 63GLenum TextureToStorageFormat(ResourceFormat format) { 64 GLenum storage_format = GL_RGBA8_OES; 65 switch (format) { 66 case RGBA_8888: 67 break; 68 case BGRA_8888: 69 storage_format = GL_BGRA8_EXT; 70 break; 71 case RGBA_4444: 72 case ALPHA_8: 73 case LUMINANCE_8: 74 case RGB_565: 75 case ETC1: 76 NOTREACHED(); 77 break; 78 } 79 80 return storage_format; 81} 82 83bool IsFormatSupportedForStorage(ResourceFormat format, bool use_bgra) { 84 switch (format) { 85 case RGBA_8888: 86 return true; 87 case BGRA_8888: 88 return use_bgra; 89 case RGBA_4444: 90 case ALPHA_8: 91 case LUMINANCE_8: 92 case RGB_565: 93 case ETC1: 94 return false; 95 } 96 return false; 97} 98 99GrPixelConfig ToGrPixelConfig(ResourceFormat format) { 100 switch (format) { 101 case RGBA_8888: 102 return kRGBA_8888_GrPixelConfig; 103 case BGRA_8888: 104 return kBGRA_8888_GrPixelConfig; 105 case RGBA_4444: 106 return kRGBA_4444_GrPixelConfig; 107 default: 108 break; 109 } 110 DCHECK(false) << "Unsupported resource format."; 111 return kSkia8888_GrPixelConfig; 112} 113 114class ScopedSetActiveTexture { 115 public: 116 ScopedSetActiveTexture(GLES2Interface* gl, GLenum unit) 117 : gl_(gl), unit_(unit) { 118 DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(gl_)); 119 120 if (unit_ != GL_TEXTURE0) 121 GLC(gl_, gl_->ActiveTexture(unit_)); 122 } 123 124 ~ScopedSetActiveTexture() { 125 // Active unit being GL_TEXTURE0 is effectively the ground state. 126 if (unit_ != GL_TEXTURE0) 127 GLC(gl_, gl_->ActiveTexture(GL_TEXTURE0)); 128 } 129 130 private: 131 GLES2Interface* gl_; 132 GLenum unit_; 133}; 134 135class TextureIdAllocator : public IdAllocator { 136 public: 137 TextureIdAllocator(GLES2Interface* gl, 138 size_t texture_id_allocation_chunk_size) 139 : IdAllocator(gl, texture_id_allocation_chunk_size) {} 140 virtual ~TextureIdAllocator() { 141 gl_->DeleteTextures(id_allocation_chunk_size_ - next_id_index_, 142 ids_.get() + next_id_index_); 143 } 144 145 // Overridden from IdAllocator: 146 virtual GLuint NextId() OVERRIDE { 147 if (next_id_index_ == id_allocation_chunk_size_) { 148 gl_->GenTextures(id_allocation_chunk_size_, ids_.get()); 149 next_id_index_ = 0; 150 } 151 152 return ids_[next_id_index_++]; 153 } 154 155 private: 156 DISALLOW_COPY_AND_ASSIGN(TextureIdAllocator); 157}; 158 159class BufferIdAllocator : public IdAllocator { 160 public: 161 BufferIdAllocator(GLES2Interface* gl, size_t buffer_id_allocation_chunk_size) 162 : IdAllocator(gl, buffer_id_allocation_chunk_size) {} 163 virtual ~BufferIdAllocator() { 164 gl_->DeleteBuffers(id_allocation_chunk_size_ - next_id_index_, 165 ids_.get() + next_id_index_); 166 } 167 168 // Overridden from IdAllocator: 169 virtual GLuint NextId() OVERRIDE { 170 if (next_id_index_ == id_allocation_chunk_size_) { 171 gl_->GenBuffers(id_allocation_chunk_size_, ids_.get()); 172 next_id_index_ = 0; 173 } 174 175 return ids_[next_id_index_++]; 176 } 177 178 private: 179 DISALLOW_COPY_AND_ASSIGN(BufferIdAllocator); 180}; 181 182// Generic fence implementation for query objects. Fence has passed when query 183// result is available. 184class QueryFence : public ResourceProvider::Fence { 185 public: 186 QueryFence(gpu::gles2::GLES2Interface* gl, unsigned query_id) 187 : gl_(gl), query_id_(query_id) {} 188 189 // Overridden from ResourceProvider::Fence: 190 virtual void Set() OVERRIDE {} 191 virtual bool HasPassed() OVERRIDE { 192 unsigned available = 1; 193 gl_->GetQueryObjectuivEXT( 194 query_id_, GL_QUERY_RESULT_AVAILABLE_EXT, &available); 195 return !!available; 196 } 197 198 private: 199 virtual ~QueryFence() {} 200 201 gpu::gles2::GLES2Interface* gl_; 202 unsigned query_id_; 203 204 DISALLOW_COPY_AND_ASSIGN(QueryFence); 205}; 206 207} // namespace 208 209ResourceProvider::Resource::Resource() 210 : child_id(0), 211 gl_id(0), 212 gl_pixel_buffer_id(0), 213 gl_upload_query_id(0), 214 gl_read_lock_query_id(0), 215 pixels(NULL), 216 lock_for_read_count(0), 217 imported_count(0), 218 exported_count(0), 219 dirty_image(false), 220 locked_for_write(false), 221 lost(false), 222 marked_for_deletion(false), 223 pending_set_pixels(false), 224 set_pixels_completion_forced(false), 225 allocated(false), 226 read_lock_fences_enabled(false), 227 has_shared_bitmap_id(false), 228 allow_overlay(false), 229 read_lock_fence(NULL), 230 size(), 231 origin(Internal), 232 target(0), 233 original_filter(0), 234 filter(0), 235 image_id(0), 236 bound_image_id(0), 237 texture_pool(0), 238 wrap_mode(0), 239 hint(TextureHintImmutable), 240 type(InvalidType), 241 format(RGBA_8888), 242 shared_bitmap(NULL) { 243} 244 245ResourceProvider::Resource::~Resource() {} 246 247ResourceProvider::Resource::Resource(GLuint texture_id, 248 const gfx::Size& size, 249 Origin origin, 250 GLenum target, 251 GLenum filter, 252 GLenum texture_pool, 253 GLint wrap_mode, 254 TextureHint hint, 255 ResourceFormat format) 256 : child_id(0), 257 gl_id(texture_id), 258 gl_pixel_buffer_id(0), 259 gl_upload_query_id(0), 260 gl_read_lock_query_id(0), 261 pixels(NULL), 262 lock_for_read_count(0), 263 imported_count(0), 264 exported_count(0), 265 dirty_image(false), 266 locked_for_write(false), 267 lost(false), 268 marked_for_deletion(false), 269 pending_set_pixels(false), 270 set_pixels_completion_forced(false), 271 allocated(false), 272 read_lock_fences_enabled(false), 273 has_shared_bitmap_id(false), 274 allow_overlay(false), 275 read_lock_fence(NULL), 276 size(size), 277 origin(origin), 278 target(target), 279 original_filter(filter), 280 filter(filter), 281 image_id(0), 282 bound_image_id(0), 283 texture_pool(texture_pool), 284 wrap_mode(wrap_mode), 285 hint(hint), 286 type(GLTexture), 287 format(format), 288 shared_bitmap(NULL) { 289 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT); 290 DCHECK_EQ(origin == Internal, !!texture_pool); 291} 292 293ResourceProvider::Resource::Resource(uint8_t* pixels, 294 SharedBitmap* bitmap, 295 const gfx::Size& size, 296 Origin origin, 297 GLenum filter, 298 GLint wrap_mode) 299 : child_id(0), 300 gl_id(0), 301 gl_pixel_buffer_id(0), 302 gl_upload_query_id(0), 303 gl_read_lock_query_id(0), 304 pixels(pixels), 305 lock_for_read_count(0), 306 imported_count(0), 307 exported_count(0), 308 dirty_image(false), 309 locked_for_write(false), 310 lost(false), 311 marked_for_deletion(false), 312 pending_set_pixels(false), 313 set_pixels_completion_forced(false), 314 allocated(false), 315 read_lock_fences_enabled(false), 316 has_shared_bitmap_id(!!bitmap), 317 allow_overlay(false), 318 read_lock_fence(NULL), 319 size(size), 320 origin(origin), 321 target(0), 322 original_filter(filter), 323 filter(filter), 324 image_id(0), 325 bound_image_id(0), 326 texture_pool(0), 327 wrap_mode(wrap_mode), 328 hint(TextureHintImmutable), 329 type(Bitmap), 330 format(RGBA_8888), 331 shared_bitmap(bitmap) { 332 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT); 333 DCHECK(origin == Delegated || pixels); 334 if (bitmap) 335 shared_bitmap_id = bitmap->id(); 336} 337 338ResourceProvider::Resource::Resource(const SharedBitmapId& bitmap_id, 339 const gfx::Size& size, 340 Origin origin, 341 GLenum filter, 342 GLint wrap_mode) 343 : child_id(0), 344 gl_id(0), 345 gl_pixel_buffer_id(0), 346 gl_upload_query_id(0), 347 gl_read_lock_query_id(0), 348 pixels(NULL), 349 lock_for_read_count(0), 350 imported_count(0), 351 exported_count(0), 352 dirty_image(false), 353 locked_for_write(false), 354 lost(false), 355 marked_for_deletion(false), 356 pending_set_pixels(false), 357 set_pixels_completion_forced(false), 358 allocated(false), 359 read_lock_fences_enabled(false), 360 has_shared_bitmap_id(true), 361 allow_overlay(false), 362 read_lock_fence(NULL), 363 size(size), 364 origin(origin), 365 target(0), 366 original_filter(filter), 367 filter(filter), 368 image_id(0), 369 bound_image_id(0), 370 texture_pool(0), 371 wrap_mode(wrap_mode), 372 hint(TextureHintImmutable), 373 type(Bitmap), 374 format(RGBA_8888), 375 shared_bitmap_id(bitmap_id), 376 shared_bitmap(NULL) { 377 DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT); 378} 379 380ResourceProvider::Child::Child() : marked_for_deletion(false) {} 381 382ResourceProvider::Child::~Child() {} 383 384scoped_ptr<ResourceProvider> ResourceProvider::Create( 385 OutputSurface* output_surface, 386 SharedBitmapManager* shared_bitmap_manager, 387 BlockingTaskRunner* blocking_main_thread_task_runner, 388 int highp_threshold_min, 389 bool use_rgba_4444_texture_format, 390 size_t id_allocation_chunk_size, 391 bool use_distance_field_text) { 392 scoped_ptr<ResourceProvider> resource_provider( 393 new ResourceProvider(output_surface, 394 shared_bitmap_manager, 395 blocking_main_thread_task_runner, 396 highp_threshold_min, 397 use_rgba_4444_texture_format, 398 id_allocation_chunk_size, 399 use_distance_field_text)); 400 401 if (resource_provider->ContextGL()) 402 resource_provider->InitializeGL(); 403 else 404 resource_provider->InitializeSoftware(); 405 406 DCHECK_NE(InvalidType, resource_provider->default_resource_type()); 407 return resource_provider.Pass(); 408} 409 410ResourceProvider::~ResourceProvider() { 411 while (!children_.empty()) 412 DestroyChildInternal(children_.begin(), ForShutdown); 413 while (!resources_.empty()) 414 DeleteResourceInternal(resources_.begin(), ForShutdown); 415 416 CleanUpGLIfNeeded(); 417} 418 419bool ResourceProvider::InUseByConsumer(ResourceId id) { 420 Resource* resource = GetResource(id); 421 return resource->lock_for_read_count > 0 || resource->exported_count > 0 || 422 resource->lost; 423} 424 425bool ResourceProvider::IsLost(ResourceId id) { 426 Resource* resource = GetResource(id); 427 return resource->lost; 428} 429 430bool ResourceProvider::AllowOverlay(ResourceId id) { 431 Resource* resource = GetResource(id); 432 return resource->allow_overlay; 433} 434 435ResourceProvider::ResourceId ResourceProvider::CreateResource( 436 const gfx::Size& size, 437 GLint wrap_mode, 438 TextureHint hint, 439 ResourceFormat format) { 440 DCHECK(!size.IsEmpty()); 441 switch (default_resource_type_) { 442 case GLTexture: 443 return CreateGLTexture(size, 444 GL_TEXTURE_2D, 445 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM, 446 wrap_mode, 447 hint, 448 format); 449 case Bitmap: 450 DCHECK_EQ(RGBA_8888, format); 451 return CreateBitmap(size, wrap_mode); 452 case InvalidType: 453 break; 454 } 455 456 LOG(FATAL) << "Invalid default resource type."; 457 return 0; 458} 459 460ResourceProvider::ResourceId ResourceProvider::CreateManagedResource( 461 const gfx::Size& size, 462 GLenum target, 463 GLint wrap_mode, 464 TextureHint hint, 465 ResourceFormat format) { 466 DCHECK(!size.IsEmpty()); 467 switch (default_resource_type_) { 468 case GLTexture: 469 return CreateGLTexture(size, 470 target, 471 GL_TEXTURE_POOL_MANAGED_CHROMIUM, 472 wrap_mode, 473 hint, 474 format); 475 case Bitmap: 476 DCHECK_EQ(RGBA_8888, format); 477 return CreateBitmap(size, wrap_mode); 478 case InvalidType: 479 break; 480 } 481 482 LOG(FATAL) << "Invalid default resource type."; 483 return 0; 484} 485 486ResourceProvider::ResourceId ResourceProvider::CreateGLTexture( 487 const gfx::Size& size, 488 GLenum target, 489 GLenum texture_pool, 490 GLint wrap_mode, 491 TextureHint hint, 492 ResourceFormat format) { 493 DCHECK_LE(size.width(), max_texture_size_); 494 DCHECK_LE(size.height(), max_texture_size_); 495 DCHECK(thread_checker_.CalledOnValidThread()); 496 497 ResourceId id = next_id_++; 498 Resource resource(0, 499 size, 500 Resource::Internal, 501 target, 502 GL_LINEAR, 503 texture_pool, 504 wrap_mode, 505 hint, 506 format); 507 resource.allocated = false; 508 resources_[id] = resource; 509 return id; 510} 511 512ResourceProvider::ResourceId ResourceProvider::CreateBitmap( 513 const gfx::Size& size, GLint wrap_mode) { 514 DCHECK(thread_checker_.CalledOnValidThread()); 515 516 scoped_ptr<SharedBitmap> bitmap; 517 if (shared_bitmap_manager_) 518 bitmap = shared_bitmap_manager_->AllocateSharedBitmap(size); 519 520 uint8_t* pixels; 521 if (bitmap) { 522 pixels = bitmap->pixels(); 523 } else { 524 size_t bytes = SharedBitmap::CheckedSizeInBytes(size); 525 pixels = new uint8_t[bytes]; 526 } 527 DCHECK(pixels); 528 529 ResourceId id = next_id_++; 530 Resource resource( 531 pixels, bitmap.release(), size, Resource::Internal, GL_LINEAR, wrap_mode); 532 resource.allocated = true; 533 resources_[id] = resource; 534 return id; 535} 536 537ResourceProvider::ResourceId ResourceProvider::CreateResourceFromIOSurface( 538 const gfx::Size& size, 539 unsigned io_surface_id) { 540 DCHECK(thread_checker_.CalledOnValidThread()); 541 542 ResourceId id = next_id_++; 543 Resource resource(0, 544 gfx::Size(), 545 Resource::Internal, 546 GL_TEXTURE_RECTANGLE_ARB, 547 GL_LINEAR, 548 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM, 549 GL_CLAMP_TO_EDGE, 550 TextureHintImmutable, 551 RGBA_8888); 552 LazyCreate(&resource); 553 GLES2Interface* gl = ContextGL(); 554 DCHECK(gl); 555 gl->BindTexture(GL_TEXTURE_RECTANGLE_ARB, resource.gl_id); 556 gl->TexImageIOSurface2DCHROMIUM( 557 GL_TEXTURE_RECTANGLE_ARB, size.width(), size.height(), io_surface_id, 0); 558 resource.allocated = true; 559 resources_[id] = resource; 560 return id; 561} 562 563ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox( 564 const TextureMailbox& mailbox, 565 scoped_ptr<SingleReleaseCallbackImpl> release_callback_impl) { 566 DCHECK(thread_checker_.CalledOnValidThread()); 567 // Just store the information. Mailbox will be consumed in LockForRead(). 568 ResourceId id = next_id_++; 569 DCHECK(mailbox.IsValid()); 570 Resource& resource = resources_[id]; 571 if (mailbox.IsTexture()) { 572 resource = Resource(0, 573 gfx::Size(), 574 Resource::External, 575 mailbox.target(), 576 GL_LINEAR, 577 0, 578 GL_CLAMP_TO_EDGE, 579 TextureHintImmutable, 580 RGBA_8888); 581 } else { 582 DCHECK(mailbox.IsSharedMemory()); 583 base::SharedMemory* shared_memory = mailbox.shared_memory(); 584 DCHECK(shared_memory->memory()); 585 uint8_t* pixels = reinterpret_cast<uint8_t*>(shared_memory->memory()); 586 DCHECK(pixels); 587 scoped_ptr<SharedBitmap> shared_bitmap; 588 if (shared_bitmap_manager_) { 589 shared_bitmap = 590 shared_bitmap_manager_->GetBitmapForSharedMemory(shared_memory); 591 } 592 resource = Resource(pixels, 593 shared_bitmap.release(), 594 mailbox.shared_memory_size(), 595 Resource::External, 596 GL_LINEAR, 597 GL_CLAMP_TO_EDGE); 598 } 599 resource.allocated = true; 600 resource.mailbox = mailbox; 601 resource.release_callback_impl = 602 base::Bind(&SingleReleaseCallbackImpl::Run, 603 base::Owned(release_callback_impl.release())); 604 resource.allow_overlay = mailbox.allow_overlay(); 605 return id; 606} 607 608void ResourceProvider::DeleteResource(ResourceId id) { 609 DCHECK(thread_checker_.CalledOnValidThread()); 610 ResourceMap::iterator it = resources_.find(id); 611 CHECK(it != resources_.end()); 612 Resource* resource = &it->second; 613 DCHECK(!resource->marked_for_deletion); 614 DCHECK_EQ(resource->imported_count, 0); 615 DCHECK(resource->pending_set_pixels || !resource->locked_for_write); 616 617 if (resource->exported_count > 0 || resource->lock_for_read_count > 0) { 618 resource->marked_for_deletion = true; 619 return; 620 } else { 621 DeleteResourceInternal(it, Normal); 622 } 623} 624 625void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it, 626 DeleteStyle style) { 627 TRACE_EVENT0("cc", "ResourceProvider::DeleteResourceInternal"); 628 Resource* resource = &it->second; 629 bool lost_resource = resource->lost; 630 631 DCHECK(resource->exported_count == 0 || style != Normal); 632 if (style == ForShutdown && resource->exported_count > 0) 633 lost_resource = true; 634 635 if (resource->image_id) { 636 DCHECK(resource->origin == Resource::Internal); 637 GLES2Interface* gl = ContextGL(); 638 DCHECK(gl); 639 GLC(gl, gl->DestroyImageCHROMIUM(resource->image_id)); 640 } 641 if (resource->gl_upload_query_id) { 642 DCHECK(resource->origin == Resource::Internal); 643 GLES2Interface* gl = ContextGL(); 644 DCHECK(gl); 645 GLC(gl, gl->DeleteQueriesEXT(1, &resource->gl_upload_query_id)); 646 } 647 if (resource->gl_read_lock_query_id) { 648 DCHECK(resource->origin == Resource::Internal); 649 GLES2Interface* gl = ContextGL(); 650 DCHECK(gl); 651 GLC(gl, gl->DeleteQueriesEXT(1, &resource->gl_read_lock_query_id)); 652 } 653 if (resource->gl_pixel_buffer_id) { 654 DCHECK(resource->origin == Resource::Internal); 655 GLES2Interface* gl = ContextGL(); 656 DCHECK(gl); 657 GLC(gl, gl->DeleteBuffers(1, &resource->gl_pixel_buffer_id)); 658 } 659 if (resource->origin == Resource::External) { 660 DCHECK(resource->mailbox.IsValid()); 661 GLuint sync_point = resource->mailbox.sync_point(); 662 if (resource->type == GLTexture) { 663 DCHECK(resource->mailbox.IsTexture()); 664 lost_resource |= lost_output_surface_; 665 GLES2Interface* gl = ContextGL(); 666 DCHECK(gl); 667 if (resource->gl_id) { 668 GLC(gl, gl->DeleteTextures(1, &resource->gl_id)); 669 resource->gl_id = 0; 670 if (!lost_resource) 671 sync_point = gl->InsertSyncPointCHROMIUM(); 672 } 673 } else { 674 DCHECK(resource->mailbox.IsSharedMemory()); 675 base::SharedMemory* shared_memory = resource->mailbox.shared_memory(); 676 if (resource->pixels && shared_memory) { 677 DCHECK(shared_memory->memory() == resource->pixels); 678 resource->pixels = NULL; 679 delete resource->shared_bitmap; 680 resource->shared_bitmap = NULL; 681 } 682 } 683 resource->release_callback_impl.Run( 684 sync_point, lost_resource, blocking_main_thread_task_runner_); 685 } 686 if (resource->gl_id) { 687 GLES2Interface* gl = ContextGL(); 688 DCHECK(gl); 689 GLC(gl, gl->DeleteTextures(1, &resource->gl_id)); 690 resource->gl_id = 0; 691 } 692 if (resource->shared_bitmap) { 693 DCHECK(resource->origin != Resource::External); 694 DCHECK_EQ(Bitmap, resource->type); 695 delete resource->shared_bitmap; 696 resource->pixels = NULL; 697 } 698 if (resource->pixels) { 699 DCHECK(resource->origin == Resource::Internal); 700 delete[] resource->pixels; 701 } 702 resources_.erase(it); 703} 704 705ResourceProvider::ResourceType ResourceProvider::GetResourceType( 706 ResourceId id) { 707 return GetResource(id)->type; 708} 709 710void ResourceProvider::SetPixels(ResourceId id, 711 const uint8_t* image, 712 const gfx::Rect& image_rect, 713 const gfx::Rect& source_rect, 714 const gfx::Vector2d& dest_offset) { 715 Resource* resource = GetResource(id); 716 DCHECK(!resource->locked_for_write); 717 DCHECK(!resource->lock_for_read_count); 718 DCHECK(resource->origin == Resource::Internal); 719 DCHECK_EQ(resource->exported_count, 0); 720 DCHECK(ReadLockFenceHasPassed(resource)); 721 LazyAllocate(resource); 722 723 if (resource->type == GLTexture) { 724 DCHECK(resource->gl_id); 725 DCHECK(!resource->pending_set_pixels); 726 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D)); 727 GLES2Interface* gl = ContextGL(); 728 DCHECK(gl); 729 DCHECK(texture_uploader_.get()); 730 gl->BindTexture(GL_TEXTURE_2D, resource->gl_id); 731 texture_uploader_->Upload(image, 732 image_rect, 733 source_rect, 734 dest_offset, 735 resource->format, 736 resource->size); 737 } else { 738 DCHECK_EQ(Bitmap, resource->type); 739 DCHECK(resource->allocated); 740 DCHECK_EQ(RGBA_8888, resource->format); 741 DCHECK(source_rect.x() >= image_rect.x()); 742 DCHECK(source_rect.y() >= image_rect.y()); 743 DCHECK(source_rect.right() <= image_rect.right()); 744 DCHECK(source_rect.bottom() <= image_rect.bottom()); 745 SkImageInfo source_info = 746 SkImageInfo::MakeN32Premul(source_rect.width(), source_rect.height()); 747 size_t image_row_bytes = image_rect.width() * 4; 748 gfx::Vector2d source_offset = source_rect.origin() - image_rect.origin(); 749 image += source_offset.y() * image_row_bytes + source_offset.x() * 4; 750 751 ScopedWriteLockSoftware lock(this, id); 752 SkCanvas* dest = lock.sk_canvas(); 753 dest->writePixels( 754 source_info, image, image_row_bytes, dest_offset.x(), dest_offset.y()); 755 } 756} 757 758size_t ResourceProvider::NumBlockingUploads() { 759 if (!texture_uploader_) 760 return 0; 761 762 return texture_uploader_->NumBlockingUploads(); 763} 764 765void ResourceProvider::MarkPendingUploadsAsNonBlocking() { 766 if (!texture_uploader_) 767 return; 768 769 texture_uploader_->MarkPendingUploadsAsNonBlocking(); 770} 771 772size_t ResourceProvider::EstimatedUploadsPerTick() { 773 if (!texture_uploader_) 774 return 1u; 775 776 double textures_per_second = texture_uploader_->EstimatedTexturesPerSecond(); 777 size_t textures_per_tick = floor( 778 kTextureUploadTickRate * textures_per_second); 779 return textures_per_tick ? textures_per_tick : 1u; 780} 781 782void ResourceProvider::FlushUploads() { 783 if (!texture_uploader_) 784 return; 785 786 texture_uploader_->Flush(); 787} 788 789void ResourceProvider::ReleaseCachedData() { 790 if (!texture_uploader_) 791 return; 792 793 texture_uploader_->ReleaseCachedQueries(); 794} 795 796base::TimeTicks ResourceProvider::EstimatedUploadCompletionTime( 797 size_t uploads_per_tick) { 798 if (lost_output_surface_) 799 return base::TimeTicks(); 800 801 // Software resource uploads happen on impl thread, so don't bother batching 802 // them up and trying to wait for them to complete. 803 if (!texture_uploader_) { 804 return gfx::FrameTime::Now() + base::TimeDelta::FromMicroseconds( 805 base::Time::kMicrosecondsPerSecond * kSoftwareUploadTickRate); 806 } 807 808 base::TimeDelta upload_one_texture_time = 809 base::TimeDelta::FromMicroseconds( 810 base::Time::kMicrosecondsPerSecond * kTextureUploadTickRate) / 811 uploads_per_tick; 812 813 size_t total_uploads = NumBlockingUploads() + uploads_per_tick; 814 return gfx::FrameTime::Now() + upload_one_texture_time * total_uploads; 815} 816 817ResourceProvider::Resource* ResourceProvider::GetResource(ResourceId id) { 818 DCHECK(thread_checker_.CalledOnValidThread()); 819 ResourceMap::iterator it = resources_.find(id); 820 CHECK(it != resources_.end()); 821 return &it->second; 822} 823 824const ResourceProvider::Resource* ResourceProvider::LockForRead(ResourceId id) { 825 Resource* resource = GetResource(id); 826 DCHECK(!resource->locked_for_write || 827 resource->set_pixels_completion_forced) << 828 "locked for write: " << resource->locked_for_write << 829 " pixels completion forced: " << resource->set_pixels_completion_forced; 830 DCHECK_EQ(resource->exported_count, 0); 831 // Uninitialized! Call SetPixels or LockForWrite first. 832 DCHECK(resource->allocated); 833 834 LazyCreate(resource); 835 836 if (resource->type == GLTexture && !resource->gl_id) { 837 DCHECK(resource->origin != Resource::Internal); 838 DCHECK(resource->mailbox.IsTexture()); 839 840 // Mailbox sync_points must be processed by a call to 841 // WaitSyncPointIfNeeded() prior to calling LockForRead(). 842 DCHECK(!resource->mailbox.sync_point()); 843 844 GLES2Interface* gl = ContextGL(); 845 DCHECK(gl); 846 resource->gl_id = texture_id_allocator_->NextId(); 847 GLC(gl, gl->BindTexture(resource->target, resource->gl_id)); 848 GLC(gl, 849 gl->ConsumeTextureCHROMIUM(resource->mailbox.target(), 850 resource->mailbox.name())); 851 } 852 853 if (!resource->pixels && resource->has_shared_bitmap_id && 854 shared_bitmap_manager_) { 855 scoped_ptr<SharedBitmap> bitmap = 856 shared_bitmap_manager_->GetSharedBitmapFromId( 857 resource->size, resource->shared_bitmap_id); 858 if (bitmap) { 859 resource->shared_bitmap = bitmap.release(); 860 resource->pixels = resource->shared_bitmap->pixels(); 861 } 862 } 863 864 resource->lock_for_read_count++; 865 if (resource->read_lock_fences_enabled) { 866 if (current_read_lock_fence_.get()) 867 current_read_lock_fence_->Set(); 868 resource->read_lock_fence = current_read_lock_fence_; 869 } 870 871 return resource; 872} 873 874void ResourceProvider::UnlockForRead(ResourceId id) { 875 DCHECK(thread_checker_.CalledOnValidThread()); 876 ResourceMap::iterator it = resources_.find(id); 877 CHECK(it != resources_.end()); 878 879 Resource* resource = &it->second; 880 DCHECK_GT(resource->lock_for_read_count, 0); 881 DCHECK_EQ(resource->exported_count, 0); 882 resource->lock_for_read_count--; 883 if (resource->marked_for_deletion && !resource->lock_for_read_count) { 884 if (!resource->child_id) { 885 // The resource belongs to this ResourceProvider, so it can be destroyed. 886 DeleteResourceInternal(it, Normal); 887 } else { 888 ChildMap::iterator child_it = children_.find(resource->child_id); 889 ResourceIdArray unused; 890 unused.push_back(id); 891 DeleteAndReturnUnusedResourcesToChild(child_it, Normal, unused); 892 } 893 } 894} 895 896const ResourceProvider::Resource* ResourceProvider::LockForWrite( 897 ResourceId id) { 898 Resource* resource = GetResource(id); 899 DCHECK(!resource->locked_for_write); 900 DCHECK(!resource->lock_for_read_count); 901 DCHECK_EQ(resource->exported_count, 0); 902 DCHECK(resource->origin == Resource::Internal); 903 DCHECK(!resource->lost); 904 DCHECK(ReadLockFenceHasPassed(resource)); 905 LazyAllocate(resource); 906 907 resource->locked_for_write = true; 908 return resource; 909} 910 911bool ResourceProvider::CanLockForWrite(ResourceId id) { 912 Resource* resource = GetResource(id); 913 return !resource->locked_for_write && !resource->lock_for_read_count && 914 !resource->exported_count && resource->origin == Resource::Internal && 915 !resource->lost && ReadLockFenceHasPassed(resource); 916} 917 918void ResourceProvider::UnlockForWrite(ResourceId id) { 919 Resource* resource = GetResource(id); 920 DCHECK(resource->locked_for_write); 921 DCHECK_EQ(resource->exported_count, 0); 922 DCHECK(resource->origin == Resource::Internal); 923 resource->locked_for_write = false; 924} 925 926ResourceProvider::ScopedReadLockGL::ScopedReadLockGL( 927 ResourceProvider* resource_provider, 928 ResourceProvider::ResourceId resource_id) 929 : resource_provider_(resource_provider), 930 resource_id_(resource_id), 931 texture_id_(resource_provider->LockForRead(resource_id)->gl_id) { 932 DCHECK(texture_id_); 933} 934 935ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() { 936 resource_provider_->UnlockForRead(resource_id_); 937} 938 939ResourceProvider::ScopedSamplerGL::ScopedSamplerGL( 940 ResourceProvider* resource_provider, 941 ResourceProvider::ResourceId resource_id, 942 GLenum filter) 943 : ScopedReadLockGL(resource_provider, resource_id), 944 unit_(GL_TEXTURE0), 945 target_(resource_provider->BindForSampling(resource_id, unit_, filter)) { 946} 947 948ResourceProvider::ScopedSamplerGL::ScopedSamplerGL( 949 ResourceProvider* resource_provider, 950 ResourceProvider::ResourceId resource_id, 951 GLenum unit, 952 GLenum filter) 953 : ScopedReadLockGL(resource_provider, resource_id), 954 unit_(unit), 955 target_(resource_provider->BindForSampling(resource_id, unit_, filter)) { 956} 957 958ResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() { 959} 960 961ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL( 962 ResourceProvider* resource_provider, 963 ResourceProvider::ResourceId resource_id) 964 : resource_provider_(resource_provider), 965 resource_id_(resource_id), 966 texture_id_(resource_provider->LockForWrite(resource_id)->gl_id) { 967 DCHECK(texture_id_); 968} 969 970ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() { 971 resource_provider_->UnlockForWrite(resource_id_); 972} 973 974void ResourceProvider::PopulateSkBitmapWithResource( 975 SkBitmap* sk_bitmap, const Resource* resource) { 976 DCHECK_EQ(RGBA_8888, resource->format); 977 SkImageInfo info = SkImageInfo::MakeN32Premul(resource->size.width(), 978 resource->size.height()); 979 sk_bitmap->installPixels(info, resource->pixels, info.minRowBytes()); 980} 981 982ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware( 983 ResourceProvider* resource_provider, 984 ResourceProvider::ResourceId resource_id) 985 : resource_provider_(resource_provider), 986 resource_id_(resource_id) { 987 const Resource* resource = resource_provider->LockForRead(resource_id); 988 wrap_mode_ = resource->wrap_mode; 989 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_, resource); 990} 991 992ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() { 993 resource_provider_->UnlockForRead(resource_id_); 994} 995 996ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware( 997 ResourceProvider* resource_provider, 998 ResourceProvider::ResourceId resource_id) 999 : resource_provider_(resource_provider), 1000 resource_id_(resource_id) { 1001 ResourceProvider::PopulateSkBitmapWithResource( 1002 &sk_bitmap_, resource_provider->LockForWrite(resource_id)); 1003 DCHECK(valid()); 1004 sk_canvas_.reset(new SkCanvas(sk_bitmap_)); 1005} 1006 1007ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() { 1008 resource_provider_->UnlockForWrite(resource_id_); 1009} 1010 1011ResourceProvider::ResourceProvider( 1012 OutputSurface* output_surface, 1013 SharedBitmapManager* shared_bitmap_manager, 1014 BlockingTaskRunner* blocking_main_thread_task_runner, 1015 int highp_threshold_min, 1016 bool use_rgba_4444_texture_format, 1017 size_t id_allocation_chunk_size, 1018 bool use_distance_field_text) 1019 : output_surface_(output_surface), 1020 shared_bitmap_manager_(shared_bitmap_manager), 1021 blocking_main_thread_task_runner_(blocking_main_thread_task_runner), 1022 lost_output_surface_(false), 1023 highp_threshold_min_(highp_threshold_min), 1024 next_id_(1), 1025 next_child_(1), 1026 default_resource_type_(InvalidType), 1027 use_texture_storage_ext_(false), 1028 use_texture_format_bgra_(false), 1029 use_texture_usage_hint_(false), 1030 use_compressed_texture_etc1_(false), 1031 max_texture_size_(0), 1032 best_texture_format_(RGBA_8888), 1033 use_rgba_4444_texture_format_(use_rgba_4444_texture_format), 1034 id_allocation_chunk_size_(id_allocation_chunk_size), 1035 use_sync_query_(false), 1036 use_distance_field_text_(use_distance_field_text) { 1037 DCHECK(output_surface_->HasClient()); 1038 DCHECK(id_allocation_chunk_size_); 1039} 1040 1041void ResourceProvider::InitializeSoftware() { 1042 DCHECK(thread_checker_.CalledOnValidThread()); 1043 DCHECK_NE(Bitmap, default_resource_type_); 1044 1045 CleanUpGLIfNeeded(); 1046 1047 default_resource_type_ = Bitmap; 1048 // Pick an arbitrary limit here similar to what hardware might. 1049 max_texture_size_ = 16 * 1024; 1050 best_texture_format_ = RGBA_8888; 1051} 1052 1053void ResourceProvider::InitializeGL() { 1054 DCHECK(thread_checker_.CalledOnValidThread()); 1055 DCHECK(!texture_uploader_); 1056 DCHECK_NE(GLTexture, default_resource_type_); 1057 DCHECK(!texture_id_allocator_); 1058 DCHECK(!buffer_id_allocator_); 1059 1060 default_resource_type_ = GLTexture; 1061 1062 const ContextProvider::Capabilities& caps = 1063 output_surface_->context_provider()->ContextCapabilities(); 1064 1065 bool use_bgra = caps.gpu.texture_format_bgra8888; 1066 use_texture_storage_ext_ = caps.gpu.texture_storage; 1067 use_texture_format_bgra_ = caps.gpu.texture_format_bgra8888; 1068 use_texture_usage_hint_ = caps.gpu.texture_usage; 1069 use_compressed_texture_etc1_ = caps.gpu.texture_format_etc1; 1070 use_sync_query_ = caps.gpu.sync_query; 1071 1072 GLES2Interface* gl = ContextGL(); 1073 DCHECK(gl); 1074 1075 texture_uploader_ = TextureUploader::Create(gl); 1076 max_texture_size_ = 0; // Context expects cleared value. 1077 GLC(gl, gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size_)); 1078 best_texture_format_ = PlatformColor::BestTextureFormat(use_bgra); 1079 1080 texture_id_allocator_.reset( 1081 new TextureIdAllocator(gl, id_allocation_chunk_size_)); 1082 buffer_id_allocator_.reset( 1083 new BufferIdAllocator(gl, id_allocation_chunk_size_)); 1084} 1085 1086void ResourceProvider::CleanUpGLIfNeeded() { 1087 GLES2Interface* gl = ContextGL(); 1088 if (default_resource_type_ != GLTexture) { 1089 // We are not in GL mode, but double check before returning. 1090 DCHECK(!gl); 1091 DCHECK(!texture_uploader_); 1092 return; 1093 } 1094 1095 DCHECK(gl); 1096#if DCHECK_IS_ON 1097 // Check that all GL resources has been deleted. 1098 for (ResourceMap::const_iterator itr = resources_.begin(); 1099 itr != resources_.end(); 1100 ++itr) { 1101 DCHECK_NE(GLTexture, itr->second.type); 1102 } 1103#endif // DCHECK_IS_ON 1104 1105 texture_uploader_.reset(); 1106 texture_id_allocator_.reset(); 1107 buffer_id_allocator_.reset(); 1108 gl->Finish(); 1109} 1110 1111int ResourceProvider::CreateChild(const ReturnCallback& return_callback) { 1112 DCHECK(thread_checker_.CalledOnValidThread()); 1113 1114 Child child_info; 1115 child_info.return_callback = return_callback; 1116 1117 int child = next_child_++; 1118 children_[child] = child_info; 1119 return child; 1120} 1121 1122void ResourceProvider::DestroyChild(int child_id) { 1123 ChildMap::iterator it = children_.find(child_id); 1124 DCHECK(it != children_.end()); 1125 DestroyChildInternal(it, Normal); 1126} 1127 1128void ResourceProvider::DestroyChildInternal(ChildMap::iterator it, 1129 DeleteStyle style) { 1130 DCHECK(thread_checker_.CalledOnValidThread()); 1131 1132 Child& child = it->second; 1133 DCHECK(style == ForShutdown || !child.marked_for_deletion); 1134 1135 ResourceIdArray resources_for_child; 1136 1137 for (ResourceIdMap::iterator child_it = child.child_to_parent_map.begin(); 1138 child_it != child.child_to_parent_map.end(); 1139 ++child_it) { 1140 ResourceId id = child_it->second; 1141 resources_for_child.push_back(id); 1142 } 1143 1144 // If the child is going away, don't consider any resources in use. 1145 child.in_use_resources.clear(); 1146 child.marked_for_deletion = true; 1147 1148 DeleteAndReturnUnusedResourcesToChild(it, style, resources_for_child); 1149} 1150 1151const ResourceProvider::ResourceIdMap& ResourceProvider::GetChildToParentMap( 1152 int child) const { 1153 DCHECK(thread_checker_.CalledOnValidThread()); 1154 ChildMap::const_iterator it = children_.find(child); 1155 DCHECK(it != children_.end()); 1156 DCHECK(!it->second.marked_for_deletion); 1157 return it->second.child_to_parent_map; 1158} 1159 1160void ResourceProvider::PrepareSendToParent(const ResourceIdArray& resources, 1161 TransferableResourceArray* list) { 1162 DCHECK(thread_checker_.CalledOnValidThread()); 1163 GLES2Interface* gl = ContextGL(); 1164 bool need_sync_point = false; 1165 for (ResourceIdArray::const_iterator it = resources.begin(); 1166 it != resources.end(); 1167 ++it) { 1168 TransferableResource resource; 1169 TransferResource(gl, *it, &resource); 1170 if (!resource.mailbox_holder.sync_point && !resource.is_software) 1171 need_sync_point = true; 1172 ++resources_.find(*it)->second.exported_count; 1173 list->push_back(resource); 1174 } 1175 if (need_sync_point) { 1176 GLuint sync_point = gl->InsertSyncPointCHROMIUM(); 1177 for (TransferableResourceArray::iterator it = list->begin(); 1178 it != list->end(); 1179 ++it) { 1180 if (!it->mailbox_holder.sync_point) 1181 it->mailbox_holder.sync_point = sync_point; 1182 } 1183 } 1184} 1185 1186void ResourceProvider::ReceiveFromChild( 1187 int child, const TransferableResourceArray& resources) { 1188 DCHECK(thread_checker_.CalledOnValidThread()); 1189 GLES2Interface* gl = ContextGL(); 1190 Child& child_info = children_.find(child)->second; 1191 DCHECK(!child_info.marked_for_deletion); 1192 for (TransferableResourceArray::const_iterator it = resources.begin(); 1193 it != resources.end(); 1194 ++it) { 1195 ResourceIdMap::iterator resource_in_map_it = 1196 child_info.child_to_parent_map.find(it->id); 1197 if (resource_in_map_it != child_info.child_to_parent_map.end()) { 1198 Resource& resource = resources_[resource_in_map_it->second]; 1199 resource.marked_for_deletion = false; 1200 resource.imported_count++; 1201 continue; 1202 } 1203 1204 if ((!it->is_software && !gl) || 1205 (it->is_software && !shared_bitmap_manager_)) { 1206 TRACE_EVENT0("cc", "ResourceProvider::ReceiveFromChild dropping invalid"); 1207 ReturnedResourceArray to_return; 1208 to_return.push_back(it->ToReturnedResource()); 1209 child_info.return_callback.Run(to_return, 1210 blocking_main_thread_task_runner_); 1211 continue; 1212 } 1213 1214 ResourceId local_id = next_id_++; 1215 Resource& resource = resources_[local_id]; 1216 if (it->is_software) { 1217 resource = Resource(it->mailbox_holder.mailbox, 1218 it->size, 1219 Resource::Delegated, 1220 GL_LINEAR, 1221 it->is_repeated ? GL_REPEAT : GL_CLAMP_TO_EDGE); 1222 } else { 1223 resource = Resource(0, 1224 it->size, 1225 Resource::Delegated, 1226 it->mailbox_holder.texture_target, 1227 it->filter, 1228 0, 1229 it->is_repeated ? GL_REPEAT : GL_CLAMP_TO_EDGE, 1230 TextureHintImmutable, 1231 it->format); 1232 resource.mailbox = TextureMailbox(it->mailbox_holder.mailbox, 1233 it->mailbox_holder.texture_target, 1234 it->mailbox_holder.sync_point); 1235 } 1236 resource.child_id = child; 1237 // Don't allocate a texture for a child. 1238 resource.allocated = true; 1239 resource.imported_count = 1; 1240 resource.allow_overlay = it->allow_overlay; 1241 child_info.parent_to_child_map[local_id] = it->id; 1242 child_info.child_to_parent_map[it->id] = local_id; 1243 } 1244} 1245 1246void ResourceProvider::DeclareUsedResourcesFromChild( 1247 int child, 1248 const ResourceIdArray& resources_from_child) { 1249 DCHECK(thread_checker_.CalledOnValidThread()); 1250 1251 ChildMap::iterator child_it = children_.find(child); 1252 DCHECK(child_it != children_.end()); 1253 Child& child_info = child_it->second; 1254 DCHECK(!child_info.marked_for_deletion); 1255 child_info.in_use_resources.clear(); 1256 1257 for (size_t i = 0; i < resources_from_child.size(); ++i) { 1258 ResourceIdMap::iterator it = 1259 child_info.child_to_parent_map.find(resources_from_child[i]); 1260 DCHECK(it != child_info.child_to_parent_map.end()); 1261 1262 ResourceId local_id = it->second; 1263 DCHECK(!resources_[local_id].marked_for_deletion); 1264 child_info.in_use_resources.insert(local_id); 1265 } 1266 1267 ResourceIdArray unused; 1268 for (ResourceIdMap::iterator it = child_info.child_to_parent_map.begin(); 1269 it != child_info.child_to_parent_map.end(); 1270 ++it) { 1271 ResourceId local_id = it->second; 1272 bool resource_is_in_use = child_info.in_use_resources.count(local_id) > 0; 1273 if (!resource_is_in_use) 1274 unused.push_back(local_id); 1275 } 1276 DeleteAndReturnUnusedResourcesToChild(child_it, Normal, unused); 1277} 1278 1279// static 1280bool ResourceProvider::CompareResourceMapIteratorsByChildId( 1281 const std::pair<ReturnedResource, ResourceMap::iterator>& a, 1282 const std::pair<ReturnedResource, ResourceMap::iterator>& b) { 1283 const ResourceMap::iterator& a_it = a.second; 1284 const ResourceMap::iterator& b_it = b.second; 1285 const Resource& a_resource = a_it->second; 1286 const Resource& b_resource = b_it->second; 1287 return a_resource.child_id < b_resource.child_id; 1288} 1289 1290void ResourceProvider::ReceiveReturnsFromParent( 1291 const ReturnedResourceArray& resources) { 1292 DCHECK(thread_checker_.CalledOnValidThread()); 1293 GLES2Interface* gl = ContextGL(); 1294 1295 int child_id = 0; 1296 ResourceIdArray resources_for_child; 1297 1298 std::vector<std::pair<ReturnedResource, ResourceMap::iterator> > 1299 sorted_resources; 1300 1301 for (ReturnedResourceArray::const_iterator it = resources.begin(); 1302 it != resources.end(); 1303 ++it) { 1304 ResourceId local_id = it->id; 1305 ResourceMap::iterator map_iterator = resources_.find(local_id); 1306 1307 // Resource was already lost (e.g. it belonged to a child that was 1308 // destroyed). 1309 if (map_iterator == resources_.end()) 1310 continue; 1311 1312 sorted_resources.push_back( 1313 std::pair<ReturnedResource, ResourceMap::iterator>(*it, map_iterator)); 1314 } 1315 1316 std::sort(sorted_resources.begin(), 1317 sorted_resources.end(), 1318 CompareResourceMapIteratorsByChildId); 1319 1320 ChildMap::iterator child_it = children_.end(); 1321 for (size_t i = 0; i < sorted_resources.size(); ++i) { 1322 ReturnedResource& returned = sorted_resources[i].first; 1323 ResourceMap::iterator& map_iterator = sorted_resources[i].second; 1324 ResourceId local_id = map_iterator->first; 1325 Resource* resource = &map_iterator->second; 1326 1327 CHECK_GE(resource->exported_count, returned.count); 1328 resource->exported_count -= returned.count; 1329 resource->lost |= returned.lost; 1330 if (resource->exported_count) 1331 continue; 1332 1333 // Need to wait for the current read lock fence to pass before we can 1334 // recycle this resource. 1335 if (resource->read_lock_fences_enabled) { 1336 if (current_read_lock_fence_.get()) 1337 current_read_lock_fence_->Set(); 1338 resource->read_lock_fence = current_read_lock_fence_; 1339 } 1340 1341 if (returned.sync_point) { 1342 DCHECK(!resource->has_shared_bitmap_id); 1343 if (resource->origin == Resource::Internal) { 1344 DCHECK(resource->gl_id); 1345 GLC(gl, gl->WaitSyncPointCHROMIUM(returned.sync_point)); 1346 } else { 1347 DCHECK(!resource->gl_id); 1348 resource->mailbox.set_sync_point(returned.sync_point); 1349 } 1350 } 1351 1352 if (!resource->marked_for_deletion) 1353 continue; 1354 1355 if (!resource->child_id) { 1356 // The resource belongs to this ResourceProvider, so it can be destroyed. 1357 DeleteResourceInternal(map_iterator, Normal); 1358 continue; 1359 } 1360 1361 DCHECK(resource->origin == Resource::Delegated); 1362 // Delete the resource and return it to the child it came from one. 1363 if (resource->child_id != child_id) { 1364 if (child_id) { 1365 DCHECK_NE(resources_for_child.size(), 0u); 1366 DCHECK(child_it != children_.end()); 1367 DeleteAndReturnUnusedResourcesToChild( 1368 child_it, Normal, resources_for_child); 1369 resources_for_child.clear(); 1370 } 1371 1372 child_it = children_.find(resource->child_id); 1373 DCHECK(child_it != children_.end()); 1374 child_id = resource->child_id; 1375 } 1376 resources_for_child.push_back(local_id); 1377 } 1378 1379 if (child_id) { 1380 DCHECK_NE(resources_for_child.size(), 0u); 1381 DCHECK(child_it != children_.end()); 1382 DeleteAndReturnUnusedResourcesToChild( 1383 child_it, Normal, resources_for_child); 1384 } 1385} 1386 1387void ResourceProvider::TransferResource(GLES2Interface* gl, 1388 ResourceId id, 1389 TransferableResource* resource) { 1390 Resource* source = GetResource(id); 1391 DCHECK(!source->locked_for_write); 1392 DCHECK(!source->lock_for_read_count); 1393 DCHECK(source->origin != Resource::External || source->mailbox.IsValid()); 1394 DCHECK(source->allocated); 1395 resource->id = id; 1396 resource->format = source->format; 1397 resource->mailbox_holder.texture_target = source->target; 1398 resource->filter = source->filter; 1399 resource->size = source->size; 1400 resource->is_repeated = (source->wrap_mode == GL_REPEAT); 1401 resource->allow_overlay = source->allow_overlay; 1402 1403 if (source->type == Bitmap) { 1404 resource->mailbox_holder.mailbox = source->shared_bitmap_id; 1405 resource->is_software = true; 1406 } else if (!source->mailbox.IsValid()) { 1407 LazyCreate(source); 1408 DCHECK(source->gl_id); 1409 DCHECK(source->origin == Resource::Internal); 1410 GLC(gl, 1411 gl->BindTexture(resource->mailbox_holder.texture_target, 1412 source->gl_id)); 1413 if (source->image_id) { 1414 DCHECK(source->dirty_image); 1415 BindImageForSampling(source); 1416 } 1417 // This is a resource allocated by the compositor, we need to produce it. 1418 // Don't set a sync point, the caller will do it. 1419 GLC(gl, gl->GenMailboxCHROMIUM(resource->mailbox_holder.mailbox.name)); 1420 GLC(gl, 1421 gl->ProduceTextureCHROMIUM(resource->mailbox_holder.texture_target, 1422 resource->mailbox_holder.mailbox.name)); 1423 source->mailbox = TextureMailbox(resource->mailbox_holder); 1424 } else { 1425 DCHECK(source->mailbox.IsTexture()); 1426 if (source->image_id && source->dirty_image) { 1427 DCHECK(source->gl_id); 1428 DCHECK(source->origin == Resource::Internal); 1429 GLC(gl, 1430 gl->BindTexture(resource->mailbox_holder.texture_target, 1431 source->gl_id)); 1432 BindImageForSampling(source); 1433 } 1434 // This is either an external resource, or a compositor resource that we 1435 // already exported. Make sure to forward the sync point that we were given. 1436 resource->mailbox_holder.mailbox = source->mailbox.mailbox(); 1437 resource->mailbox_holder.texture_target = source->mailbox.target(); 1438 resource->mailbox_holder.sync_point = source->mailbox.sync_point(); 1439 source->mailbox.set_sync_point(0); 1440 } 1441} 1442 1443void ResourceProvider::DeleteAndReturnUnusedResourcesToChild( 1444 ChildMap::iterator child_it, 1445 DeleteStyle style, 1446 const ResourceIdArray& unused) { 1447 DCHECK(thread_checker_.CalledOnValidThread()); 1448 DCHECK(child_it != children_.end()); 1449 Child* child_info = &child_it->second; 1450 1451 if (unused.empty() && !child_info->marked_for_deletion) 1452 return; 1453 1454 ReturnedResourceArray to_return; 1455 1456 GLES2Interface* gl = ContextGL(); 1457 bool need_sync_point = false; 1458 for (size_t i = 0; i < unused.size(); ++i) { 1459 ResourceId local_id = unused[i]; 1460 1461 ResourceMap::iterator it = resources_.find(local_id); 1462 CHECK(it != resources_.end()); 1463 Resource& resource = it->second; 1464 1465 DCHECK(!resource.locked_for_write); 1466 DCHECK_EQ(0u, child_info->in_use_resources.count(local_id)); 1467 DCHECK(child_info->parent_to_child_map.count(local_id)); 1468 1469 ResourceId child_id = child_info->parent_to_child_map[local_id]; 1470 DCHECK(child_info->child_to_parent_map.count(child_id)); 1471 1472 bool is_lost = 1473 resource.lost || (resource.type == GLTexture && lost_output_surface_); 1474 if (resource.exported_count > 0 || resource.lock_for_read_count > 0) { 1475 if (style != ForShutdown) { 1476 // Defer this until we receive the resource back from the parent or 1477 // the read lock is released. 1478 resource.marked_for_deletion = true; 1479 continue; 1480 } 1481 1482 // We still have an exported_count, so we'll have to lose it. 1483 is_lost = true; 1484 } 1485 1486 if (gl && resource.filter != resource.original_filter) { 1487 DCHECK(resource.target); 1488 DCHECK(resource.gl_id); 1489 1490 GLC(gl, gl->BindTexture(resource.target, resource.gl_id)); 1491 GLC(gl, 1492 gl->TexParameteri(resource.target, 1493 GL_TEXTURE_MIN_FILTER, 1494 resource.original_filter)); 1495 GLC(gl, 1496 gl->TexParameteri(resource.target, 1497 GL_TEXTURE_MAG_FILTER, 1498 resource.original_filter)); 1499 } 1500 1501 ReturnedResource returned; 1502 returned.id = child_id; 1503 returned.sync_point = resource.mailbox.sync_point(); 1504 if (!returned.sync_point && resource.type == GLTexture) 1505 need_sync_point = true; 1506 returned.count = resource.imported_count; 1507 returned.lost = is_lost; 1508 to_return.push_back(returned); 1509 1510 child_info->parent_to_child_map.erase(local_id); 1511 child_info->child_to_parent_map.erase(child_id); 1512 resource.imported_count = 0; 1513 DeleteResourceInternal(it, style); 1514 } 1515 if (need_sync_point) { 1516 DCHECK(gl); 1517 GLuint sync_point = gl->InsertSyncPointCHROMIUM(); 1518 for (size_t i = 0; i < to_return.size(); ++i) { 1519 if (!to_return[i].sync_point) 1520 to_return[i].sync_point = sync_point; 1521 } 1522 } 1523 1524 if (!to_return.empty()) 1525 child_info->return_callback.Run(to_return, 1526 blocking_main_thread_task_runner_); 1527 1528 if (child_info->marked_for_deletion && 1529 child_info->parent_to_child_map.empty()) { 1530 DCHECK(child_info->child_to_parent_map.empty()); 1531 children_.erase(child_it); 1532 } 1533} 1534 1535void ResourceProvider::AcquirePixelBuffer(ResourceId id) { 1536 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), 1537 "ResourceProvider::AcquirePixelBuffer"); 1538 1539 Resource* resource = GetResource(id); 1540 DCHECK(resource->origin == Resource::Internal); 1541 DCHECK_EQ(resource->exported_count, 0); 1542 DCHECK(!resource->image_id); 1543 DCHECK_NE(ETC1, resource->format); 1544 1545 DCHECK_EQ(GLTexture, resource->type); 1546 GLES2Interface* gl = ContextGL(); 1547 DCHECK(gl); 1548 if (!resource->gl_pixel_buffer_id) 1549 resource->gl_pixel_buffer_id = buffer_id_allocator_->NextId(); 1550 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 1551 resource->gl_pixel_buffer_id); 1552 unsigned bytes_per_pixel = BitsPerPixel(resource->format) / 8; 1553 gl->BufferData(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 1554 resource->size.height() * 1555 RoundUp(bytes_per_pixel * resource->size.width(), 4u), 1556 NULL, 1557 GL_DYNAMIC_DRAW); 1558 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0); 1559} 1560 1561void ResourceProvider::ReleasePixelBuffer(ResourceId id) { 1562 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), 1563 "ResourceProvider::ReleasePixelBuffer"); 1564 1565 Resource* resource = GetResource(id); 1566 DCHECK(resource->origin == Resource::Internal); 1567 DCHECK_EQ(resource->exported_count, 0); 1568 DCHECK(!resource->image_id); 1569 1570 // The pixel buffer can be released while there is a pending "set pixels" 1571 // if completion has been forced. Any shared memory associated with this 1572 // pixel buffer will not be freed until the waitAsyncTexImage2DCHROMIUM 1573 // command has been processed on the service side. It is also safe to 1574 // reuse any query id associated with this resource before they complete 1575 // as each new query has a unique submit count. 1576 if (resource->pending_set_pixels) { 1577 DCHECK(resource->set_pixels_completion_forced); 1578 resource->pending_set_pixels = false; 1579 resource->locked_for_write = false; 1580 } 1581 1582 DCHECK_EQ(GLTexture, resource->type); 1583 if (!resource->gl_pixel_buffer_id) 1584 return; 1585 GLES2Interface* gl = ContextGL(); 1586 DCHECK(gl); 1587 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 1588 resource->gl_pixel_buffer_id); 1589 gl->BufferData( 1590 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0, NULL, GL_DYNAMIC_DRAW); 1591 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0); 1592} 1593 1594uint8_t* ResourceProvider::MapPixelBuffer(ResourceId id, int* stride) { 1595 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), 1596 "ResourceProvider::MapPixelBuffer"); 1597 1598 Resource* resource = GetResource(id); 1599 DCHECK(resource->origin == Resource::Internal); 1600 DCHECK_EQ(resource->exported_count, 0); 1601 DCHECK(!resource->image_id); 1602 1603 *stride = 0; 1604 DCHECK_EQ(GLTexture, resource->type); 1605 GLES2Interface* gl = ContextGL(); 1606 DCHECK(gl); 1607 DCHECK(resource->gl_pixel_buffer_id); 1608 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 1609 resource->gl_pixel_buffer_id); 1610 uint8_t* image = static_cast<uint8_t*>(gl->MapBufferCHROMIUM( 1611 GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, GL_WRITE_ONLY)); 1612 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0); 1613 // Buffer is required to be 4-byte aligned. 1614 CHECK(!(reinterpret_cast<intptr_t>(image) & 3)); 1615 return image; 1616} 1617 1618void ResourceProvider::UnmapPixelBuffer(ResourceId id) { 1619 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), 1620 "ResourceProvider::UnmapPixelBuffer"); 1621 1622 Resource* resource = GetResource(id); 1623 DCHECK(resource->origin == Resource::Internal); 1624 DCHECK_EQ(resource->exported_count, 0); 1625 DCHECK(!resource->image_id); 1626 1627 DCHECK_EQ(GLTexture, resource->type); 1628 GLES2Interface* gl = ContextGL(); 1629 DCHECK(gl); 1630 DCHECK(resource->gl_pixel_buffer_id); 1631 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 1632 resource->gl_pixel_buffer_id); 1633 gl->UnmapBufferCHROMIUM(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM); 1634 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0); 1635} 1636 1637GLenum ResourceProvider::BindForSampling(ResourceId resource_id, 1638 GLenum unit, 1639 GLenum filter) { 1640 DCHECK(thread_checker_.CalledOnValidThread()); 1641 GLES2Interface* gl = ContextGL(); 1642 ResourceMap::iterator it = resources_.find(resource_id); 1643 DCHECK(it != resources_.end()); 1644 Resource* resource = &it->second; 1645 DCHECK(resource->lock_for_read_count); 1646 DCHECK(!resource->locked_for_write || resource->set_pixels_completion_forced); 1647 1648 ScopedSetActiveTexture scoped_active_tex(gl, unit); 1649 GLenum target = resource->target; 1650 GLC(gl, gl->BindTexture(target, resource->gl_id)); 1651 if (filter != resource->filter) { 1652 GLC(gl, gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, filter)); 1653 GLC(gl, gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, filter)); 1654 resource->filter = filter; 1655 } 1656 1657 if (resource->image_id && resource->dirty_image) 1658 BindImageForSampling(resource); 1659 1660 return target; 1661} 1662 1663void ResourceProvider::BeginSetPixels(ResourceId id) { 1664 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), 1665 "ResourceProvider::BeginSetPixels"); 1666 1667 Resource* resource = GetResource(id); 1668 DCHECK(!resource->pending_set_pixels); 1669 1670 LazyCreate(resource); 1671 DCHECK(resource->origin == Resource::Internal); 1672 DCHECK(resource->gl_id || resource->allocated); 1673 DCHECK(ReadLockFenceHasPassed(resource)); 1674 DCHECK(!resource->image_id); 1675 1676 bool allocate = !resource->allocated; 1677 resource->allocated = true; 1678 LockForWrite(id); 1679 1680 DCHECK_EQ(GLTexture, resource->type); 1681 DCHECK(resource->gl_id); 1682 GLES2Interface* gl = ContextGL(); 1683 DCHECK(gl); 1684 DCHECK(resource->gl_pixel_buffer_id); 1685 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D)); 1686 gl->BindTexture(GL_TEXTURE_2D, resource->gl_id); 1687 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 1688 resource->gl_pixel_buffer_id); 1689 if (!resource->gl_upload_query_id) 1690 gl->GenQueriesEXT(1, &resource->gl_upload_query_id); 1691 gl->BeginQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM, 1692 resource->gl_upload_query_id); 1693 if (allocate) { 1694 gl->AsyncTexImage2DCHROMIUM(GL_TEXTURE_2D, 1695 0, /* level */ 1696 GLInternalFormat(resource->format), 1697 resource->size.width(), 1698 resource->size.height(), 1699 0, /* border */ 1700 GLDataFormat(resource->format), 1701 GLDataType(resource->format), 1702 NULL); 1703 } else { 1704 gl->AsyncTexSubImage2DCHROMIUM(GL_TEXTURE_2D, 1705 0, /* level */ 1706 0, /* x */ 1707 0, /* y */ 1708 resource->size.width(), 1709 resource->size.height(), 1710 GLDataFormat(resource->format), 1711 GLDataType(resource->format), 1712 NULL); 1713 } 1714 gl->EndQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM); 1715 gl->BindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0); 1716 1717 resource->pending_set_pixels = true; 1718 resource->set_pixels_completion_forced = false; 1719} 1720 1721void ResourceProvider::ForceSetPixelsToComplete(ResourceId id) { 1722 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), 1723 "ResourceProvider::ForceSetPixelsToComplete"); 1724 1725 Resource* resource = GetResource(id); 1726 1727 DCHECK(resource->locked_for_write); 1728 DCHECK(resource->pending_set_pixels); 1729 DCHECK(!resource->set_pixels_completion_forced); 1730 1731 if (resource->gl_id) { 1732 GLES2Interface* gl = ContextGL(); 1733 GLC(gl, gl->BindTexture(GL_TEXTURE_2D, resource->gl_id)); 1734 GLC(gl, gl->WaitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D)); 1735 GLC(gl, gl->BindTexture(GL_TEXTURE_2D, 0)); 1736 } 1737 1738 resource->set_pixels_completion_forced = true; 1739} 1740 1741bool ResourceProvider::DidSetPixelsComplete(ResourceId id) { 1742 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), 1743 "ResourceProvider::DidSetPixelsComplete"); 1744 1745 Resource* resource = GetResource(id); 1746 1747 DCHECK(resource->locked_for_write); 1748 DCHECK(resource->pending_set_pixels); 1749 1750 if (resource->gl_id) { 1751 GLES2Interface* gl = ContextGL(); 1752 DCHECK(gl); 1753 DCHECK(resource->gl_upload_query_id); 1754 GLuint complete = 1; 1755 gl->GetQueryObjectuivEXT( 1756 resource->gl_upload_query_id, GL_QUERY_RESULT_AVAILABLE_EXT, &complete); 1757 if (!complete) 1758 return false; 1759 } 1760 1761 resource->pending_set_pixels = false; 1762 UnlockForWrite(id); 1763 1764 return true; 1765} 1766 1767void ResourceProvider::CreateForTesting(ResourceId id) { 1768 LazyCreate(GetResource(id)); 1769} 1770 1771GLenum ResourceProvider::TargetForTesting(ResourceId id) { 1772 Resource* resource = GetResource(id); 1773 return resource->target; 1774} 1775 1776void ResourceProvider::LazyCreate(Resource* resource) { 1777 if (resource->type != GLTexture || resource->origin != Resource::Internal) 1778 return; 1779 1780 if (resource->gl_id) 1781 return; 1782 1783 DCHECK(resource->texture_pool); 1784 DCHECK(resource->origin == Resource::Internal); 1785 DCHECK(!resource->mailbox.IsValid()); 1786 resource->gl_id = texture_id_allocator_->NextId(); 1787 1788 GLES2Interface* gl = ContextGL(); 1789 DCHECK(gl); 1790 1791 // Create and set texture properties. Allocation is delayed until needed. 1792 GLC(gl, gl->BindTexture(resource->target, resource->gl_id)); 1793 GLC(gl, 1794 gl->TexParameteri( 1795 resource->target, GL_TEXTURE_MIN_FILTER, resource->original_filter)); 1796 GLC(gl, 1797 gl->TexParameteri( 1798 resource->target, GL_TEXTURE_MAG_FILTER, resource->original_filter)); 1799 GLC(gl, 1800 gl->TexParameteri( 1801 resource->target, GL_TEXTURE_WRAP_S, resource->wrap_mode)); 1802 GLC(gl, 1803 gl->TexParameteri( 1804 resource->target, GL_TEXTURE_WRAP_T, resource->wrap_mode)); 1805 GLC(gl, 1806 gl->TexParameteri( 1807 resource->target, GL_TEXTURE_POOL_CHROMIUM, resource->texture_pool)); 1808 if (use_texture_usage_hint_ && (resource->hint & TextureHintFramebuffer)) { 1809 GLC(gl, 1810 gl->TexParameteri(resource->target, 1811 GL_TEXTURE_USAGE_ANGLE, 1812 GL_FRAMEBUFFER_ATTACHMENT_ANGLE)); 1813 } 1814} 1815 1816void ResourceProvider::AllocateForTesting(ResourceId id) { 1817 LazyAllocate(GetResource(id)); 1818} 1819 1820void ResourceProvider::LazyAllocate(Resource* resource) { 1821 DCHECK(resource); 1822 if (resource->allocated) 1823 return; 1824 LazyCreate(resource); 1825 if (!resource->gl_id) 1826 return; 1827 resource->allocated = true; 1828 GLES2Interface* gl = ContextGL(); 1829 gfx::Size& size = resource->size; 1830 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D)); 1831 ResourceFormat format = resource->format; 1832 GLC(gl, gl->BindTexture(GL_TEXTURE_2D, resource->gl_id)); 1833 if (use_texture_storage_ext_ && 1834 IsFormatSupportedForStorage(format, use_texture_format_bgra_) && 1835 (resource->hint & TextureHintImmutable)) { 1836 GLenum storage_format = TextureToStorageFormat(format); 1837 GLC(gl, 1838 gl->TexStorage2DEXT( 1839 GL_TEXTURE_2D, 1, storage_format, size.width(), size.height())); 1840 } else { 1841 // ETC1 does not support preallocation. 1842 if (format != ETC1) { 1843 GLC(gl, 1844 gl->TexImage2D(GL_TEXTURE_2D, 1845 0, 1846 GLInternalFormat(format), 1847 size.width(), 1848 size.height(), 1849 0, 1850 GLDataFormat(format), 1851 GLDataType(format), 1852 NULL)); 1853 } 1854 } 1855} 1856 1857void ResourceProvider::BindImageForSampling(Resource* resource) { 1858 GLES2Interface* gl = ContextGL(); 1859 DCHECK(resource->gl_id); 1860 DCHECK(resource->image_id); 1861 1862 // Release image currently bound to texture. 1863 if (resource->bound_image_id) 1864 gl->ReleaseTexImage2DCHROMIUM(resource->target, resource->bound_image_id); 1865 gl->BindTexImage2DCHROMIUM(resource->target, resource->image_id); 1866 resource->bound_image_id = resource->image_id; 1867 resource->dirty_image = false; 1868} 1869 1870void ResourceProvider::EnableReadLockFences(ResourceId id) { 1871 Resource* resource = GetResource(id); 1872 resource->read_lock_fences_enabled = true; 1873} 1874 1875void ResourceProvider::AcquireImage(ResourceId id) { 1876 Resource* resource = GetResource(id); 1877 DCHECK(resource->origin == Resource::Internal); 1878 DCHECK_EQ(resource->exported_count, 0); 1879 DCHECK_EQ(GLTexture, resource->type); 1880 1881 if (resource->image_id) 1882 return; 1883 1884 resource->allocated = true; 1885 GLES2Interface* gl = ContextGL(); 1886 DCHECK(gl); 1887 resource->image_id = 1888 gl->CreateImageCHROMIUM(resource->size.width(), 1889 resource->size.height(), 1890 TextureToStorageFormat(resource->format), 1891 GL_IMAGE_MAP_CHROMIUM); 1892 DCHECK(resource->image_id); 1893} 1894 1895void ResourceProvider::ReleaseImage(ResourceId id) { 1896 Resource* resource = GetResource(id); 1897 DCHECK(resource->origin == Resource::Internal); 1898 DCHECK_EQ(resource->exported_count, 0); 1899 DCHECK_EQ(GLTexture, resource->type); 1900 1901 if (!resource->image_id) 1902 return; 1903 1904 GLES2Interface* gl = ContextGL(); 1905 DCHECK(gl); 1906 gl->DestroyImageCHROMIUM(resource->image_id); 1907 resource->image_id = 0; 1908 resource->bound_image_id = 0; 1909 resource->dirty_image = false; 1910 resource->allocated = false; 1911} 1912 1913uint8_t* ResourceProvider::MapImage(ResourceId id, int* stride) { 1914 Resource* resource = GetResource(id); 1915 DCHECK(ReadLockFenceHasPassed(resource)); 1916 DCHECK(resource->origin == Resource::Internal); 1917 DCHECK_EQ(resource->exported_count, 0); 1918 DCHECK(resource->image_id); 1919 1920 LockForWrite(id); 1921 1922 GLES2Interface* gl = ContextGL(); 1923 DCHECK(gl); 1924 // MapImageCHROMIUM should be called prior to GetImageParameterivCHROMIUM. 1925 uint8_t* pixels = 1926 static_cast<uint8_t*>(gl->MapImageCHROMIUM(resource->image_id)); 1927 gl->GetImageParameterivCHROMIUM( 1928 resource->image_id, GL_IMAGE_ROWBYTES_CHROMIUM, stride); 1929 return pixels; 1930} 1931 1932void ResourceProvider::UnmapImage(ResourceId id) { 1933 Resource* resource = GetResource(id); 1934 DCHECK(resource->origin == Resource::Internal); 1935 DCHECK_EQ(resource->exported_count, 0); 1936 DCHECK(resource->image_id); 1937 DCHECK(resource->locked_for_write); 1938 1939 GLES2Interface* gl = ContextGL(); 1940 DCHECK(gl); 1941 gl->UnmapImageCHROMIUM(resource->image_id); 1942 resource->dirty_image = true; 1943 1944 UnlockForWrite(id); 1945} 1946 1947void ResourceProvider::AcquireSkSurface(ResourceId id) { 1948 Resource* resource = GetResource(id); 1949 DCHECK(resource->origin == Resource::Internal); 1950 DCHECK_EQ(resource->exported_count, 0); 1951 DCHECK_EQ(GLTexture, resource->type); 1952 1953 if (resource->sk_surface) 1954 return; 1955 1956 class GrContext* gr_context = GrContext(); 1957 // TODO(alokp): Implement TestContextProvider::GrContext(). 1958 if (!gr_context) 1959 return; 1960 1961 LazyAllocate(resource); 1962 1963 GrBackendTextureDesc desc; 1964 desc.fFlags = kRenderTarget_GrBackendTextureFlag; 1965 desc.fWidth = resource->size.width(); 1966 desc.fHeight = resource->size.height(); 1967 desc.fConfig = ToGrPixelConfig(resource->format); 1968 desc.fOrigin = kTopLeft_GrSurfaceOrigin; 1969 desc.fTextureHandle = resource->gl_id; 1970 skia::RefPtr<GrTexture> gr_texture = 1971 skia::AdoptRef(gr_context->wrapBackendTexture(desc)); 1972 if (!gr_texture) 1973 return; 1974 SkSurface::TextRenderMode text_render_mode = 1975 use_distance_field_text_ ? SkSurface::kDistanceField_TextRenderMode 1976 : SkSurface::kStandard_TextRenderMode; 1977 resource->sk_surface = skia::AdoptRef(SkSurface::NewRenderTargetDirect( 1978 gr_texture->asRenderTarget(), text_render_mode)); 1979} 1980 1981void ResourceProvider::ReleaseSkSurface(ResourceId id) { 1982 Resource* resource = GetResource(id); 1983 DCHECK(resource->origin == Resource::Internal); 1984 DCHECK_EQ(resource->exported_count, 0); 1985 DCHECK_EQ(GLTexture, resource->type); 1986 1987 resource->sk_surface.clear(); 1988} 1989 1990SkSurface* ResourceProvider::LockForWriteToSkSurface(ResourceId id) { 1991 Resource* resource = GetResource(id); 1992 DCHECK(resource->origin == Resource::Internal); 1993 DCHECK_EQ(resource->exported_count, 0); 1994 DCHECK_EQ(GLTexture, resource->type); 1995 1996 LockForWrite(id); 1997 return resource->sk_surface.get(); 1998} 1999 2000void ResourceProvider::UnlockForWriteToSkSurface(ResourceId id) { 2001 UnlockForWrite(id); 2002} 2003 2004void ResourceProvider::CopyResource(ResourceId source_id, ResourceId dest_id) { 2005 TRACE_EVENT0("cc", "ResourceProvider::CopyResource"); 2006 2007 Resource* source_resource = GetResource(source_id); 2008 DCHECK(!source_resource->lock_for_read_count); 2009 DCHECK(source_resource->origin == Resource::Internal); 2010 DCHECK_EQ(source_resource->exported_count, 0); 2011 DCHECK_EQ(GLTexture, source_resource->type); 2012 DCHECK(source_resource->allocated); 2013 LazyCreate(source_resource); 2014 2015 Resource* dest_resource = GetResource(dest_id); 2016 DCHECK(!dest_resource->locked_for_write); 2017 DCHECK(!dest_resource->lock_for_read_count); 2018 DCHECK(dest_resource->origin == Resource::Internal); 2019 DCHECK_EQ(dest_resource->exported_count, 0); 2020 DCHECK_EQ(GLTexture, dest_resource->type); 2021 LazyCreate(dest_resource); 2022 2023 DCHECK_EQ(source_resource->type, dest_resource->type); 2024 DCHECK_EQ(source_resource->format, dest_resource->format); 2025 DCHECK(source_resource->size == dest_resource->size); 2026 2027 GLES2Interface* gl = ContextGL(); 2028 DCHECK(gl); 2029 if (source_resource->image_id && source_resource->dirty_image) { 2030 gl->BindTexture(source_resource->target, source_resource->gl_id); 2031 BindImageForSampling(source_resource); 2032 } 2033 DCHECK(use_sync_query_) << "CHROMIUM_sync_query extension missing"; 2034 if (!source_resource->gl_read_lock_query_id) 2035 gl->GenQueriesEXT(1, &source_resource->gl_read_lock_query_id); 2036 gl->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, 2037 source_resource->gl_read_lock_query_id); 2038 DCHECK(!dest_resource->image_id); 2039 dest_resource->allocated = true; 2040 gl->CopyTextureCHROMIUM(dest_resource->target, 2041 source_resource->gl_id, 2042 dest_resource->gl_id, 2043 0, 2044 GLInternalFormat(dest_resource->format), 2045 GLDataType(dest_resource->format)); 2046 // End query and create a read lock fence that will prevent access to 2047 // source resource until CopyTextureCHROMIUM command has completed. 2048 gl->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM); 2049 source_resource->read_lock_fence = make_scoped_refptr( 2050 new QueryFence(gl, source_resource->gl_read_lock_query_id)); 2051} 2052 2053void ResourceProvider::WaitSyncPointIfNeeded(ResourceId id) { 2054 Resource* resource = GetResource(id); 2055 DCHECK_EQ(resource->exported_count, 0); 2056 DCHECK(resource->allocated); 2057 if (resource->type != GLTexture || resource->gl_id) 2058 return; 2059 if (!resource->mailbox.sync_point()) 2060 return; 2061 DCHECK(resource->mailbox.IsValid()); 2062 GLES2Interface* gl = ContextGL(); 2063 DCHECK(gl); 2064 GLC(gl, gl->WaitSyncPointCHROMIUM(resource->mailbox.sync_point())); 2065 resource->mailbox.set_sync_point(0); 2066} 2067 2068GLint ResourceProvider::GetActiveTextureUnit(GLES2Interface* gl) { 2069 GLint active_unit = 0; 2070 gl->GetIntegerv(GL_ACTIVE_TEXTURE, &active_unit); 2071 return active_unit; 2072} 2073 2074GLES2Interface* ResourceProvider::ContextGL() const { 2075 ContextProvider* context_provider = output_surface_->context_provider(); 2076 return context_provider ? context_provider->ContextGL() : NULL; 2077} 2078 2079class GrContext* ResourceProvider::GrContext() const { 2080 ContextProvider* context_provider = output_surface_->context_provider(); 2081 return context_provider ? context_provider->GrContext() : NULL; 2082} 2083 2084} // namespace cc 2085