blob: 66af72984caef9c1c6a45770bbb881aef400a509 [file] [log] [blame]
// Copyright 2013 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 "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
#include <stdint.h>
#include <utility>
#include "base/lazy_instance.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/process_memory_dump.h"
#include "components/viz/common/resources/resource_sizes.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "ui/gfx/geometry/size.h"
namespace viz {
class BitmapData : public base::RefCounted<BitmapData> {
public:
explicit BitmapData(size_t buffer_size) : buffer_size(buffer_size) {}
std::unique_ptr<base::SharedMemory> memory;
size_t buffer_size;
private:
friend class base::RefCounted<BitmapData>;
~BitmapData() {}
DISALLOW_COPY_AND_ASSIGN(BitmapData);
};
namespace {
// Holds a reference on the BitmapData so that the SharedMemory can outlive the
// SharedBitmapId registration as long as this SharedBitmap object is held
// alive.
class ServerSharedBitmap : public SharedBitmap {
public:
explicit ServerSharedBitmap(scoped_refptr<BitmapData> bitmap_data)
: SharedBitmap(static_cast<uint8_t*>(bitmap_data->memory->memory())),
bitmap_data_(std::move(bitmap_data)) {}
~ServerSharedBitmap() override {
}
private:
scoped_refptr<BitmapData> bitmap_data_;
};
} // namespace
ServerSharedBitmapManager::ServerSharedBitmapManager() = default;
ServerSharedBitmapManager::~ServerSharedBitmapManager() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(handle_map_.empty());
}
std::unique_ptr<SharedBitmap> ServerSharedBitmapManager::GetSharedBitmapFromId(
const gfx::Size& size,
ResourceFormat format,
const SharedBitmapId& id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto it = handle_map_.find(id);
if (it == handle_map_.end())
return nullptr;
BitmapData* data = it->second.get();
size_t bitmap_size;
if (!ResourceSizes::MaybeSizeInBytes(size, format, &bitmap_size) ||
bitmap_size > data->buffer_size)
return nullptr;
if (!data->memory->memory()) {
return nullptr;
}
return std::make_unique<ServerSharedBitmap>(data);
}
base::UnguessableToken
ServerSharedBitmapManager::GetSharedBitmapTracingGUIDFromId(
const SharedBitmapId& id) {
auto it = handle_map_.find(id);
if (it == handle_map_.end())
return {};
BitmapData* data = it->second.get();
return data->memory->mapped_id();
}
bool ServerSharedBitmapManager::ChildAllocatedSharedBitmap(
mojo::ScopedSharedBufferHandle buffer,
const SharedBitmapId& id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// Duplicate ids are not allowed.
if (base::ContainsKey(handle_map_, id))
return false;
base::SharedMemoryHandle memory_handle;
size_t buffer_size;
MojoResult result = mojo::UnwrapSharedMemoryHandle(
std::move(buffer), &memory_handle, &buffer_size, nullptr);
// This function handles public API requests, so verify we unwrapped a shared
// memory handle before trying to use the handle.
if (result != MOJO_RESULT_OK)
return false;
auto data = base::MakeRefCounted<BitmapData>(buffer_size);
data->memory = std::make_unique<base::SharedMemory>(memory_handle, false);
// Map the memory to get a pointer to it, then close it to free up the fd so
// it can be reused. This doesn't unmap the memory. Some OS have a very
// limited number of fds and this avoids consuming them all.
data->memory->Map(data->buffer_size);
data->memory->Close();
handle_map_[id] = std::move(data);
return true;
}
void ServerSharedBitmapManager::ChildDeletedSharedBitmap(
const SharedBitmapId& id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
handle_map_.erase(id);
}
bool ServerSharedBitmapManager::OnMemoryDump(
const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
for (const auto& pair : handle_map_) {
const SharedBitmapId& id = pair.first;
BitmapData* data = pair.second.get();
std::string dump_str = base::StringPrintf(
"sharedbitmap/%s", base::HexEncode(id.name, sizeof(id.name)).c_str());
base::trace_event::MemoryAllocatorDump* dump =
pmd->CreateAllocatorDump(dump_str);
if (!dump)
return false;
dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
base::trace_event::MemoryAllocatorDump::kUnitsBytes,
data->buffer_size);
// This GUID is the same returned by GetSharedBitmapTracingGUIDFromId() so
// other components use a consistent GUID for a given SharedBitmapId.
base::UnguessableToken shared_memory_guid = data->memory->mapped_id();
DCHECK(!shared_memory_guid.is_empty());
pmd->CreateSharedMemoryOwnershipEdge(dump->guid(), shared_memory_guid,
0 /* importance*/);
}
return true;
}
} // namespace viz