| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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 "content/browser/gpu/gpu_process_host.h" | 5 #include "content/browser/gpu/gpu_process_host.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <list> | 10 #include <list> |
| (...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 678 IPC_MESSAGE_HANDLER(GpuHostMsg_DestroyingVideoSurfaceAck, | 678 IPC_MESSAGE_HANDLER(GpuHostMsg_DestroyingVideoSurfaceAck, |
| 679 OnDestroyingVideoSurfaceAck) | 679 OnDestroyingVideoSurfaceAck) |
| 680 #endif | 680 #endif |
| 681 IPC_MESSAGE_HANDLER(GpuHostMsg_FieldTrialActivated, OnFieldTrialActivated); | 681 IPC_MESSAGE_HANDLER(GpuHostMsg_FieldTrialActivated, OnFieldTrialActivated); |
| 682 IPC_MESSAGE_UNHANDLED(RouteOnUIThread(message)) | 682 IPC_MESSAGE_UNHANDLED(RouteOnUIThread(message)) |
| 683 IPC_END_MESSAGE_MAP() | 683 IPC_END_MESSAGE_MAP() |
| 684 | 684 |
| 685 return true; | 685 return true; |
| 686 } | 686 } |
| 687 | 687 |
| 688 #if defined(OS_WIN) | |
| 689 void GpuProcessHost::OnAcceleratedSurfaceCreatedChildWindow( | |
| 690 gpu::SurfaceHandle parent_handle, | |
| 691 gpu::SurfaceHandle window_handle) { | |
| 692 constexpr char kBadMessageError[] = "Bad parenting request from gpu process."; | |
| 693 if (!in_process_) { | |
| 694 DCHECK(process_); | |
| 695 { | |
| 696 DWORD process_id = 0; | |
| 697 DWORD thread_id = GetWindowThreadProcessId(parent_handle, &process_id); | |
| 698 | |
| 699 if (!thread_id || process_id != ::GetCurrentProcessId()) { | |
| 700 process_->TerminateOnBadMessageReceived(kBadMessageError); | |
| 701 return; | |
| 702 } | |
| 703 } | |
| 704 | |
| 705 { | |
| 706 DWORD process_id = 0; | |
| 707 DWORD thread_id = GetWindowThreadProcessId(window_handle, &process_id); | |
| 708 | |
| 709 if (!thread_id || process_id != process_->GetProcess().Pid()) { | |
| 710 process_->TerminateOnBadMessageReceived(kBadMessageError); | |
| 711 return; | |
| 712 } | |
| 713 } | |
| 714 } | |
| 715 | |
| 716 if (!gfx::RenderingWindowManager::GetInstance()->RegisterChild( | |
| 717 parent_handle, window_handle)) { | |
| 718 process_->TerminateOnBadMessageReceived(kBadMessageError); | |
| 719 } | |
| 720 } | |
| 721 #endif | |
| 722 | |
| 723 void GpuProcessHost::OnChannelConnected(int32_t peer_pid) { | 688 void GpuProcessHost::OnChannelConnected(int32_t peer_pid) { |
| 724 TRACE_EVENT0("gpu", "GpuProcessHost::OnChannelConnected"); | 689 TRACE_EVENT0("gpu", "GpuProcessHost::OnChannelConnected"); |
| 725 | 690 |
| 726 while (!queued_messages_.empty()) { | 691 while (!queued_messages_.empty()) { |
| 727 Send(queued_messages_.front()); | 692 Send(queued_messages_.front()); |
| 728 queued_messages_.pop(); | 693 queued_messages_.pop(); |
| 729 } | 694 } |
| 730 } | 695 } |
| 731 | 696 |
| 732 void GpuProcessHost::EstablishGpuChannel( | 697 void GpuProcessHost::EstablishGpuChannel( |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 872 } | 837 } |
| 873 | 838 |
| 874 #if defined(OS_ANDROID) | 839 #if defined(OS_ANDROID) |
| 875 void GpuProcessHost::OnDestroyingVideoSurfaceAck(int surface_id) { | 840 void GpuProcessHost::OnDestroyingVideoSurfaceAck(int surface_id) { |
| 876 TRACE_EVENT0("gpu", "GpuProcessHost::OnDestroyingVideoSurfaceAck"); | 841 TRACE_EVENT0("gpu", "GpuProcessHost::OnDestroyingVideoSurfaceAck"); |
| 877 if (!send_destroying_video_surface_done_cb_.is_null()) | 842 if (!send_destroying_video_surface_done_cb_.is_null()) |
| 878 base::ResetAndReturn(&send_destroying_video_surface_done_cb_).Run(); | 843 base::ResetAndReturn(&send_destroying_video_surface_done_cb_).Run(); |
| 879 } | 844 } |
| 880 #endif | 845 #endif |
| 881 | 846 |
| 882 void GpuProcessHost::OnDidCreateOffscreenContext(const GURL& url) { | |
| 883 urls_with_live_offscreen_contexts_.insert(url); | |
| 884 } | |
| 885 | |
| 886 void GpuProcessHost::OnDidLoseContext(bool offscreen, | |
| 887 gpu::error::ContextLostReason reason, | |
| 888 const GURL& url) { | |
| 889 // TODO(kbr): would be nice to see the "offscreen" flag too. | |
| 890 TRACE_EVENT2("gpu", "GpuProcessHost::OnDidLoseContext", | |
| 891 "reason", reason, | |
| 892 "url", | |
| 893 url.possibly_invalid_spec()); | |
| 894 | |
| 895 if (!offscreen || url.is_empty()) { | |
| 896 // Assume that the loss of the compositor's or accelerated canvas' | |
| 897 // context is a serious event and blame the loss on all live | |
| 898 // offscreen contexts. This more robustly handles situations where | |
| 899 // the GPU process may not actually detect the context loss in the | |
| 900 // offscreen context. | |
| 901 BlockLiveOffscreenContexts(); | |
| 902 return; | |
| 903 } | |
| 904 | |
| 905 GpuDataManagerImpl::DomainGuilt guilt = | |
| 906 GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN; | |
| 907 switch (reason) { | |
| 908 case gpu::error::kGuilty: | |
| 909 guilt = GpuDataManagerImpl::DOMAIN_GUILT_KNOWN; | |
| 910 break; | |
| 911 // Treat most other error codes as though they had unknown provenance. | |
| 912 // In practice this doesn't affect the user experience. A lost context | |
| 913 // of either known or unknown guilt still causes user-level 3D APIs | |
| 914 // (e.g. WebGL) to be blocked on that domain until the user manually | |
| 915 // reenables them. | |
| 916 case gpu::error::kUnknown: | |
| 917 case gpu::error::kOutOfMemory: | |
| 918 case gpu::error::kMakeCurrentFailed: | |
| 919 case gpu::error::kGpuChannelLost: | |
| 920 case gpu::error::kInvalidGpuMessage: | |
| 921 break; | |
| 922 case gpu::error::kInnocent: | |
| 923 return; | |
| 924 } | |
| 925 | |
| 926 GpuDataManagerImpl::GetInstance()->BlockDomainFrom3DAPIs(url, guilt); | |
| 927 } | |
| 928 | |
| 929 void GpuProcessHost::OnDidDestroyOffscreenContext(const GURL& url) { | |
| 930 urls_with_live_offscreen_contexts_.erase(url); | |
| 931 } | |
| 932 | |
| 933 void GpuProcessHost::OnFieldTrialActivated(const std::string& trial_name) { | 847 void GpuProcessHost::OnFieldTrialActivated(const std::string& trial_name) { |
| 934 // Activate the trial in the browser process to match its state in the | 848 // Activate the trial in the browser process to match its state in the |
| 935 // GPU process. This is done by calling FindFullName which finalizes the group | 849 // GPU process. This is done by calling FindFullName which finalizes the group |
| 936 // and activates the trial. | 850 // and activates the trial. |
| 937 base::FieldTrialList::FindFullName(trial_name); | 851 base::FieldTrialList::FindFullName(trial_name); |
| 938 } | 852 } |
| 939 | 853 |
| 940 void GpuProcessHost::OnProcessLaunched() { | 854 void GpuProcessHost::OnProcessLaunched() { |
| 941 UMA_HISTOGRAM_TIMES("GPU.GPUProcessLaunchTime", | 855 UMA_HISTOGRAM_TIMES("GPU.GPUProcessLaunchTime", |
| 942 base::TimeTicks::Now() - init_start_time_); | 856 base::TimeTicks::Now() - init_start_time_); |
| 943 } | 857 } |
| 944 | 858 |
| 945 void GpuProcessHost::OnProcessLaunchFailed(int error_code) { | 859 void GpuProcessHost::OnProcessLaunchFailed(int error_code) { |
| 946 // TODO(wfh): do something more useful with this error code. | 860 // TODO(wfh): do something more useful with this error code. |
| 947 RecordProcessCrash(); | 861 RecordProcessCrash(); |
| 948 } | 862 } |
| 949 | 863 |
| 950 void GpuProcessHost::OnProcessCrashed(int exit_code) { | 864 void GpuProcessHost::OnProcessCrashed(int exit_code) { |
| 951 SendOutstandingReplies(); | 865 SendOutstandingReplies(); |
| 952 RecordProcessCrash(); | 866 RecordProcessCrash(); |
| 953 GpuDataManagerImpl::GetInstance()->ProcessCrashed( | 867 GpuDataManagerImpl::GetInstance()->ProcessCrashed( |
| 954 process_->GetTerminationStatus(true /* known_dead */, NULL)); | 868 process_->GetTerminationStatus(true /* known_dead */, NULL)); |
| 955 } | 869 } |
| 956 | 870 |
| 957 void GpuProcessHost::DidInitialize(const gpu::GPUInfo& gpu_info) { | 871 void GpuProcessHost::DidInitialize(const gpu::GPUInfo& gpu_info) { |
| 958 // TODO(sad): This should call OnInitialized(). | 872 // TODO(sad): This should call OnInitialized(). |
| 959 } | 873 } |
| 960 | 874 |
| 961 void GpuProcessHost::DidCreateOffscreenContext(const GURL& url) { | 875 void GpuProcessHost::DidCreateOffscreenContext(const GURL& url) { |
| 962 OnDidCreateOffscreenContext(url); | 876 urls_with_live_offscreen_contexts_.insert(url); |
| 963 } | 877 } |
| 964 | 878 |
| 965 void GpuProcessHost::DidDestroyOffscreenContext(const GURL& url) { | 879 void GpuProcessHost::DidDestroyOffscreenContext(const GURL& url) { |
| 966 OnDidDestroyOffscreenContext(url); | 880 urls_with_live_offscreen_contexts_.erase(url); |
| 967 } | 881 } |
| 968 | 882 |
| 969 void GpuProcessHost::DidDestroyChannel(int32_t client_id) { | 883 void GpuProcessHost::DidDestroyChannel(int32_t client_id) { |
| 970 OnDestroyChannel(client_id); | 884 TRACE_EVENT0("gpu", "GpuProcessHost::DidDestroyChannel"); |
| 885 client_id_to_shader_cache_.erase(client_id); |
| 971 } | 886 } |
| 972 | 887 |
| 973 void GpuProcessHost::DidLoseContext(bool offscreen, | 888 void GpuProcessHost::DidLoseContext(bool offscreen, |
| 974 gpu::error::ContextLostReason reason, | 889 gpu::error::ContextLostReason reason, |
| 975 const GURL& active_url) { | 890 const GURL& active_url) { |
| 976 OnDidLoseContext(offscreen, reason, active_url); | 891 // TODO(kbr): would be nice to see the "offscreen" flag too. |
| 892 TRACE_EVENT2("gpu", "GpuProcessHost::DidLoseContext", "reason", reason, "url", |
| 893 active_url.possibly_invalid_spec()); |
| 894 |
| 895 if (!offscreen || active_url.is_empty()) { |
| 896 // Assume that the loss of the compositor's or accelerated canvas' |
| 897 // context is a serious event and blame the loss on all live |
| 898 // offscreen contexts. This more robustly handles situations where |
| 899 // the GPU process may not actually detect the context loss in the |
| 900 // offscreen context. |
| 901 BlockLiveOffscreenContexts(); |
| 902 return; |
| 903 } |
| 904 |
| 905 GpuDataManagerImpl::DomainGuilt guilt = |
| 906 GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN; |
| 907 switch (reason) { |
| 908 case gpu::error::kGuilty: |
| 909 guilt = GpuDataManagerImpl::DOMAIN_GUILT_KNOWN; |
| 910 break; |
| 911 // Treat most other error codes as though they had unknown provenance. |
| 912 // In practice this doesn't affect the user experience. A lost context |
| 913 // of either known or unknown guilt still causes user-level 3D APIs |
| 914 // (e.g. WebGL) to be blocked on that domain until the user manually |
| 915 // reenables them. |
| 916 case gpu::error::kUnknown: |
| 917 case gpu::error::kOutOfMemory: |
| 918 case gpu::error::kMakeCurrentFailed: |
| 919 case gpu::error::kGpuChannelLost: |
| 920 case gpu::error::kInvalidGpuMessage: |
| 921 break; |
| 922 case gpu::error::kInnocent: |
| 923 return; |
| 924 } |
| 925 |
| 926 GpuDataManagerImpl::GetInstance()->BlockDomainFrom3DAPIs(active_url, guilt); |
| 977 } | 927 } |
| 978 | 928 |
| 979 void GpuProcessHost::SetChildSurface(gpu::SurfaceHandle parent, | 929 void GpuProcessHost::SetChildSurface(gpu::SurfaceHandle parent_handle, |
| 980 gpu::SurfaceHandle child) { | 930 gpu::SurfaceHandle window_handle) { |
| 981 #if defined(OS_WIN) | 931 #if defined(OS_WIN) |
| 982 OnAcceleratedSurfaceCreatedChildWindow(parent, child); | 932 constexpr char kBadMessageError[] = "Bad parenting request from gpu process."; |
| 933 if (!in_process_) { |
| 934 DCHECK(process_); |
| 935 { |
| 936 DWORD process_id = 0; |
| 937 DWORD thread_id = GetWindowThreadProcessId(parent_handle, &process_id); |
| 938 |
| 939 if (!thread_id || process_id != ::GetCurrentProcessId()) { |
| 940 process_->TerminateOnBadMessageReceived(kBadMessageError); |
| 941 return; |
| 942 } |
| 943 } |
| 944 |
| 945 { |
| 946 DWORD process_id = 0; |
| 947 DWORD thread_id = GetWindowThreadProcessId(window_handle, &process_id); |
| 948 |
| 949 if (!thread_id || process_id != process_->GetProcess().Pid()) { |
| 950 process_->TerminateOnBadMessageReceived(kBadMessageError); |
| 951 return; |
| 952 } |
| 953 } |
| 954 } |
| 955 |
| 956 if (!gfx::RenderingWindowManager::GetInstance()->RegisterChild( |
| 957 parent_handle, window_handle)) { |
| 958 process_->TerminateOnBadMessageReceived(kBadMessageError); |
| 959 } |
| 983 #endif | 960 #endif |
| 984 } | 961 } |
| 985 | 962 |
| 986 void GpuProcessHost::StoreShaderToDisk(int32_t client_id, | 963 void GpuProcessHost::StoreShaderToDisk(int32_t client_id, |
| 987 const std::string& key, | 964 const std::string& key, |
| 988 const std::string& shader) { | 965 const std::string& shader) { |
| 989 OnCacheShader(client_id, key, shader); | 966 TRACE_EVENT0("gpu", "GpuProcessHost::StoreShaderToDisk"); |
| 967 ClientIdToShaderCacheMap::iterator iter = |
| 968 client_id_to_shader_cache_.find(client_id); |
| 969 // If the cache doesn't exist then this is an off the record profile. |
| 970 if (iter == client_id_to_shader_cache_.end()) |
| 971 return; |
| 972 iter->second->Cache(GetShaderPrefixKey(shader) + ":" + key, shader); |
| 990 } | 973 } |
| 991 | 974 |
| 992 GpuProcessHost::GpuProcessKind GpuProcessHost::kind() { | 975 GpuProcessHost::GpuProcessKind GpuProcessHost::kind() { |
| 993 return kind_; | 976 return kind_; |
| 994 } | 977 } |
| 995 | 978 |
| 996 void GpuProcessHost::ForceShutdown() { | 979 void GpuProcessHost::ForceShutdown() { |
| 997 // This is only called on the IO thread so no race against the constructor | 980 // This is only called on the IO thread so no race against the constructor |
| 998 // for another GpuProcessHost. | 981 // for another GpuProcessHost. |
| 999 if (g_gpu_process_hosts[kind_] == this) | 982 if (g_gpu_process_hosts[kind_] == this) |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1218 scoped_refptr<gpu::ShaderDiskCache> cache = | 1201 scoped_refptr<gpu::ShaderDiskCache> cache = |
| 1219 GetShaderCacheFactorySingleton()->Get(client_id); | 1202 GetShaderCacheFactorySingleton()->Get(client_id); |
| 1220 if (!cache.get()) | 1203 if (!cache.get()) |
| 1221 return; | 1204 return; |
| 1222 | 1205 |
| 1223 cache->set_shader_loaded_callback(base::Bind(&HostLoadedShader, host_id_)); | 1206 cache->set_shader_loaded_callback(base::Bind(&HostLoadedShader, host_id_)); |
| 1224 | 1207 |
| 1225 client_id_to_shader_cache_[client_id] = cache; | 1208 client_id_to_shader_cache_[client_id] = cache; |
| 1226 } | 1209 } |
| 1227 | 1210 |
| 1228 void GpuProcessHost::OnDestroyChannel(int32_t client_id) { | |
| 1229 TRACE_EVENT0("gpu", "GpuProcessHost::OnDestroyChannel"); | |
| 1230 client_id_to_shader_cache_.erase(client_id); | |
| 1231 } | |
| 1232 | |
| 1233 void GpuProcessHost::OnCacheShader(int32_t client_id, | |
| 1234 const std::string& key, | |
| 1235 const std::string& shader) { | |
| 1236 TRACE_EVENT0("gpu", "GpuProcessHost::OnCacheShader"); | |
| 1237 ClientIdToShaderCacheMap::iterator iter = | |
| 1238 client_id_to_shader_cache_.find(client_id); | |
| 1239 // If the cache doesn't exist then this is an off the record profile. | |
| 1240 if (iter == client_id_to_shader_cache_.end()) | |
| 1241 return; | |
| 1242 iter->second->Cache(GetShaderPrefixKey(shader) + ":" + key, shader); | |
| 1243 } | |
| 1244 | |
| 1245 } // namespace content | 1211 } // namespace content |
| OLD | NEW |