OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 #include "content/browser/browser_io_surface_manager_mac.h" | |
6 | |
7 #include <bsm/libbsm.h> | |
Robert Sesek
2015/05/15 21:45:05
Unused.
reveman
2015/05/18 18:15:38
Done.
| |
8 #include <servers/bootstrap.h> | |
9 | |
10 #include <string> | |
11 | |
12 #include "base/bind.h" | |
13 #include "base/logging.h" | |
14 #include "base/mac/foundation_util.h" | |
15 #include "base/mac/mach_logging.h" | |
16 #include "base/strings/stringprintf.h" | |
17 #include "content/browser/gpu/browser_gpu_channel_host_factory.h" | |
18 #include "content/browser/renderer_host/render_process_host_impl.h" | |
19 #include "content/common/mac/io_surface_manager.h" | |
20 #include "content/common/mac/io_surface_manager_messages.h" | |
21 #include "content/public/browser/browser_thread.h" | |
22 | |
23 namespace content { | |
24 | |
25 // static | |
26 BrowserIOSurfaceManager* BrowserIOSurfaceManager::GetInstance() { | |
27 return Singleton<BrowserIOSurfaceManager, | |
28 LeakySingletonTraits<BrowserIOSurfaceManager>>::get(); | |
29 } | |
30 | |
31 bool BrowserIOSurfaceManager::RegisterIOSurface(int io_surface_id, | |
32 int client_id, | |
33 IOSurfaceRef io_surface) { | |
34 base::AutoLock lock(lock_); | |
35 | |
36 IOSurfaceMapKey key(io_surface_id, client_id); | |
37 DCHECK(io_surfaces_.find(key) == io_surfaces_.end()); | |
Robert Sesek
2015/05/15 21:45:04
This DCHECK will continue in release mode (same bu
reveman
2015/05/18 18:15:38
This is for in-process use only. e.g. the browser
| |
38 io_surfaces_.add(key, make_scoped_ptr(new base::mac::ScopedMachSendRight( | |
39 IOSurfaceCreateMachPort(io_surface)))); | |
40 return true; | |
41 } | |
42 | |
43 void BrowserIOSurfaceManager::UnregisterIOSurface(int io_surface_id, | |
44 int client_id) { | |
45 base::AutoLock lock(lock_); | |
46 | |
47 IOSurfaceMapKey key(io_surface_id, client_id); | |
48 DCHECK(io_surfaces_.find(key) != io_surfaces_.end()); | |
Robert Sesek
2015/05/15 21:45:04
Same.
reveman
2015/05/18 18:15:38
Same reply.
| |
49 io_surfaces_.erase(key); | |
50 } | |
51 | |
52 IOSurfaceRef BrowserIOSurfaceManager::AcquireIOSurface(int io_surface_id) { | |
53 base::AutoLock lock(lock_); | |
54 | |
55 IOSurfaceMapKey key( | |
56 io_surface_id, | |
57 BrowserGpuChannelHostFactory::instance()->GetGpuChannelId()); | |
58 auto it = io_surfaces_.find(key); | |
59 if (it == io_surfaces_.end()) { | |
60 LOG(ERROR) << "Invalid Id for IOSurface " << io_surface_id; | |
61 return nullptr; | |
62 } | |
63 | |
64 return IOSurfaceLookupFromMachPort(it->second->get()); | |
65 } | |
66 | |
67 gpu::Mailbox BrowserIOSurfaceManager::GenerateChildProcessMailbox( | |
68 int client_id) { | |
69 base::AutoLock lock(lock_); | |
70 | |
71 gpu::Mailbox mailbox = gpu::Mailbox::Generate(); | |
72 DCHECK(mailbox.Verify()); | |
73 child_process_ids_[mailbox] = client_id; | |
74 return mailbox; | |
75 } | |
76 | |
77 void BrowserIOSurfaceManager::InvalidateChildProcessMailbox( | |
78 const gpu::Mailbox& mailbox) { | |
79 base::AutoLock lock(lock_); | |
80 | |
81 DCHECK(child_process_ids_.find(mailbox) != child_process_ids_.end()); | |
82 child_process_ids_.erase(mailbox); | |
83 } | |
84 | |
85 gpu::Mailbox BrowserIOSurfaceManager::GetGpuProcessMailbox() const { | |
86 DCHECK(gpu_process_mailbox_.Verify()); | |
87 return gpu_process_mailbox_; | |
88 } | |
89 | |
90 BrowserIOSurfaceManager::BrowserIOSurfaceManager() | |
91 : gpu_process_mailbox_(gpu::Mailbox::Generate()) { | |
Robert Sesek
2015/05/15 21:45:04
DCHECK(gpu_process_mailbox_.Verify()) ?
reveman
2015/05/18 18:15:38
Done. Removed the DCHECK in GetGpuProcessMailbox()
| |
92 // Check in with launchd and publish the service name. | |
93 std::string mach_port_name = base::StringPrintf( | |
94 "%s.iosurfacemgr.%d", base::mac::BaseBundleID(), getpid()); | |
95 mach_port_t port; | |
96 kern_return_t kr = | |
97 bootstrap_check_in(bootstrap_port, mach_port_name.c_str(), &port); | |
98 if (kr != KERN_SUCCESS) { | |
99 BOOTSTRAP_LOG(ERROR, kr) << "bootstrap_check_in"; | |
100 return; | |
101 } | |
102 server_port_.reset(port); | |
103 | |
104 // Start the dispatch source. | |
105 std::string queue_name = | |
106 base::StringPrintf("%s.IOSurfaceManager", base::mac::BaseBundleID()); | |
107 dispatch_source_.reset( | |
108 new base::DispatchSourceMach(queue_name.c_str(), server_port_.get(), ^{ | |
109 HandleRequest(); | |
110 })); | |
111 dispatch_source_->Resume(); | |
112 } | |
113 | |
114 BrowserIOSurfaceManager::~BrowserIOSurfaceManager() { | |
115 } | |
116 | |
117 void BrowserIOSurfaceManager::HandleRequest() { | |
118 struct { | |
119 union { | |
120 mach_msg_header_t header; | |
121 struct { | |
122 mach_msg_header_t header; | |
123 mach_msg_body_t body; | |
124 IOSurfaceManagerHostMsg_RegisterIOSurface msg; | |
Robert Sesek
2015/05/15 21:45:04
This entire struct is the message. The struct decl
reveman
2015/05/18 18:15:38
Done by using mailbox_name[64] in the message stru
| |
125 gpu::Mailbox mailbox; | |
126 } register_io_surface; | |
Robert Sesek
2015/05/15 21:45:04
These message structs should be in a common file,
reveman
2015/05/18 18:15:38
Done.
reveman
2015/05/18 18:15:38
Done.
| |
127 struct { | |
128 mach_msg_header_t header; | |
129 mach_msg_body_t body; | |
130 IOSurfaceManagerHostMsg_UnregisterIOSurface msg; | |
131 gpu::Mailbox mailbox; | |
132 } unregister_io_surface; | |
133 struct { | |
134 mach_msg_header_t header; | |
135 mach_msg_body_t body; | |
136 IOSurfaceManagerHostMsg_AcquireIOSurface msg; | |
137 gpu::Mailbox mailbox; | |
138 } acquire_io_surface; | |
139 } msg; | |
140 mach_msg_trailer_t trailer; | |
141 } data = {{{0}}}; | |
142 data.msg.header.msgh_size = sizeof(data); | |
143 data.msg.header.msgh_local_port = server_port_.get(); | |
144 | |
145 kern_return_t kr = | |
146 mach_msg(&data.msg.header, MACH_RCV_MSG, 0, sizeof(data), server_port_, | |
147 MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); | |
148 if (kr != KERN_SUCCESS) { | |
149 MACH_LOG(ERROR, kr) << "mach_msg"; | |
150 return; | |
151 } | |
152 | |
153 switch (data.msg.header.msgh_id) { | |
154 case IOSurfaceManagerHostMsg_RegisterIOSurface::ID: | |
155 OnRegisterIOSurface(data.msg.header, | |
156 data.msg.register_io_surface.msg.io_surface_id, | |
157 data.msg.register_io_surface.msg.client_id, | |
158 data.msg.register_io_surface.msg.io_surface_port.name, | |
159 data.msg.register_io_surface.mailbox); | |
160 break; | |
161 case IOSurfaceManagerHostMsg_UnregisterIOSurface::ID: | |
162 OnUnregisterIOSurface(data.msg.header, | |
163 data.msg.unregister_io_surface.msg.io_surface_id, | |
164 data.msg.unregister_io_surface.msg.client_id, | |
165 data.msg.unregister_io_surface.mailbox); | |
166 break; | |
167 case IOSurfaceManagerHostMsg_AcquireIOSurface::ID: | |
168 OnAcquireIOSurface(data.msg.header, | |
169 data.msg.acquire_io_surface.msg.io_surface_id, | |
170 data.msg.acquire_io_surface.mailbox); | |
171 break; | |
172 } | |
173 } | |
174 | |
175 void BrowserIOSurfaceManager::OnRegisterIOSurface( | |
176 const mach_msg_header_t& header, | |
177 int io_surface_id, | |
178 int client_id, | |
179 mach_port_t io_surface_port, | |
180 const gpu::Mailbox& mailbox) { | |
181 base::AutoLock lock(lock_); | |
182 | |
183 if (mailbox != gpu_process_mailbox_) { | |
184 LOG(ERROR) << "Illegal message from non-GPU process!"; | |
185 return; | |
186 } | |
187 | |
188 IOSurfaceMapKey key(io_surface_id, client_id); | |
189 io_surfaces_.add( | |
190 key, | |
191 make_scoped_ptr(new base::mac::ScopedMachSendRight(io_surface_port))); | |
192 | |
193 struct { | |
194 mach_msg_header_t header; | |
195 mach_msg_body_t body; | |
196 IOSurfaceManagerMsg_RegisterIOSurfaceReply msg; | |
197 } reply = {{0}}; | |
198 reply.header.msgh_bits = MACH_MSGH_BITS_REMOTE(header.msgh_bits); | |
199 reply.header.msgh_remote_port = header.msgh_remote_port; | |
200 reply.header.msgh_size = sizeof(reply); | |
201 reply.msg.result = true; | |
202 kern_return_t kr = | |
203 mach_msg(&reply.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, sizeof(reply), | |
204 0, MACH_PORT_NULL, 100 /*milliseconds*/, MACH_PORT_NULL); | |
205 if (kr != KERN_SUCCESS) { | |
206 MACH_LOG(ERROR, kr) << "mach_msg"; | |
207 } | |
208 } | |
209 | |
210 void BrowserIOSurfaceManager::OnUnregisterIOSurface( | |
211 const mach_msg_header_t& header, | |
212 int io_surface_id, | |
213 int client_id, | |
214 const gpu::Mailbox& mailbox) { | |
215 base::AutoLock lock(lock_); | |
216 | |
217 if (mailbox != gpu_process_mailbox_) { | |
218 LOG(ERROR) << "Illegal message from non-GPU process!"; | |
219 return; | |
220 } | |
221 | |
222 IOSurfaceMapKey key(io_surface_id, client_id); | |
223 io_surfaces_.erase(key); | |
224 } | |
Robert Sesek
2015/05/15 21:45:05
Registration gets a reply but unregistration does
reveman
2015/05/18 18:15:38
Registration needs to be synchronous to prevent th
Robert Sesek
2015/05/19 23:26:23
Makes sense. It's fine to leave this as a one-way
| |
225 | |
226 void BrowserIOSurfaceManager::OnAcquireIOSurface( | |
227 const mach_msg_header_t& header, | |
228 int io_surface_id, | |
229 const gpu::Mailbox& mailbox) { | |
230 base::AutoLock lock(lock_); | |
231 | |
232 auto child_process_id_it = child_process_ids_.find(mailbox); | |
233 if (child_process_id_it == child_process_ids_.end()) { | |
234 LOG(ERROR) << "Illegal message from non-child process!"; | |
235 return; | |
236 } | |
237 | |
238 IOSurfaceMapKey key(io_surface_id, child_process_id_it->second); | |
239 auto it = io_surfaces_.find(key); | |
240 if (it == io_surfaces_.end()) { | |
241 LOG(ERROR) << "Invalid Id for IOSurface " << io_surface_id; | |
242 return; | |
243 } | |
244 | |
245 struct { | |
246 mach_msg_header_t header; | |
247 mach_msg_body_t body; | |
248 IOSurfaceManagerMsg_AcquireIOSurfaceReply msg; | |
249 } reply = {{0}}; | |
250 reply.header.msgh_bits = | |
251 MACH_MSGH_BITS_REMOTE(header.msgh_bits) | MACH_MSGH_BITS_COMPLEX; | |
252 reply.header.msgh_remote_port = header.msgh_remote_port; | |
253 reply.header.msgh_size = sizeof(reply); | |
254 reply.body.msgh_descriptor_count = 1; | |
255 reply.msg.io_surface_port.name = it->second->get(); | |
256 reply.msg.io_surface_port.disposition = MACH_MSG_TYPE_COPY_SEND; | |
257 reply.msg.io_surface_port.type = MACH_MSG_PORT_DESCRIPTOR; | |
258 kern_return_t kr = | |
259 mach_msg(&reply.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, sizeof(reply), | |
260 0, MACH_PORT_NULL, 100 /*milliseconds*/, MACH_PORT_NULL); | |
261 if (kr != KERN_SUCCESS) { | |
262 MACH_LOG(ERROR, kr) << "mach_msg"; | |
263 } | |
264 } | |
265 | |
266 } // namespace content | |
OLD | NEW |