1 | /* |
2 | Copyright (c) 2012, Broadcom Europe Ltd |
3 | All rights reserved. |
4 | |
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the following conditions are met: |
7 | * Redistributions of source code must retain the above copyright |
8 | notice, this list of conditions and the following disclaimer. |
9 | * Redistributions in binary form must reproduce the above copyright |
10 | notice, this list of conditions and the following disclaimer in the |
11 | documentation and/or other materials provided with the distribution. |
12 | * Neither the name of the copyright holder nor the |
13 | names of its contributors may be used to endorse or promote products |
14 | derived from this software without specific prior written permission. |
15 | |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY |
20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ |
27 | |
28 | #include "interface/khronos/wf/wfc_server_api.h" |
29 | #include "interface/khronos/wf/wfc_client_ipc.h" |
30 | #include "interface/khronos/wf/wfc_ipc.h" |
31 | #include "interface/vcos/vcos.h" |
32 | #include "interface/khronos/include/WF/wfc.h" |
33 | #include "interface/khronos/wf/wfc_int.h" |
34 | #include "interface/khronos/include/EGL/eglext.h" |
35 | |
36 | #define VCOS_LOG_CATEGORY (&wfc_client_server_api_log_category) |
37 | |
38 | //#define WFC_FULL_LOGGING |
39 | #ifdef WFC_FULL_LOGGING |
40 | #define WFC_CLIENT_SERVER_API_LOGLEVEL VCOS_LOG_TRACE |
41 | #else |
42 | #define WFC_CLIENT_SERVER_API_LOGLEVEL VCOS_LOG_WARN |
43 | #endif |
44 | |
45 | static VCOS_LOG_CAT_T wfc_client_server_api_log_category; |
46 | |
47 | /** Implement "void foo(WFCContext context)" */ |
48 | static VCOS_STATUS_T wfc_client_server_api_send_context(WFC_IPC_MSG_TYPE msg_type, WFCContext context) |
49 | { |
50 | WFC_IPC_MSG_CONTEXT_T msg; |
51 | |
52 | msg.header.type = msg_type; |
53 | msg.context = context; |
54 | |
55 | return wfc_client_ipc_send(&msg.header, sizeof(msg)); |
56 | } |
57 | |
58 | /** Implement "void foo(WFCNativeStreamType stream)" */ |
59 | static VCOS_STATUS_T wfc_client_server_api_send_stream(WFC_IPC_MSG_TYPE msg_type, WFCNativeStreamType stream) |
60 | { |
61 | WFC_IPC_MSG_STREAM_T msg; |
62 | |
63 | msg.header.type = msg_type; |
64 | msg.stream = stream; |
65 | |
66 | return wfc_client_ipc_send(&msg.header, sizeof(msg)); |
67 | } |
68 | |
69 | /** Implement "foo(WFCNativeStreamType stream)" where a result is returned. |
70 | * This may either be as a return value, or via a pointer parameter. |
71 | */ |
72 | static VCOS_STATUS_T wfc_client_server_api_sendwait_stream(WFC_IPC_MSG_TYPE msg_type, WFCNativeStreamType stream, |
73 | void *result, size_t *result_len) |
74 | { |
75 | WFC_IPC_MSG_STREAM_T msg; |
76 | |
77 | msg.header.type = msg_type; |
78 | msg.stream = stream; |
79 | |
80 | return wfc_client_ipc_sendwait(&msg.header, sizeof(msg), result, result_len); |
81 | } |
82 | |
83 | /* ========================================================================= */ |
84 | |
85 | VCOS_STATUS_T wfc_server_connect(void) |
86 | { |
87 | VCOS_STATUS_T status; |
88 | |
89 | vcos_log_set_level(VCOS_LOG_CATEGORY, WFC_CLIENT_SERVER_API_LOGLEVEL); |
90 | vcos_log_register("wfccsapi" , VCOS_LOG_CATEGORY); |
91 | |
92 | status = wfc_client_ipc_init(); |
93 | |
94 | vcos_log_trace("%s: result %d" , VCOS_FUNCTION, status); |
95 | |
96 | if (status != VCOS_SUCCESS) |
97 | { |
98 | vcos_log_unregister(VCOS_LOG_CATEGORY); |
99 | } |
100 | |
101 | return status; |
102 | } |
103 | |
104 | /* ------------------------------------------------------------------------- */ |
105 | |
106 | void wfc_server_disconnect(void) |
107 | { |
108 | vcos_log_trace("%s: called" , VCOS_FUNCTION); |
109 | |
110 | if (wfc_client_ipc_deinit()) |
111 | { |
112 | vcos_log_unregister(VCOS_LOG_CATEGORY); |
113 | } |
114 | } |
115 | |
116 | /* ------------------------------------------------------------------------- */ |
117 | |
118 | void wfc_server_use_keep_alive(void) |
119 | { |
120 | wfc_client_ipc_use_keep_alive(); |
121 | } |
122 | |
123 | /* ------------------------------------------------------------------------- */ |
124 | |
125 | void wfc_server_release_keep_alive(void) |
126 | { |
127 | wfc_client_ipc_release_keep_alive(); |
128 | } |
129 | |
130 | /* ------------------------------------------------------------------------- */ |
131 | |
132 | uint32_t wfc_server_create_context(WFCContext context, uint32_t context_type, |
133 | uint32_t screen_or_stream_num, uint32_t pid_lo, uint32_t pid_hi) |
134 | { |
135 | WFC_IPC_MSG_CREATE_CONTEXT_T msg; |
136 | VCOS_STATUS_T status; |
137 | uint32_t result = -1; |
138 | size_t result_len = sizeof(result); |
139 | |
140 | vcos_log_trace("%s: context 0x%x type 0x%x num 0x%x pid 0x%x%08x" , VCOS_FUNCTION, |
141 | context, context_type, screen_or_stream_num, pid_hi, pid_lo); |
142 | |
143 | msg.header.type = WFC_IPC_MSG_CREATE_CONTEXT; |
144 | msg.context = context; |
145 | msg.context_type = context_type; |
146 | msg.screen_or_stream_num = screen_or_stream_num; |
147 | msg.pid_lo = pid_lo; |
148 | msg.pid_hi = pid_hi; |
149 | |
150 | status = wfc_client_ipc_sendwait(&msg.header, sizeof(msg), &result, &result_len); |
151 | |
152 | vcos_log_trace("%s: status 0x%x, result 0x%x" , VCOS_FUNCTION, status, result); |
153 | |
154 | if (status != VCOS_SUCCESS) |
155 | result = -1; |
156 | |
157 | return result; |
158 | } |
159 | |
160 | /* ------------------------------------------------------------------------- */ |
161 | |
162 | void wfc_server_destroy_context(WFCContext context) |
163 | { |
164 | VCOS_STATUS_T status; |
165 | |
166 | vcos_log_trace("%s: context 0x%x" , VCOS_FUNCTION, context); |
167 | |
168 | status = wfc_client_server_api_send_context(WFC_IPC_MSG_DESTROY_CONTEXT, context); |
169 | |
170 | vcos_assert(status == VCOS_SUCCESS); |
171 | } |
172 | |
173 | /* ------------------------------------------------------------------------- */ |
174 | |
175 | uint32_t wfc_server_commit_scene(WFCContext context, const WFC_SCENE_T *scene, |
176 | uint32_t flags, WFC_CALLBACK_T scene_taken_cb, void *scene_taken_data) |
177 | { |
178 | WFC_IPC_MSG_COMMIT_SCENE_T msg; |
179 | VCOS_STATUS_T status = VCOS_SUCCESS; |
180 | uint32_t result = VCOS_ENOSYS; |
181 | size_t result_len = sizeof(result); |
182 | uint32_t i; |
183 | |
184 | vcos_log_trace("%s: context 0x%x commit %u elements %u flags 0x%x" , |
185 | VCOS_FUNCTION, context, scene->commit_count, scene->element_count, flags); |
186 | for (i = 0; i < scene->element_count; i++) |
187 | { |
188 | vcos_log_trace("%s: element[%u] stream 0x%x" , VCOS_FUNCTION, i, scene->elements[i].source_stream); |
189 | } |
190 | |
191 | msg.header.type = WFC_IPC_MSG_COMMIT_SCENE; |
192 | msg.context = context; |
193 | msg.flags = flags; |
194 | msg.scene_taken_cb.ptr = scene_taken_cb; |
195 | msg.scene_taken_data.ptr = scene_taken_data; |
196 | memcpy(&msg.scene, scene, sizeof(*scene)); |
197 | |
198 | if (flags & WFC_SERVER_COMMIT_WAIT) |
199 | { |
200 | /* Caller will wait for callback, call cannot fail */ |
201 | vcos_assert(scene_taken_cb != NULL); |
202 | vcos_assert(scene_taken_data != NULL); |
203 | } |
204 | else |
205 | { |
206 | /* Caller will not wait for callback, so need to at least wait for result. */ |
207 | vcos_assert(scene_taken_cb == NULL); |
208 | vcos_assert(scene_taken_data == NULL); |
209 | } |
210 | |
211 | status = wfc_client_ipc_sendwait(&msg.header, sizeof(msg), &result, &result_len); |
212 | |
213 | /* Override the result if the status was an error */ |
214 | if (status != VCOS_SUCCESS) |
215 | result = status; |
216 | |
217 | return result; |
218 | } |
219 | |
220 | /* ------------------------------------------------------------------------- */ |
221 | |
222 | void wfc_server_activate(WFCContext context) |
223 | { |
224 | VCOS_STATUS_T status; |
225 | |
226 | vcos_log_trace("%s: context 0x%x" , VCOS_FUNCTION, context); |
227 | |
228 | status = wfc_client_server_api_send_context(WFC_IPC_MSG_ACTIVATE, context); |
229 | |
230 | vcos_assert(status == VCOS_SUCCESS); |
231 | } |
232 | |
233 | /* ------------------------------------------------------------------------- */ |
234 | |
235 | void wfc_server_deactivate(WFCContext context) |
236 | { |
237 | VCOS_STATUS_T status; |
238 | |
239 | vcos_log_trace("%s: context 0x%x" , VCOS_FUNCTION, context); |
240 | |
241 | status = wfc_client_server_api_send_context(WFC_IPC_MSG_DEACTIVATE, context); |
242 | |
243 | vcos_assert(status == VCOS_SUCCESS); |
244 | } |
245 | |
246 | /* ------------------------------------------------------------------------- */ |
247 | |
248 | void wfc_server_set_deferral_stream(WFCContext context, WFCNativeStreamType stream) |
249 | { |
250 | WFC_IPC_MSG_SET_DEFERRAL_STREAM_T msg; |
251 | VCOS_STATUS_T status; |
252 | |
253 | vcos_log_trace("%s: context 0x%x stream 0x%x" , VCOS_FUNCTION, context, stream); |
254 | |
255 | msg.header.type = WFC_IPC_MSG_SET_DEFERRAL_STREAM; |
256 | msg.context = context; |
257 | msg.stream = stream; |
258 | |
259 | status = wfc_client_ipc_send(&msg.header, sizeof(msg)); |
260 | |
261 | vcos_assert(status == VCOS_SUCCESS); |
262 | } |
263 | |
264 | /* ------------------------------------------------------------------------- */ |
265 | |
266 | WFCNativeStreamType wfc_server_stream_create(WFCNativeStreamType stream, uint32_t flags, uint32_t pid_lo, uint32_t pid_hi) |
267 | { |
268 | WFC_IPC_MSG_SS_CREATE_INFO_T msg; |
269 | VCOS_STATUS_T status; |
270 | WFCNativeStreamType result = WFC_INVALID_HANDLE; |
271 | size_t result_len = sizeof(result); |
272 | |
273 | vcos_log_trace("%s: stream 0x%x flags 0x%x pid 0x%x%08x" , VCOS_FUNCTION, stream, flags, pid_hi, pid_lo); |
274 | |
275 | msg.header.type = WFC_IPC_MSG_SS_CREATE_INFO; |
276 | msg.stream = stream; |
277 | memset(&msg.info, 0, sizeof(msg.info)); |
278 | msg.info.size = sizeof(msg.info); |
279 | msg.info.flags = flags; |
280 | msg.pid_lo = pid_lo; |
281 | msg.pid_hi = pid_hi; |
282 | |
283 | status = wfc_client_ipc_sendwait(&msg.header, sizeof(msg), &result, &result_len); |
284 | |
285 | vcos_log_trace("%s: status 0x%x, result 0x%x" , VCOS_FUNCTION, status, result); |
286 | |
287 | if (status != VCOS_SUCCESS) |
288 | result = WFC_INVALID_HANDLE; |
289 | |
290 | return result; |
291 | } |
292 | |
293 | /* ------------------------------------------------------------------------- */ |
294 | |
295 | WFCNativeStreamType wfc_server_stream_create_info(WFCNativeStreamType stream, const WFC_STREAM_INFO_T *info, uint32_t pid_lo, uint32_t pid_hi) |
296 | { |
297 | WFC_IPC_MSG_SS_CREATE_INFO_T msg; |
298 | uint32_t copy_size; |
299 | VCOS_STATUS_T status; |
300 | WFCNativeStreamType result = WFC_INVALID_HANDLE; |
301 | size_t result_len = sizeof(result); |
302 | |
303 | if (!info) |
304 | { |
305 | vcos_log_error("%s: NULL info pointer passed" , VCOS_FUNCTION); |
306 | return WFC_INVALID_HANDLE; |
307 | } |
308 | |
309 | if (info->size < sizeof(uint32_t)) |
310 | { |
311 | vcos_log_error("%s: invalid info pointer passed (size:%u)" , VCOS_FUNCTION, info->size); |
312 | return WFC_INVALID_HANDLE; |
313 | } |
314 | |
315 | vcos_log_trace("%s: stream 0x%x flags 0x%x pid 0x%x%08x" , VCOS_FUNCTION, stream, info->flags, pid_hi, pid_lo); |
316 | |
317 | msg.header.type = WFC_IPC_MSG_SS_CREATE_INFO; |
318 | msg.stream = stream; |
319 | copy_size = vcos_min(info->size, sizeof(msg.info)); |
320 | memcpy(&msg.info, info, copy_size); |
321 | msg.info.size = copy_size; |
322 | msg.pid_lo = pid_lo; |
323 | msg.pid_hi = pid_hi; |
324 | |
325 | status = wfc_client_ipc_sendwait(&msg.header, sizeof(msg), &result, &result_len); |
326 | |
327 | vcos_log_trace("%s: status 0x%x, result 0x%x" , VCOS_FUNCTION, status, result); |
328 | |
329 | if (status != VCOS_SUCCESS) |
330 | result = WFC_INVALID_HANDLE; |
331 | |
332 | return result; |
333 | } |
334 | |
335 | /* ------------------------------------------------------------------------- */ |
336 | |
337 | void wfc_server_stream_destroy(WFCNativeStreamType stream, uint32_t pid_lo, uint32_t pid_hi) |
338 | { |
339 | WFC_IPC_MSG_SS_DESTROY_T msg; |
340 | VCOS_STATUS_T status; |
341 | |
342 | vcos_log_trace("%s: stream 0x%x" , VCOS_FUNCTION, stream); |
343 | |
344 | msg.header.type = WFC_IPC_MSG_SS_DESTROY; |
345 | msg.stream = stream; |
346 | msg.pid_lo = pid_lo; |
347 | msg.pid_hi = pid_hi; |
348 | |
349 | status = wfc_client_ipc_send(&msg.header, sizeof(msg)); |
350 | |
351 | vcos_assert(status == VCOS_SUCCESS); |
352 | } |
353 | |
354 | /* ------------------------------------------------------------------------- */ |
355 | |
356 | void wfc_server_stream_on_rects_change(WFCNativeStreamType stream, WFC_CALLBACK_T rects_change_cb, void *rects_change_data) |
357 | { |
358 | WFC_IPC_MSG_SS_ON_RECTS_CHANGE_T msg; |
359 | VCOS_STATUS_T status; |
360 | |
361 | vcos_log_trace("%s: stream 0x%x cb %p data %p" , VCOS_FUNCTION, stream, rects_change_cb, rects_change_data); |
362 | |
363 | msg.header.type = WFC_IPC_MSG_SS_ON_RECTS_CHANGE; |
364 | msg.stream = stream; |
365 | msg.rects_change_cb.ptr = rects_change_cb; |
366 | msg.rects_change_data.ptr = rects_change_data; |
367 | |
368 | status = wfc_client_ipc_send(&msg.header, sizeof(msg)); |
369 | |
370 | if (!vcos_verify(status == VCOS_SUCCESS)) |
371 | { |
372 | (*rects_change_cb)(rects_change_data); |
373 | } |
374 | } |
375 | |
376 | /* ------------------------------------------------------------------------- */ |
377 | |
378 | uint32_t wfc_server_stream_get_rects(WFCNativeStreamType stream, int32_t rects[WFC_SERVER_STREAM_RECTS_SIZE]) |
379 | { |
380 | uint32_t result; |
381 | VCOS_STATUS_T status; |
382 | WFC_IPC_MSG_SS_GET_RECTS_T reply; |
383 | size_t rects_len = sizeof(reply) - sizeof(WFC_IPC_MSG_HEADER_T); |
384 | |
385 | vcos_log_trace("%s: stream 0x%x" , VCOS_FUNCTION, stream); |
386 | memset(&reply, 0, sizeof(reply)); |
387 | status = wfc_client_server_api_sendwait_stream(WFC_IPC_MSG_SS_GET_RECTS, stream, &reply.result, &rects_len); |
388 | |
389 | if (status == VCOS_SUCCESS) |
390 | { |
391 | result = reply.result; |
392 | |
393 | if (result == VCOS_SUCCESS) |
394 | { |
395 | memcpy(rects, reply.rects, WFC_SERVER_STREAM_RECTS_SIZE * sizeof(*rects)); |
396 | vcos_log_trace("%s: rects (%d,%d,%d,%d) (%d,%d,%d,%d)" , VCOS_FUNCTION, |
397 | rects[0], rects[1], rects[2], rects[3], rects[4], rects[5], rects[6], rects[7]); |
398 | } |
399 | else |
400 | { |
401 | vcos_log_error("%s: result %d" , VCOS_FUNCTION, result); |
402 | } |
403 | } |
404 | else |
405 | { |
406 | vcos_log_error("%s: send msg status %d" , VCOS_FUNCTION, status); |
407 | result = status; |
408 | } |
409 | |
410 | return result; |
411 | } |
412 | |
413 | /* ------------------------------------------------------------------------- */ |
414 | |
415 | bool wfc_server_stream_is_in_use(WFCNativeStreamType stream) |
416 | { |
417 | VCOS_STATUS_T status; |
418 | uint32_t result = 0; |
419 | size_t result_len = sizeof(result); |
420 | |
421 | vcos_log_trace("%s: stream 0x%x" , VCOS_FUNCTION, stream); |
422 | |
423 | status = wfc_client_server_api_sendwait_stream(WFC_IPC_MSG_SS_IS_IN_USE, stream, &result, &result_len); |
424 | |
425 | vcos_log_trace("%s: status 0x%x, result %u" , VCOS_FUNCTION, status, result); |
426 | |
427 | if (status != VCOS_SUCCESS) |
428 | result = 0; |
429 | |
430 | return result != 0; |
431 | } |
432 | |
433 | /* ------------------------------------------------------------------------- */ |
434 | |
435 | bool wfc_server_stream_allocate_images(WFCNativeStreamType stream, uint32_t width, uint32_t height, uint32_t nbufs) |
436 | { |
437 | WFC_IPC_MSG_SS_ALLOCATE_IMAGES_T msg; |
438 | VCOS_STATUS_T status; |
439 | uint32_t result = 0; |
440 | size_t result_len = sizeof(result); |
441 | |
442 | vcos_log_trace("%s: stream 0x%x width %u height %u nbufs %u" , VCOS_FUNCTION, stream, width, height, nbufs); |
443 | |
444 | msg.header.type = WFC_IPC_MSG_SS_ALLOCATE_IMAGES; |
445 | msg.stream = stream; |
446 | msg.width = width; |
447 | msg.height = height; |
448 | msg.nbufs = nbufs; |
449 | |
450 | status = wfc_client_ipc_sendwait(&msg.header, sizeof(msg), &result, &result_len); |
451 | |
452 | vcos_log_trace("%s: status 0x%x result %u" , VCOS_FUNCTION, status, result); |
453 | |
454 | if (status != VCOS_SUCCESS) |
455 | result = 0; |
456 | |
457 | return result; |
458 | } |
459 | |
460 | /* ------------------------------------------------------------------------- */ |
461 | |
462 | void wfc_server_stream_signal_eglimage_data(WFCNativeStreamType stream, |
463 | uint32_t ustorage, uint32_t width, uint32_t height, uint32_t stride, |
464 | uint32_t offset, uint32_t format, uint32_t flags, bool flip) |
465 | { |
466 | WFC_IPC_MSG_SS_SIGNAL_EGLIMAGE_DATA_T msg; |
467 | VCOS_STATUS_T status; |
468 | |
469 | memset(&msg, 0, sizeof msg); |
470 | msg.header.type = WFC_IPC_MSG_SS_SIGNAL_EGLIMAGE_DATA; |
471 | msg.stream = stream; |
472 | msg.ustorage = ustorage; |
473 | msg.width = width; |
474 | msg.height = height; |
475 | msg.stride = stride; |
476 | msg.offset = offset; |
477 | msg.format = format; |
478 | msg.flags = flags; |
479 | msg.flip = flip; |
480 | |
481 | vcos_log_trace("%s: stream 0x%x image storage 0x%x" , |
482 | VCOS_FUNCTION, stream, ustorage); |
483 | |
484 | status = wfc_client_ipc_send(&msg.header, sizeof(msg)); |
485 | |
486 | vcos_assert(status == VCOS_SUCCESS); |
487 | } |
488 | |
489 | /* ------------------------------------------------------------------------- */ |
490 | |
491 | void wfc_server_stream_signal_mm_image_data(WFCNativeStreamType stream, uint32_t image_handle) |
492 | { |
493 | WFC_IPC_MSG_SS_SIGNAL_MM_IMAGE_DATA_T msg; |
494 | VCOS_STATUS_T status; |
495 | |
496 | vcos_log_trace("%s: stream 0x%x image 0x%x" , VCOS_FUNCTION, stream, image_handle); |
497 | |
498 | msg.header.type = WFC_IPC_MSG_SS_SIGNAL_MM_IMAGE_DATA; |
499 | msg.stream = stream; |
500 | msg.image_handle = image_handle; |
501 | |
502 | status = wfc_client_ipc_send(&msg.header, sizeof(msg)); |
503 | |
504 | vcos_assert(status == VCOS_SUCCESS); |
505 | } |
506 | |
507 | /* ------------------------------------------------------------------------- */ |
508 | |
509 | void wfc_server_stream_signal_raw_pixels(WFCNativeStreamType stream, |
510 | uint32_t handle, uint32_t format, uint32_t width, uint32_t height, |
511 | uint32_t pitch, uint32_t vpitch) |
512 | { |
513 | WFC_IPC_MSG_SS_SIGNAL_RAW_PIXELS_T msg; |
514 | VCOS_STATUS_T status; |
515 | |
516 | vcos_log_trace("%s: stream 0x%x image 0x%x format 0x%x width %u height %u" |
517 | " pitch %u vpitch %u" , |
518 | VCOS_FUNCTION, stream, handle, format, width, height, pitch, vpitch); |
519 | |
520 | msg.header.type = WFC_IPC_MSG_SS_SIGNAL_RAW_PIXELS; |
521 | msg.stream = stream; |
522 | msg.handle = handle; |
523 | msg.format = format; |
524 | msg.width = width; |
525 | msg.height = height; |
526 | msg.pitch = pitch; |
527 | msg.vpitch = vpitch; |
528 | |
529 | status = wfc_client_ipc_send(&msg.header, sizeof(msg)); |
530 | vcos_assert(status == VCOS_SUCCESS); |
531 | } |
532 | |
533 | /* ------------------------------------------------------------------------- */ |
534 | void wfc_server_stream_signal_image(WFCNativeStreamType stream, |
535 | const WFC_STREAM_IMAGE_T *image) |
536 | { |
537 | WFC_IPC_MSG_SS_SIGNAL_IMAGE_T msg; |
538 | VCOS_STATUS_T status; |
539 | |
540 | vcos_log_trace("%s: stream 0x%x type 0x%x handle 0x%x " |
541 | " format 0x%x protection 0x%x width %u height %u " |
542 | " pitch %u vpitch %u" , |
543 | VCOS_FUNCTION, stream, image->type, image->handle, |
544 | image->format, image->protection, image->width, image->height, |
545 | image->pitch, image->vpitch); |
546 | |
547 | msg.header.type = WFC_IPC_MSG_SS_SIGNAL_IMAGE; |
548 | msg.stream = stream; |
549 | if vcos_verify(image->length <= sizeof(msg.image)) |
550 | { |
551 | msg.image = *image; |
552 | } |
553 | else |
554 | { |
555 | /* Client is newer than VC ? */ |
556 | memcpy(&msg.image, image, sizeof(msg.image)); |
557 | msg.image.length = sizeof(msg.image); |
558 | } |
559 | |
560 | status = wfc_client_ipc_send(&msg.header, sizeof(msg)); |
561 | |
562 | vcos_assert(status == VCOS_SUCCESS); |
563 | } |
564 | |
565 | /* ------------------------------------------------------------------------- */ |
566 | |
567 | void wfc_server_stream_register(WFCNativeStreamType stream, uint32_t pid_lo, uint32_t pid_hi) |
568 | { |
569 | WFC_IPC_MSG_SS_REGISTER_T msg; |
570 | VCOS_STATUS_T status; |
571 | |
572 | vcos_log_trace("%s: stream 0x%x pid 0x%x%08x" , VCOS_FUNCTION, stream, pid_hi, pid_lo); |
573 | |
574 | msg.header.type = WFC_IPC_MSG_SS_REGISTER; |
575 | msg.stream = stream; |
576 | msg.pid_lo = pid_lo; |
577 | msg.pid_hi = pid_hi; |
578 | |
579 | status = wfc_client_ipc_send(&msg.header, sizeof(msg)); |
580 | |
581 | vcos_assert(status == VCOS_SUCCESS); |
582 | } |
583 | |
584 | /* ------------------------------------------------------------------------- */ |
585 | |
586 | void wfc_server_stream_unregister(WFCNativeStreamType stream, uint32_t pid_lo, uint32_t pid_hi) |
587 | { |
588 | WFC_IPC_MSG_SS_UNREGISTER_T msg; |
589 | VCOS_STATUS_T status; |
590 | |
591 | vcos_log_trace("%s: stream 0x%x pid 0x%x%08x" , VCOS_FUNCTION, stream, pid_hi, pid_lo); |
592 | |
593 | msg.header.type = WFC_IPC_MSG_SS_UNREGISTER; |
594 | msg.stream = stream; |
595 | msg.pid_lo = pid_lo; |
596 | msg.pid_hi = pid_hi; |
597 | |
598 | status = wfc_client_ipc_send(&msg.header, sizeof(msg)); |
599 | |
600 | vcos_assert(status == VCOS_SUCCESS); |
601 | } |
602 | |
603 | /* ------------------------------------------------------------------------- */ |
604 | |
605 | uint32_t wfc_server_stream_get_info(WFCNativeStreamType stream, WFC_STREAM_INFO_T *info) |
606 | { |
607 | uint32_t result; |
608 | VCOS_STATUS_T status; |
609 | WFC_IPC_MSG_SS_GET_INFO_T reply; |
610 | size_t info_len = sizeof(reply) - sizeof(WFC_IPC_MSG_HEADER_T); |
611 | |
612 | if (!info) |
613 | { |
614 | vcos_log_error("%s: NULL info pointer passed" , VCOS_FUNCTION); |
615 | return WFC_INVALID_HANDLE; |
616 | } |
617 | |
618 | if (info->size < sizeof(uint32_t)) |
619 | { |
620 | vcos_log_error("%s: invalid info pointer passed (size:%u)" , VCOS_FUNCTION, info->size); |
621 | return WFC_INVALID_HANDLE; |
622 | } |
623 | |
624 | vcos_log_trace("%s: stream 0x%x" , VCOS_FUNCTION, stream); |
625 | memset(&reply, 0, sizeof(reply)); |
626 | status = wfc_client_server_api_sendwait_stream(WFC_IPC_MSG_SS_GET_INFO, stream, &reply.result, &info_len); |
627 | |
628 | if (status == VCOS_SUCCESS) |
629 | { |
630 | result = reply.result; |
631 | |
632 | if (result == VCOS_SUCCESS) |
633 | { |
634 | uint32_t copy_size = vcos_min(info->size, reply.info.size); |
635 | memcpy(info, &reply.info, copy_size); |
636 | info->size = copy_size; |
637 | vcos_log_trace("%s: copied %u bytes" , VCOS_FUNCTION, copy_size); |
638 | } |
639 | else |
640 | { |
641 | vcos_log_error("%s: result %d" , VCOS_FUNCTION, result); |
642 | } |
643 | } |
644 | else |
645 | { |
646 | vcos_log_error("%s: send msg status %d" , VCOS_FUNCTION, status); |
647 | result = status; |
648 | } |
649 | |
650 | return result; |
651 | } |
652 | |
653 | /* ------------------------------------------------------------------------- */ |
654 | |
655 | void wfc_server_stream_on_image_available(WFCNativeStreamType stream, WFC_CALLBACK_T image_available_cb, void *image_available_data) |
656 | { |
657 | WFC_IPC_MSG_SS_ON_IMAGE_AVAILABLE_T msg; |
658 | VCOS_STATUS_T status; |
659 | |
660 | vcos_log_trace("%s: stream 0x%x cb %p data %p" , VCOS_FUNCTION, stream, image_available_cb, image_available_data); |
661 | |
662 | msg.header.type = WFC_IPC_MSG_SS_ON_IMAGE_AVAILABLE; |
663 | msg.stream = stream; |
664 | msg.image_available_cb.ptr = image_available_cb; |
665 | msg.image_available_data.ptr = image_available_data; |
666 | |
667 | status = wfc_client_ipc_send(&msg.header, sizeof(msg)); |
668 | |
669 | if (!vcos_verify(status == VCOS_SUCCESS)) |
670 | { |
671 | (*image_available_cb)(image_available_data); |
672 | } |
673 | } |
674 | |