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 |