1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/layers/ipc/ImageBridgeParent.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,280 @@ 1.4 +/* vim: set ts=2 sw=2 et tw=80: */ 1.5 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "ImageBridgeParent.h" 1.11 +#include <stdint.h> // for uint64_t, uint32_t 1.12 +#include "CompositableHost.h" // for CompositableParent, Create 1.13 +#include "base/message_loop.h" // for MessageLoop 1.14 +#include "base/process.h" // for ProcessHandle 1.15 +#include "base/process_util.h" // for OpenProcessHandle 1.16 +#include "base/task.h" // for CancelableTask, DeleteTask, etc 1.17 +#include "base/tracked.h" // for FROM_HERE 1.18 +#include "mozilla/gfx/Point.h" // for IntSize 1.19 +#include "mozilla/ipc/MessageChannel.h" // for MessageChannel, etc 1.20 +#include "mozilla/ipc/ProtocolUtils.h" 1.21 +#include "mozilla/ipc/Transport.h" // for Transport 1.22 +#include "mozilla/layers/CompositableTransactionParent.h" 1.23 +#include "mozilla/layers/CompositorParent.h" // for CompositorParent 1.24 +#include "mozilla/layers/LayerManagerComposite.h" 1.25 +#include "mozilla/layers/LayersMessages.h" // for EditReply 1.26 +#include "mozilla/layers/LayersSurfaces.h" // for PGrallocBufferParent 1.27 +#include "mozilla/layers/PCompositableParent.h" 1.28 +#include "mozilla/layers/PImageBridgeParent.h" 1.29 +#include "mozilla/layers/Compositor.h" 1.30 +#include "mozilla/mozalloc.h" // for operator new, etc 1.31 +#include "nsAutoPtr.h" // for nsRefPtr 1.32 +#include "nsDebug.h" // for NS_RUNTIMEABORT, etc 1.33 +#include "nsISupportsImpl.h" // for ImageBridgeParent::Release, etc 1.34 +#include "nsTArray.h" // for nsTArray, nsTArray_Impl 1.35 +#include "nsTArrayForwardDeclare.h" // for InfallibleTArray 1.36 +#include "nsXULAppAPI.h" // for XRE_GetIOMessageLoop 1.37 +#include "mozilla/layers/TextureHost.h" 1.38 +#include "nsThreadUtils.h" 1.39 + 1.40 +using namespace mozilla::ipc; 1.41 +using namespace mozilla::gfx; 1.42 + 1.43 +namespace mozilla { 1.44 +namespace layers { 1.45 + 1.46 +class PGrallocBufferParent; 1.47 + 1.48 +ImageBridgeParent::ImageBridgeParent(MessageLoop* aLoop, Transport* aTransport) 1.49 + : mMessageLoop(aLoop) 1.50 + , mTransport(aTransport) 1.51 +{ 1.52 + // creates the map only if it has not been created already, so it is safe 1.53 + // with several bridges 1.54 + CompositableMap::Create(); 1.55 +} 1.56 + 1.57 +ImageBridgeParent::~ImageBridgeParent() 1.58 +{ 1.59 + if (mTransport) { 1.60 + XRE_GetIOMessageLoop()->PostTask(FROM_HERE, 1.61 + new DeleteTask<Transport>(mTransport)); 1.62 + } 1.63 +} 1.64 + 1.65 +LayersBackend 1.66 +ImageBridgeParent::GetCompositorBackendType() const 1.67 +{ 1.68 + return Compositor::GetBackend(); 1.69 +} 1.70 + 1.71 +void 1.72 +ImageBridgeParent::ActorDestroy(ActorDestroyReason aWhy) 1.73 +{ 1.74 + MessageLoop::current()->PostTask( 1.75 + FROM_HERE, 1.76 + NewRunnableMethod(this, &ImageBridgeParent::DeferredDestroy)); 1.77 +} 1.78 + 1.79 +bool 1.80 +ImageBridgeParent::RecvUpdate(const EditArray& aEdits, EditReplyArray* aReply) 1.81 +{ 1.82 + // If we don't actually have a compositor, then don't bother 1.83 + // creating any textures. 1.84 + if (Compositor::GetBackend() == LayersBackend::LAYERS_NONE) { 1.85 + return true; 1.86 + } 1.87 + 1.88 + // Clear fence handles used in previsou transaction. 1.89 + ClearPrevFenceHandles(); 1.90 + 1.91 + EditReplyVector replyv; 1.92 + for (EditArray::index_type i = 0; i < aEdits.Length(); ++i) { 1.93 + if (!ReceiveCompositableUpdate(aEdits[i], replyv)) { 1.94 + return false; 1.95 + } 1.96 + } 1.97 + 1.98 + aReply->SetCapacity(replyv.size()); 1.99 + if (replyv.size() > 0) { 1.100 + aReply->AppendElements(&replyv.front(), replyv.size()); 1.101 + } 1.102 + 1.103 + // Ensure that any pending operations involving back and front 1.104 + // buffers have completed, so that neither process stomps on the 1.105 + // other's buffer contents. 1.106 + LayerManagerComposite::PlatformSyncBeforeReplyUpdate(); 1.107 + 1.108 + return true; 1.109 +} 1.110 + 1.111 +bool 1.112 +ImageBridgeParent::RecvUpdateNoSwap(const EditArray& aEdits) 1.113 +{ 1.114 + InfallibleTArray<EditReply> noReplies; 1.115 + bool success = RecvUpdate(aEdits, &noReplies); 1.116 + NS_ABORT_IF_FALSE(noReplies.Length() == 0, "RecvUpdateNoSwap requires a sync Update to carry Edits"); 1.117 + return success; 1.118 +} 1.119 + 1.120 +static void 1.121 +ConnectImageBridgeInParentProcess(ImageBridgeParent* aBridge, 1.122 + Transport* aTransport, 1.123 + base::ProcessHandle aOtherProcess) 1.124 +{ 1.125 + aBridge->Open(aTransport, aOtherProcess, XRE_GetIOMessageLoop(), ipc::ParentSide); 1.126 +} 1.127 + 1.128 +/*static*/ PImageBridgeParent* 1.129 +ImageBridgeParent::Create(Transport* aTransport, ProcessId aOtherProcess) 1.130 +{ 1.131 + base::ProcessHandle processHandle; 1.132 + if (!base::OpenProcessHandle(aOtherProcess, &processHandle)) { 1.133 + return nullptr; 1.134 + } 1.135 + 1.136 + MessageLoop* loop = CompositorParent::CompositorLoop(); 1.137 + nsRefPtr<ImageBridgeParent> bridge = new ImageBridgeParent(loop, aTransport); 1.138 + bridge->mSelfRef = bridge; 1.139 + loop->PostTask(FROM_HERE, 1.140 + NewRunnableFunction(ConnectImageBridgeInParentProcess, 1.141 + bridge.get(), aTransport, processHandle)); 1.142 + return bridge.get(); 1.143 +} 1.144 + 1.145 +bool ImageBridgeParent::RecvWillStop() 1.146 +{ 1.147 + // If there is any texture still alive we have to force it to deallocate the 1.148 + // device data (GL textures, etc.) now because shortly after SenStop() returns 1.149 + // on the child side the widget will be destroyed along with it's associated 1.150 + // GL context. 1.151 + InfallibleTArray<PTextureParent*> textures; 1.152 + ManagedPTextureParent(textures); 1.153 + for (unsigned int i = 0; i < textures.Length(); ++i) { 1.154 + RefPtr<TextureHost> tex = TextureHost::AsTextureHost(textures[i]); 1.155 + tex->DeallocateDeviceData(); 1.156 + } 1.157 + return true; 1.158 +} 1.159 + 1.160 +bool ImageBridgeParent::RecvStop() 1.161 +{ 1.162 + // Nothing to do. This message just serves as synchronization between the 1.163 + // child and parent threads during shutdown. 1.164 + return true; 1.165 +} 1.166 + 1.167 +static uint64_t GenImageContainerID() { 1.168 + static uint64_t sNextImageID = 1; 1.169 + 1.170 + ++sNextImageID; 1.171 + return sNextImageID; 1.172 +} 1.173 + 1.174 +PGrallocBufferParent* 1.175 +ImageBridgeParent::AllocPGrallocBufferParent(const IntSize& aSize, 1.176 + const uint32_t& aFormat, 1.177 + const uint32_t& aUsage, 1.178 + MaybeMagicGrallocBufferHandle* aOutHandle) 1.179 +{ 1.180 +#ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC 1.181 + return GrallocBufferActor::Create(aSize, aFormat, aUsage, aOutHandle); 1.182 +#else 1.183 + NS_RUNTIMEABORT("No gralloc buffers for you"); 1.184 + return nullptr; 1.185 +#endif 1.186 +} 1.187 + 1.188 +bool 1.189 +ImageBridgeParent::DeallocPGrallocBufferParent(PGrallocBufferParent* actor) 1.190 +{ 1.191 +#ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC 1.192 + delete actor; 1.193 + return true; 1.194 +#else 1.195 + NS_RUNTIMEABORT("Um, how did we get here?"); 1.196 + return false; 1.197 +#endif 1.198 +} 1.199 + 1.200 +PCompositableParent* 1.201 +ImageBridgeParent::AllocPCompositableParent(const TextureInfo& aInfo, 1.202 + uint64_t* aID) 1.203 +{ 1.204 + uint64_t id = GenImageContainerID(); 1.205 + *aID = id; 1.206 + return CompositableHost::CreateIPDLActor(this, aInfo, id); 1.207 +} 1.208 + 1.209 +bool ImageBridgeParent::DeallocPCompositableParent(PCompositableParent* aActor) 1.210 +{ 1.211 + return CompositableHost::DestroyIPDLActor(aActor); 1.212 +} 1.213 + 1.214 +PTextureParent* 1.215 +ImageBridgeParent::AllocPTextureParent(const SurfaceDescriptor& aSharedData, 1.216 + const TextureFlags& aFlags) 1.217 +{ 1.218 + return TextureHost::CreateIPDLActor(this, aSharedData, aFlags); 1.219 +} 1.220 + 1.221 +bool 1.222 +ImageBridgeParent::DeallocPTextureParent(PTextureParent* actor) 1.223 +{ 1.224 + return TextureHost::DestroyIPDLActor(actor); 1.225 +} 1.226 + 1.227 +MessageLoop * ImageBridgeParent::GetMessageLoop() { 1.228 + return mMessageLoop; 1.229 +} 1.230 + 1.231 +class ReleaseRunnable : public nsRunnable 1.232 +{ 1.233 +public: 1.234 + ReleaseRunnable(ImageBridgeParent* aRef) 1.235 + : mRef(aRef) 1.236 + { 1.237 + } 1.238 + 1.239 + NS_IMETHOD Run() 1.240 + { 1.241 + mRef->Release(); 1.242 + return NS_OK; 1.243 + } 1.244 + 1.245 +private: 1.246 + ImageBridgeParent* mRef; 1.247 +}; 1.248 + 1.249 +void 1.250 +ImageBridgeParent::DeferredDestroy() 1.251 +{ 1.252 + ImageBridgeParent* self; 1.253 + mSelfRef.forget(&self); 1.254 + 1.255 + nsCOMPtr<nsIRunnable> runnable = new ReleaseRunnable(self); 1.256 + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(runnable))); 1.257 +} 1.258 + 1.259 +IToplevelProtocol* 1.260 +ImageBridgeParent::CloneToplevel(const InfallibleTArray<ProtocolFdMapping>& aFds, 1.261 + base::ProcessHandle aPeerProcess, 1.262 + mozilla::ipc::ProtocolCloneContext* aCtx) 1.263 +{ 1.264 + for (unsigned int i = 0; i < aFds.Length(); i++) { 1.265 + if (aFds[i].protocolId() == unsigned(GetProtocolId())) { 1.266 + Transport* transport = OpenDescriptor(aFds[i].fd(), 1.267 + Transport::MODE_SERVER); 1.268 + PImageBridgeParent* bridge = Create(transport, base::GetProcId(aPeerProcess)); 1.269 + bridge->CloneManagees(this, aCtx); 1.270 + bridge->IToplevelProtocol::SetTransport(transport); 1.271 + return bridge; 1.272 + } 1.273 + } 1.274 + return nullptr; 1.275 +} 1.276 + 1.277 +bool ImageBridgeParent::IsSameProcess() const 1.278 +{ 1.279 + return OtherProcess() == ipc::kInvalidProcessHandle; 1.280 +} 1.281 + 1.282 +} // layers 1.283 +} // mozilla