1/*
2Copyright (c) 2012-2014, Broadcom Europe Ltd
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, 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
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23ON 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
25SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/
27#include <string.h>
28#include <stdlib.h>
29
30#include "vchost_platform_config.h"
31#include "vchost.h"
32
33#include "interface/vcos/vcos.h"
34#include "vc_dispservice_x_defs.h"
35#include "vc_dispmanx.h"
36#include "interface/vchi/vchi.h"
37#include "vcinclude/common.h"
38#include "interface/vchi/common/endian.h"
39#include "interface/vchi/message_drivers/message.h"
40#include "vc_vchi_dispmanx.h"
41/******************************************************************************
42Local types and defines.
43******************************************************************************/
44//DispmanX service
45typedef struct {
46 VCHI_SERVICE_HANDLE_T client_handle[VCHI_MAX_NUM_CONNECTIONS]; //To connect to server on VC
47 VCHI_SERVICE_HANDLE_T notify_handle[VCHI_MAX_NUM_CONNECTIONS]; //For incoming notification
48 uint32_t msg_flag[VCHI_MAX_NUM_CONNECTIONS];
49 char command_buffer[DISPMANX_MSGFIFO_SIZE];
50 char response_buffer[DISPMANX_MSGFIFO_SIZE];
51 uint32_t response_length;
52 uint32_t notify_buffer[DISPMANX_MSGFIFO_SIZE/sizeof(uint32_t)];
53 uint32_t notify_length;
54 uint32_t num_connections;
55 VCOS_MUTEX_T lock;
56 char dispmanx_devices[DISPMANX_MAX_HOST_DEVICES][DISPMANX_MAX_DEVICE_NAME_LEN];
57 uint32_t num_devices;
58 uint32_t num_modes[DISPMANX_MAX_HOST_DEVICES];
59
60 //Callback for update
61 DISPMANX_CALLBACK_FUNC_T update_callback;
62 void *update_callback_param;
63 DISPMANX_UPDATE_HANDLE_T pending_update_handle;
64
65 //Callback for vsync
66 DISPMANX_CALLBACK_FUNC_T vsync_callback;
67 void *vsync_callback_param;
68 int vsync_enabled;
69
70 int initialised;
71} DISPMANX_SERVICE_T;
72
73/******************************************************************************
74Static data.
75******************************************************************************/
76static DISPMANX_SERVICE_T dispmanx_client;
77static VCOS_EVENT_T dispmanx_message_available_event;
78static VCOS_EVENT_T dispmanx_notify_available_event;
79static VCOS_THREAD_T dispmanx_notify_task;
80
81/******************************************************************************
82Static functions.
83******************************************************************************/
84//Lock the host state
85static __inline void lock_obtain (void) {
86 VCOS_STATUS_T status;
87 uint32_t i;
88 vcos_assert(dispmanx_client.initialised);
89 status = vcos_mutex_lock( &dispmanx_client.lock );
90 if(dispmanx_client.initialised)
91 {
92 for (i=0; i<dispmanx_client.num_connections; i++) {
93 vchi_service_use(dispmanx_client.client_handle[i]);
94 }
95 }
96 vcos_assert(status == VCOS_SUCCESS);
97}
98
99//Unlock the host state
100static __inline void lock_release (void) {
101 uint32_t i;
102 vcos_assert(dispmanx_client.initialised);
103 if(dispmanx_client.initialised)
104 {
105 for (i=0; i<dispmanx_client.num_connections; i++) {
106 vchi_service_release(dispmanx_client.client_handle[i]);
107 }
108 }
109 vcos_mutex_unlock( &dispmanx_client.lock );
110}
111
112//Forward declarations
113static void dispmanx_client_callback( void *callback_param,
114 VCHI_CALLBACK_REASON_T reason,
115 void *msg_handle );
116
117static void dispmanx_notify_callback( void *callback_param,
118 VCHI_CALLBACK_REASON_T reason,
119 void *msg_handle );
120
121static int32_t dispmanx_wait_for_reply(void *response, uint32_t max_length);
122
123static int32_t dispmanx_send_command( uint32_t command, void *buffer, uint32_t length);
124
125static int32_t dispmanx_send_command_reply( uint32_t command, void *buffer, uint32_t length,
126 void *response, uint32_t max_length);
127
128static uint32_t dispmanx_get_handle( uint32_t command, void *buffer, uint32_t length);
129
130static void *dispmanx_notify_func( void *arg );
131
132
133/******************************************************************************
134NAME
135 vc_vchi_gencmd_init
136
137SYNOPSIS
138 void vc_vchi_gencmd_init(VCHI_INSTANCE_T initialise_instance, VCHI_CONNECTION_T **connections, uint32_t num_connections )
139
140FUNCTION
141 Initialise the general command service for use. A negative return value
142 indicates failure (which may mean it has not been started on VideoCore).
143
144RETURNS
145 int
146******************************************************************************/
147
148void vc_vchi_dispmanx_init (VCHI_INSTANCE_T initialise_instance, VCHI_CONNECTION_T **connections, uint32_t num_connections ) {
149 VCOS_STATUS_T status;
150 int32_t success;
151 uint32_t i;
152
153 if (dispmanx_client.initialised)
154 return;
155
156 // record the number of connections
157 memset( &dispmanx_client, 0, sizeof(DISPMANX_SERVICE_T) );
158 dispmanx_client.num_connections = num_connections;
159
160 status = vcos_mutex_create(&dispmanx_client.lock, "HDispmanx");
161 vcos_assert(status == VCOS_SUCCESS);
162
163 status = vcos_event_create(&dispmanx_message_available_event, "HDispmanx");
164 vcos_assert(status == VCOS_SUCCESS);
165
166 status = vcos_event_create(&dispmanx_notify_available_event, "HDispmanx");
167 vcos_assert(status == VCOS_SUCCESS);
168
169 dispmanx_client.initialised = 1;
170
171 for (i=0; i<dispmanx_client.num_connections; i++) {
172
173 VCOS_THREAD_ATTR_T attrs;
174
175 // Create a 'Client' service on the each of the connections
176 SERVICE_CREATION_T dispmanx_parameters = { VCHI_VERSION(VC_DISPMANX_VERSION),
177 DISPMANX_CLIENT_NAME, // 4cc service code
178 connections[i], // passed in fn ptrs
179 0, // tx fifo size (unused)
180 0, // tx fifo size (unused)
181 &dispmanx_client_callback, // service callback
182 &dispmanx_message_available_event, // callback parameter
183 VC_FALSE, // want_unaligned_bulk_rx
184 VC_FALSE, // want_unaligned_bulk_tx
185 VC_FALSE, // want_crc
186 };
187
188 SERVICE_CREATION_T dispmanx_parameters2 = { VCHI_VERSION(VC_DISPMANX_VERSION),
189 DISPMANX_NOTIFY_NAME, // 4cc service code
190 connections[i], // passed in fn ptrs
191 0, // tx fifo size (unused)
192 0, // tx fifo size (unused)
193 &dispmanx_notify_callback, // service callback
194 &dispmanx_notify_available_event, // callback parameter
195 VC_FALSE, // want_unaligned_bulk_rx
196 VC_FALSE, // want_unaligned_bulk_tx
197 VC_FALSE, // want_crc
198 };
199
200 success = vchi_service_open( initialise_instance, &dispmanx_parameters, &dispmanx_client.client_handle[i] );
201 vcos_assert( success == 0 );
202
203 // Create the async service of dispman to handle update callback
204
205 success = vchi_service_open( initialise_instance, &dispmanx_parameters2, &dispmanx_client.notify_handle[i] );
206 vcos_assert( success == 0 );
207
208 //Create the notifier task
209 vcos_thread_attr_init(&attrs);
210 vcos_thread_attr_setstacksize(&attrs, 2048);
211 vcos_thread_attr_settimeslice(&attrs, 1);
212
213 status = vcos_thread_create(&dispmanx_notify_task, "HDispmanx Notify", &attrs, dispmanx_notify_func, NULL);
214 vcos_assert(status == VCOS_SUCCESS);
215
216 // release services until they're actually used
217 vchi_service_release(dispmanx_client.client_handle[i]);
218 vchi_service_release(dispmanx_client.notify_handle[i]);
219 }
220}
221
222/***********************************************************
223 * Name: vc_dispmanx_stop
224 *
225 * Arguments:
226 * -
227 *
228 * Description: Stops the Host side part of dispmanx
229 *
230 * Returns: -
231 *
232 ***********************************************************/
233VCHPRE_ void VCHPOST_ vc_dispmanx_stop( void ) {
234 // Wait for the current lock-holder to finish before zapping dispmanx.
235 //TODO: kill the notifier task
236 void *dummy;
237 uint32_t i;
238
239 if (!dispmanx_client.initialised)
240 return;
241
242 lock_obtain();
243 for (i=0; i<dispmanx_client.num_connections; i++) {
244 int32_t result;
245 result = vchi_service_close(dispmanx_client.client_handle[i]);
246 vcos_assert( result == 0 );
247 result = vchi_service_close(dispmanx_client.notify_handle[i]);
248 vcos_assert( result == 0 );
249 }
250 lock_release();
251 dispmanx_client.initialised = 0;
252
253 vcos_event_signal(&dispmanx_notify_available_event);
254 vcos_thread_join(&dispmanx_notify_task, &dummy);
255 vcos_mutex_delete(&dispmanx_client.lock);
256 vcos_event_delete(&dispmanx_message_available_event);
257 vcos_event_delete(&dispmanx_notify_available_event);
258}
259
260/***********************************************************
261 * Name: vc_dispmanx_rect_set
262 *
263 * Arguments:
264 * VC_RECT_T *rect
265 * uint32_t x_offset
266 * uint32_t y_offset
267 * uint32_t width
268 * uint32_t height
269 *
270 * Description: Fills in the fields of the supplied VC_RECT_T structure
271 *
272 * Returns: 0 or failure
273 *
274 ***********************************************************/
275VCHPRE_ int VCHPOST_ vc_dispmanx_rect_set( VC_RECT_T *rect, uint32_t x_offset, uint32_t y_offset, uint32_t width, uint32_t height ) {
276 rect->x = (int32_t) x_offset;
277 rect->y = (int32_t) y_offset;
278 rect->width = (int32_t) width;
279 rect->height = (int32_t) height;
280 return 0;
281}
282
283/******************************************************************************
284NAME
285 vc_dispmanx_query_image_formats
286
287PARAMS
288 uint32_t *support_formats - the returned supported image formats
289
290FUNCTION
291 Returns the support image formats from the VMCS host
292
293RETURNS
294 Success: 0
295 Otherwise non-zero
296******************************************************************************/
297VCHPRE_ int VCHPOST_ vc_dispmanx_query_image_formats( uint32_t *supported_formats ) {
298 *supported_formats = dispmanx_get_handle(EDispmanQueryImageFormats, NULL, 0);
299 return (*supported_formats)? 0 : -1;
300}
301
302/***********************************************************
303 * Name: vc_dispmanx_resource_create
304 *
305 * Arguments:
306 * VC_IMAGE_TYPE_T type
307 * uint32_t width
308 * uint32_t height
309 *
310 * Description: Create a new resource (in Videocore memory)
311 *
312 * Returns: resource handle
313 *
314 ***********************************************************/
315VCHPRE_ DISPMANX_RESOURCE_HANDLE_T VCHPOST_ vc_dispmanx_resource_create( VC_IMAGE_TYPE_T type, uint32_t width, uint32_t height, uint32_t *native_image_handle ) {
316 uint32_t resourceCreateParams[] = { (uint32_t)VC_HTOV32(type), VC_HTOV32(width), VC_HTOV32(height) };
317
318 uint32_t resource = 0;
319
320 resource = dispmanx_get_handle(EDispmanResourceCreate, resourceCreateParams, sizeof(resourceCreateParams));
321
322 //We don't get an image handle back, so explicitly set this to zero to let the caller know
323 *native_image_handle = 0;
324 //The caller should call vc_dispmanx_resource_get_image_handle below to get the VC_IMAGE_T *
325 //This will be deprecated soon, however
326
327 return (DISPMANX_RESOURCE_HANDLE_T) resource;
328}
329
330/***********************************************************
331 * Name: vc_dispmanx_resource_get_image_handle
332 *
333 * Arguments: resource handle
334 *
335 * Description: xxx only for hacking purpose, will be obsolete soon
336 *
337 * Returns: vc_image pointer
338 *
339 ***********************************************************/
340VCHPRE_ uint32_t VCHPOST_ vc_dispmanx_resource_get_image_handle( DISPMANX_RESOURCE_HANDLE_T res) {
341 return dispmanx_get_handle(EDispmanResourceGetImage, &res, sizeof(res));
342}
343
344/***********************************************************
345 * Name: vc_dispmanx_resource_delete
346 *
347 * Arguments:
348 * DISPMANX_RESOURCE_HANDLE_T res
349 *
350 * Description:
351 *
352 * Returns: 0 or failure
353 *
354 ***********************************************************/
355VCHPRE_ int VCHPOST_ vc_dispmanx_resource_delete( DISPMANX_RESOURCE_HANDLE_T res ) {
356 int status;
357 res = VC_HTOV32(res);
358 //We block to make sure the memory is freed after the call
359 status = (int) dispmanx_send_command(EDispmanResourceDelete, &res, sizeof(res));
360
361 return status;
362}
363
364/***********************************************************
365 * Name: vc_dispmanx_resource_write_data
366 *
367 * Arguments:
368 * DISPMANX_RESOURCE_HANDLE_T res
369 * int src_pitch
370 * void * src_address
371 * const VC_RECT_T * rect
372 *
373 * Description: Copy the bitmap data to VideoCore memory
374 *
375 * Returns: 0 or failure
376 *
377 ***********************************************************/
378VCHPRE_ int VCHPOST_ vc_dispmanx_resource_write_data( DISPMANX_RESOURCE_HANDLE_T handle, VC_IMAGE_TYPE_T src_type /* not used */,
379 int src_pitch, void * src_address, const VC_RECT_T * rect ) {
380 (void)src_type;
381
382 //Note that x coordinate of the rect is NOT used
383 //Address of data in host
384 uint8_t *host_start = (uint8_t *)src_address + src_pitch * rect->y;
385 int32_t bulk_len = src_pitch * rect->height, success = 0;
386
387 //Now send the bulk transfer across
388 //command parameters: resource handle, destination y, bulk length
389 uint32_t param[] = {VC_HTOV32(handle), VC_HTOV32(rect->y), VC_HTOV32(bulk_len), VC_HTOV32(src_type) };
390 success = dispmanx_send_command( EDispmanBulkWrite | DISPMANX_NO_REPLY_MASK, param, sizeof(param));
391 if(success == 0)
392 {
393 lock_obtain();
394 success = vchi_bulk_queue_transmit( dispmanx_client.client_handle[0],
395 host_start,
396 bulk_len,
397 VCHI_FLAGS_BLOCK_UNTIL_DATA_READ,
398 NULL );
399 lock_release();
400 }
401 return (int) success;
402}
403/***********************************************************
404 * Name: vc_dispmanx_resource_read_data
405 *
406 * Arguments:
407 * DISPMANX_RESOURCE_HANDLE_T res
408 * int src_pitch
409 * void * src_address
410 * const VC_RECT_T * rect
411 *
412 * Description: Copy the bitmap data from VideoCore memory
413 *
414 * Returns: 0 or failure
415 *
416 ***********************************************************/
417VCHPRE_ int VCHPOST_
418vc_dispmanx_resource_read_data(
419 DISPMANX_RESOURCE_HANDLE_T handle,
420 const VC_RECT_T* p_rect,
421 void * dst_address,
422 uint32_t dst_pitch )
423{
424 uint8_t* host_start;
425 int32_t bulk_len;
426 int32_t success = 0;
427
428 if ( p_rect == 0 || dst_address == 0 || dst_pitch == 0 )
429 {
430 return -1;
431 }
432
433 host_start = (uint8_t *)dst_address + (dst_pitch * p_rect->y);
434 bulk_len = (int32_t)dst_pitch * p_rect->height;
435
436 // Now send the bulk transfer across
437 // command parameters: resource handle, destination y, bulk length
438 uint32_t param[] = { VC_HTOV32(handle), VC_HTOV32(p_rect->y), VC_HTOV32(bulk_len) };
439 success = dispmanx_send_command( EDispmanBulkRead | DISPMANX_NO_REPLY_MASK, param, sizeof(param));
440 if (success == 0)
441 {
442 lock_obtain();
443 success = vchi_bulk_queue_receive( dispmanx_client.client_handle[0],
444 host_start,
445 bulk_len,
446 VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE,
447 0 );
448 lock_release();
449 }
450 return (int) success;
451}
452
453/***********************************************************
454 * Name: vc_dispmanx_resource_write_data_handle
455 *
456 * Arguments:
457 * DISPMANX_RESOURCE_HANDLE_T res
458 * int src_pitch
459 * MEM_HANDLE_T handle
460 * uint32_t offset
461 * const VC_RECT_T * rect
462 *
463 * Description: Copy the bitmap data to VideoCore memory
464 *
465 * Returns: 0 or failure
466 *
467 ***********************************************************/
468#ifdef SELF_HOSTED
469VCHPRE_ int VCHPOST_ vc_dispmanx_resource_write_data_handle( DISPMANX_RESOURCE_HANDLE_T handle, VC_IMAGE_TYPE_T src_type /* not used */,
470 int src_pitch, VCHI_MEM_HANDLE_T mem_handle, uint32_t offset,
471 const VC_RECT_T * rect ) {
472 int32_t bulk_len;
473 uint32_t param[3];
474 uint32_t success = 0;
475
476 //Note that x coordinate of the rect is NOT used
477 //Address of data in host
478 offset += src_pitch * rect->y;
479 bulk_len = src_pitch * rect->height;
480
481 //Now send the bulk transfer across
482 //command parameters: resource handle, destination y, bulk length
483 param[0] = VC_HTOV32(handle);
484 param[1] = VC_HTOV32(rect->y);
485 param[2] = VC_HTOV32(bulk_len);
486 success = dispmanx_send_command( EDispmanBulkWrite | DISPMANX_NO_REPLY_MASK, param, sizeof(param));
487 if(success == 0)
488 {
489 lock_obtain();
490 success = vchi_bulk_queue_transmit_reloc( dispmanx_client.client_handle[0],
491 mem_handle, offset,
492 bulk_len,
493 VCHI_FLAGS_BLOCK_UNTIL_DATA_READ,
494 NULL );
495 lock_release();
496 }
497 return (int) success;
498}
499#endif
500
501/***********************************************************
502 * Name: vc_dispmanx_display_open
503 *
504 * Arguments:
505 * uint32_t device
506 *
507 * Description:
508 *
509 * Returns:
510 *
511 ***********************************************************/
512VCHPRE_ DISPMANX_DISPLAY_HANDLE_T VCHPOST_ vc_dispmanx_display_open( uint32_t device ) {
513 uint32_t display_handle;
514 char *env = getenv("VC_DISPLAY");
515
516 if (device == 0 && env)
517 {
518 device = atoi(env);
519 }
520
521 device = VC_HTOV32(device);
522 display_handle = dispmanx_get_handle(EDispmanDisplayOpen,
523 &device, sizeof(device));
524
525 return (DISPMANX_DISPLAY_HANDLE_T) display_handle;
526}
527
528/***********************************************************
529 * Name: vc_dispmanx_display_open_mode
530 *
531 * Arguments:
532 * uint32_t device
533 * uint32_t mode
534 *
535 * Description:
536 *
537 * Returns:
538 *
539 ***********************************************************/
540VCHPRE_ DISPMANX_DISPLAY_HANDLE_T VCHPOST_ vc_dispmanx_display_open_mode( uint32_t device, uint32_t mode ) {
541 uint32_t display_open_param[] = {VC_HTOV32(device), VC_HTOV32(mode)};
542 uint32_t display_handle = dispmanx_get_handle(EDispmanDisplayOpenMode,
543 &display_open_param, sizeof(display_open_param));
544
545 return (DISPMANX_DISPLAY_HANDLE_T) display_handle;
546}
547
548/***********************************************************
549 * Name: vc_dispmanx_display_open_offscreen
550 *
551 * Arguments:
552 * DISPMANX_RESOURCE_HANDLE_T dest
553 * DISPMANX_TRANSFORM_T orientation
554 *
555 * Description:
556 *
557 * Returns:
558 *
559 ***********************************************************/
560VCHPRE_ DISPMANX_DISPLAY_HANDLE_T VCHPOST_ vc_dispmanx_display_open_offscreen( DISPMANX_RESOURCE_HANDLE_T dest, DISPMANX_TRANSFORM_T orientation ) {
561 uint32_t display_open_param[] = {(uint32_t)VC_HTOV32(dest), (uint32_t)VC_HTOV32(orientation)};
562 uint32_t display_handle = dispmanx_get_handle(EDispmanDisplayOpenOffscreen,
563 &display_open_param, sizeof(display_open_param));
564
565 return (DISPMANX_DISPLAY_HANDLE_T) display_handle;
566}
567
568/***********************************************************
569 * Name: vc_dispmanx_display_reconfigure
570 *
571 * Arguments:
572 * DISPMANX_DISPLAY_HANDLE_T display
573 * uint32_t mode
574 *
575 * Description:
576 *
577 * Returns:
578 *
579 ***********************************************************/
580VCHPRE_ int VCHPOST_ vc_dispmanx_display_reconfigure( DISPMANX_DISPLAY_HANDLE_T device, uint32_t mode ) {
581 uint32_t display_param[] = {(uint32_t)VC_HTOV32(device), VC_HTOV32(mode)};
582 int32_t success = dispmanx_send_command( EDispmanDisplayReconfigure | DISPMANX_NO_REPLY_MASK,
583 display_param, sizeof(display_param));
584 return (int) success;
585}
586
587/***********************************************************
588 * Name: vc_dispmanx_display_set_destination
589 *
590 * Arguments:
591 * DISPMANX_DISPLAY_HANDLE_T display
592 * DISPMANX_RESOURCE_HANDLE_T dest
593 *
594 * Description:
595 *
596 * Returns:
597 *
598 ***********************************************************/
599VCHPRE_ int VCHPOST_ vc_dispmanx_display_set_destination( DISPMANX_DISPLAY_HANDLE_T display, DISPMANX_RESOURCE_HANDLE_T dest ) {
600 uint32_t display_param[] = {(uint32_t)VC_HTOV32(display), (uint32_t)VC_HTOV32(dest)};
601 int32_t success = dispmanx_send_command( EDispmanDisplaySetDestination | DISPMANX_NO_REPLY_MASK,
602 display_param, sizeof(display_param));
603 return (int) success;
604}
605
606/***********************************************************
607 * Name: vc_dispmanx_display_set_background
608 *
609 * Arguments:
610 * DISPMANX_UPDATE_HANDLE_T update
611 * DISPMANX_DISPLAY_HANDLE_T display
612 * uint8_t red
613 * uint8_t green
614 * uint8_t blue
615 *
616 * Description:
617 *
618 * Returns:
619 *
620 ***********************************************************/
621VCHPRE_ int VCHPOST_ vc_dispmanx_display_set_background( DISPMANX_UPDATE_HANDLE_T update, DISPMANX_DISPLAY_HANDLE_T display,
622 uint8_t red, uint8_t green, uint8_t blue ) {
623 uint32_t display_param[] = {(uint32_t)VC_HTOV32(update), (uint32_t) VC_HTOV32(display), VC_HTOV32(red), VC_HTOV32(green), VC_HTOV32(blue)};
624 int success = (int) dispmanx_send_command( EDispmanDisplaySetBackground | DISPMANX_NO_REPLY_MASK,
625 display_param, sizeof(display_param));
626 return success;
627}
628
629/***********************************************************
630 * Name: vc_dispmanx_display_get_info
631 *
632 * Arguments:
633 * DISPMANX_DISPLAY_HANDLE_T display
634 * DISPMANX_MODEINFO_T * pinfo
635 *
636 * Description:
637 *
638 * Returns: VCHI error
639 *
640 ***********************************************************/
641VCHPRE_ int VCHPOST_
642vc_dispmanx_display_get_info (DISPMANX_DISPLAY_HANDLE_T display,
643 DISPMANX_MODEINFO_T *pinfo)
644{
645 GET_INFO_DATA_T info;
646 int32_t success;
647 display = VC_HTOV32(display);
648 success = dispmanx_send_command_reply (EDispmanDisplayGetInfo,
649 &display, sizeof(display),
650 &info, sizeof(info));
651 if(success == 0) {
652 pinfo->width = VC_VTOH32(info.width);
653 pinfo->height = VC_VTOH32(info.height);
654 pinfo->transform = (DISPMANX_TRANSFORM_T)VC_VTOH32(info.transform);
655 pinfo->input_format = (DISPLAY_INPUT_FORMAT_T)VC_VTOH32(info.input_format);
656 }
657
658 return (int) success;
659}
660
661/***********************************************************
662 * Name: vc_dispmanx_display_close
663 *
664 * Arguments:
665 * DISPMANX_DISPLAY_HANDLE_T display
666 *
667 * Description:
668 *
669 * Returns:
670 *
671 ***********************************************************/
672VCHPRE_ int VCHPOST_ vc_dispmanx_display_close( DISPMANX_DISPLAY_HANDLE_T display ) {
673 int success;
674 display = VC_HTOV32(display);
675 success = (int) dispmanx_send_command( EDispmanDisplayClose | DISPMANX_NO_REPLY_MASK,
676 &display, sizeof(display));
677 return success;
678}
679/***********************************************************
680 * Name: vc_dispmanx_update_start
681 *
682 * Arguments:
683 * int32_t priority
684 *
685 * Description:
686 *
687 * Returns:
688 *
689 ***********************************************************/
690VCHPRE_ DISPMANX_UPDATE_HANDLE_T VCHPOST_ vc_dispmanx_update_start( int32_t priority ) {
691 uint32_t handle;
692 priority = VC_HTOV32(priority);
693 handle = dispmanx_get_handle(EDispmanUpdateStart,
694 &priority, sizeof(priority));
695
696 return (DISPMANX_UPDATE_HANDLE_T) handle;
697}
698
699
700/***********************************************************
701 * Name: vc_dispmanx_update_submit
702 *
703 * Arguments:
704 * DISPMANX_UPDATE_HANDLE_T update
705 * DISPMANX_CALLBACK_FUNC_T cb_func
706 * void *cb_arg
707 *
708 * Description:
709 *
710 * Returns:
711 *
712 ***********************************************************/
713VCHPRE_ int VCHPOST_ vc_dispmanx_update_submit( DISPMANX_UPDATE_HANDLE_T update, DISPMANX_CALLBACK_FUNC_T cb_func, void *cb_arg ) {
714 uint32_t update_param[] = {(uint32_t) VC_HTOV32(update), (uint32_t) ((cb_func)? VC_HTOV32(1) : 0)};
715 int success;
716
717 vcos_assert(update); // handles must be non-zero
718 if (update)
719 {
720 //Set the callback
721 dispmanx_client.update_callback = cb_func;
722 dispmanx_client.update_callback_param = cb_arg;
723 dispmanx_client.pending_update_handle = update;
724 vchi_service_use(dispmanx_client.notify_handle[0]); // corresponding release is in dispmanx_notify_func
725 success = (int) dispmanx_send_command( EDispmanUpdateSubmit | DISPMANX_NO_REPLY_MASK,
726 update_param, sizeof(update_param));
727 }
728 else
729 {
730 success = -1;
731 }
732 return success;
733}
734
735/***********************************************************
736 * Name: vc_dispmanx_update_submit_sync
737 *
738 * Arguments:
739 * DISPMANX_UPDATE_HANDLE_T update
740 *
741 * Description:
742 *
743 * Returns: VCHI error code
744 *
745 ***********************************************************/
746VCHPRE_ int VCHPOST_ vc_dispmanx_update_submit_sync( DISPMANX_UPDATE_HANDLE_T update ) {
747 int success;
748 update = VC_HTOV32(update);
749 success = (int) dispmanx_send_command( EDispmanUpdateSubmitSync,
750 &update, sizeof(update));
751 return success;
752}
753
754
755/***********************************************************
756 * Name: vc_dispmanx_element_add
757 *
758 * Arguments:
759 * DISPMANX_UPDATE_HANDLE_T update
760 * DISPMANX_DISPLAY_HANDLE_T display
761 * int32_t layer
762 * const VC_RECT_T *dest_rect
763 * DISPMANX_RESOURCE_HANDLE_T src
764 * const VC_RECT_T *src_rect
765 * DISPMANX_FLAGS_T flags
766 * uint8_t opacity
767 * DISPMANX_RESOURCE_HANDLE_T mask
768 * DISPMANX_TRANSFORM_T transform
769 *
770 * Description:
771 *
772 * Returns: VCHI error code
773 *
774 ***********************************************************/
775VCHPRE_ DISPMANX_ELEMENT_HANDLE_T VCHPOST_ vc_dispmanx_element_add ( DISPMANX_UPDATE_HANDLE_T update,
776 DISPMANX_DISPLAY_HANDLE_T display,
777 int32_t layer,
778 const VC_RECT_T *dest_rect,
779 DISPMANX_RESOURCE_HANDLE_T src,
780 const VC_RECT_T *src_rect,
781 DISPMANX_PROTECTION_T protection,
782 VC_DISPMANX_ALPHA_T *alpha,
783 DISPMANX_CLAMP_T *clamp,
784 DISPMANX_TRANSFORM_T transform ) {
785
786 int32_t element_param[] = {
787 (int32_t) VC_HTOV32(update),
788 (int32_t) VC_HTOV32(display),
789 (int32_t) VC_HTOV32(layer),
790 (int32_t) VC_HTOV32(dest_rect->x),
791 (int32_t) VC_HTOV32(dest_rect->y),
792 (int32_t) VC_HTOV32(dest_rect->width),
793 (int32_t) VC_HTOV32(dest_rect->height),
794 (int32_t) VC_HTOV32(src),
795 (int32_t) VC_HTOV32(src_rect->x),
796 (int32_t) VC_HTOV32(src_rect->y),
797 (int32_t) VC_HTOV32(src_rect->width),
798 (int32_t) VC_HTOV32(src_rect->height),
799 (int32_t) VC_HTOV32(protection),
800 alpha ? (int32_t) VC_HTOV32(alpha->flags) : 0,
801 alpha ? (int32_t) VC_HTOV32(alpha->opacity) : 0,
802 alpha ? (int32_t) VC_HTOV32(alpha->mask) : 0,
803 clamp ? (int32_t) VC_HTOV32(clamp->mode) : 0,
804 clamp ? (int32_t) VC_HTOV32(clamp->key_mask) : 0,
805 clamp ? (int32_t) VC_HTOV32(clamp->key_value.yuv.yy_upper) : 0,
806 clamp ? (int32_t) VC_HTOV32(clamp->key_value.yuv.yy_lower) : 0,
807 clamp ? (int32_t) VC_HTOV32(clamp->key_value.yuv.cr_upper) : 0,
808 clamp ? (int32_t) VC_HTOV32(clamp->key_value.yuv.cr_lower) : 0,
809 clamp ? (int32_t) VC_HTOV32(clamp->key_value.yuv.cb_upper) : 0,
810 clamp ? (int32_t) VC_HTOV32(clamp->key_value.yuv.cb_lower) : 0,
811 clamp ? (int32_t) VC_HTOV32(clamp->replace_value) : 0,
812 (int32_t) VC_HTOV32(transform)
813 };
814
815 uint32_t handle = dispmanx_get_handle(EDispmanElementAdd,
816 element_param, sizeof(element_param));
817 return (DISPMANX_ELEMENT_HANDLE_T) handle;
818}
819
820/***********************************************************
821 * Name: vc_dispmanx_element_change_source
822 *
823 * Arguments:
824 * DISPMANX_UPDATE_HANDLE_T update
825 * DISPMANX_ELEMENT_HANDLE_T element
826 * DISPMANX_RESOURCE_HANDLE_T src
827 *
828 * Description:
829 *
830 * Returns: VCHI error code
831 *
832 ***********************************************************/
833VCHPRE_ int VCHPOST_ vc_dispmanx_element_change_source( DISPMANX_UPDATE_HANDLE_T update, DISPMANX_ELEMENT_HANDLE_T element,
834 DISPMANX_RESOURCE_HANDLE_T src ) {
835 uint32_t element_param[] = { (uint32_t) VC_HTOV32(update),
836 (uint32_t) VC_HTOV32(element),
837 (uint32_t) VC_HTOV32(src) };
838
839 int success = (int) dispmanx_send_command( EDispmanElementChangeSource | DISPMANX_NO_REPLY_MASK,
840 element_param, sizeof(element_param));
841 return success;
842
843}
844
845/***********************************************************
846 * Name: vc_dispmanx_element_change_layer
847 *
848 * Arguments:
849 * DISPMANX_UPDATE_HANDLE_T update
850 * DISPMANX_ELEMENT_HANDLE_T element
851 * int32_t layer
852 *
853 * Description:
854 *
855 * Returns: VCHI error code
856 *
857 ***********************************************************/
858VCHPRE_ int VCHPOST_ vc_dispmanx_element_change_layer (DISPMANX_UPDATE_HANDLE_T update,
859 DISPMANX_ELEMENT_HANDLE_T element,
860 int32_t layer)
861{
862 uint32_t element_param[] = { (uint32_t) VC_HTOV32(update),
863 (uint32_t) VC_HTOV32(element),
864 (uint32_t) VC_HTOV32(layer) };
865
866 int success = (int) dispmanx_send_command( EDispmanElementChangeLayer | DISPMANX_NO_REPLY_MASK,
867 element_param, sizeof(element_param));
868 return success;
869
870}
871
872/***********************************************************
873 * Name: vc_dispmanx_element_modified
874 *
875 * Arguments:
876 * DISPMANX_UPDATE_HANDLE_T update
877 * DISPMANX_ELEMENT_HANDLE_T element
878 * const VC_RECT_T * rect
879 *
880 * Description:
881 *
882 * Returns: VCHI error code
883 *
884 ***********************************************************/
885VCHPRE_ int VCHPOST_ vc_dispmanx_element_modified( DISPMANX_UPDATE_HANDLE_T update, DISPMANX_ELEMENT_HANDLE_T element, const VC_RECT_T * rect ) {
886
887 uint32_t element_param[6] = { (uint32_t) VC_HTOV32(update),
888 (uint32_t) VC_HTOV32(element), 0, 0, 0, 0};
889 uint32_t param_length = 2*sizeof(uint32_t);
890 int success;
891
892 if(rect) {
893 element_param[2] = VC_HTOV32(rect->x);
894 element_param[3] = VC_HTOV32(rect->y);
895 element_param[4] = VC_HTOV32(rect->width);
896 element_param[5] = VC_HTOV32(rect->height);
897 param_length = 6*sizeof(uint32_t);
898 }
899 success = (int) dispmanx_send_command( EDispmanElementModified | DISPMANX_NO_REPLY_MASK,
900 element_param, param_length);
901 return success;
902}
903
904/***********************************************************
905 * Name: vc_dispmanx_element_remove
906 *
907 * Arguments:
908 * DISPMANX_UPDATE_HANDLE_T update
909 * DISPMANX_ELEMENT_HANDLE_T element
910 *
911 * Description:
912 *
913 * Returns:
914 *
915 ***********************************************************/
916VCHPRE_ int VCHPOST_ vc_dispmanx_element_remove( DISPMANX_UPDATE_HANDLE_T update, DISPMANX_ELEMENT_HANDLE_T element ) {
917 uint32_t element_param[] = {(uint32_t) VC_HTOV32(update), (uint32_t) VC_HTOV32(element)};
918 int success = (int) dispmanx_send_command( EDispmanElementRemove | DISPMANX_NO_REPLY_MASK,
919 element_param, sizeof(element_param));
920 return success;
921}
922
923/***********************************************************
924 * Name: vc_dispmanx_element_change_attributes
925 *
926 * Arguments:
927 * DISPMANX_UPDATE_HANDLE_T update
928 * DISPMANX_ELEMENT_HANDLE_T element
929 * uint32_t change flags (bit 0 layer, bit 1 opacity, bit 2 dest rect, bit 3 src rect, bit 4 mask, bit 5 transform
930 * uint32_t layer
931 * uint8_t opacity
932 * const VC_RECT_T *dest rect
933 * const VC_RECT_T *src rect
934 * DISPMANX_RESOURCE_HANDLE_T mask
935 * VC_DISPMAN_TRANSFORM_T transform
936 *
937 * Description:
938 *
939 * Returns:
940 *
941 ***********************************************************/
942VCHPRE_ int VCHPOST_ vc_dispmanx_element_change_attributes( DISPMANX_UPDATE_HANDLE_T update,
943 DISPMANX_ELEMENT_HANDLE_T element,
944 uint32_t change_flags,
945 int32_t layer,
946 uint8_t opacity,
947 const VC_RECT_T *dest_rect,
948 const VC_RECT_T *src_rect,
949 DISPMANX_RESOURCE_HANDLE_T mask,
950 DISPMANX_TRANSFORM_T transform ) {
951
952 uint32_t element_param[15] = { (uint32_t) VC_HTOV32(update),
953 (uint32_t) VC_HTOV32(element),
954 VC_HTOV32(change_flags),
955 VC_HTOV32(layer),
956 VC_HTOV32(opacity),
957 (uint32_t) VC_HTOV32(mask),
958 (uint32_t) VC_HTOV32(transform), 0, 0, 0, 0, 0, 0, 0, 0};
959
960 uint32_t param_length = 7*sizeof(uint32_t);
961 int success;
962 if(dest_rect) {
963 element_param[7] = VC_HTOV32(dest_rect->x);
964 element_param[8] = VC_HTOV32(dest_rect->y);
965 element_param[9] = VC_HTOV32(dest_rect->width);
966 element_param[10] = VC_HTOV32(dest_rect->height);
967 element_param[2] |= ELEMENT_CHANGE_DEST_RECT;
968 param_length += 4*sizeof(uint32_t);
969 }
970 if(src_rect) {
971 element_param[11] = VC_HTOV32(src_rect->x);
972 element_param[12] = VC_HTOV32(src_rect->y);
973 element_param[13] = VC_HTOV32(src_rect->width);
974 element_param[14] = VC_HTOV32(src_rect->height);
975 element_param[2] |= ELEMENT_CHANGE_SRC_RECT;
976 param_length += 4*sizeof(uint32_t);
977 }
978
979
980 success = (int) dispmanx_send_command( EDispmanElementChangeAttributes | DISPMANX_NO_REPLY_MASK,
981 element_param, param_length);
982 return success;
983}
984
985
986/***********************************************************
987 * Name: vc_dispmanx_snapshot
988 *
989 * Arguments:
990 * DISPMANX_DISPLAY_HANDLE_T display
991 * DISPMANX_RESOURCE_HANDLE_T snapshot_resource
992 * DISPMANX_TRANSFORM_T transform
993 *
994 * Description: Take a snapshot of a display in its current state
995 *
996 * Returns:
997 *
998 ***********************************************************/
999VCHPRE_ int VCHPOST_ vc_dispmanx_snapshot( DISPMANX_DISPLAY_HANDLE_T display,
1000 DISPMANX_RESOURCE_HANDLE_T snapshot_resource,
1001 DISPMANX_TRANSFORM_T transform )
1002{
1003 uint32_t display_snapshot_param[] = {
1004 VC_HTOV32(display),
1005 VC_HTOV32(snapshot_resource),
1006 VC_HTOV32(transform)};
1007
1008 int success = (int) dispmanx_send_command( EDispmanSnapshot,
1009 display_snapshot_param,
1010 sizeof(display_snapshot_param));
1011 return success;
1012}
1013
1014/***********************************************************
1015 * Name: vc_dispmanx_resource_set_palette
1016 *
1017 * Arguments:
1018 * DISPMANX_RESOURCE_HANDLE_T res
1019 * void * src_address
1020 * int offset
1021 * int size
1022 *
1023 * Description: Set the resource palette (for VC_IMAGE_4BPP and VC_IMAGE_8BPP)
1024 * offset should be 0
1025 * size is 16*2 for 4BPP and 256*2 for 8BPP
1026 * Returns: 0 or failure
1027 *
1028 ***********************************************************/
1029VCHPRE_ int VCHPOST_ vc_dispmanx_resource_set_palette( DISPMANX_RESOURCE_HANDLE_T handle,
1030 void * src_address, int offset, int size) {
1031 //Note that x coordinate of the rect is NOT used
1032 //Address of data in host
1033 uint8_t *host_start = src_address;
1034 int32_t bulk_len = size, success = 0;
1035
1036 //Now send the bulk transfer across
1037 //command parameters: resource size
1038 uint32_t param[] = {VC_HTOV32(handle), VC_HTOV32(offset), VC_HTOV32(bulk_len) };
1039 success = dispmanx_send_command( EDispmanSetPalette | DISPMANX_NO_REPLY_MASK, param, sizeof(param));
1040 if(success == 0)
1041 {
1042 lock_obtain();
1043 success = vchi_bulk_queue_transmit( dispmanx_client.client_handle[0],
1044 host_start,
1045 bulk_len,
1046 VCHI_FLAGS_BLOCK_UNTIL_DATA_READ,
1047 NULL );
1048 lock_release();
1049 }
1050 return (int) success;
1051}
1052
1053
1054/***********************************************************
1055 * Name: vc_dispmanx_vsync_callback
1056 *
1057 * Arguments:
1058 * DISPMANX_DISPLAY_HANDLE_T display
1059 * DISPMANX_CALLBACK_FUNC_T cb_func
1060 * void *cb_arg
1061 *
1062 * Description: start sending callbacks on vsync events
1063 * Use a NULL cb_func to stop the callbacks
1064 * Returns: 0 or failure
1065 *
1066 ***********************************************************/
1067VCHPRE_ int VCHPOST_ vc_dispmanx_vsync_callback( DISPMANX_DISPLAY_HANDLE_T display, DISPMANX_CALLBACK_FUNC_T cb_func, void *cb_arg )
1068{
1069 // Steal the invalid 0 handle to indicate this is a vsync request
1070 DISPMANX_UPDATE_HANDLE_T update = 0;
1071 int enable = (cb_func != NULL);
1072 uint32_t update_param[] = {(uint32_t) VC_HTOV32(display), VC_HTOV32(update), (int32_t)enable};
1073 int success;
1074
1075 // Set the callback
1076 dispmanx_client.vsync_callback = cb_func;
1077 dispmanx_client.vsync_callback_param = cb_arg;
1078
1079 if (!dispmanx_client.vsync_enabled && enable) {
1080 // An extra "use" is required while a vsync callback is registered.
1081 // The corresponding "release" is below.
1082 vchi_service_use(dispmanx_client.notify_handle[0]);
1083 }
1084
1085 success = (int) dispmanx_send_command( EDispmanVsyncCallback | DISPMANX_NO_REPLY_MASK,
1086 update_param, sizeof(update_param));
1087
1088 if (dispmanx_client.vsync_enabled && !enable) {
1089 // The extra "use" added above is no longer required.
1090 vchi_service_release(dispmanx_client.notify_handle[0]);
1091 }
1092
1093 dispmanx_client.vsync_enabled = enable;
1094
1095 return (int) success;
1096}
1097
1098
1099/*********************************************************************************
1100 *
1101 * Static functions definitions
1102 *
1103 *********************************************************************************/
1104//TODO: Might need to handle multiple connections later
1105/***********************************************************
1106 * Name: dispmanx_client_callback
1107 *
1108 * Arguments: semaphore, callback reason and message handle
1109 *
1110 * Description: VCHI callback for the DISP service
1111 *
1112 ***********************************************************/
1113static void dispmanx_client_callback( void *callback_param,
1114 const VCHI_CALLBACK_REASON_T reason,
1115 void *msg_handle ) {
1116
1117 (void)msg_handle;
1118
1119 VCOS_EVENT_T *event = (VCOS_EVENT_T *)callback_param;
1120
1121 if ( reason != VCHI_CALLBACK_MSG_AVAILABLE )
1122 return;
1123
1124 if ( event == NULL )
1125 return;
1126
1127 vcos_event_signal(event);
1128}
1129
1130/***********************************************************
1131 * Name: dispmanx_notify_callback
1132 *
1133 * Arguments: semaphore, callback reason and message handle
1134 *
1135 * Description: VCHI callback for the update callback
1136 *
1137 ***********************************************************/
1138
1139static void dispmanx_notify_callback( void *callback_param,
1140 const VCHI_CALLBACK_REASON_T reason,
1141 void *msg_handle ) {
1142 VCOS_EVENT_T *event = (VCOS_EVENT_T *)callback_param;
1143
1144 (void)msg_handle;
1145
1146 if ( reason != VCHI_CALLBACK_MSG_AVAILABLE )
1147 return;
1148
1149 if ( event == NULL )
1150 return;
1151
1152 vcos_event_signal(event);
1153}
1154
1155/***********************************************************
1156 * Name: dispmanx_wait_for_reply
1157 *
1158 * Arguments: response buffer, buffer length
1159 *
1160 * Description: blocked until something is in the buffer
1161 *
1162 * Returns error code of vchi
1163 *
1164 ***********************************************************/
1165static int32_t dispmanx_wait_for_reply(void *response, uint32_t max_length) {
1166 int32_t success = 0;
1167 uint32_t length_read = 0;
1168 do {
1169 //TODO : we need to deal with messages coming through on more than one connections properly
1170 //At the moment it will always try to read the first connection if there is something there
1171 //Check if there is something in the queue, if so return immediately
1172 //otherwise wait for the semaphore and read again
1173 success = vchi_msg_dequeue( dispmanx_client.client_handle[0], response, max_length, &length_read, VCHI_FLAGS_NONE );
1174 } while( length_read == 0 && vcos_event_wait(&dispmanx_message_available_event) == VCOS_SUCCESS );
1175
1176 return success;
1177
1178}
1179/***********************************************************
1180 * Name: dispmanx_send_command
1181 *
1182 * Arguments: command, parameter buffer, parameter legnth
1183 *
1184 * Description: send a command and wait for its response (int)
1185 *
1186 * Returns: response
1187 *
1188 ***********************************************************/
1189
1190static int32_t dispmanx_send_command( uint32_t command, void *buffer, uint32_t length) {
1191 VCHI_MSG_VECTOR_T vector[] = { {&command, sizeof(command)},
1192 {buffer, length} };
1193 int32_t success = 0, response = -1;
1194 lock_obtain();
1195 success = vchi_msg_queuev( dispmanx_client.client_handle[0],
1196 vector, sizeof(vector)/sizeof(vector[0]),
1197 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL );
1198 if(success == 0 && !(command & DISPMANX_NO_REPLY_MASK)) {
1199 //otherwise only wait for a reply if we ask for one
1200 success = dispmanx_wait_for_reply(&response, sizeof(response));
1201 } else {
1202 //Not waiting for a reply, send the success code back instead
1203 response = success;
1204 }
1205 lock_release();
1206 return VC_VTOH32(response);
1207}
1208
1209int32_t vc_dispmanx_send_command (uint32_t command, void *buffer,
1210 uint32_t length)
1211{
1212 return dispmanx_send_command (command, buffer, length);
1213}
1214
1215/***********************************************************
1216 * Name: dispmanx_send_command_reply
1217 *
1218 * Arguments: command, parameter buffer, parameter legnth, reply buffer, buffer length
1219 *
1220 * Description: send a command and wait for its response (in a buffer)
1221 *
1222 * Returns: error code
1223 *
1224 ***********************************************************/
1225
1226static int32_t dispmanx_send_command_reply( uint32_t command, void *buffer, uint32_t length,
1227 void *response, uint32_t max_length) {
1228 VCHI_MSG_VECTOR_T vector[] = { {&command, sizeof(command)},
1229 {buffer, length} };
1230
1231 int32_t success = 0;
1232 lock_obtain();
1233 success = vchi_msg_queuev( dispmanx_client.client_handle[0],
1234 vector, sizeof(vector)/sizeof(vector[0]),
1235 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL );
1236 if(success == 0)
1237 success = dispmanx_wait_for_reply(response, max_length);
1238
1239 lock_release();
1240
1241 return success;
1242}
1243
1244int32_t vc_dispmanx_send_command_reply (uint32_t command, void *buffer, uint32_t length,
1245 void *response, uint32_t max_length)
1246{
1247 return dispmanx_send_command_reply (command, buffer, length, response, max_length);
1248}
1249
1250/***********************************************************
1251 * Name: dispmanx_get_handle
1252 *
1253 * Arguments: command, parameter buffer, parameter legnth
1254 *
1255 * Description: same as dispmanx_send_command but returns uint instead
1256 *
1257 * Returns: handle
1258 *
1259 ***********************************************************/
1260static uint32_t dispmanx_get_handle( uint32_t command, void *buffer, uint32_t length) {
1261 VCHI_MSG_VECTOR_T vector[] = { {&command, sizeof(command)},
1262 {buffer, length} };
1263 uint32_t success = 0;
1264 uint32_t response = 0;
1265 lock_obtain();
1266 success += vchi_msg_queuev( dispmanx_client.client_handle[0],
1267 vector, sizeof(vector)/sizeof(vector[0]),
1268 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL );
1269 if(success == 0)
1270 success = dispmanx_wait_for_reply(&response, sizeof(response));
1271
1272 lock_release();
1273 return VC_VTOH32(response);
1274}
1275
1276/***********************************************************
1277 * Name: dispmanx_notify_handle
1278 *
1279 * Arguments: not used
1280 *
1281 * Description: this purely notifies the update callback
1282 *
1283 * Returns: does not return
1284 *
1285 ***********************************************************/
1286static void *dispmanx_notify_func( void *arg ) {
1287 int32_t success;
1288 VCOS_STATUS_T status;
1289
1290 (void)arg;
1291
1292 while (1) {
1293 DISPMANX_UPDATE_HANDLE_T handle;
1294 status = vcos_event_wait(&dispmanx_notify_available_event);
1295 if (status != VCOS_SUCCESS || !dispmanx_client.initialised)
1296 break;
1297
1298 while (1) {
1299 success = vchi_msg_dequeue( dispmanx_client.notify_handle[0], dispmanx_client.notify_buffer, sizeof(dispmanx_client.notify_buffer), &dispmanx_client.notify_length, VCHI_FLAGS_NONE );
1300 if (success != 0)
1301 break;
1302
1303 handle = (DISPMANX_UPDATE_HANDLE_T)dispmanx_client.notify_buffer[0];
1304 if (handle) {
1305 // This is the response to an update submit
1306 // Decrement the use count - the corresponding "use" is in vc_dispmanx_update_submit.
1307 vchi_service_release(dispmanx_client.notify_handle[0]);
1308 if (dispmanx_client.update_callback ) {
1309 vcos_assert( dispmanx_client.pending_update_handle == handle);
1310 dispmanx_client.update_callback(handle, dispmanx_client.update_callback_param);
1311 }
1312 } else {
1313 // This is a vsync notification
1314 if (dispmanx_client.vsync_callback ) {
1315 dispmanx_client.vsync_callback(handle, dispmanx_client.vsync_callback_param);
1316 }
1317 }
1318 }
1319 }
1320 return 0;
1321}
1322