blob: 569e01562968c6507d52354d0dbe81843a9da23a [file] [log] [blame]
// Copyright 2014 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 "gpu/ipc/common/gpu_memory_buffer_impl_native_pixmap.h"
#include <utility>
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "gpu/ipc/common/gpu_memory_buffer_support.h"
#include "ui/gfx/buffer_format_util.h"
#include "ui/gfx/client_native_pixmap_factory.h"
#include "ui/gfx/native_pixmap.h"
#if defined(USE_OZONE)
#include "ui/ozone/public/ozone_platform.h"
#include "ui/ozone/public/surface_factory_ozone.h"
#endif
namespace gpu {
namespace {
void FreeNativePixmapForTesting(
scoped_refptr<gfx::NativePixmap> native_pixmap) {
// Nothing to do here. |native_pixmap| will be freed when this function
// returns and reference count drops to 0.
}
} // namespace
GpuMemoryBufferImplNativePixmap::GpuMemoryBufferImplNativePixmap(
gfx::GpuMemoryBufferId id,
const gfx::Size& size,
gfx::BufferFormat format,
DestructionCallback callback,
std::unique_ptr<gfx::ClientNativePixmap> pixmap,
const std::vector<gfx::NativePixmapPlane>& planes,
std::vector<base::ScopedFD> fds)
: GpuMemoryBufferImpl(id, size, format, std::move(callback)),
pixmap_(std::move(pixmap)),
planes_(planes),
fds_(std::move(fds)) {}
GpuMemoryBufferImplNativePixmap::~GpuMemoryBufferImplNativePixmap() = default;
// static
std::unique_ptr<GpuMemoryBufferImplNativePixmap>
GpuMemoryBufferImplNativePixmap::CreateFromHandle(
gfx::ClientNativePixmapFactory* client_native_pixmap_factory,
const gfx::GpuMemoryBufferHandle& handle,
const gfx::Size& size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
DestructionCallback callback) {
std::vector<base::ScopedFD> fds;
std::vector<base::ScopedFD> dup_fds;
for (auto& fd : handle.native_pixmap_handle.fds) {
DCHECK(fd.auto_close);
// Take ownership of FD
fds.emplace_back(fd.fd);
// Duplicate FD for GpuMemoryBufferImplNativePixmap ctor.
dup_fds.emplace_back(HANDLE_EINTR(dup(fd.fd)));
if (!dup_fds.back().is_valid()) {
PLOG(ERROR) << "dup";
return nullptr;
}
}
gfx::NativePixmapHandle native_pixmap_handle;
for (auto& fd : dup_fds) {
native_pixmap_handle.fds.emplace_back(fd.release(), true /* auto_close */);
}
native_pixmap_handle.planes = handle.native_pixmap_handle.planes;
std::unique_ptr<gfx::ClientNativePixmap> native_pixmap =
client_native_pixmap_factory->ImportFromHandle(
std::move(native_pixmap_handle), size, usage);
DCHECK(native_pixmap);
return base::WrapUnique(new GpuMemoryBufferImplNativePixmap(
handle.id, size, format, std::move(callback), std::move(native_pixmap),
handle.native_pixmap_handle.planes, std::move(fds)));
}
// static
base::OnceClosure GpuMemoryBufferImplNativePixmap::AllocateForTesting(
const gfx::Size& size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
gfx::GpuMemoryBufferHandle* handle) {
#if defined(USE_OZONE)
scoped_refptr<gfx::NativePixmap> pixmap =
ui::OzonePlatform::GetInstance()
->GetSurfaceFactoryOzone()
->CreateNativePixmap(gfx::kNullAcceleratedWidget, size, format,
usage);
handle->native_pixmap_handle = pixmap->ExportHandle();
#else
// TODO(j.isorce): use gbm_bo_create / gbm_bo_get_fd from system libgbm.
scoped_refptr<gfx::NativePixmap> pixmap;
NOTIMPLEMENTED();
#endif
handle->type = gfx::NATIVE_PIXMAP;
return base::BindOnce(&FreeNativePixmapForTesting, pixmap);
}
bool GpuMemoryBufferImplNativePixmap::Map() {
DCHECK(!mapped_);
mapped_ = pixmap_->Map();
return mapped_;
}
void* GpuMemoryBufferImplNativePixmap::memory(size_t plane) {
DCHECK(mapped_);
return pixmap_->GetMemoryAddress(plane);
}
void GpuMemoryBufferImplNativePixmap::Unmap() {
DCHECK(mapped_);
pixmap_->Unmap();
mapped_ = false;
}
int GpuMemoryBufferImplNativePixmap::stride(size_t plane) const {
DCHECK_LT(plane, gfx::NumberOfPlanesForBufferFormat(format_));
return pixmap_->GetStride(plane);
}
gfx::GpuMemoryBufferType GpuMemoryBufferImplNativePixmap::GetType() const {
return gfx::NATIVE_PIXMAP;
}
gfx::GpuMemoryBufferHandle GpuMemoryBufferImplNativePixmap::CloneHandle()
const {
gfx::GpuMemoryBufferHandle handle;
handle.type = gfx::NATIVE_PIXMAP;
handle.id = id_;
gfx::NativePixmapHandle native_pixmap_handle;
for (const auto& fd : fds_) {
native_pixmap_handle.fds.emplace_back(fd.get(), false /* auto_close */);
}
native_pixmap_handle.planes = planes_;
handle.native_pixmap_handle = gfx::CloneHandleForIPC(native_pixmap_handle);
return handle;
}
} // namespace gpu