blob: fbaae57876be031c2734800bc88bff60906b6bc5 [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 "media/video/fake_gpu_memory_buffer.h"
#include "base/atomic_sequence_num.h"
#include "base/no_destructor.h"
#include "build/build_config.h"
#include "media/base/format_utils.h"
#include "media/base/video_frame.h"
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#endif
namespace media {
namespace {
class FakeGpuMemoryBufferImpl : public gpu::GpuMemoryBufferImpl {
public:
FakeGpuMemoryBufferImpl(const gfx::Size& size, gfx::BufferFormat format)
: gpu::GpuMemoryBufferImpl(
gfx::GpuMemoryBufferId(),
size,
format,
gpu::GpuMemoryBufferImpl::DestructionCallback()),
fake_gmb_(std::make_unique<media::FakeGpuMemoryBuffer>(size, format)) {}
// gfx::GpuMemoryBuffer implementation
bool Map() override { return fake_gmb_->Map(); }
void* memory(size_t plane) override { return fake_gmb_->memory(plane); }
void Unmap() override { fake_gmb_->Unmap(); }
int stride(size_t plane) const override { return fake_gmb_->stride(plane); }
gfx::GpuMemoryBufferType GetType() const override {
return fake_gmb_->GetType();
}
gfx::GpuMemoryBufferHandle CloneHandle() const override {
return fake_gmb_->CloneHandle();
}
private:
std::unique_ptr<media::FakeGpuMemoryBuffer> fake_gmb_;
};
} // namespace
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
base::ScopedFD GetDummyFD() {
base::ScopedFD fd(open("/dev/zero", O_RDWR));
DCHECK(fd.is_valid());
return fd;
}
#endif
FakeGpuMemoryBuffer::FakeGpuMemoryBuffer(const gfx::Size& size,
gfx::BufferFormat format)
: FakeGpuMemoryBuffer(size, format, gfx::NativePixmapHandle::kNoModifier) {}
FakeGpuMemoryBuffer::FakeGpuMemoryBuffer(const gfx::Size& size,
gfx::BufferFormat format,
uint64_t modifier)
: size_(size), format_(format) {
absl::optional<VideoPixelFormat> video_pixel_format =
GfxBufferFormatToVideoPixelFormat(format);
CHECK(video_pixel_format);
video_pixel_format_ = *video_pixel_format;
const size_t allocation_size =
VideoFrame::AllocationSize(video_pixel_format_, size_);
data_ = std::vector<uint8_t>(allocation_size);
handle_.type = gfx::NATIVE_PIXMAP;
static base::AtomicSequenceNumber buffer_id_generator;
handle_.id = gfx::GpuMemoryBufferId(buffer_id_generator.GetNext());
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
for (size_t i = 0; i < VideoFrame::NumPlanes(video_pixel_format_); i++) {
const gfx::Size plane_size_in_bytes =
VideoFrame::PlaneSize(video_pixel_format_, i, size_);
handle_.native_pixmap_handle.planes.emplace_back(
plane_size_in_bytes.width(), 0, plane_size_in_bytes.GetArea(),
GetDummyFD());
}
handle_.native_pixmap_handle.modifier = modifier;
#endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
}
FakeGpuMemoryBuffer::~FakeGpuMemoryBuffer() = default;
bool FakeGpuMemoryBuffer::Map() {
return true;
}
void* FakeGpuMemoryBuffer::memory(size_t plane) {
DCHECK_LT(plane, VideoFrame::NumPlanes(video_pixel_format_));
auto* data_ptr = data_.data();
for (size_t i = 1; i <= plane; i++) {
data_ptr +=
VideoFrame::PlaneSize(video_pixel_format_, i - 1, size_).GetArea();
}
return data_ptr;
}
void FakeGpuMemoryBuffer::Unmap() {}
gfx::Size FakeGpuMemoryBuffer::GetSize() const {
return size_;
}
gfx::BufferFormat FakeGpuMemoryBuffer::GetFormat() const {
return format_;
}
int FakeGpuMemoryBuffer::stride(size_t plane) const {
DCHECK_LT(plane, VideoFrame::NumPlanes(video_pixel_format_));
return VideoFrame::PlaneSize(video_pixel_format_, plane, size_).width();
}
void FakeGpuMemoryBuffer::SetColorSpace(const gfx::ColorSpace& color_space) {}
gfx::GpuMemoryBufferId FakeGpuMemoryBuffer::GetId() const {
return handle_.id;
}
gfx::GpuMemoryBufferType FakeGpuMemoryBuffer::GetType() const {
return gfx::NATIVE_PIXMAP;
}
gfx::GpuMemoryBufferHandle FakeGpuMemoryBuffer::CloneHandle() const {
gfx::GpuMemoryBufferHandle handle;
handle.type = gfx::NATIVE_PIXMAP;
handle.id = handle_.id;
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
handle.native_pixmap_handle =
gfx::CloneHandleForIPC(handle_.native_pixmap_handle);
#endif
return handle;
}
ClientBuffer FakeGpuMemoryBuffer::AsClientBuffer() {
NOTREACHED();
return ClientBuffer();
}
void FakeGpuMemoryBuffer::OnMemoryDump(
base::trace_event::ProcessMemoryDump* pmd,
const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid,
uint64_t tracing_process_id,
int importance) const {}
std::unique_ptr<gpu::GpuMemoryBufferImpl>
FakeGpuMemoryBufferSupport::CreateGpuMemoryBufferImplFromHandle(
gfx::GpuMemoryBufferHandle handle,
const gfx::Size& size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
gpu::GpuMemoryBufferImpl::DestructionCallback callback,
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
scoped_refptr<base::UnsafeSharedMemoryPool> pool) {
return std::make_unique<FakeGpuMemoryBufferImpl>(size, format);
}
} // namespace media