| 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" |
| 13 | 18 |
| 14 namespace viz { | 19 namespace viz { |
| 15 | 20 |
| 21 ServerGpuMemoryBufferManager::BufferInfo::BufferInfo() = default; |
| 22 ServerGpuMemoryBufferManager::BufferInfo::~BufferInfo() = default; |
| 23 |
| 16 ServerGpuMemoryBufferManager::ServerGpuMemoryBufferManager( | 24 ServerGpuMemoryBufferManager::ServerGpuMemoryBufferManager( |
| 17 ui::mojom::GpuService* gpu_service, | 25 ui::mojom::GpuService* gpu_service, |
| 18 int client_id) | 26 int client_id) |
| 19 : gpu_service_(gpu_service), | 27 : gpu_service_(gpu_service), |
| 20 client_id_(client_id), | 28 client_id_(client_id), |
| 21 native_configurations_(gpu::GetNativeGpuMemoryBufferConfigurations()), | 29 native_configurations_(gpu::GetNativeGpuMemoryBufferConfigurations()), |
| 22 task_runner_(base::SequencedTaskRunnerHandle::Get()), | 30 task_runner_(base::SequencedTaskRunnerHandle::Get()), |
| 23 weak_factory_(this) {} | 31 weak_factory_(this) {} |
| 24 | 32 |
| 25 ServerGpuMemoryBufferManager::~ServerGpuMemoryBufferManager() {} | 33 ServerGpuMemoryBufferManager::~ServerGpuMemoryBufferManager() {} |
| 26 | 34 |
| 27 void ServerGpuMemoryBufferManager::AllocateGpuMemoryBuffer( | 35 void ServerGpuMemoryBufferManager::AllocateGpuMemoryBuffer( |
| 28 gfx::GpuMemoryBufferId id, | 36 gfx::GpuMemoryBufferId id, |
| 29 int client_id, | 37 int client_id, |
| 30 const gfx::Size& size, | 38 const gfx::Size& size, |
| 31 gfx::BufferFormat format, | 39 gfx::BufferFormat format, |
| 32 gfx::BufferUsage usage, | 40 gfx::BufferUsage usage, |
| 33 gpu::SurfaceHandle surface_handle, | 41 gpu::SurfaceHandle surface_handle, |
| 34 base::OnceCallback<void(const gfx::GpuMemoryBufferHandle&)> callback) { | 42 base::OnceCallback<void(const gfx::GpuMemoryBufferHandle&)> callback) { |
| 35 DCHECK(task_runner_->RunsTasksInCurrentSequence()); | 43 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
| 36 if (gpu::GetNativeGpuMemoryBufferType() != gfx::EMPTY_BUFFER) { | 44 if (gpu::GetNativeGpuMemoryBufferType() != gfx::EMPTY_BUFFER) { |
| 37 const bool is_native = native_configurations_.find(std::make_pair( | 45 const bool is_native = native_configurations_.find(std::make_pair( |
| 38 format, usage)) != native_configurations_.end(); | 46 format, usage)) != native_configurations_.end(); |
| 39 if (is_native) { | 47 if (is_native) { |
| 40 pending_buffers_.insert(client_id); | 48 pending_buffers_.insert(client_id); |
| 41 gpu_service_->CreateGpuMemoryBuffer( | 49 gpu_service_->CreateGpuMemoryBuffer( |
| 42 id, size, format, usage, client_id, surface_handle, | 50 id, size, format, usage, client_id, surface_handle, |
| 43 base::Bind(&ServerGpuMemoryBufferManager::OnGpuMemoryBufferAllocated, | 51 base::Bind(&ServerGpuMemoryBufferManager::OnGpuMemoryBufferAllocated, |
| 44 weak_factory_.GetWeakPtr(), client_id, | 52 weak_factory_.GetWeakPtr(), client_id, |
| 53 gfx::BufferSizeForBufferFormat(size, format), |
| 45 base::Passed(std::move(callback)))); | 54 base::Passed(std::move(callback)))); |
| 46 return; | 55 return; |
| 47 } | 56 } |
| 48 } | 57 } |
| 49 | 58 |
| 50 gfx::GpuMemoryBufferHandle buffer_handle; | 59 gfx::GpuMemoryBufferHandle buffer_handle; |
| 51 // The requests are coming in from untrusted clients. So verify that it is | 60 // The requests are coming in from untrusted clients. So verify that it is |
| 52 // possible to allocate shared memory buffer first. | 61 // possible to allocate shared memory buffer first. |
| 53 if (gpu::GpuMemoryBufferImplSharedMemory::IsUsageSupported(usage) && | 62 if (gpu::GpuMemoryBufferImplSharedMemory::IsUsageSupported(usage) && |
| 54 gpu::GpuMemoryBufferImplSharedMemory::IsSizeValidForFormat(size, | 63 gpu::GpuMemoryBufferImplSharedMemory::IsSizeValidForFormat(size, |
| 55 format)) { | 64 format)) { |
| 56 buffer_handle = gpu::GpuMemoryBufferImplSharedMemory::CreateGpuMemoryBuffer( | 65 buffer_handle = gpu::GpuMemoryBufferImplSharedMemory::CreateGpuMemoryBuffer( |
| 57 id, size, format); | 66 id, size, format); |
| 67 BufferInfo buffer_info; |
| 68 DCHECK_EQ(gfx::SHARED_MEMORY_BUFFER, buffer_handle.type); |
| 69 buffer_info.type = gfx::SHARED_MEMORY_BUFFER; |
| 70 buffer_info.buffer_size_in_bytes = |
| 71 gfx::BufferSizeForBufferFormat(size, format); |
| 72 buffer_info.shared_memory_guid = buffer_handle.handle.GetGUID(); |
| 73 allocated_buffers_[client_id].insert( |
| 74 std::make_pair(buffer_handle.id, buffer_info)); |
| 58 } | 75 } |
| 59 | 76 |
| 60 task_runner_->PostTask(FROM_HERE, | 77 task_runner_->PostTask(FROM_HERE, |
| 61 base::BindOnce(std::move(callback), buffer_handle)); | 78 base::BindOnce(std::move(callback), buffer_handle)); |
| 62 } | 79 } |
| 63 | 80 |
| 64 std::unique_ptr<gfx::GpuMemoryBuffer> | 81 std::unique_ptr<gfx::GpuMemoryBuffer> |
| 65 ServerGpuMemoryBufferManager::CreateGpuMemoryBuffer( | 82 ServerGpuMemoryBufferManager::CreateGpuMemoryBuffer( |
| 66 const gfx::Size& size, | 83 const gfx::Size& size, |
| 67 gfx::BufferFormat format, | 84 gfx::BufferFormat format, |
| (...skipping 29 matching lines...) Expand all Loading... |
| 97 weak_factory_.GetWeakPtr(), id, client_id_)); | 114 weak_factory_.GetWeakPtr(), id, client_id_)); |
| 98 } | 115 } |
| 99 | 116 |
| 100 void ServerGpuMemoryBufferManager::SetDestructionSyncToken( | 117 void ServerGpuMemoryBufferManager::SetDestructionSyncToken( |
| 101 gfx::GpuMemoryBuffer* buffer, | 118 gfx::GpuMemoryBuffer* buffer, |
| 102 const gpu::SyncToken& sync_token) { | 119 const gpu::SyncToken& sync_token) { |
| 103 static_cast<gpu::GpuMemoryBufferImpl*>(buffer)->set_destruction_sync_token( | 120 static_cast<gpu::GpuMemoryBufferImpl*>(buffer)->set_destruction_sync_token( |
| 104 sync_token); | 121 sync_token); |
| 105 } | 122 } |
| 106 | 123 |
| 124 bool ServerGpuMemoryBufferManager::OnMemoryDump( |
| 125 const base::trace_event::MemoryDumpArgs& args, |
| 126 base::trace_event::ProcessMemoryDump* pmd) { |
| 127 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
| 128 for (const auto& pair : allocated_buffers_) { |
| 129 int client_id = pair.first; |
| 130 for (const auto& buffer_pair : pair.second) { |
| 131 gfx::GpuMemoryBufferId buffer_id = buffer_pair.first; |
| 132 const BufferInfo& buffer_info = buffer_pair.second; |
| 133 base::trace_event::MemoryAllocatorDump* dump = |
| 134 pmd->CreateAllocatorDump(base::StringPrintf( |
| 135 "gpumemorybuffer/client_%d/buffer_%d", client_id, buffer_id.id)); |
| 136 if (!dump) |
| 137 return false; |
| 138 dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, |
| 139 base::trace_event::MemoryAllocatorDump::kUnitsBytes, |
| 140 buffer_info.buffer_size_in_bytes); |
| 141 |
| 142 // Create the cross-process ownership edge. If the client creates a |
| 143 // corresponding dump for the same buffer, this will avoid to |
| 144 // double-count them in tracing. If, instead, no other process will emit a |
| 145 // dump with the same guid, the segment will be accounted to the browser. |
| 146 uint64_t client_tracing_process_id = ClientIdToTracingId(client_id); |
| 147 |
| 148 if (buffer_info.type == gfx::SHARED_MEMORY_BUFFER) { |
| 149 auto shared_buffer_guid = gfx::GetSharedMemoryGUIDForTracing( |
| 150 client_tracing_process_id, buffer_id); |
| 151 pmd->CreateSharedMemoryOwnershipEdge(dump->guid(), shared_buffer_guid, |
| 152 buffer_info.shared_memory_guid, |
| 153 0 /* importance */); |
| 154 } else { |
| 155 auto shared_buffer_guid = gfx::GetGenericSharedGpuMemoryGUIDForTracing( |
| 156 client_tracing_process_id, buffer_id); |
| 157 pmd->CreateSharedGlobalAllocatorDump(shared_buffer_guid); |
| 158 pmd->AddOwnershipEdge(dump->guid(), shared_buffer_guid); |
| 159 } |
| 160 } |
| 161 } |
| 162 return true; |
| 163 } |
| 164 |
| 107 void ServerGpuMemoryBufferManager::DestroyGpuMemoryBuffer( | 165 void ServerGpuMemoryBufferManager::DestroyGpuMemoryBuffer( |
| 108 gfx::GpuMemoryBufferId id, | 166 gfx::GpuMemoryBufferId id, |
| 109 int client_id, | 167 int client_id, |
| 110 const gpu::SyncToken& sync_token) { | 168 const gpu::SyncToken& sync_token) { |
| 111 DCHECK(task_runner_->RunsTasksInCurrentSequence()); | 169 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
| 112 if (native_buffers_[client_id].erase(id)) | 170 auto iter = allocated_buffers_[client_id].find(id); |
| 171 if (iter == allocated_buffers_[client_id].end()) |
| 172 return; |
| 173 DCHECK_NE(gfx::EMPTY_BUFFER, iter->second.type); |
| 174 allocated_buffers_[client_id].erase(id); |
| 175 if (iter->second.type != gfx::SHARED_MEMORY_BUFFER) |
| 113 gpu_service_->DestroyGpuMemoryBuffer(id, client_id, sync_token); | 176 gpu_service_->DestroyGpuMemoryBuffer(id, client_id, sync_token); |
| 114 } | 177 } |
| 115 | 178 |
| 116 void ServerGpuMemoryBufferManager::DestroyAllGpuMemoryBufferForClient( | 179 void ServerGpuMemoryBufferManager::DestroyAllGpuMemoryBufferForClient( |
| 117 int client_id) { | 180 int client_id) { |
| 118 DCHECK(task_runner_->RunsTasksInCurrentSequence()); | 181 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
| 119 for (gfx::GpuMemoryBufferId id : native_buffers_[client_id]) | 182 for (auto pair : allocated_buffers_[client_id]) { |
| 120 gpu_service_->DestroyGpuMemoryBuffer(id, client_id, gpu::SyncToken()); | 183 DCHECK_NE(gfx::EMPTY_BUFFER, pair.second.type); |
| 121 native_buffers_.erase(client_id); | 184 if (pair.second.type != gfx::SHARED_MEMORY_BUFFER) { |
| 185 gpu_service_->DestroyGpuMemoryBuffer(pair.first, client_id, |
| 186 gpu::SyncToken()); |
| 187 } |
| 188 } |
| 189 allocated_buffers_.erase(client_id); |
| 122 pending_buffers_.erase(client_id); | 190 pending_buffers_.erase(client_id); |
| 123 } | 191 } |
| 124 | 192 |
| 193 uint64_t ServerGpuMemoryBufferManager::ClientIdToTracingId( |
| 194 int client_id) const { |
| 195 if (client_id == client_id_) { |
| 196 return base::trace_event::MemoryDumpManager::GetInstance() |
| 197 ->GetTracingProcessId(); |
| 198 } |
| 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 |