blob: 4858596dbe0eac209e5437f9cedc3a9911dc5bc6 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/gpu/peak_gpu_memory_tracker_impl.h"
#include <memory>
#include "base/bind.h"
#include "base/location.h"
#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/public/browser/gpu_data_manager.h"
#include "services/viz/privileged/mojom/gl/gpu_service.mojom.h"
namespace content {
// static
std::unique_ptr<PeakGpuMemoryTracker> PeakGpuMemoryTracker::Create(
PeakMemoryCallback callback) {
return std::make_unique<PeakGpuMemoryTrackerImpl>(std::move(callback));
}
// static
uint32_t PeakGpuMemoryTrackerImpl::next_sequence_number_ = 0;
PeakGpuMemoryTrackerImpl::PeakGpuMemoryTrackerImpl(PeakMemoryCallback callback)
: callback_(std::move(callback)),
callback_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
// Actually performs request to GPU service to begin memory tracking for
// |sequence_number_|. This will normally be created from the UI thread, so
// repost to the IO thread.
GpuProcessHost::CallOnIO(
GPU_PROCESS_KIND_SANDBOXED, /* force_create=*/false,
base::BindOnce(
[](uint32_t sequence_num, GpuProcessHost* host) {
// There may be no host nor service available. This may occur during
// shutdown, when the service is fully disabled, and in some tests.
// In those cases do nothing.
if (!host)
return;
if (auto* gpu_service = host->gpu_service()) {
gpu_service->StartPeakMemoryMonitor(sequence_num);
}
},
sequence_num_));
}
PeakGpuMemoryTrackerImpl::~PeakGpuMemoryTrackerImpl() {
// The reply arrives on the IO Thread, repost to the callback's thread.
auto wrap_callback = base::BindOnce(
[](base::SingleThreadTaskRunner* task_runner, PeakMemoryCallback callback,
const uint64_t peak_memory) {
if (callback.is_null())
return;
task_runner->PostTask(FROM_HERE,
base::BindOnce(std::move(callback), peak_memory));
},
base::RetainedRef(std::move(callback_task_runner_)),
std::move(callback_));
GpuProcessHost::CallOnIO(
GPU_PROCESS_KIND_SANDBOXED, /* force_create=*/false,
base::BindOnce(
[](uint32_t sequence_num, PeakMemoryCallback callback,
GpuProcessHost* host) {
// There may be no host nor service available. This may occur during
// shutdown, when the service is fully disabled, and in some tests.
// In those cases run the callback, reporting 0 memory usage. This
// will signify a failure state, and allow for the callback to
// perform any needed cleanup.
if (!host) {
std::move(callback).Run(0u);
return;
}
if (auto* gpu_service = host->gpu_service()) {
gpu_service->GetPeakMemoryUsage(sequence_num,
std::move(callback));
}
},
sequence_num_, std::move(wrap_callback)));
}
void PeakGpuMemoryTrackerImpl::Cancel() {
callback_ = PeakMemoryCallback();
}
} // namespace content