123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- // Copyright 2021 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 "media/fuchsia/common/vmo_buffer.h"
- #include <zircon/rights.h>
- #include <algorithm>
- #include "base/bits.h"
- #include "base/fuchsia/fuchsia_logging.h"
- #include "base/memory/page_size.h"
- namespace media {
- // static
- fuchsia::sysmem::BufferCollectionConstraints
- VmoBuffer::GetRecommendedConstraints(size_t min_buffer_count,
- absl::optional<size_t> min_buffer_size,
- bool writable) {
- fuchsia::sysmem::BufferCollectionConstraints buffer_constraints;
- buffer_constraints.usage.cpu = fuchsia::sysmem::cpuUsageRead;
- if (writable)
- buffer_constraints.usage.cpu |= fuchsia::sysmem::cpuUsageWrite;
- buffer_constraints.min_buffer_count = min_buffer_count;
- if (min_buffer_size) {
- buffer_constraints.has_buffer_memory_constraints = true;
- buffer_constraints.buffer_memory_constraints.min_size_bytes =
- min_buffer_size.value();
- buffer_constraints.buffer_memory_constraints.ram_domain_supported = true;
- buffer_constraints.buffer_memory_constraints.cpu_domain_supported = true;
- }
- return buffer_constraints;
- }
- // static
- std::vector<VmoBuffer> VmoBuffer::CreateBuffersFromSysmemCollection(
- fuchsia::sysmem::BufferCollectionInfo_2* info,
- bool writable) {
- std::vector<VmoBuffer> buffers;
- buffers.resize(info->buffer_count);
- fuchsia::sysmem::BufferMemorySettings& settings =
- info->settings.buffer_settings;
- for (size_t i = 0; i < info->buffer_count; ++i) {
- fuchsia::sysmem::VmoBuffer& buffer = info->buffers[i];
- if (!buffers[i].Initialize(std::move(buffer.vmo), writable,
- buffer.vmo_usable_start, settings.size_bytes,
- settings.coherency_domain)) {
- return {};
- }
- }
- return buffers;
- }
- VmoBuffer::VmoBuffer() = default;
- VmoBuffer::~VmoBuffer() {
- if (!base_address_) {
- return;
- }
- zx_status_t status = zx::vmar::root_self()->unmap(
- reinterpret_cast<uintptr_t>(base_address_), mapped_size());
- ZX_DCHECK(status == ZX_OK, status) << "zx_vmar_unmap";
- }
- VmoBuffer::VmoBuffer(VmoBuffer&&) = default;
- VmoBuffer& VmoBuffer::operator=(VmoBuffer&&) = default;
- bool VmoBuffer::Initialize(zx::vmo vmo,
- bool writable,
- size_t offset,
- size_t size,
- fuchsia::sysmem::CoherencyDomain coherency_domain) {
- DCHECK(!base_address_);
- DCHECK(vmo);
- writable_ = writable;
- offset_ = offset;
- size_ = size;
- coherency_domain_ = coherency_domain;
- zx_vm_option_t options = ZX_VM_PERM_READ;
- if (writable)
- options |= ZX_VM_PERM_WRITE;
- uintptr_t addr;
- zx_status_t status =
- zx::vmar::root_self()->map(options, /*vmar_offset=*/0, vmo,
- /*vmo_offset=*/0, mapped_size(), &addr);
- if (status != ZX_OK) {
- ZX_DLOG(ERROR, status) << "zx_vmar_map";
- return false;
- }
- vmo_ = std::move(vmo);
- base_address_ = reinterpret_cast<uint8_t*>(addr);
- return true;
- }
- size_t VmoBuffer::Read(size_t offset, base::span<uint8_t> data) {
- if (offset >= size_)
- return 0U;
- size_t bytes_to_fill = std::min(size_ - offset, data.size());
- FlushCache(offset, bytes_to_fill, /*invalidate=*/true);
- memcpy(data.data(), base_address_ + offset_ + offset, bytes_to_fill);
- return bytes_to_fill;
- }
- size_t VmoBuffer::Write(base::span<const uint8_t> data) {
- DCHECK(writable_);
- size_t bytes_to_fill = std::min(size_, data.size());
- memcpy(base_address_ + offset_, data.data(), bytes_to_fill);
- FlushCache(0, bytes_to_fill, /*invalidate=*/false);
- return bytes_to_fill;
- }
- base::span<const uint8_t> VmoBuffer::GetMemory() {
- FlushCache(0, size_, /*invalidate=*/true);
- return base::make_span(base_address_ + offset_, size_);
- }
- base::span<uint8_t> VmoBuffer::GetWritableMemory() {
- DCHECK(writable_);
- return base::make_span(base_address_ + offset_, size_);
- }
- void VmoBuffer::FlushCache(size_t flush_offset,
- size_t flush_size,
- bool invalidate) {
- DCHECK_LE(flush_size, size_ - flush_offset);
- if (coherency_domain_ != fuchsia::sysmem::CoherencyDomain::RAM)
- return;
- uint8_t* address = base_address_ + offset_ + flush_offset;
- uint32_t options = ZX_CACHE_FLUSH_DATA;
- if (invalidate)
- options |= ZX_CACHE_FLUSH_INVALIDATE;
- zx_status_t status = zx_cache_flush(address, flush_size, options);
- ZX_DCHECK(status == ZX_OK, status) << "zx_cache_flush";
- }
- size_t VmoBuffer::mapped_size() {
- return base::bits::AlignUp(offset_ + size_, base::GetPageSize());
- }
- zx::vmo VmoBuffer::Duplicate(bool writable) {
- zx_rights_t rights = ZX_RIGHT_DUPLICATE | ZX_RIGHT_TRANSFER | ZX_RIGHT_READ |
- ZX_RIGHT_MAP | ZX_RIGHT_GET_PROPERTY;
- if (writable)
- rights |= ZX_RIGHT_WRITE;
- zx::vmo vmo;
- zx_status_t status = vmo_.duplicate(rights, &vmo);
- ZX_CHECK(status == ZX_OK, status) << "zx_handle_duplicate";
- return vmo;
- }
- } // namespace media
|