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