Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "components/viz/host/server_gpu_memory_buffer_manager.h" | 5 #include "components/viz/host/server_gpu_memory_buffer_manager.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/strings/stringprintf.h" | |
| 8 #include "base/threading/sequenced_task_runner_handle.h" | 9 #include "base/threading/sequenced_task_runner_handle.h" |
| 10 #include "base/trace_event/memory_dump_manager.h" | |
| 11 #include "base/trace_event/process_memory_dump.h" | |
| 9 #include "gpu/ipc/client/gpu_memory_buffer_impl.h" | 12 #include "gpu/ipc/client/gpu_memory_buffer_impl.h" |
| 10 #include "gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.h" | 13 #include "gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.h" |
| 11 #include "gpu/ipc/common/gpu_memory_buffer_support.h" | 14 #include "gpu/ipc/common/gpu_memory_buffer_support.h" |
| 12 #include "services/ui/gpu/interfaces/gpu_service.mojom.h" | 15 #include "services/ui/gpu/interfaces/gpu_service.mojom.h" |
| 16 #include "ui/gfx/buffer_format_util.h" | |
| 17 #include "ui/gfx/gpu_memory_buffer_tracing.h" | |
| 18 | |
| 19 using base::trace_event::MemoryDumpManager; | |
|
reveman
2017/07/08 11:14:10
what's the justification for this? I think we pref
sadrul
2017/07/08 21:15:13
I have removed it.
Initially I was registering as
| |
| 13 | 20 |
| 14 namespace viz { | 21 namespace viz { |
| 15 | 22 |
| 23 ServerGpuMemoryBufferManager::BufferInfo::BufferInfo() = default; | |
| 24 ServerGpuMemoryBufferManager::BufferInfo::~BufferInfo() = default; | |
| 25 | |
| 16 ServerGpuMemoryBufferManager::ServerGpuMemoryBufferManager( | 26 ServerGpuMemoryBufferManager::ServerGpuMemoryBufferManager( |
| 17 ui::mojom::GpuService* gpu_service, | 27 ui::mojom::GpuService* gpu_service, |
| 18 int client_id) | 28 int client_id) |
| 19 : gpu_service_(gpu_service), | 29 : gpu_service_(gpu_service), |
| 20 client_id_(client_id), | 30 client_id_(client_id), |
| 21 native_configurations_(gpu::GetNativeGpuMemoryBufferConfigurations()), | 31 native_configurations_(gpu::GetNativeGpuMemoryBufferConfigurations()), |
| 22 task_runner_(base::SequencedTaskRunnerHandle::Get()), | 32 task_runner_(base::SequencedTaskRunnerHandle::Get()), |
| 23 weak_factory_(this) {} | 33 weak_factory_(this) {} |
| 24 | 34 |
| 25 ServerGpuMemoryBufferManager::~ServerGpuMemoryBufferManager() {} | 35 ServerGpuMemoryBufferManager::~ServerGpuMemoryBufferManager() {} |
| 26 | 36 |
| 27 void ServerGpuMemoryBufferManager::AllocateGpuMemoryBuffer( | 37 void ServerGpuMemoryBufferManager::AllocateGpuMemoryBuffer( |
| 28 gfx::GpuMemoryBufferId id, | 38 gfx::GpuMemoryBufferId id, |
| 29 int client_id, | 39 int client_id, |
| 30 const gfx::Size& size, | 40 const gfx::Size& size, |
| 31 gfx::BufferFormat format, | 41 gfx::BufferFormat format, |
| 32 gfx::BufferUsage usage, | 42 gfx::BufferUsage usage, |
| 33 gpu::SurfaceHandle surface_handle, | 43 gpu::SurfaceHandle surface_handle, |
| 34 base::OnceCallback<void(const gfx::GpuMemoryBufferHandle&)> callback) { | 44 base::OnceCallback<void(const gfx::GpuMemoryBufferHandle&)> callback) { |
| 35 DCHECK(task_runner_->RunsTasksInCurrentSequence()); | 45 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
| 36 if (gpu::GetNativeGpuMemoryBufferType() != gfx::EMPTY_BUFFER) { | 46 if (gpu::GetNativeGpuMemoryBufferType() != gfx::EMPTY_BUFFER) { |
| 37 const bool is_native = native_configurations_.find(std::make_pair( | 47 const bool is_native = native_configurations_.find(std::make_pair( |
| 38 format, usage)) != native_configurations_.end(); | 48 format, usage)) != native_configurations_.end(); |
| 39 if (is_native) { | 49 if (is_native) { |
| 40 pending_buffers_.insert(client_id); | 50 pending_buffers_.insert(client_id); |
| 41 gpu_service_->CreateGpuMemoryBuffer( | 51 gpu_service_->CreateGpuMemoryBuffer( |
| 42 id, size, format, usage, client_id, surface_handle, | 52 id, size, format, usage, client_id, surface_handle, |
| 43 base::Bind(&ServerGpuMemoryBufferManager::OnGpuMemoryBufferAllocated, | 53 base::Bind(&ServerGpuMemoryBufferManager::OnGpuMemoryBufferAllocated, |
| 44 weak_factory_.GetWeakPtr(), client_id, | 54 weak_factory_.GetWeakPtr(), client_id, |
| 55 gfx::BufferSizeForBufferFormat(size, format), | |
| 45 base::Passed(std::move(callback)))); | 56 base::Passed(std::move(callback)))); |
| 46 return; | 57 return; |
| 47 } | 58 } |
| 48 } | 59 } |
| 49 | 60 |
| 50 gfx::GpuMemoryBufferHandle buffer_handle; | 61 gfx::GpuMemoryBufferHandle buffer_handle; |
| 51 // The requests are coming in from untrusted clients. So verify that it is | 62 // The requests are coming in from untrusted clients. So verify that it is |
| 52 // possible to allocate shared memory buffer first. | 63 // possible to allocate shared memory buffer first. |
| 53 if (gpu::GpuMemoryBufferImplSharedMemory::IsUsageSupported(usage) && | 64 if (gpu::GpuMemoryBufferImplSharedMemory::IsUsageSupported(usage) && |
| 54 gpu::GpuMemoryBufferImplSharedMemory::IsSizeValidForFormat(size, | 65 gpu::GpuMemoryBufferImplSharedMemory::IsSizeValidForFormat(size, |
| 55 format)) { | 66 format)) { |
| 56 buffer_handle = gpu::GpuMemoryBufferImplSharedMemory::CreateGpuMemoryBuffer( | 67 buffer_handle = gpu::GpuMemoryBufferImplSharedMemory::CreateGpuMemoryBuffer( |
| 57 id, size, format); | 68 id, size, format); |
| 69 BufferInfo buffer_info; | |
| 70 DCHECK_EQ(gfx::SHARED_MEMORY_BUFFER, buffer_handle.type); | |
| 71 buffer_info.type = gfx::SHARED_MEMORY_BUFFER; | |
| 72 buffer_info.buffer_size_in_bytes = | |
| 73 gfx::BufferSizeForBufferFormat(size, format); | |
| 74 buffer_info.shared_memory_guid = buffer_handle.handle.GetGUID(); | |
| 75 allocated_buffers_[client_id].insert( | |
| 76 std::make_pair(buffer_handle.id, buffer_info)); | |
| 58 } | 77 } |
| 59 | 78 |
| 60 task_runner_->PostTask(FROM_HERE, | 79 task_runner_->PostTask(FROM_HERE, |
| 61 base::BindOnce(std::move(callback), buffer_handle)); | 80 base::BindOnce(std::move(callback), buffer_handle)); |
| 62 } | 81 } |
| 63 | 82 |
| 64 std::unique_ptr<gfx::GpuMemoryBuffer> | 83 std::unique_ptr<gfx::GpuMemoryBuffer> |
| 65 ServerGpuMemoryBufferManager::CreateGpuMemoryBuffer( | 84 ServerGpuMemoryBufferManager::CreateGpuMemoryBuffer( |
| 66 const gfx::Size& size, | 85 const gfx::Size& size, |
| 67 gfx::BufferFormat format, | 86 gfx::BufferFormat format, |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 97 weak_factory_.GetWeakPtr(), id, client_id_)); | 116 weak_factory_.GetWeakPtr(), id, client_id_)); |
| 98 } | 117 } |
| 99 | 118 |
| 100 void ServerGpuMemoryBufferManager::SetDestructionSyncToken( | 119 void ServerGpuMemoryBufferManager::SetDestructionSyncToken( |
| 101 gfx::GpuMemoryBuffer* buffer, | 120 gfx::GpuMemoryBuffer* buffer, |
| 102 const gpu::SyncToken& sync_token) { | 121 const gpu::SyncToken& sync_token) { |
| 103 static_cast<gpu::GpuMemoryBufferImpl*>(buffer)->set_destruction_sync_token( | 122 static_cast<gpu::GpuMemoryBufferImpl*>(buffer)->set_destruction_sync_token( |
| 104 sync_token); | 123 sync_token); |
| 105 } | 124 } |
| 106 | 125 |
| 126 bool ServerGpuMemoryBufferManager::OnMemoryDump( | |
| 127 const base::trace_event::MemoryDumpArgs& args, | |
| 128 base::trace_event::ProcessMemoryDump* pmd) { | |
| 129 DCHECK(task_runner_->RunsTasksInCurrentSequence()); | |
| 130 for (const auto& pair : allocated_buffers_) { | |
| 131 int client_id = pair.first; | |
| 132 for (const auto& buffer_pair : pair.second) { | |
| 133 gfx::GpuMemoryBufferId buffer_id = buffer_pair.first; | |
| 134 const BufferInfo& buffer_info = buffer_pair.second; | |
| 135 base::trace_event::MemoryAllocatorDump* dump = | |
| 136 pmd->CreateAllocatorDump(base::StringPrintf( | |
| 137 "gpumemorybuffer/client_%d/buffer_%d", client_id, buffer_id.id)); | |
| 138 if (!dump) | |
| 139 return false; | |
| 140 dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, | |
| 141 base::trace_event::MemoryAllocatorDump::kUnitsBytes, | |
| 142 buffer_info.buffer_size_in_bytes); | |
| 143 | |
| 144 // Create the cross-process ownership edge. If the client creates a | |
| 145 // corresponding dump for the same buffer, this will avoid to | |
| 146 // double-count them in tracing. If, instead, no other process will emit a | |
| 147 // dump with the same guid, the segment will be accounted to the browser. | |
| 148 uint64_t client_tracing_process_id = ClientIdToTracingId(client_id); | |
| 149 | |
| 150 if (buffer_info.type == gfx::SHARED_MEMORY_BUFFER) { | |
| 151 auto shared_buffer_guid = gfx::GetSharedMemoryGUIDForTracing( | |
| 152 client_tracing_process_id, buffer_id); | |
| 153 pmd->CreateSharedMemoryOwnershipEdge(dump->guid(), shared_buffer_guid, | |
| 154 buffer_info.shared_memory_guid, | |
| 155 0 /* importance */); | |
| 156 } else { | |
| 157 auto shared_buffer_guid = gfx::GetGenericSharedGpuMemoryGUIDForTracing( | |
| 158 client_tracing_process_id, buffer_id); | |
| 159 pmd->CreateSharedGlobalAllocatorDump(shared_buffer_guid); | |
| 160 pmd->AddOwnershipEdge(dump->guid(), shared_buffer_guid); | |
| 161 } | |
| 162 } | |
| 163 } | |
| 164 return true; | |
| 165 } | |
| 166 | |
| 107 void ServerGpuMemoryBufferManager::DestroyGpuMemoryBuffer( | 167 void ServerGpuMemoryBufferManager::DestroyGpuMemoryBuffer( |
| 108 gfx::GpuMemoryBufferId id, | 168 gfx::GpuMemoryBufferId id, |
| 109 int client_id, | 169 int client_id, |
| 110 const gpu::SyncToken& sync_token) { | 170 const gpu::SyncToken& sync_token) { |
| 111 DCHECK(task_runner_->RunsTasksInCurrentSequence()); | 171 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
| 112 if (native_buffers_[client_id].erase(id)) | 172 auto iter = allocated_buffers_[client_id].find(id); |
| 173 if (iter == allocated_buffers_[client_id].end()) | |
| 174 return; | |
| 175 DCHECK_NE(gfx::EMPTY_BUFFER, iter->second.type); | |
| 176 allocated_buffers_[client_id].erase(id); | |
| 177 if (iter->second.type != gfx::SHARED_MEMORY_BUFFER) | |
| 113 gpu_service_->DestroyGpuMemoryBuffer(id, client_id, sync_token); | 178 gpu_service_->DestroyGpuMemoryBuffer(id, client_id, sync_token); |
| 114 } | 179 } |
| 115 | 180 |
| 116 void ServerGpuMemoryBufferManager::DestroyAllGpuMemoryBufferForClient( | 181 void ServerGpuMemoryBufferManager::DestroyAllGpuMemoryBufferForClient( |
| 117 int client_id) { | 182 int client_id) { |
| 118 DCHECK(task_runner_->RunsTasksInCurrentSequence()); | 183 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
| 119 for (gfx::GpuMemoryBufferId id : native_buffers_[client_id]) | 184 for (auto pair : allocated_buffers_[client_id]) { |
| 120 gpu_service_->DestroyGpuMemoryBuffer(id, client_id, gpu::SyncToken()); | 185 DCHECK_NE(gfx::EMPTY_BUFFER, pair.second.type); |
| 121 native_buffers_.erase(client_id); | 186 if (pair.second.type != gfx::SHARED_MEMORY_BUFFER) { |
| 187 gpu_service_->DestroyGpuMemoryBuffer(pair.first, client_id, | |
| 188 gpu::SyncToken()); | |
| 189 } | |
| 190 } | |
| 191 allocated_buffers_.erase(client_id); | |
| 122 pending_buffers_.erase(client_id); | 192 pending_buffers_.erase(client_id); |
| 123 } | 193 } |
| 124 | 194 |
| 195 uint64_t ServerGpuMemoryBufferManager::ClientIdToTracingId( | |
| 196 int client_id) const { | |
| 197 if (client_id == client_id_) | |
| 198 return MemoryDumpManager::GetInstance()->GetTracingProcessId(); | |
| 199 // TODO(sad|ssid): Find a better way once crbug.com/661257 is resolved. | |
| 200 // The hash value is incremented so that the tracing id is never equal to | |
| 201 // MemoryDumpManager::kInvalidTracingProcessId. | |
| 202 return static_cast<uint64_t>(base::Hash( | |
| 203 reinterpret_cast<const char*>(&client_id), sizeof(client_id))) + | |
| 204 1; | |
| 205 } | |
| 206 | |
| 125 void ServerGpuMemoryBufferManager::OnGpuMemoryBufferAllocated( | 207 void ServerGpuMemoryBufferManager::OnGpuMemoryBufferAllocated( |
| 126 int client_id, | 208 int client_id, |
| 209 size_t buffer_size_in_bytes, | |
| 127 base::OnceCallback<void(const gfx::GpuMemoryBufferHandle&)> callback, | 210 base::OnceCallback<void(const gfx::GpuMemoryBufferHandle&)> callback, |
| 128 const gfx::GpuMemoryBufferHandle& handle) { | 211 const gfx::GpuMemoryBufferHandle& handle) { |
| 129 DCHECK(task_runner_->RunsTasksInCurrentSequence()); | 212 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
| 130 if (pending_buffers_.find(client_id) == pending_buffers_.end()) { | 213 if (pending_buffers_.find(client_id) == pending_buffers_.end()) { |
| 131 // The client has been destroyed since the allocation request was made. | 214 // The client has been destroyed since the allocation request was made. |
| 132 if (!handle.is_null()) { | 215 if (!handle.is_null()) { |
| 133 gpu_service_->DestroyGpuMemoryBuffer(handle.id, client_id, | 216 gpu_service_->DestroyGpuMemoryBuffer(handle.id, client_id, |
| 134 gpu::SyncToken()); | 217 gpu::SyncToken()); |
| 135 } | 218 } |
| 136 std::move(callback).Run(gfx::GpuMemoryBufferHandle()); | 219 std::move(callback).Run(gfx::GpuMemoryBufferHandle()); |
| 137 return; | 220 return; |
| 138 } | 221 } |
| 139 if (!handle.is_null()) | 222 if (!handle.is_null()) { |
| 140 native_buffers_[client_id].insert(handle.id); | 223 BufferInfo buffer_info; |
| 224 buffer_info.type = handle.type; | |
| 225 buffer_info.buffer_size_in_bytes = buffer_size_in_bytes; | |
| 226 allocated_buffers_[client_id].insert( | |
| 227 std::make_pair(handle.id, buffer_info)); | |
| 228 } | |
| 141 std::move(callback).Run(handle); | 229 std::move(callback).Run(handle); |
| 142 } | 230 } |
| 143 | 231 |
| 144 } // namespace viz | 232 } // namespace viz |
| OLD | NEW |