Commit 48792632 authored by Christopher Cameron's avatar Christopher Cameron Committed by Commit Bot

Use IOSurface directly in gfx::BufferHandle

Change gfx::BufferHandle to use a gfx::ScopedIOSurface instead of a
gfx::ScopedRefCountedIOSurfaceMachPort.

Reason for using a mach port: It's the thing that goes over all forms
of IPC.

Reason for not using a mach port: The mach port's existence makes the
IOSurface report that it is in use. This makes it so that things like
CVPixelBufferPools will not re-use that IOSurface. The capture pipeline
keeps lots of gfx::BufferHandles around, which causes the underlying
CVPixelBufferPool to go haywire (in this case growing without bound,
but another valid way to blow up is to just hang and never capture
any more frames).

Also remove some debugging code.

Bug: 1139105
Change-Id: I1ffa11a325b6a8e1811a23b1c4d7dac00fad49db
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2485992Reviewed-by: default avatarRobert Sesek <rsesek@chromium.org>
Reviewed-by: default avatarPeng Huang <penghuang@chromium.org>
Reviewed-by: default avatarDan Sanders <sandersd@chromium.org>
Commit-Queue: ccameron <ccameron@chromium.org>
Cr-Commit-Position: refs/heads/master@{#818727}
parent e48aaa45
...@@ -67,13 +67,12 @@ GpuMemoryBufferImplIOSurface::CreateFromHandle( ...@@ -67,13 +67,12 @@ GpuMemoryBufferImplIOSurface::CreateFromHandle(
gfx::BufferFormat format, gfx::BufferFormat format,
gfx::BufferUsage usage, gfx::BufferUsage usage,
DestructionCallback callback) { DestructionCallback callback) {
if (!handle.mach_port) { if (!handle.io_surface) {
LOG(ERROR) << "Invalid IOSurface mach port returned to client."; LOG(ERROR) << "Invalid IOSurface returned to client.";
return nullptr; return nullptr;
} }
base::ScopedCFTypeRef<IOSurfaceRef> io_surface( gfx::ScopedIOSurface io_surface = handle.io_surface;
IOSurfaceLookupFromMachPort(handle.mach_port.get()));
if (!io_surface) { if (!io_surface) {
LOG(ERROR) << "Failed to open IOSurface via mach port returned to client."; LOG(ERROR) << "Failed to open IOSurface via mach port returned to client.";
static int dump_counter = kMaxCrashDumps; static int dump_counter = kMaxCrashDumps;
...@@ -101,13 +100,11 @@ base::OnceClosure GpuMemoryBufferImplIOSurface::AllocateForTesting( ...@@ -101,13 +100,11 @@ base::OnceClosure GpuMemoryBufferImplIOSurface::AllocateForTesting(
gfx::BufferFormat format, gfx::BufferFormat format,
gfx::BufferUsage usage, gfx::BufferUsage usage,
gfx::GpuMemoryBufferHandle* handle) { gfx::GpuMemoryBufferHandle* handle) {
base::ScopedCFTypeRef<IOSurfaceRef> io_surface(
gfx::CreateIOSurface(size, format));
DCHECK(io_surface);
gfx::GpuMemoryBufferId kBufferId(1); gfx::GpuMemoryBufferId kBufferId(1);
handle->type = gfx::IO_SURFACE_BUFFER; handle->type = gfx::IO_SURFACE_BUFFER;
handle->id = kBufferId; handle->id = kBufferId;
handle->mach_port.reset(IOSurfaceCreateMachPort(io_surface)); handle->io_surface.reset(gfx::CreateIOSurface(size, format));
DCHECK(handle->io_surface);
return base::DoNothing(); return base::DoNothing();
} }
...@@ -152,7 +149,7 @@ gfx::GpuMemoryBufferHandle GpuMemoryBufferImplIOSurface::CloneHandle() const { ...@@ -152,7 +149,7 @@ gfx::GpuMemoryBufferHandle GpuMemoryBufferImplIOSurface::CloneHandle() const {
gfx::GpuMemoryBufferHandle handle; gfx::GpuMemoryBufferHandle handle;
handle.type = gfx::IO_SURFACE_BUFFER; handle.type = gfx::IO_SURFACE_BUFFER;
handle.id = id_; handle.id = id_;
handle.mach_port.reset(IOSurfaceCreateMachPort(io_surface_)); handle.io_surface = io_surface_;
return handle; return handle;
} }
......
...@@ -19,12 +19,10 @@ ...@@ -19,12 +19,10 @@
namespace gpu { namespace gpu {
namespace { namespace {
// A GpuMemoryBuffer with client_id = 0 behaves like anonymous shared memory. // A GpuMemoryBuffer with client_id = 0 behaves like anonymous shared memory.
const int kAnonymousClientId = 0; const int kAnonymousClientId = 0;
// The maximum number of times to dump before throttling (to avoid sending
// thousands of crash dumps).
const int kMaxCrashDumps = 10;
} // namespace } // namespace
GpuMemoryBufferFactoryIOSurface::GpuMemoryBufferFactoryIOSurface() { GpuMemoryBufferFactoryIOSurface::GpuMemoryBufferFactoryIOSurface() {
...@@ -56,27 +54,7 @@ GpuMemoryBufferFactoryIOSurface::CreateGpuMemoryBuffer( ...@@ -56,27 +54,7 @@ GpuMemoryBufferFactoryIOSurface::CreateGpuMemoryBuffer(
gfx::GpuMemoryBufferHandle handle; gfx::GpuMemoryBufferHandle handle;
handle.type = gfx::IO_SURFACE_BUFFER; handle.type = gfx::IO_SURFACE_BUFFER;
handle.id = id; handle.id = id;
handle.mach_port.reset(IOSurfaceCreateMachPort(io_surface)); handle.io_surface = io_surface;
CHECK(handle.mach_port);
// This IOSurface will be opened via mach port in the client process. It has
// been observed in https://crbug.com/574014 that these ports sometimes fail
// to be opened in the client process. It has further been observed in
// https://crbug.com/795649#c30 that these ports fail to be opened in creating
// process. To determine if these failures are independent, attempt to open
// the creating process first (and don't not return those that fail).
base::ScopedCFTypeRef<IOSurfaceRef> io_surface_from_mach_port(
IOSurfaceLookupFromMachPort(handle.mach_port.get()));
if (!io_surface_from_mach_port) {
LOG(ERROR) << "Failed to locally open IOSurface from mach port to be "
"returned to client, not returning to client.";
static int dump_counter = kMaxCrashDumps;
if (dump_counter) {
dump_counter -= 1;
base::debug::DumpWithoutCrashing();
}
return gfx::GpuMemoryBufferHandle();
}
{ {
base::AutoLock lock(io_surfaces_lock_); base::AutoLock lock(io_surfaces_lock_);
...@@ -127,8 +105,8 @@ GpuMemoryBufferFactoryIOSurface::CreateImageForGpuMemoryBuffer( ...@@ -127,8 +105,8 @@ GpuMemoryBufferFactoryIOSurface::CreateImageForGpuMemoryBuffer(
IOSurfaceMap::iterator it = io_surfaces_.find(key); IOSurfaceMap::iterator it = io_surfaces_.find(key);
if (it != io_surfaces_.end()) if (it != io_surfaces_.end())
io_surface = it->second; io_surface = it->second;
} else if (handle.mach_port) { } else if (handle.io_surface) {
io_surface.reset(IOSurfaceLookupFromMachPort(handle.mach_port.get())); io_surface = handle.io_surface;
if (!io_surface) { if (!io_surface) {
DLOG(ERROR) << "Failed to open IOSurface from handle."; DLOG(ERROR) << "Failed to open IOSurface from handle.";
return nullptr; return nullptr;
...@@ -181,28 +159,6 @@ GpuMemoryBufferFactoryIOSurface::CreateAnonymousImage( ...@@ -181,28 +159,6 @@ GpuMemoryBufferFactoryIOSurface::CreateAnonymousImage(
return nullptr; return nullptr;
} }
// This IOSurface does not require passing via a mach port, but attempt to
// locally open via a mach port to gather data to include in a Radar about
// this failure.
// https://crbug.com/795649
gfx::ScopedRefCountedIOSurfaceMachPort mach_port(
IOSurfaceCreateMachPort(io_surface));
if (mach_port) {
base::ScopedCFTypeRef<IOSurfaceRef> io_surface_from_mach_port(
IOSurfaceLookupFromMachPort(mach_port.get()));
if (!io_surface_from_mach_port) {
LOG(ERROR) << "Failed to locally open anonymous IOSurface mach port "
"(ignoring failure).";
static int dump_counter = kMaxCrashDumps;
if (dump_counter) {
dump_counter -= 1;
base::debug::DumpWithoutCrashing();
}
}
} else {
LOG(ERROR) << "Failed to create IOSurface mach port.";
}
unsigned internalformat = gl::BufferFormatToGLInternalFormat(format); unsigned internalformat = gl::BufferFormatToGLInternalFormat(format);
scoped_refptr<gl::GLImageIOSurface> image( scoped_refptr<gl::GLImageIOSurface> image(
gl::GLImageIOSurface::Create(size, internalformat)); gl::GLImageIOSurface::Create(size, internalformat));
......
...@@ -48,8 +48,7 @@ WrapVideoFrameInCVPixelBuffer(const VideoFrame& frame) { ...@@ -48,8 +48,7 @@ WrapVideoFrameInCVPixelBuffer(const VideoFrame& frame) {
gfx::GpuMemoryBufferHandle handle = gfx::GpuMemoryBufferHandle handle =
frame.GetGpuMemoryBuffer()->CloneHandle(); frame.GetGpuMemoryBuffer()->CloneHandle();
if (handle.type == gfx::GpuMemoryBufferType::IO_SURFACE_BUFFER) { if (handle.type == gfx::GpuMemoryBufferType::IO_SURFACE_BUFFER) {
base::ScopedCFTypeRef<IOSurfaceRef> io_surface = gfx::ScopedIOSurface io_surface = handle.io_surface;
gfx::IOSurfaceMachPortToIOSurface(std::move(handle.mach_port));
if (io_surface) { if (io_surface) {
const CVReturn cv_return = CVPixelBufferCreateWithIOSurface( const CVReturn cv_return = CVPixelBufferCreateWithIOSurface(
nullptr, io_surface, nullptr, pixel_buffer.InitializeInto()); nullptr, io_surface, nullptr, pixel_buffer.InitializeInto());
......
...@@ -697,8 +697,7 @@ scoped_refptr<VideoFrame> VideoFrame::WrapIOSurface( ...@@ -697,8 +697,7 @@ scoped_refptr<VideoFrame> VideoFrame::WrapIOSurface(
DLOG(ERROR) << "Non-IOSurface handle."; DLOG(ERROR) << "Non-IOSurface handle.";
return nullptr; return nullptr;
} }
base::ScopedCFTypeRef<IOSurfaceRef> io_surface = gfx::ScopedIOSurface io_surface = handle.io_surface;
gfx::IOSurfaceMachPortToIOSurface(std::move(handle.mach_port));
if (!io_surface) { if (!io_surface) {
return nullptr; return nullptr;
} }
......
...@@ -606,9 +606,7 @@ AVCaptureDeviceFormat* FindBestCaptureFormat( ...@@ -606,9 +606,7 @@ AVCaptureDeviceFormat* FindBestCaptureFormat(
gfx::GpuMemoryBufferHandle handle; gfx::GpuMemoryBufferHandle handle;
handle.id.id = -1; handle.id.id = -1;
handle.type = gfx::GpuMemoryBufferType::IO_SURFACE_BUFFER; handle.type = gfx::GpuMemoryBufferType::IO_SURFACE_BUFFER;
handle.mach_port.reset(IOSurfaceCreateMachPort(ioSurface)); handle.io_surface.reset(ioSurface, base::scoped_policy::RETAIN);
if (!handle.mach_port)
return NO;
_lock.AssertAcquired(); _lock.AssertAcquired();
_frameReceiver->ReceiveExternalGpuMemoryBufferFrame( _frameReceiver->ReceiveExternalGpuMemoryBufferFrame(
std::move(handle), std::move(handle),
......
...@@ -37,7 +37,7 @@ GpuMemoryBufferHandle GpuMemoryBufferHandle::Clone() const { ...@@ -37,7 +37,7 @@ GpuMemoryBufferHandle GpuMemoryBufferHandle::Clone() const {
#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_FUCHSIA) #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_FUCHSIA)
handle.native_pixmap_handle = CloneHandleForIPC(native_pixmap_handle); handle.native_pixmap_handle = CloneHandleForIPC(native_pixmap_handle);
#elif defined(OS_MAC) #elif defined(OS_MAC)
handle.mach_port = mach_port; handle.io_surface = io_surface;
#elif defined(OS_WIN) #elif defined(OS_WIN)
NOTIMPLEMENTED(); NOTIMPLEMENTED();
#elif defined(OS_ANDROID) #elif defined(OS_ANDROID)
......
...@@ -72,7 +72,7 @@ struct GFX_EXPORT GpuMemoryBufferHandle { ...@@ -72,7 +72,7 @@ struct GFX_EXPORT GpuMemoryBufferHandle {
#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_FUCHSIA) #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_FUCHSIA)
NativePixmapHandle native_pixmap_handle; NativePixmapHandle native_pixmap_handle;
#elif defined(OS_MAC) #elif defined(OS_MAC)
ScopedRefCountedIOSurfaceMachPort mach_port; gfx::ScopedIOSurface io_surface;
#elif defined(OS_WIN) #elif defined(OS_WIN)
base::win::ScopedHandle dxgi_handle; base::win::ScopedHandle dxgi_handle;
#elif defined(OS_ANDROID) #elif defined(OS_ANDROID)
......
...@@ -22,4 +22,9 @@ component("ipc") { ...@@ -22,4 +22,9 @@ component("ipc") {
"//ui/gfx/ipc/geometry", "//ui/gfx/ipc/geometry",
"//ui/gfx/range", "//ui/gfx/range",
] ]
frameworks = [
"CoreFoundation.framework",
"IOSurface.framework",
]
} }
...@@ -63,6 +63,39 @@ void ParamTraits<gfx::ScopedRefCountedIOSurfaceMachPort>::Log( ...@@ -63,6 +63,39 @@ void ParamTraits<gfx::ScopedRefCountedIOSurfaceMachPort>::Log(
l->append("IOSurface Mach send right: "); l->append("IOSurface Mach send right: ");
LogParam(p.get(), l); LogParam(p.get(), l);
} }
void ParamTraits<gfx::ScopedIOSurface>::Write(base::Pickle* m,
const param_type p) {
gfx::ScopedRefCountedIOSurfaceMachPort io_surface_mach_port(
IOSurfaceCreateMachPort(p.get()));
MachPortMac mach_port_mac(io_surface_mach_port.get());
ParamTraits<MachPortMac>::Write(m, mach_port_mac);
}
bool ParamTraits<gfx::ScopedIOSurface>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
MachPortMac mach_port_mac;
if (!ParamTraits<MachPortMac>::Read(m, iter, &mach_port_mac))
return false;
gfx::ScopedRefCountedIOSurfaceMachPort io_surface_mach_port(
mach_port_mac.get_mach_port());
if (io_surface_mach_port)
r->reset(IOSurfaceLookupFromMachPort(io_surface_mach_port.get()));
else
r->reset();
return true;
}
void ParamTraits<gfx::ScopedIOSurface>::Log(const param_type& p,
std::string* l) {
l->append("IOSurface(");
if (p) {
uint32_t io_surface_id = IOSurfaceGetID(p.get());
LogParam(io_surface_id, l);
}
l->append(")");
}
#endif // defined(OS_MAC) #endif // defined(OS_MAC)
void ParamTraits<gfx::SelectionBound>::Write(base::Pickle* m, void ParamTraits<gfx::SelectionBound>::Write(base::Pickle* m,
......
...@@ -48,6 +48,16 @@ struct GFX_IPC_EXPORT ParamTraits<gfx::ScopedRefCountedIOSurfaceMachPort> { ...@@ -48,6 +48,16 @@ struct GFX_IPC_EXPORT ParamTraits<gfx::ScopedRefCountedIOSurfaceMachPort> {
param_type* r); param_type* r);
static void Log(const param_type& p, std::string* l); static void Log(const param_type& p, std::string* l);
}; };
template <>
struct GFX_IPC_EXPORT ParamTraits<gfx::ScopedIOSurface> {
typedef gfx::ScopedIOSurface param_type;
static void Write(base::Pickle* m, const param_type p);
static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r);
static void Log(const param_type& p, std::string* l);
};
#endif // defined(OS_MAC) #endif // defined(OS_MAC)
template <> template <>
......
...@@ -51,7 +51,7 @@ IPC_STRUCT_TRAITS_BEGIN(gfx::GpuMemoryBufferHandle) ...@@ -51,7 +51,7 @@ IPC_STRUCT_TRAITS_BEGIN(gfx::GpuMemoryBufferHandle)
#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_FUCHSIA) #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_FUCHSIA)
IPC_STRUCT_TRAITS_MEMBER(native_pixmap_handle) IPC_STRUCT_TRAITS_MEMBER(native_pixmap_handle)
#elif defined(OS_APPLE) #elif defined(OS_APPLE)
IPC_STRUCT_TRAITS_MEMBER(mach_port) IPC_STRUCT_TRAITS_MEMBER(io_surface)
#elif defined(OS_WIN) #elif defined(OS_WIN)
IPC_STRUCT_TRAITS_MEMBER(dxgi_handle) IPC_STRUCT_TRAITS_MEMBER(dxgi_handle)
#elif defined(OS_ANDROID) #elif defined(OS_ANDROID)
......
...@@ -62,6 +62,9 @@ using ScopedRefCountedIOSurfaceMachPort = ...@@ -62,6 +62,9 @@ using ScopedRefCountedIOSurfaceMachPort =
using ScopedInUseIOSurface = using ScopedInUseIOSurface =
base::ScopedTypeRef<IOSurfaceRef, internal::ScopedInUseIOSurfaceTraits>; base::ScopedTypeRef<IOSurfaceRef, internal::ScopedInUseIOSurfaceTraits>;
// A scoper for holding a reference to an IOSurface.
using ScopedIOSurface = base::ScopedCFTypeRef<IOSurfaceRef>;
// Return true if there exists a value for IOSurfaceColorSpace or // Return true if there exists a value for IOSurfaceColorSpace or
// IOSurfaceICCProfile that will make CoreAnimation render using |color_space|. // IOSurfaceICCProfile that will make CoreAnimation render using |color_space|.
GFX_EXPORT bool IOSurfaceCanSetColorSpace(const gfx::ColorSpace& color_space); GFX_EXPORT bool IOSurfaceCanSetColorSpace(const gfx::ColorSpace& color_space);
......
...@@ -300,4 +300,8 @@ component("shared_mojom_traits") { ...@@ -300,4 +300,8 @@ component("shared_mojom_traits") {
":native_handle_types", ":native_handle_types",
"//ui/gfx", "//ui/gfx",
] ]
frameworks = [
"CoreFoundation.framework",
"IOSurface.framework",
]
} }
...@@ -39,14 +39,17 @@ gfx::mojom::GpuMemoryBufferPlatformHandlePtr StructTraits< ...@@ -39,14 +39,17 @@ gfx::mojom::GpuMemoryBufferPlatformHandlePtr StructTraits<
#else #else
break; break;
#endif #endif
case gfx::IO_SURFACE_BUFFER: case gfx::IO_SURFACE_BUFFER: {
#if defined(OS_MAC) #if defined(OS_MAC)
gfx::ScopedRefCountedIOSurfaceMachPort io_surface_mach_port(
IOSurfaceCreateMachPort(handle.io_surface.get()));
return gfx::mojom::GpuMemoryBufferPlatformHandle::NewMachPort( return gfx::mojom::GpuMemoryBufferPlatformHandle::NewMachPort(
mojo::PlatformHandle( mojo::PlatformHandle(
base::mac::RetainMachSendRight(handle.mach_port.get()))); base::mac::RetainMachSendRight(io_surface_mach_port.get())));
#else #else
break; break;
#endif #endif
}
case gfx::DXGI_SHARED_HANDLE: case gfx::DXGI_SHARED_HANDLE:
#if defined(OS_WIN) #if defined(OS_WIN)
DCHECK(handle.dxgi_handle.IsValid()); DCHECK(handle.dxgi_handle.IsValid());
...@@ -121,8 +124,14 @@ bool StructTraits<gfx::mojom::GpuMemoryBufferHandleDataView, ...@@ -121,8 +124,14 @@ bool StructTraits<gfx::mojom::GpuMemoryBufferHandleDataView,
out->type = gfx::IO_SURFACE_BUFFER; out->type = gfx::IO_SURFACE_BUFFER;
if (!platform_handle->get_mach_port().is_mach_send()) if (!platform_handle->get_mach_port().is_mach_send())
return false; return false;
out->mach_port.reset( gfx::ScopedRefCountedIOSurfaceMachPort io_surface_mach_port(
platform_handle->get_mach_port().ReleaseMachSendRight()); 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; return true;
} }
#elif defined(OS_WIN) #elif defined(OS_WIN)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment