|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- |
|
2 * vim: sw=2 ts=8 et : |
|
3 */ |
|
4 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
5 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
7 |
|
8 #include "GLContext.h" |
|
9 #include "mozilla/unused.h" |
|
10 #include "nsXULAppAPI.h" |
|
11 |
|
12 #include "FenceUtilsGonk.h" |
|
13 |
|
14 using namespace android; |
|
15 using namespace base; |
|
16 using namespace mozilla::layers; |
|
17 |
|
18 namespace IPC { |
|
19 |
|
20 void |
|
21 ParamTraits<FenceHandle>::Write(Message* aMsg, |
|
22 const paramType& aParam) |
|
23 { |
|
24 #if ANDROID_VERSION >= 19 |
|
25 sp<Fence> flattenable = aParam.mFence; |
|
26 #else |
|
27 Flattenable *flattenable = aParam.mFence.get(); |
|
28 #endif |
|
29 size_t nbytes = flattenable->getFlattenedSize(); |
|
30 size_t nfds = flattenable->getFdCount(); |
|
31 |
|
32 char data[nbytes]; |
|
33 int fds[nfds]; |
|
34 |
|
35 #if ANDROID_VERSION >= 19 |
|
36 // Make a copy of "data" and "fds" for flatten() to avoid casting problem |
|
37 void *pdata = (void *)data; |
|
38 int *pfds = fds; |
|
39 |
|
40 flattenable->flatten(pdata, nbytes, pfds, nfds); |
|
41 |
|
42 // In Kitkat, flatten() will change the value of nbytes and nfds, which dues |
|
43 // to multiple parcelable object consumption. The actual size and fd count |
|
44 // which returned by getFlattenedSize() and getFdCount() are not changed. |
|
45 // So we change nbytes and nfds back by call corresponding calls. |
|
46 nbytes = flattenable->getFlattenedSize(); |
|
47 nfds = flattenable->getFdCount(); |
|
48 #else |
|
49 flattenable->flatten(data, nbytes, fds, nfds); |
|
50 #endif |
|
51 aMsg->WriteSize(nbytes); |
|
52 aMsg->WriteSize(nfds); |
|
53 |
|
54 aMsg->WriteBytes(data, nbytes); |
|
55 for (size_t n = 0; n < nfds; ++n) { |
|
56 // These buffers can't die in transit because they're created |
|
57 // synchonously and the parent-side buffer can only be dropped if |
|
58 // there's a crash. |
|
59 aMsg->WriteFileDescriptor(FileDescriptor(fds[n], false)); |
|
60 } |
|
61 } |
|
62 |
|
63 bool |
|
64 ParamTraits<FenceHandle>::Read(const Message* aMsg, |
|
65 void** aIter, paramType* aResult) |
|
66 { |
|
67 size_t nbytes; |
|
68 size_t nfds; |
|
69 const char* data; |
|
70 |
|
71 if (!aMsg->ReadSize(aIter, &nbytes) || |
|
72 !aMsg->ReadSize(aIter, &nfds) || |
|
73 !aMsg->ReadBytes(aIter, &data, nbytes)) { |
|
74 return false; |
|
75 } |
|
76 |
|
77 int fds[nfds]; |
|
78 |
|
79 for (size_t n = 0; n < nfds; ++n) { |
|
80 FileDescriptor fd; |
|
81 if (!aMsg->ReadFileDescriptor(aIter, &fd)) { |
|
82 return false; |
|
83 } |
|
84 // If the GraphicBuffer was shared cross-process, SCM_RIGHTS does |
|
85 // the right thing and dup's the fd. If it's shared cross-thread, |
|
86 // SCM_RIGHTS doesn't dup the fd. That's surprising, but we just |
|
87 // deal with it here. NB: only the "default" (master) process can |
|
88 // alloc gralloc buffers. |
|
89 bool sameProcess = (XRE_GetProcessType() == GeckoProcessType_Default); |
|
90 int dupFd = sameProcess ? dup(fd.fd) : fd.fd; |
|
91 fds[n] = dupFd; |
|
92 } |
|
93 |
|
94 sp<Fence> buffer(new Fence()); |
|
95 #if ANDROID_VERSION >= 19 |
|
96 // Make a copy of "data" and "fds" for unflatten() to avoid casting problem |
|
97 void const *pdata = (void const *)data; |
|
98 int const *pfds = fds; |
|
99 |
|
100 if (NO_ERROR == buffer->unflatten(pdata, nbytes, pfds, nfds)) { |
|
101 #else |
|
102 Flattenable *flattenable = buffer.get(); |
|
103 |
|
104 if (NO_ERROR == flattenable->unflatten(data, nbytes, fds, nfds)) { |
|
105 #endif |
|
106 aResult->mFence = buffer; |
|
107 return true; |
|
108 } |
|
109 return false; |
|
110 } |
|
111 |
|
112 } // namespace IPC |
|
113 |
|
114 namespace mozilla { |
|
115 namespace layers { |
|
116 |
|
117 FenceHandle::FenceHandle(const sp<Fence>& aFence) |
|
118 : mFence(aFence) |
|
119 { |
|
120 } |
|
121 |
|
122 } // namespace layers |
|
123 } // namespace mozilla |