blob: 9af344380cbf80cb27245d89ae8f01d3f45ada9e [file] [log] [blame]
// Copyright 2016 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 "ui/gfx/mojom/buffer_types_mojom_traits.h"
#include "build/build_config.h"
#if defined(OS_ANDROID)
#include "base/android/scoped_hardware_buffer_handle.h"
#include "mojo/public/cpp/system/message_pipe.h"
#include "mojo/public/cpp/system/scope_to_message_pipe.h"
#endif
namespace mojo {
// static
bool StructTraits<gfx::mojom::BufferUsageAndFormatDataView,
gfx::BufferUsageAndFormat>::
Read(gfx::mojom::BufferUsageAndFormatDataView data,
gfx::BufferUsageAndFormat* out) {
return data.ReadUsage(&out->usage) && data.ReadFormat(&out->format);
}
gfx::mojom::GpuMemoryBufferPlatformHandlePtr StructTraits<
gfx::mojom::GpuMemoryBufferHandleDataView,
gfx::GpuMemoryBufferHandle>::platform_handle(gfx::GpuMemoryBufferHandle&
handle) {
switch (handle.type) {
case gfx::EMPTY_BUFFER:
break;
case gfx::SHARED_MEMORY_BUFFER:
return gfx::mojom::GpuMemoryBufferPlatformHandle::NewSharedMemoryHandle(
std::move(handle.region));
case gfx::NATIVE_PIXMAP:
#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(USE_OZONE)
return gfx::mojom::GpuMemoryBufferPlatformHandle::NewNativePixmapHandle(
std::move(handle.native_pixmap_handle));
#else
break;
#endif
case gfx::IO_SURFACE_BUFFER: {
#if defined(OS_MAC)
gfx::ScopedRefCountedIOSurfaceMachPort io_surface_mach_port(
IOSurfaceCreateMachPort(handle.io_surface.get()));
return gfx::mojom::GpuMemoryBufferPlatformHandle::NewMachPort(
mojo::PlatformHandle(
base::mac::RetainMachSendRight(io_surface_mach_port.get())));
#else
break;
#endif
}
case gfx::DXGI_SHARED_HANDLE:
#if defined(OS_WIN)
DCHECK(handle.dxgi_handle.IsValid());
return gfx::mojom::GpuMemoryBufferPlatformHandle::NewDxgiHandle(
gfx::mojom::DxgiHandle::New(
mojo::PlatformHandle(std::move(handle.dxgi_handle)),
std::move(handle.region)));
#else
break;
#endif
case gfx::ANDROID_HARDWARE_BUFFER: {
#if defined(OS_ANDROID)
// We must keep a ref to the AHardwareBuffer alive until the receiver has
// acquired its own reference. We do this by sending a message pipe handle
// along with the buffer. When the receiver deserializes (or even if they
// die without ever reading the message) their end of the pipe will be
// closed. We will eventually detect this and release the AHB reference.
mojo::MessagePipe tracking_pipe;
auto wrapped_handle = gfx::mojom::AHardwareBufferHandle::New(
mojo::PlatformHandle(
handle.android_hardware_buffer.SerializeAsFileDescriptor()),
std::move(tracking_pipe.handle0));
// Pass ownership of the input handle to our tracking pipe to keep the AHB
// alive until it's deserialized.
mojo::ScopeToMessagePipe(std::move(handle.android_hardware_buffer),
std::move(tracking_pipe.handle1));
return gfx::mojom::GpuMemoryBufferPlatformHandle::
NewAndroidHardwareBufferHandle(std::move(wrapped_handle));
#else
break;
#endif
}
}
return nullptr;
}
bool StructTraits<gfx::mojom::GpuMemoryBufferHandleDataView,
gfx::GpuMemoryBufferHandle>::
Read(gfx::mojom::GpuMemoryBufferHandleDataView data,
gfx::GpuMemoryBufferHandle* out) {
if (!data.ReadId(&out->id))
return false;
out->offset = data.offset();
out->stride = data.stride();
gfx::mojom::GpuMemoryBufferPlatformHandlePtr platform_handle;
if (!data.ReadPlatformHandle(&platform_handle)) {
return false;
}
if (!platform_handle) {
out->type = gfx::EMPTY_BUFFER;
return true;
}
switch (platform_handle->which()) {
case gfx::mojom::GpuMemoryBufferPlatformHandleDataView::Tag::
SHARED_MEMORY_HANDLE:
out->type = gfx::SHARED_MEMORY_BUFFER;
out->region = std::move(platform_handle->get_shared_memory_handle());
return true;
#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(USE_OZONE)
case gfx::mojom::GpuMemoryBufferPlatformHandleDataView::Tag::
NATIVE_PIXMAP_HANDLE:
out->type = gfx::NATIVE_PIXMAP;
out->native_pixmap_handle =
std::move(platform_handle->get_native_pixmap_handle());
return true;
#elif defined(OS_MAC)
case gfx::mojom::GpuMemoryBufferPlatformHandleDataView::Tag::MACH_PORT: {
out->type = gfx::IO_SURFACE_BUFFER;
if (!platform_handle->get_mach_port().is_mach_send())
return false;
gfx::ScopedRefCountedIOSurfaceMachPort io_surface_mach_port(
platform_handle->get_mach_port().ReleaseMachSendRight());
if (io_surface_mach_port) {
out->io_surface.reset(
IOSurfaceLookupFromMachPort(io_surface_mach_port.get()));
} else {
out->io_surface.reset();
}
return true;
}
#elif defined(OS_WIN)
case gfx::mojom::GpuMemoryBufferPlatformHandleDataView::Tag::DXGI_HANDLE: {
out->type = gfx::DXGI_SHARED_HANDLE;
auto dxgi_handle = std::move(platform_handle->get_dxgi_handle());
out->dxgi_handle = dxgi_handle->buffer_handle.TakeHandle();
out->region = std::move(dxgi_handle->shared_memory_handle);
return true;
}
#elif defined(OS_ANDROID)
case gfx::mojom::GpuMemoryBufferPlatformHandleDataView::Tag::
ANDROID_HARDWARE_BUFFER_HANDLE: {
out->type = gfx::ANDROID_HARDWARE_BUFFER;
gfx::mojom::AHardwareBufferHandlePtr buffer_handle =
std::move(platform_handle->get_android_hardware_buffer_handle());
if (!buffer_handle)
return false;
base::ScopedFD scoped_fd = buffer_handle->buffer_handle.TakeFD();
if (!scoped_fd.is_valid())
return false;
out->android_hardware_buffer = base::android::ScopedHardwareBufferHandle::
DeserializeFromFileDescriptor(std::move(scoped_fd));
return out->android_hardware_buffer.is_valid();
}
#endif
}
return false;
}
} // namespace mojo