Chromium Code Reviews| 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 |