OSDN Git Service

Merge "CpuConsumer: Properly track acquired buffers" into jb-mr2-dev
[android-x86/frameworks-native.git] / libs / gui / IGraphicBufferProducer.cpp
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdint.h>
18 #include <sys/types.h>
19
20 #include <utils/Errors.h>
21 #include <utils/RefBase.h>
22 #include <utils/Vector.h>
23 #include <utils/Timers.h>
24
25 #include <binder/Parcel.h>
26 #include <binder/IInterface.h>
27
28 #include <gui/IGraphicBufferProducer.h>
29
30 namespace android {
31 // ----------------------------------------------------------------------------
32
33 enum {
34     REQUEST_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
35     SET_BUFFER_COUNT,
36     DEQUEUE_BUFFER,
37     QUEUE_BUFFER,
38     CANCEL_BUFFER,
39     QUERY,
40     SET_SYNCHRONOUS_MODE,
41     CONNECT,
42     DISCONNECT,
43 };
44
45
46 class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
47 {
48 public:
49     BpGraphicBufferProducer(const sp<IBinder>& impl)
50         : BpInterface<IGraphicBufferProducer>(impl)
51     {
52     }
53
54     virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) {
55         Parcel data, reply;
56         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
57         data.writeInt32(bufferIdx);
58         status_t result =remote()->transact(REQUEST_BUFFER, data, &reply);
59         if (result != NO_ERROR) {
60             return result;
61         }
62         bool nonNull = reply.readInt32();
63         if (nonNull) {
64             *buf = new GraphicBuffer();
65             reply.read(**buf);
66         }
67         result = reply.readInt32();
68         return result;
69     }
70
71     virtual status_t setBufferCount(int bufferCount)
72     {
73         Parcel data, reply;
74         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
75         data.writeInt32(bufferCount);
76         status_t result =remote()->transact(SET_BUFFER_COUNT, data, &reply);
77         if (result != NO_ERROR) {
78             return result;
79         }
80         result = reply.readInt32();
81         return result;
82     }
83
84     virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence,
85             uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
86         Parcel data, reply;
87         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
88         data.writeInt32(w);
89         data.writeInt32(h);
90         data.writeInt32(format);
91         data.writeInt32(usage);
92         status_t result = remote()->transact(DEQUEUE_BUFFER, data, &reply);
93         if (result != NO_ERROR) {
94             return result;
95         }
96         *buf = reply.readInt32();
97         bool fenceWasWritten = reply.readInt32();
98         if (fenceWasWritten) {
99             // If the fence was written by the callee, then overwrite the
100             // caller's fence here.  If it wasn't written then don't touch the
101             // caller's fence.
102             *fence = new Fence();
103             reply.read(*(fence->get()));
104         }
105         result = reply.readInt32();
106         return result;
107     }
108
109     virtual status_t queueBuffer(int buf,
110             const QueueBufferInput& input, QueueBufferOutput* output) {
111         Parcel data, reply;
112         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
113         data.writeInt32(buf);
114         data.write(input);
115         status_t result = remote()->transact(QUEUE_BUFFER, data, &reply);
116         if (result != NO_ERROR) {
117             return result;
118         }
119         memcpy(output, reply.readInplace(sizeof(*output)), sizeof(*output));
120         result = reply.readInt32();
121         return result;
122     }
123
124     virtual void cancelBuffer(int buf, const sp<Fence>& fence) {
125         Parcel data, reply;
126         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
127         data.writeInt32(buf);
128         data.write(*fence.get());
129         remote()->transact(CANCEL_BUFFER, data, &reply);
130     }
131
132     virtual int query(int what, int* value) {
133         Parcel data, reply;
134         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
135         data.writeInt32(what);
136         status_t result = remote()->transact(QUERY, data, &reply);
137         if (result != NO_ERROR) {
138             return result;
139         }
140         value[0] = reply.readInt32();
141         result = reply.readInt32();
142         return result;
143     }
144
145     virtual status_t setSynchronousMode(bool enabled) {
146         Parcel data, reply;
147         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
148         data.writeInt32(enabled);
149         status_t result = remote()->transact(SET_SYNCHRONOUS_MODE, data, &reply);
150         if (result != NO_ERROR) {
151             return result;
152         }
153         result = reply.readInt32();
154         return result;
155     }
156
157     virtual status_t connect(int api, QueueBufferOutput* output) {
158         Parcel data, reply;
159         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
160         data.writeInt32(api);
161         status_t result = remote()->transact(CONNECT, data, &reply);
162         if (result != NO_ERROR) {
163             return result;
164         }
165         memcpy(output, reply.readInplace(sizeof(*output)), sizeof(*output));
166         result = reply.readInt32();
167         return result;
168     }
169
170     virtual status_t disconnect(int api) {
171         Parcel data, reply;
172         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
173         data.writeInt32(api);
174         status_t result =remote()->transact(DISCONNECT, data, &reply);
175         if (result != NO_ERROR) {
176             return result;
177         }
178         result = reply.readInt32();
179         return result;
180     }
181 };
182
183 IMPLEMENT_META_INTERFACE(GraphicBufferProducer, "android.gui.IGraphicBufferProducer");
184
185 // ----------------------------------------------------------------------
186
187 status_t BnGraphicBufferProducer::onTransact(
188     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
189 {
190     switch(code) {
191         case REQUEST_BUFFER: {
192             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
193             int bufferIdx   = data.readInt32();
194             sp<GraphicBuffer> buffer;
195             int result = requestBuffer(bufferIdx, &buffer);
196             reply->writeInt32(buffer != 0);
197             if (buffer != 0) {
198                 reply->write(*buffer);
199             }
200             reply->writeInt32(result);
201             return NO_ERROR;
202         } break;
203         case SET_BUFFER_COUNT: {
204             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
205             int bufferCount = data.readInt32();
206             int result = setBufferCount(bufferCount);
207             reply->writeInt32(result);
208             return NO_ERROR;
209         } break;
210         case DEQUEUE_BUFFER: {
211             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
212             uint32_t w      = data.readInt32();
213             uint32_t h      = data.readInt32();
214             uint32_t format = data.readInt32();
215             uint32_t usage  = data.readInt32();
216             int buf;
217             sp<Fence> fence;
218             int result = dequeueBuffer(&buf, &fence, w, h, format, usage);
219             reply->writeInt32(buf);
220             reply->writeInt32(fence != NULL);
221             if (fence != NULL) {
222                 reply->write(*fence.get());
223             }
224             reply->writeInt32(result);
225             return NO_ERROR;
226         } break;
227         case QUEUE_BUFFER: {
228             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
229             int buf = data.readInt32();
230             QueueBufferInput input(data);
231             QueueBufferOutput* const output =
232                     reinterpret_cast<QueueBufferOutput *>(
233                             reply->writeInplace(sizeof(QueueBufferOutput)));
234             status_t result = queueBuffer(buf, input, output);
235             reply->writeInt32(result);
236             return NO_ERROR;
237         } break;
238         case CANCEL_BUFFER: {
239             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
240             int buf = data.readInt32();
241             sp<Fence> fence = new Fence();
242             data.read(*fence.get());
243             cancelBuffer(buf, fence);
244             return NO_ERROR;
245         } break;
246         case QUERY: {
247             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
248             int value;
249             int what = data.readInt32();
250             int res = query(what, &value);
251             reply->writeInt32(value);
252             reply->writeInt32(res);
253             return NO_ERROR;
254         } break;
255         case SET_SYNCHRONOUS_MODE: {
256             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
257             bool enabled = data.readInt32();
258             status_t res = setSynchronousMode(enabled);
259             reply->writeInt32(res);
260             return NO_ERROR;
261         } break;
262         case CONNECT: {
263             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
264             int api = data.readInt32();
265             QueueBufferOutput* const output =
266                     reinterpret_cast<QueueBufferOutput *>(
267                             reply->writeInplace(sizeof(QueueBufferOutput)));
268             status_t res = connect(api, output);
269             reply->writeInt32(res);
270             return NO_ERROR;
271         } break;
272         case DISCONNECT: {
273             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
274             int api = data.readInt32();
275             status_t res = disconnect(api);
276             reply->writeInt32(res);
277             return NO_ERROR;
278         } break;
279     }
280     return BBinder::onTransact(code, data, reply, flags);
281 }
282
283 // ----------------------------------------------------------------------------
284
285 IGraphicBufferProducer::QueueBufferInput::QueueBufferInput(const Parcel& parcel) {
286     parcel.read(*this);
287 }
288
289 size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const
290 {
291     return sizeof(timestamp)
292          + sizeof(crop)
293          + sizeof(scalingMode)
294          + sizeof(transform)
295          + fence->getFlattenedSize();
296 }
297
298 size_t IGraphicBufferProducer::QueueBufferInput::getFdCount() const
299 {
300     return fence->getFdCount();
301 }
302
303 status_t IGraphicBufferProducer::QueueBufferInput::flatten(void* buffer, size_t size,
304         int fds[], size_t count) const
305 {
306     status_t err = NO_ERROR;
307     char* p = (char*)buffer;
308     memcpy(p, &timestamp,   sizeof(timestamp));   p += sizeof(timestamp);
309     memcpy(p, &crop,        sizeof(crop));        p += sizeof(crop);
310     memcpy(p, &scalingMode, sizeof(scalingMode)); p += sizeof(scalingMode);
311     memcpy(p, &transform,   sizeof(transform));   p += sizeof(transform);
312     err = fence->flatten(p, size - (p - (char*)buffer), fds, count);
313     return err;
314 }
315
316 status_t IGraphicBufferProducer::QueueBufferInput::unflatten(void const* buffer,
317         size_t size, int fds[], size_t count)
318 {
319     status_t err = NO_ERROR;
320     const char* p = (const char*)buffer;
321     memcpy(&timestamp,   p, sizeof(timestamp));   p += sizeof(timestamp);
322     memcpy(&crop,        p, sizeof(crop));        p += sizeof(crop);
323     memcpy(&scalingMode, p, sizeof(scalingMode)); p += sizeof(scalingMode);
324     memcpy(&transform,   p, sizeof(transform));   p += sizeof(transform);
325     fence = new Fence();
326     err = fence->unflatten(p, size - (p - (const char*)buffer), fds, count);
327     return err;
328 }
329
330 }; // namespace android