| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "cc/resources/resource_provider.h" | 5 #include "cc/resources/resource_provider.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 | 9 |
| 10 #include "base/containers/hash_tables.h" | 10 #include "base/containers/hash_tables.h" |
| 11 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
| 12 #include "base/numerics/safe_math.h" | 12 #include "base/numerics/safe_math.h" |
| 13 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
| 14 #include "base/strings/string_split.h" | 14 #include "base/strings/string_split.h" |
| 15 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
| 16 #include "base/trace_event/trace_event.h" | 16 #include "base/trace_event/trace_event.h" |
| 17 #include "cc/base/math_util.h" | 17 #include "cc/base/math_util.h" |
| 18 #include "cc/resources/platform_color.h" | 18 #include "cc/resources/platform_color.h" |
| 19 #include "cc/resources/returned_resource.h" | 19 #include "cc/resources/returned_resource.h" |
| 20 #include "cc/resources/shared_bitmap_manager.h" | 20 #include "cc/resources/shared_bitmap_manager.h" |
| 21 #include "cc/resources/texture_uploader.h" | |
| 22 #include "cc/resources/transferable_resource.h" | 21 #include "cc/resources/transferable_resource.h" |
| 23 #include "gpu/GLES2/gl2extchromium.h" | 22 #include "gpu/GLES2/gl2extchromium.h" |
| 24 #include "gpu/command_buffer/client/gles2_interface.h" | 23 #include "gpu/command_buffer/client/gles2_interface.h" |
| 25 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" | 24 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" |
| 26 #include "third_party/khronos/GLES2/gl2.h" | 25 #include "third_party/khronos/GLES2/gl2.h" |
| 27 #include "third_party/khronos/GLES2/gl2ext.h" | 26 #include "third_party/khronos/GLES2/gl2ext.h" |
| 28 #include "third_party/skia/include/core/SkSurface.h" | 27 #include "third_party/skia/include/core/SkSurface.h" |
| 29 #include "third_party/skia/include/gpu/GrContext.h" | 28 #include "third_party/skia/include/gpu/GrContext.h" |
| 30 #include "third_party/skia/include/gpu/GrTextureProvider.h" | 29 #include "third_party/skia/include/gpu/GrTextureProvider.h" |
| 31 #include "ui/gfx/geometry/rect.h" | 30 #include "ui/gfx/geometry/rect.h" |
| (...skipping 22 matching lines...) Expand all Loading... |
| 54 } | 53 } |
| 55 | 54 |
| 56 GLES2Interface* gl_; | 55 GLES2Interface* gl_; |
| 57 const size_t id_allocation_chunk_size_; | 56 const size_t id_allocation_chunk_size_; |
| 58 scoped_ptr<GLuint[]> ids_; | 57 scoped_ptr<GLuint[]> ids_; |
| 59 size_t next_id_index_; | 58 size_t next_id_index_; |
| 60 }; | 59 }; |
| 61 | 60 |
| 62 namespace { | 61 namespace { |
| 63 | 62 |
| 64 // Measured in seconds. | |
| 65 const double kSoftwareUploadTickRate = 0.000250; | |
| 66 const double kTextureUploadTickRate = 0.004; | |
| 67 | |
| 68 GLenum TextureToStorageFormat(ResourceFormat format) { | 63 GLenum TextureToStorageFormat(ResourceFormat format) { |
| 69 GLenum storage_format = GL_RGBA8_OES; | 64 GLenum storage_format = GL_RGBA8_OES; |
| 70 switch (format) { | 65 switch (format) { |
| 71 case RGBA_8888: | 66 case RGBA_8888: |
| 72 break; | 67 break; |
| 73 case BGRA_8888: | 68 case BGRA_8888: |
| 74 storage_format = GL_BGRA8_EXT; | 69 storage_format = GL_BGRA8_EXT; |
| 75 break; | 70 break; |
| 76 case RGBA_4444: | 71 case RGBA_4444: |
| 77 case ALPHA_8: | 72 case ALPHA_8: |
| (...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 411 ResourceProvider::~ResourceProvider() { | 406 ResourceProvider::~ResourceProvider() { |
| 412 while (!children_.empty()) | 407 while (!children_.empty()) |
| 413 DestroyChildInternal(children_.begin(), FOR_SHUTDOWN); | 408 DestroyChildInternal(children_.begin(), FOR_SHUTDOWN); |
| 414 while (!resources_.empty()) | 409 while (!resources_.empty()) |
| 415 DeleteResourceInternal(resources_.begin(), FOR_SHUTDOWN); | 410 DeleteResourceInternal(resources_.begin(), FOR_SHUTDOWN); |
| 416 | 411 |
| 417 GLES2Interface* gl = ContextGL(); | 412 GLES2Interface* gl = ContextGL(); |
| 418 if (default_resource_type_ != RESOURCE_TYPE_GL_TEXTURE) { | 413 if (default_resource_type_ != RESOURCE_TYPE_GL_TEXTURE) { |
| 419 // We are not in GL mode, but double check before returning. | 414 // We are not in GL mode, but double check before returning. |
| 420 DCHECK(!gl); | 415 DCHECK(!gl); |
| 421 DCHECK(!texture_uploader_); | |
| 422 return; | 416 return; |
| 423 } | 417 } |
| 424 | 418 |
| 425 DCHECK(gl); | 419 DCHECK(gl); |
| 426 #if DCHECK_IS_ON() | 420 #if DCHECK_IS_ON() |
| 427 // Check that all GL resources has been deleted. | 421 // Check that all GL resources has been deleted. |
| 428 for (ResourceMap::const_iterator itr = resources_.begin(); | 422 for (ResourceMap::const_iterator itr = resources_.begin(); |
| 429 itr != resources_.end(); ++itr) { | 423 itr != resources_.end(); ++itr) { |
| 430 DCHECK_NE(RESOURCE_TYPE_GL_TEXTURE, itr->second.type); | 424 DCHECK_NE(RESOURCE_TYPE_GL_TEXTURE, itr->second.type); |
| 431 } | 425 } |
| 432 #endif // DCHECK_IS_ON() | 426 #endif // DCHECK_IS_ON() |
| 433 | 427 |
| 434 texture_uploader_ = nullptr; | |
| 435 texture_id_allocator_ = nullptr; | 428 texture_id_allocator_ = nullptr; |
| 436 buffer_id_allocator_ = nullptr; | 429 buffer_id_allocator_ = nullptr; |
| 437 gl->Finish(); | 430 gl->Finish(); |
| 438 } | 431 } |
| 439 | 432 |
| 440 bool ResourceProvider::InUseByConsumer(ResourceId id) { | 433 bool ResourceProvider::InUseByConsumer(ResourceId id) { |
| 441 Resource* resource = GetResource(id); | 434 Resource* resource = GetResource(id); |
| 442 return resource->lock_for_read_count > 0 || resource->exported_count > 0 || | 435 return resource->lock_for_read_count > 0 || resource->exported_count > 0 || |
| 443 resource->lost; | 436 resource->lost; |
| 444 } | 437 } |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 684 resource->gpu_memory_buffer = NULL; | 677 resource->gpu_memory_buffer = NULL; |
| 685 } | 678 } |
| 686 resources_.erase(it); | 679 resources_.erase(it); |
| 687 } | 680 } |
| 688 | 681 |
| 689 ResourceProvider::ResourceType ResourceProvider::GetResourceType( | 682 ResourceProvider::ResourceType ResourceProvider::GetResourceType( |
| 690 ResourceId id) { | 683 ResourceId id) { |
| 691 return GetResource(id)->type; | 684 return GetResource(id)->type; |
| 692 } | 685 } |
| 693 | 686 |
| 694 void ResourceProvider::SetPixels(ResourceId id, | |
| 695 const uint8_t* image, | |
| 696 const gfx::Rect& image_rect, | |
| 697 const gfx::Rect& source_rect, | |
| 698 const gfx::Vector2d& dest_offset) { | |
| 699 Resource* resource = GetResource(id); | |
| 700 DCHECK(!resource->locked_for_write); | |
| 701 DCHECK(!resource->lock_for_read_count); | |
| 702 DCHECK(resource->origin == Resource::INTERNAL); | |
| 703 DCHECK_EQ(resource->exported_count, 0); | |
| 704 DCHECK(ReadLockFenceHasPassed(resource)); | |
| 705 LazyAllocate(resource); | |
| 706 | |
| 707 if (resource->type == RESOURCE_TYPE_GL_TEXTURE) { | |
| 708 DCHECK(resource->gl_id); | |
| 709 DCHECK(!resource->pending_set_pixels); | |
| 710 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D)); | |
| 711 GLES2Interface* gl = ContextGL(); | |
| 712 DCHECK(gl); | |
| 713 DCHECK(texture_uploader_.get()); | |
| 714 gl->BindTexture(GL_TEXTURE_2D, resource->gl_id); | |
| 715 texture_uploader_->Upload(image, | |
| 716 image_rect, | |
| 717 source_rect, | |
| 718 dest_offset, | |
| 719 resource->format, | |
| 720 resource->size); | |
| 721 } else { | |
| 722 DCHECK_EQ(RESOURCE_TYPE_BITMAP, resource->type); | |
| 723 DCHECK(resource->allocated); | |
| 724 DCHECK_EQ(RGBA_8888, resource->format); | |
| 725 DCHECK(source_rect.x() >= image_rect.x()); | |
| 726 DCHECK(source_rect.y() >= image_rect.y()); | |
| 727 DCHECK(source_rect.right() <= image_rect.right()); | |
| 728 DCHECK(source_rect.bottom() <= image_rect.bottom()); | |
| 729 SkImageInfo source_info = | |
| 730 SkImageInfo::MakeN32Premul(source_rect.width(), source_rect.height()); | |
| 731 size_t image_row_bytes = image_rect.width() * 4; | |
| 732 gfx::Vector2d source_offset = source_rect.origin() - image_rect.origin(); | |
| 733 image += source_offset.y() * image_row_bytes + source_offset.x() * 4; | |
| 734 | |
| 735 ScopedWriteLockSoftware lock(this, id); | |
| 736 SkCanvas dest(lock.sk_bitmap()); | |
| 737 dest.writePixels(source_info, image, image_row_bytes, dest_offset.x(), | |
| 738 dest_offset.y()); | |
| 739 } | |
| 740 } | |
| 741 | |
| 742 void ResourceProvider::CopyToResource(ResourceId id, | 687 void ResourceProvider::CopyToResource(ResourceId id, |
| 743 const uint8_t* image, | 688 const uint8_t* image, |
| 744 const gfx::Size& image_size) { | 689 const gfx::Size& image_size) { |
| 745 Resource* resource = GetResource(id); | 690 Resource* resource = GetResource(id); |
| 746 DCHECK(!resource->locked_for_write); | 691 DCHECK(!resource->locked_for_write); |
| 747 DCHECK(!resource->lock_for_read_count); | 692 DCHECK(!resource->lock_for_read_count); |
| 748 DCHECK(resource->origin == Resource::INTERNAL); | 693 DCHECK(resource->origin == Resource::INTERNAL); |
| 749 DCHECK_EQ(resource->exported_count, 0); | 694 DCHECK_EQ(resource->exported_count, 0); |
| 750 DCHECK(ReadLockFenceHasPassed(resource)); | 695 DCHECK(ReadLockFenceHasPassed(resource)); |
| 751 LazyAllocate(resource); | 696 LazyAllocate(resource); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 763 | 708 |
| 764 ScopedWriteLockSoftware lock(this, id); | 709 ScopedWriteLockSoftware lock(this, id); |
| 765 SkCanvas dest(lock.sk_bitmap()); | 710 SkCanvas dest(lock.sk_bitmap()); |
| 766 dest.writePixels(source_info, image, image_stride, 0, 0); | 711 dest.writePixels(source_info, image, image_stride, 0, 0); |
| 767 } else { | 712 } else { |
| 768 DCHECK(resource->gl_id); | 713 DCHECK(resource->gl_id); |
| 769 DCHECK(!resource->pending_set_pixels); | 714 DCHECK(!resource->pending_set_pixels); |
| 770 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D)); | 715 DCHECK_EQ(resource->target, static_cast<GLenum>(GL_TEXTURE_2D)); |
| 771 GLES2Interface* gl = ContextGL(); | 716 GLES2Interface* gl = ContextGL(); |
| 772 DCHECK(gl); | 717 DCHECK(gl); |
| 773 DCHECK(texture_uploader_.get()); | |
| 774 gl->BindTexture(GL_TEXTURE_2D, resource->gl_id); | 718 gl->BindTexture(GL_TEXTURE_2D, resource->gl_id); |
| 775 | 719 |
| 776 if (resource->format == ETC1) { | 720 if (resource->format == ETC1) { |
| 777 base::CheckedNumeric<int> num_bytes = BitsPerPixel(ETC1); | 721 base::CheckedNumeric<int> num_bytes = BitsPerPixel(ETC1); |
| 778 num_bytes *= image_size.width(); | 722 num_bytes *= image_size.width(); |
| 779 num_bytes *= image_size.height(); | 723 num_bytes *= image_size.height(); |
| 780 num_bytes /= 8; | 724 num_bytes /= 8; |
| 781 gl->CompressedTexImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(ETC1), | 725 gl->CompressedTexImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(ETC1), |
| 782 image_size.width(), image_size.height(), 0, | 726 image_size.width(), image_size.height(), 0, |
| 783 num_bytes.ValueOrDie(), image); | 727 num_bytes.ValueOrDie(), image); |
| 784 } else { | 728 } else { |
| 785 gl->TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image_size.width(), | 729 gl->TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image_size.width(), |
| 786 image_size.height(), GLDataFormat(resource->format), | 730 image_size.height(), GLDataFormat(resource->format), |
| 787 GLDataType(resource->format), image); | 731 GLDataType(resource->format), image); |
| 788 } | 732 } |
| 789 } | 733 } |
| 790 } | 734 } |
| 791 | 735 |
| 792 size_t ResourceProvider::NumBlockingUploads() { | |
| 793 if (!texture_uploader_) | |
| 794 return 0; | |
| 795 | |
| 796 return texture_uploader_->NumBlockingUploads(); | |
| 797 } | |
| 798 | |
| 799 void ResourceProvider::MarkPendingUploadsAsNonBlocking() { | |
| 800 if (!texture_uploader_) | |
| 801 return; | |
| 802 | |
| 803 texture_uploader_->MarkPendingUploadsAsNonBlocking(); | |
| 804 } | |
| 805 | |
| 806 size_t ResourceProvider::EstimatedUploadsPerTick() { | |
| 807 if (!texture_uploader_) | |
| 808 return 1u; | |
| 809 | |
| 810 double textures_per_second = texture_uploader_->EstimatedTexturesPerSecond(); | |
| 811 size_t textures_per_tick = floor( | |
| 812 kTextureUploadTickRate * textures_per_second); | |
| 813 return textures_per_tick ? textures_per_tick : 1u; | |
| 814 } | |
| 815 | |
| 816 void ResourceProvider::FlushUploads() { | |
| 817 if (!texture_uploader_) | |
| 818 return; | |
| 819 | |
| 820 texture_uploader_->Flush(); | |
| 821 } | |
| 822 | |
| 823 void ResourceProvider::ReleaseCachedData() { | |
| 824 if (!texture_uploader_) | |
| 825 return; | |
| 826 | |
| 827 texture_uploader_->ReleaseCachedQueries(); | |
| 828 } | |
| 829 | |
| 830 base::TimeTicks ResourceProvider::EstimatedUploadCompletionTime( | |
| 831 size_t uploads_per_tick) { | |
| 832 if (lost_output_surface_) | |
| 833 return base::TimeTicks(); | |
| 834 | |
| 835 // Software resource uploads happen on impl thread, so don't bother batching | |
| 836 // them up and trying to wait for them to complete. | |
| 837 if (!texture_uploader_) { | |
| 838 return base::TimeTicks::Now() + | |
| 839 base::TimeDelta::FromMicroseconds( | |
| 840 base::Time::kMicrosecondsPerSecond * kSoftwareUploadTickRate); | |
| 841 } | |
| 842 | |
| 843 base::TimeDelta upload_one_texture_time = | |
| 844 base::TimeDelta::FromMicroseconds( | |
| 845 base::Time::kMicrosecondsPerSecond * kTextureUploadTickRate) / | |
| 846 uploads_per_tick; | |
| 847 | |
| 848 size_t total_uploads = NumBlockingUploads() + uploads_per_tick; | |
| 849 return base::TimeTicks::Now() + upload_one_texture_time * total_uploads; | |
| 850 } | |
| 851 | |
| 852 ResourceProvider::Resource* ResourceProvider::InsertResource( | 736 ResourceProvider::Resource* ResourceProvider::InsertResource( |
| 853 ResourceId id, | 737 ResourceId id, |
| 854 const Resource& resource) { | 738 const Resource& resource) { |
| 855 std::pair<ResourceMap::iterator, bool> result = | 739 std::pair<ResourceMap::iterator, bool> result = |
| 856 resources_.insert(ResourceMap::value_type(id, resource)); | 740 resources_.insert(ResourceMap::value_type(id, resource)); |
| 857 DCHECK(result.second); | 741 DCHECK(result.second); |
| 858 return &result.first->second; | 742 return &result.first->second; |
| 859 } | 743 } |
| 860 | 744 |
| 861 ResourceProvider::Resource* ResourceProvider::GetResource(ResourceId id) { | 745 ResourceProvider::Resource* ResourceProvider::GetResource(ResourceId id) { |
| (...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1228 | 1112 |
| 1229 GLES2Interface* gl = ContextGL(); | 1113 GLES2Interface* gl = ContextGL(); |
| 1230 if (!gl) { | 1114 if (!gl) { |
| 1231 default_resource_type_ = RESOURCE_TYPE_BITMAP; | 1115 default_resource_type_ = RESOURCE_TYPE_BITMAP; |
| 1232 // Pick an arbitrary limit here similar to what hardware might. | 1116 // Pick an arbitrary limit here similar to what hardware might. |
| 1233 max_texture_size_ = 16 * 1024; | 1117 max_texture_size_ = 16 * 1024; |
| 1234 best_texture_format_ = RGBA_8888; | 1118 best_texture_format_ = RGBA_8888; |
| 1235 return; | 1119 return; |
| 1236 } | 1120 } |
| 1237 | 1121 |
| 1238 DCHECK(!texture_uploader_); | |
| 1239 DCHECK(!texture_id_allocator_); | 1122 DCHECK(!texture_id_allocator_); |
| 1240 DCHECK(!buffer_id_allocator_); | 1123 DCHECK(!buffer_id_allocator_); |
| 1241 | 1124 |
| 1242 const ContextProvider::Capabilities& caps = | 1125 const ContextProvider::Capabilities& caps = |
| 1243 output_surface_->context_provider()->ContextCapabilities(); | 1126 output_surface_->context_provider()->ContextCapabilities(); |
| 1244 | 1127 |
| 1245 default_resource_type_ = RESOURCE_TYPE_GL_TEXTURE; | 1128 default_resource_type_ = RESOURCE_TYPE_GL_TEXTURE; |
| 1246 use_texture_storage_ext_ = caps.gpu.texture_storage; | 1129 use_texture_storage_ext_ = caps.gpu.texture_storage; |
| 1247 use_texture_format_bgra_ = caps.gpu.texture_format_bgra8888; | 1130 use_texture_format_bgra_ = caps.gpu.texture_format_bgra8888; |
| 1248 use_texture_usage_hint_ = caps.gpu.texture_usage; | 1131 use_texture_usage_hint_ = caps.gpu.texture_usage; |
| 1249 use_compressed_texture_etc1_ = caps.gpu.texture_format_etc1; | 1132 use_compressed_texture_etc1_ = caps.gpu.texture_format_etc1; |
| 1250 yuv_resource_format_ = caps.gpu.texture_rg ? RED_8 : LUMINANCE_8; | 1133 yuv_resource_format_ = caps.gpu.texture_rg ? RED_8 : LUMINANCE_8; |
| 1251 use_sync_query_ = caps.gpu.sync_query; | 1134 use_sync_query_ = caps.gpu.sync_query; |
| 1252 | 1135 |
| 1253 texture_uploader_ = TextureUploader::Create(gl); | |
| 1254 max_texture_size_ = 0; // Context expects cleared value. | 1136 max_texture_size_ = 0; // Context expects cleared value. |
| 1255 gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size_); | 1137 gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size_); |
| 1256 best_texture_format_ = | 1138 best_texture_format_ = |
| 1257 PlatformColor::BestTextureFormat(use_texture_format_bgra_); | 1139 PlatformColor::BestTextureFormat(use_texture_format_bgra_); |
| 1258 | 1140 |
| 1259 texture_id_allocator_.reset( | 1141 texture_id_allocator_.reset( |
| 1260 new TextureIdAllocator(gl, id_allocation_chunk_size_)); | 1142 new TextureIdAllocator(gl, id_allocation_chunk_size_)); |
| 1261 buffer_id_allocator_.reset( | 1143 buffer_id_allocator_.reset( |
| 1262 new BufferIdAllocator(gl, id_allocation_chunk_size_)); | 1144 new BufferIdAllocator(gl, id_allocation_chunk_size_)); |
| 1263 } | 1145 } |
| (...skipping 794 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2058 } | 1940 } |
| 2059 | 1941 |
| 2060 class GrContext* ResourceProvider::GrContext(bool worker_context) const { | 1942 class GrContext* ResourceProvider::GrContext(bool worker_context) const { |
| 2061 ContextProvider* context_provider = | 1943 ContextProvider* context_provider = |
| 2062 worker_context ? output_surface_->worker_context_provider() | 1944 worker_context ? output_surface_->worker_context_provider() |
| 2063 : output_surface_->context_provider(); | 1945 : output_surface_->context_provider(); |
| 2064 return context_provider ? context_provider->GrContext() : NULL; | 1946 return context_provider ? context_provider->GrContext() : NULL; |
| 2065 } | 1947 } |
| 2066 | 1948 |
| 2067 } // namespace cc | 1949 } // namespace cc |
| OLD | NEW |