1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/child/child_io_surface_manager_mac.h"
7 #include "base/mac/mach_logging.h"
8 #include "content/common/mac/io_surface_manager_messages.h"
13 ChildIOSurfaceManager
* ChildIOSurfaceManager::GetInstance() {
14 return base::Singleton
<
15 ChildIOSurfaceManager
,
16 base::LeakySingletonTraits
<ChildIOSurfaceManager
>>::get();
19 bool ChildIOSurfaceManager::RegisterIOSurface(IOSurfaceId io_surface_id
,
21 IOSurfaceRef io_surface
) {
22 DCHECK(service_port_
.is_valid());
23 DCHECK(!token_
.IsZero());
25 mach_port_t reply_port
;
26 kern_return_t kr
= mach_port_allocate(mach_task_self(),
27 MACH_PORT_RIGHT_RECEIVE
, &reply_port
);
28 if (kr
!= KERN_SUCCESS
) {
29 MACH_LOG(ERROR
, kr
) << "mach_port_allocate";
32 base::mac::ScopedMachReceiveRight
scoped_receive_right(reply_port
);
34 // Deallocate the right after sending a copy to the parent.
35 base::mac::ScopedMachSendRight
scoped_io_surface_right(
36 IOSurfaceCreateMachPort(io_surface
));
39 IOSurfaceManagerHostMsg_RegisterIOSurface request
;
41 IOSurfaceManagerMsg_RegisterIOSurfaceReply msg
;
42 mach_msg_trailer_t trailer
;
45 data
.request
.header
.msgh_bits
=
46 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
, MACH_MSG_TYPE_MAKE_SEND_ONCE
) |
47 MACH_MSGH_BITS_COMPLEX
;
48 data
.request
.header
.msgh_remote_port
= service_port_
;
49 data
.request
.header
.msgh_local_port
= reply_port
;
50 data
.request
.header
.msgh_size
= sizeof(data
.request
);
51 data
.request
.header
.msgh_id
= IOSurfaceManagerHostMsg_RegisterIOSurface::ID
;
52 data
.request
.body
.msgh_descriptor_count
= 1;
53 data
.request
.io_surface_port
.name
= scoped_io_surface_right
;
54 data
.request
.io_surface_port
.disposition
= MACH_MSG_TYPE_COPY_SEND
;
55 data
.request
.io_surface_port
.type
= MACH_MSG_PORT_DESCRIPTOR
;
56 data
.request
.io_surface_id
= io_surface_id
.id
;
57 data
.request
.client_id
= client_id
;
58 memcpy(data
.request
.token_name
, token_
.name
, sizeof(token_
.name
));
60 kr
= mach_msg(&data
.request
.header
, MACH_SEND_MSG
| MACH_RCV_MSG
,
61 sizeof(data
.request
), sizeof(data
.reply
), reply_port
,
62 MACH_MSG_TIMEOUT_NONE
, MACH_PORT_NULL
);
63 if (kr
!= KERN_SUCCESS
) {
64 MACH_LOG(ERROR
, kr
) << "mach_msg";
68 return data
.reply
.msg
.result
;
71 void ChildIOSurfaceManager::UnregisterIOSurface(IOSurfaceId io_surface_id
,
73 DCHECK(service_port_
.is_valid());
74 DCHECK(!token_
.IsZero());
76 IOSurfaceManagerHostMsg_UnregisterIOSurface request
= {{0}};
77 request
.header
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
, 0);
78 request
.header
.msgh_remote_port
= service_port_
;
79 request
.header
.msgh_local_port
= MACH_PORT_NULL
;
80 request
.header
.msgh_size
= sizeof(request
);
81 request
.header
.msgh_id
= IOSurfaceManagerHostMsg_UnregisterIOSurface::ID
;
82 request
.io_surface_id
= io_surface_id
.id
;
83 request
.client_id
= client_id
;
84 memcpy(request
.token_name
, token_
.name
, sizeof(token_
.name
));
87 mach_msg(&request
.header
, MACH_SEND_MSG
, sizeof(request
), 0,
88 MACH_PORT_NULL
, MACH_MSG_TIMEOUT_NONE
, MACH_PORT_NULL
);
89 if (kr
!= KERN_SUCCESS
) {
90 MACH_LOG(ERROR
, kr
) << "mach_msg";
94 IOSurfaceRef
ChildIOSurfaceManager::AcquireIOSurface(
95 IOSurfaceId io_surface_id
) {
96 DCHECK(service_port_
.is_valid());
97 DCHECK(!token_
.IsZero());
99 mach_port_t reply_port
;
100 kern_return_t kr
= mach_port_allocate(mach_task_self(),
101 MACH_PORT_RIGHT_RECEIVE
, &reply_port
);
102 if (kr
!= KERN_SUCCESS
) {
103 MACH_LOG(ERROR
, kr
) << "mach_port_allocate";
106 base::mac::ScopedMachReceiveRight
scoped_receive_right(reply_port
);
109 IOSurfaceManagerHostMsg_AcquireIOSurface request
;
111 IOSurfaceManagerMsg_AcquireIOSurfaceReply msg
;
112 mach_msg_trailer_t trailer
;
115 data
.request
.header
.msgh_bits
=
116 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
, MACH_MSG_TYPE_MAKE_SEND_ONCE
);
117 data
.request
.header
.msgh_remote_port
= service_port_
;
118 data
.request
.header
.msgh_local_port
= reply_port
;
119 data
.request
.header
.msgh_size
= sizeof(data
.request
);
120 data
.request
.header
.msgh_id
= IOSurfaceManagerHostMsg_AcquireIOSurface::ID
;
121 data
.request
.io_surface_id
= io_surface_id
.id
;
122 memcpy(data
.request
.token_name
, token_
.name
, sizeof(token_
.name
));
124 kr
= mach_msg(&data
.request
.header
, MACH_SEND_MSG
| MACH_RCV_MSG
,
125 sizeof(data
.request
), sizeof(data
.reply
), reply_port
,
126 MACH_MSG_TIMEOUT_NONE
, MACH_PORT_NULL
);
127 if (kr
!= KERN_SUCCESS
) {
128 MACH_LOG(ERROR
, kr
) << "mach_msg";
131 if (!data
.reply
.msg
.result
) {
132 DLOG(ERROR
) << "Browser refused AcquireIOSurface request";
136 // Deallocate the right after creating an IOSurface reference.
137 base::mac::ScopedMachSendRight
scoped_io_surface_right(
138 data
.reply
.msg
.io_surface_port
.name
);
140 return IOSurfaceLookupFromMachPort(scoped_io_surface_right
);
143 ChildIOSurfaceManager::ChildIOSurfaceManager() {}
145 ChildIOSurfaceManager::~ChildIOSurfaceManager() {}
147 } // namespace content