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 Singleton
<ChildIOSurfaceManager
,
15 LeakySingletonTraits
<ChildIOSurfaceManager
>>::get();
18 bool ChildIOSurfaceManager::RegisterIOSurface(int io_surface_id
,
20 IOSurfaceRef io_surface
) {
21 DCHECK(service_port_
.is_valid());
22 DCHECK(!token_
.IsZero());
24 mach_port_t reply_port
;
25 kern_return_t kr
= mach_port_allocate(mach_task_self(),
26 MACH_PORT_RIGHT_RECEIVE
, &reply_port
);
27 if (kr
!= KERN_SUCCESS
) {
28 MACH_LOG(ERROR
, kr
) << "mach_port_allocate";
31 base::mac::ScopedMachReceiveRight
scoped_receive_right(reply_port
);
33 // Deallocate the right after sending a copy to the parent.
34 base::mac::ScopedMachSendRight
scoped_io_surface_right(
35 IOSurfaceCreateMachPort(io_surface
));
38 IOSurfaceManagerHostMsg_RegisterIOSurface request
;
40 IOSurfaceManagerMsg_RegisterIOSurfaceReply msg
;
41 mach_msg_trailer_t trailer
;
44 data
.request
.header
.msgh_bits
=
45 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
, MACH_MSG_TYPE_MAKE_SEND_ONCE
) |
46 MACH_MSGH_BITS_COMPLEX
;
47 data
.request
.header
.msgh_remote_port
= service_port_
;
48 data
.request
.header
.msgh_local_port
= reply_port
;
49 data
.request
.header
.msgh_size
= sizeof(data
.request
);
50 data
.request
.header
.msgh_id
= IOSurfaceManagerHostMsg_RegisterIOSurface::ID
;
51 data
.request
.body
.msgh_descriptor_count
= 1;
52 data
.request
.io_surface_port
.name
= scoped_io_surface_right
;
53 data
.request
.io_surface_port
.disposition
= MACH_MSG_TYPE_COPY_SEND
;
54 data
.request
.io_surface_port
.type
= MACH_MSG_PORT_DESCRIPTOR
;
55 data
.request
.io_surface_id
= io_surface_id
;
56 data
.request
.client_id
= client_id
;
57 memcpy(data
.request
.token_name
, token_
.name
, sizeof(token_
.name
));
59 kr
= mach_msg(&data
.request
.header
, MACH_SEND_MSG
| MACH_RCV_MSG
,
60 sizeof(data
.request
), sizeof(data
.reply
), reply_port
,
61 MACH_MSG_TIMEOUT_NONE
, MACH_PORT_NULL
);
62 if (kr
!= KERN_SUCCESS
) {
63 MACH_LOG(ERROR
, kr
) << "mach_msg";
67 return data
.reply
.msg
.result
;
70 void ChildIOSurfaceManager::UnregisterIOSurface(int io_surface_id
,
72 DCHECK(service_port_
.is_valid());
73 DCHECK(!token_
.IsZero());
75 IOSurfaceManagerHostMsg_UnregisterIOSurface request
= {{0}};
76 request
.header
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
, 0);
77 request
.header
.msgh_remote_port
= service_port_
;
78 request
.header
.msgh_local_port
= MACH_PORT_NULL
;
79 request
.header
.msgh_size
= sizeof(request
);
80 request
.header
.msgh_id
= IOSurfaceManagerHostMsg_UnregisterIOSurface::ID
;
81 request
.io_surface_id
= io_surface_id
;
82 request
.client_id
= client_id
;
83 memcpy(request
.token_name
, token_
.name
, sizeof(token_
.name
));
86 mach_msg(&request
.header
, MACH_SEND_MSG
, sizeof(request
), 0,
87 MACH_PORT_NULL
, MACH_MSG_TIMEOUT_NONE
, MACH_PORT_NULL
);
88 if (kr
!= KERN_SUCCESS
) {
89 MACH_LOG(ERROR
, kr
) << "mach_msg";
93 IOSurfaceRef
ChildIOSurfaceManager::AcquireIOSurface(int io_surface_id
) {
94 DCHECK(service_port_
.is_valid());
96 // A valid token is required to acquire an IOSurface. This will wait for a
97 // valid token if one has not yet been set.
98 set_token_event_
.Wait();
100 DCHECK(!(set_token_thread_id_
== base::PlatformThread::CurrentRef()));
102 DCHECK(!token_
.IsZero());
104 mach_port_t reply_port
;
105 kern_return_t kr
= mach_port_allocate(mach_task_self(),
106 MACH_PORT_RIGHT_RECEIVE
, &reply_port
);
107 if (kr
!= KERN_SUCCESS
) {
108 MACH_LOG(ERROR
, kr
) << "mach_port_allocate";
111 base::mac::ScopedMachReceiveRight
scoped_receive_right(reply_port
);
114 IOSurfaceManagerHostMsg_AcquireIOSurface request
;
116 IOSurfaceManagerMsg_AcquireIOSurfaceReply msg
;
117 mach_msg_trailer_t trailer
;
120 data
.request
.header
.msgh_bits
=
121 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
, MACH_MSG_TYPE_MAKE_SEND_ONCE
);
122 data
.request
.header
.msgh_remote_port
= service_port_
;
123 data
.request
.header
.msgh_local_port
= reply_port
;
124 data
.request
.header
.msgh_size
= sizeof(data
.request
);
125 data
.request
.header
.msgh_id
= IOSurfaceManagerHostMsg_AcquireIOSurface::ID
;
126 data
.request
.io_surface_id
= io_surface_id
;
127 memcpy(data
.request
.token_name
, token_
.name
, sizeof(token_
.name
));
129 kr
= mach_msg(&data
.request
.header
, MACH_SEND_MSG
| MACH_RCV_MSG
,
130 sizeof(data
.request
), sizeof(data
.reply
), reply_port
,
131 MACH_MSG_TIMEOUT_NONE
, MACH_PORT_NULL
);
132 if (kr
!= KERN_SUCCESS
) {
133 MACH_LOG(ERROR
, kr
) << "mach_msg";
137 // Deallocate the right after creating an IOSurface reference.
138 base::mac::ScopedMachSendRight
scoped_io_surface_right(
139 data
.reply
.msg
.io_surface_port
.name
);
141 return IOSurfaceLookupFromMachPort(scoped_io_surface_right
);
144 ChildIOSurfaceManager::ChildIOSurfaceManager()
145 : set_token_event_(true, false) {}
147 ChildIOSurfaceManager::~ChildIOSurfaceManager() {
150 } // namespace content