1 /*****************************************************************************
2 * vout_qnx.c: QNX RTOS video output display method
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
6 * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
21 *****************************************************************************/
23 #define MODULE_NAME qnx
24 #include "modules_inner.h"
26 /*****************************************************************************
28 *****************************************************************************/
31 #include <errno.h> /* ENOMEM */
32 #include <stdlib.h> /* free() */
33 #include <string.h> /* strerror() */
35 #include <photon/PtWidget.h>
36 #include <photon/PtWindow.h>
37 #include <photon/PtLabel.h>
38 #include <photon/PdDirect.h>
47 #include "video_output.h"
49 #include "interface.h"
54 #include "modules_export.h"
56 /*****************************************************************************
57 * vout_sys_t: video output QNX method descriptor
58 *****************************************************************************
59 * This structure is part of the video output thread descriptor.
60 * It describes the QNX specific properties of an output thread. QNX video
61 * output is performed through regular resizable windows. Windows can be
62 * dynamically resized to adapt to the size of the streams.
63 *****************************************************************************/
65 #define MODE_NORMAL_MEM 0
66 #define MODE_SHARED_MEM 1
67 #define MODE_VIDEO_MEM 2
68 #define MODE_VIDEO_OVERLAY 3
70 typedef struct vout_sys_s
76 PtWidget_t * p_window;
78 /* [shared] memory blit */
79 PhImage_t * p_image[2];
82 /* video memory blit */
83 PdOffscreenContext_t * p_ctx[2];
87 PgVideoChannel_t * p_channel;
94 /* position & dimensions */
101 /*****************************************************************************
103 *****************************************************************************/
104 static int vout_Probe ( probedata_t *p_data );
105 static int vout_Create ( struct vout_thread_s * );
106 static int vout_Init ( struct vout_thread_s * );
107 static void vout_End ( struct vout_thread_s * );
108 static void vout_Destroy ( struct vout_thread_s * );
109 static int vout_Manage ( struct vout_thread_s * );
110 static void vout_Display ( struct vout_thread_s * );
112 static int QNXCreateWnd ( struct vout_thread_s * );
113 static int QNXDestroyWnd ( struct vout_thread_s * );
114 static int QNXInitDisplay ( struct vout_thread_s * );
116 /*****************************************************************************
117 * Functions exported as capabilities. They are declared as static so that
118 * we don't pollute the namespace too much.
119 *****************************************************************************/
120 void _M( vout_getfunctions )( function_list_t * p_function_list )
122 p_function_list->pf_probe = vout_Probe;
123 p_function_list->functions.vout.pf_create = vout_Create;
124 p_function_list->functions.vout.pf_init = vout_Init;
125 p_function_list->functions.vout.pf_end = vout_End;
126 p_function_list->functions.vout.pf_destroy = vout_Destroy;
127 p_function_list->functions.vout.pf_manage = vout_Manage;
128 p_function_list->functions.vout.pf_display = vout_Display;
129 p_function_list->functions.vout.pf_setpalette = NULL;
132 /*****************************************************************************
133 * vout_Probe: probe the video driver and return a score
134 *****************************************************************************
135 * This function tries to initialize SDL and returns a score to the
136 * plugin manager so that it can select the best plugin.
137 *****************************************************************************/
138 static int vout_Probe( probedata_t *p_data )
140 if( TestMethod( VOUT_METHOD_VAR, "qnx" ) )
148 /*****************************************************************************
149 * vout_Create: allocate QNX video thread output method
150 *****************************************************************************
151 * This function allocate and initialize a QNX vout method. It uses some of the
152 * vout properties to choose the window size, and change them according to the
153 * actual properties of the display.
154 *****************************************************************************/
155 static int vout_Create( vout_thread_t *p_vout )
157 /* init connection to photon */
158 if( PtInit( "/dev/photon" ) != 0 )
160 intf_ErrMsg( "vout error: unable to connect to photon" );
164 /* allocate structure */
165 p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
166 if( p_vout->p_sys == NULL )
168 intf_ErrMsg( "vout error: %s", strerror( ENOMEM ) );
172 memset( p_vout->p_sys, 0, sizeof( vout_sys_t ) );
174 p_vout->b_fullscreen =
175 main_GetIntVariable( VOUT_FULLSCREEN_VAR, VOUT_FULLSCREEN_DEFAULT );
176 p_vout->p_sys->i_mode =
177 main_GetIntVariable( VOUT_OVERLAY_VAR, VOUT_OVERLAY_DEFAULT ) ?
178 MODE_VIDEO_OVERLAY : MODE_NORMAL_MEM;
179 p_vout->p_sys->dim.w =
180 main_GetIntVariable( VOUT_WIDTH_VAR, VOUT_WIDTH_DEFAULT );
181 p_vout->p_sys->dim.h =
182 main_GetIntVariable( VOUT_HEIGHT_VAR, VOUT_HEIGHT_DEFAULT );
184 /* init display and create window */
185 if( QNXInitDisplay( p_vout ) || QNXCreateWnd( p_vout ) )
187 free( p_vout->p_sys );
194 /*****************************************************************************
195 * vout_Init: initialize QNX video thread output method
196 *****************************************************************************
197 * This function create the buffers needed by the output thread. It is called
198 * at the beginning of the thread, but also each time the window is resized.
199 *****************************************************************************/
200 static int vout_Init( vout_thread_t *p_vout )
202 if( p_vout->p_sys->i_mode == MODE_NORMAL_MEM ||
203 p_vout->p_sys->i_mode == MODE_SHARED_MEM )
205 /* create images for [shared] memory blit */
207 if( !( p_vout->p_sys->p_image[0] = PhCreateImage( NULL,
208 p_vout->p_sys->dim.w, p_vout->p_sys->dim.h,
209 p_vout->p_sys->i_img_type, NULL, 0,
210 p_vout->p_sys->i_mode == MODE_SHARED_MEM ) ) ) {
211 intf_ErrMsg( "vout error: cannot create image" );
215 if( !( p_vout->p_sys->p_image[1] = PhCreateImage( NULL,
216 p_vout->p_sys->dim.w, p_vout->p_sys->dim.h,
217 p_vout->p_sys->i_img_type, NULL, 0,
218 p_vout->p_sys->i_mode == MODE_SHARED_MEM ) ) ) {
219 intf_ErrMsg( "vout error: cannot create image" );
220 PhReleaseImage( p_vout->p_sys->p_image[0] );
221 free( p_vout->p_sys->p_image[0] );
222 p_vout->p_sys->p_image[0] = NULL;
226 /* set bytes per line, set buffers */
227 p_vout->i_bytes_per_line = p_vout->p_sys->p_image[0]->bpl;
228 p_vout->pf_setbuffers( p_vout, p_vout->p_sys->p_image[0]->image,
229 p_vout->p_sys->p_image[1]->image );
231 else if( p_vout->p_sys->i_mode == MODE_VIDEO_MEM )
233 /* create offscreen contexts for video memory blit */
235 if( ( p_vout->p_sys->p_ctx[0] = PdCreateOffscreenContext( 0,
236 p_vout->p_sys->dim.w, p_vout->p_sys->dim.h,
237 Pg_OSC_MEM_PAGE_ALIGN ) ) == NULL )
239 intf_ErrMsg( "vout error: unable to create offscreen context" );
243 if( ( p_vout->p_sys->p_ctx[1] = PdCreateOffscreenContext( 0,
244 p_vout->p_sys->dim.w, p_vout->p_sys->dim.h,
245 Pg_OSC_MEM_PAGE_ALIGN ) ) == NULL )
247 intf_ErrMsg( "vout error: unable to create offscreen context" );
248 PhDCRelease ( p_vout->p_sys->p_ctx[0] );
249 p_vout->p_sys->p_ctx[0] = NULL;
253 /* get context pointers */
254 if( ( ( p_vout->p_sys->p_buf[0] =
255 PdGetOffscreenContextPtr ( p_vout->p_sys->p_ctx[0] ) ) == NULL ) ||
256 ( p_vout->p_sys->p_buf[1] =
257 PdGetOffscreenContextPtr ( p_vout->p_sys->p_ctx[1] ) ) == NULL )
259 intf_ErrMsg( "vout error: unable to get offscreen context ptr" );
260 PhDCRelease ( p_vout->p_sys->p_ctx[0] );
261 PhDCRelease ( p_vout->p_sys->p_ctx[1] );
262 p_vout->p_sys->p_ctx[0] = NULL;
263 p_vout->p_sys->p_ctx[1] = NULL;
267 /* set bytes per line, clear buffers, set buffers */
268 p_vout->i_bytes_per_line =
269 p_vout->i_bytes_per_pixel * p_vout->p_sys->dim.w;
270 memset( p_vout->p_sys->p_buf[0], 0,
271 p_vout->i_bytes_per_line * p_vout->p_sys->dim.h );
272 memset( p_vout->p_sys->p_buf[1], 0,
273 p_vout->i_bytes_per_line * p_vout->p_sys->dim.h );
274 p_vout->pf_setbuffers( p_vout, p_vout->p_sys->p_buf[0],
275 p_vout->p_sys->p_buf[1] );
277 else if( p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY )
279 PgScalerProps_t props;
281 props.size = sizeof( props );
282 props.format = p_vout->p_sys->i_vc_format;
283 props.viewport.ul.x = p_vout->p_sys->pos.x + 4;
284 props.viewport.ul.y = p_vout->p_sys->pos.y + 20;
285 props.viewport.lr.x = p_vout->p_sys->dim.w + props.viewport.ul.x;
286 props.viewport.lr.y = p_vout->p_sys->dim.h + props.viewport.ul.y;
287 props.src_dim.w = p_vout->p_sys->dim.w;
288 props.src_dim.h = p_vout->p_sys->dim.h;
289 props.flags = Pg_SCALER_PROP_SCALER_ENABLE |
290 Pg_SCALER_PROP_DOUBLE_BUFFER;
292 if( PgConfigScalerChannel( p_vout->p_sys->p_channel, &props ) == -1 )
294 intf_ErrMsg( "vout error: unable to configure video channel" );
298 p_vout->p_sys->p_vc_y[0] =
299 PdGetOffscreenContextPtr( p_vout->p_sys->p_channel->yplane1 );
300 p_vout->p_sys->p_vc_y[1] =
301 PdGetOffscreenContextPtr( p_vout->p_sys->p_channel->yplane2 );
303 if( p_vout->p_sys->p_vc_y[0] == NULL ||
304 p_vout->p_sys->p_vc_y[1] == NULL )
306 intf_ErrMsg( "vout error: unable to get video channel ctx ptr" );
310 if( p_vout->p_sys->i_vc_format == Pg_VIDEO_FORMAT_YV12 )
312 p_vout->b_need_render = 0;
314 p_vout->p_sys->p_vc_u[0] =
315 PdGetOffscreenContextPtr( p_vout->p_sys->p_channel->uplane1 );
316 p_vout->p_sys->p_vc_u[1] =
317 PdGetOffscreenContextPtr( p_vout->p_sys->p_channel->uplane2 );
318 p_vout->p_sys->p_vc_v[0] =
319 PdGetOffscreenContextPtr( p_vout->p_sys->p_channel->vplane1 );
320 p_vout->p_sys->p_vc_v[1] =
321 PdGetOffscreenContextPtr( p_vout->p_sys->p_channel->vplane2 );
323 if( p_vout->p_sys->p_vc_u[0] == NULL ||
324 p_vout->p_sys->p_vc_u[1] == NULL ||
325 p_vout->p_sys->p_vc_v[0] == NULL ||
326 p_vout->p_sys->p_vc_v[1] == NULL )
328 intf_ErrMsg( "vout error: unable to get video channel ctx ptr" );
332 else if( p_vout->p_sys->i_vc_format == Pg_VIDEO_FORMAT_RGB8888 )
334 /* set bytes per line, clear buffers, set buffers */
335 p_vout->i_bytes_per_line =
336 p_vout->i_bytes_per_pixel * p_vout->p_sys->dim.w;
337 memset( p_vout->p_sys->p_vc_y[0], 0,
338 p_vout->i_bytes_per_line * p_vout->p_sys->dim.h );
339 memset( p_vout->p_sys->p_vc_y[1], 0,
340 p_vout->i_bytes_per_line * p_vout->p_sys->dim.h );
341 p_vout->pf_setbuffers( p_vout,
342 p_vout->p_sys->p_vc_y[0], p_vout->p_sys->p_vc_y[1] );
349 /*****************************************************************************
350 * vout_End: terminate QNX video thread output method
351 *****************************************************************************
352 * Destroy the buffers created by vout_Init. It is called at the end of
353 * the thread, but also each time the window is resized.
354 *****************************************************************************/
355 static void vout_End( vout_thread_t *p_vout )
357 if( ( p_vout->p_sys->i_mode == MODE_NORMAL_MEM ||
358 p_vout->p_sys->i_mode == MODE_SHARED_MEM ) &&
359 p_vout->p_sys->p_image[0] )
361 PhReleaseImage( p_vout->p_sys->p_image[0] );
362 PhReleaseImage( p_vout->p_sys->p_image[1] );
363 free( p_vout->p_sys->p_image[0] );
364 free( p_vout->p_sys->p_image[1] );
366 else if( p_vout->p_sys->i_mode == MODE_VIDEO_MEM &&
367 p_vout->p_sys->p_ctx[0] )
369 PhDCRelease( p_vout->p_sys->p_ctx[0] );
370 PhDCRelease( p_vout->p_sys->p_ctx[1] );
374 /*****************************************************************************
375 * vout_Destroy: destroy QNX video thread output method
376 *****************************************************************************
377 * Terminate an output method created by vout_CreateOutputMethod
378 *****************************************************************************/
379 static void vout_Destroy( vout_thread_t *p_vout )
381 /* destroy the window */
382 QNXDestroyWnd( p_vout );
384 /* destroy structure */
385 free( p_vout->p_sys );
388 /*****************************************************************************
389 * vout_Manage: handle QNX events
390 *****************************************************************************
391 * This function should be called regularly by video output thread. It allows
392 * window resizing. It returns a non null value on error.
393 *****************************************************************************/
394 static int vout_Manage( vout_thread_t *p_vout )
398 boolean_t b_repos = 0;
400 /* allocate buffer for event */
401 i_buflen = sizeof( PhEvent_t ) * 4;
402 if( ( p_event = malloc( i_buflen ) ) == NULL )
404 intf_ErrMsg( "vout error: %s", strerror( ENOMEM ) );
411 memset( p_event, 0, i_buflen );
412 i_ev = PhEventPeek( p_event, i_buflen );
414 if( i_ev == Ph_RESIZE_MSG )
416 i_buflen = PhGetMsgSize( p_event );
417 if( ( p_event = realloc( p_event, i_buflen ) ) == NULL )
419 intf_ErrMsg( "vout error: %s", strerror( ENOMEM ) );
423 else if( i_ev == Ph_EVENT_MSG )
425 PtEventHandler( p_event );
427 if( p_event->type == Ph_EV_WM )
429 PhWindowEvent_t *p_ev = PhGetData( p_event );
431 switch( p_ev->event_f )
434 p_main->p_intf->b_die = 1;
439 p_vout->p_sys->pos.x = p_ev->pos.x;
440 p_vout->p_sys->pos.y = p_ev->pos.y;
444 p_vout->p_sys->old_dim.w = p_vout->p_sys->dim.w;
445 p_vout->p_sys->old_dim.h = p_vout->p_sys->dim.h;
446 p_vout->p_sys->dim.w = p_vout->i_width = p_ev->size.w;
447 p_vout->p_sys->dim.h = p_vout->i_height = p_ev->size.h;
448 p_vout->i_changes |= VOUT_SIZE_CHANGE;
452 else if( p_event->type == Ph_EV_KEY )
454 PhKeyEvent_t *p_ev = PhGetData( p_event );
455 long i_key = p_ev->key_sym;
457 if( ( p_ev->key_flags & Pk_KF_Key_Down ) &&
458 ( p_ev->key_flags & Pk_KF_Sym_Valid ) )
464 p_main->p_intf->b_die = 1;
469 p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
474 p_vout->b_grayscale = ! p_vout->b_grayscale;
475 p_vout->i_changes |= VOUT_GRAYSCALE_CHANGE;
479 if( i_key >= Pk_0 && i_key <= Pk_9 )
481 network_ChannelJoin( i_key );
483 else if( intf_ProcessKey( p_main->p_intf,
486 intf_DbgMsg( "vout: unhandled key '%c' (%i)",
487 (char) i_key, i_key );
494 } while( i_ev != -1 && i_ev != 0 );
501 if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
506 intf_DbgMsg( "vout: changing full-screen status" );
508 p_vout->b_fullscreen = !p_vout->b_fullscreen;
509 p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
511 if( p_vout->b_fullscreen )
514 dim.w = p_vout->p_sys->screen_dim.w + 1;
515 dim.h = p_vout->p_sys->screen_dim.h + 1;
519 pos.x = p_vout->p_sys->pos.x;
520 pos.y = p_vout->p_sys->pos.y;
521 dim.w = p_vout->p_sys->old_dim.w + 1;
522 dim.h = p_vout->p_sys->old_dim.h + 1;
525 PtSetResource( p_vout->p_sys->p_window,
526 Pt_ARG_WINDOW_RENDER_FLAGS,
527 p_vout->b_fullscreen ? Pt_FALSE : Pt_TRUE,
528 Ph_WM_RENDER_BORDER | Ph_WM_RENDER_TITLE );
529 PtSetResource( p_vout->p_sys->p_window,
530 Pt_ARG_POS, &pos, 0 );
531 PtSetResource( p_vout->p_sys->p_window,
532 Pt_ARG_DIM, &dim, 0 );
536 * vout window resizing
538 if( ( p_vout->i_width != p_vout->p_sys->dim.w ) ||
539 ( p_vout->i_height != p_vout->p_sys->dim.h ) )
541 intf_DbgMsg( "vout: resizing output window" );
543 p_vout->p_sys->dim.w = p_vout->i_width;
544 p_vout->p_sys->dim.h = p_vout->i_height;
546 /* set new dimension */
547 PtSetResource( p_vout->p_sys->p_window,
548 Pt_ARG_DIM, &p_vout->p_sys->dim, 0 );
554 if( p_vout->i_changes & VOUT_SIZE_CHANGE )
556 intf_DbgMsg( "vout: resizing window" );
557 p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
560 if( vout_Init( p_vout ) )
562 intf_ErrMsg( "vout error: cannot resize display" );
566 p_vout->i_changes |= VOUT_YUV_CHANGE;
567 intf_Msg( "vout: video display resized (%dx%d)",
568 p_vout->i_width, p_vout->i_height );
572 * position change, move video channel
574 if( b_repos && p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY )
576 intf_DbgMsg( "vout: moving video channel" );
579 if( vout_Init( p_vout ) )
581 intf_ErrMsg( "vout error: unable to move video channel" );
586 return( i_ev == -1 );
589 /*****************************************************************************
590 * vout_Display: displays previously rendered output
591 *****************************************************************************
592 * This function send the currently rendered image to QNX server, wait until
593 * it is displayed and switch the two rendering buffer, preparing next frame.
594 *****************************************************************************/
595 static void vout_Display( vout_thread_t *p_vout )
597 if( p_vout->p_sys->i_mode == MODE_NORMAL_MEM ||
598 p_vout->p_sys->i_mode == MODE_SHARED_MEM )
600 PhPoint_t pos = { 0, 0 };
602 PgSetRegion( PtWidgetRid( p_vout->p_sys->p_window ) );
603 PgDrawPhImagemx( &pos, p_vout->p_sys->p_image[p_vout->i_buffer_index], 0 );
606 else if( p_vout->p_sys->i_mode == MODE_VIDEO_MEM )
608 PhRect_t rc = { { 0, 0 }, {
609 p_vout->p_sys->dim.w,
613 PgSetRegion( PtWidgetRid ( p_vout->p_sys->p_window ) );
614 PgContextBlit( p_vout->p_sys->p_ctx[p_vout->i_buffer_index], &rc, NULL, &rc );
617 else if( p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY &&
618 p_vout->p_sys->i_vc_format == Pg_VIDEO_FORMAT_YV12 )
622 /* this code has NOT been tested */
624 i_size = p_vout->p_rendered_pic->i_width *
625 p_vout->p_rendered_pic->i_height;
626 i_index = PgNextVideoFrame( p_vout->p_sys->p_channel );
628 memcpy( p_vout->p_sys->p_vc_y[i_index],
629 p_vout->p_rendered_pic->p_y, i_size );
630 memcpy( p_vout->p_sys->p_vc_v[i_index],
631 p_vout->p_rendered_pic->p_v, i_size / 4 );
632 memcpy( p_vout->p_sys->p_vc_u[i_index],
633 p_vout->p_rendered_pic->p_u, i_size / 4 );
637 /*****************************************************************************
638 * QNXInitDisplay: check screen resolution, depth, amount of video ram, etc
639 *****************************************************************************/
640 static int QNXInitDisplay( p_vout_thread_t p_vout )
643 PgDisplaySettings_t cfg;
644 PgVideoModeInfo_t minfo;
646 /* get graphics card hw capabilities */
647 if( PgGetGraphicsHWCaps( &hwcaps ) != 0 )
649 intf_ErrMsg( "vout error: unable to get gfx card capabilities" );
653 /* get current video mode */
654 if( PgGetVideoMode( &cfg ) != 0 )
656 intf_ErrMsg( "vout error: unable to get current video mode" );
660 /* get video mode info */
661 if( PgGetVideoModeInfo( cfg.mode, &minfo ) != 0 )
663 intf_ErrMsg( "vout error: unable to get info for video mode" );
667 /* use video ram if we have enough available */
668 if( p_vout->p_sys->i_mode == MODE_NORMAL_MEM &&
669 hwcaps.currently_available_video_ram >=
670 ( ( minfo.width * minfo.height * minfo.bits_per_pixel ) / 8 ) )
672 intf_DbgMsg( "vout: using video ram" );
673 p_vout->p_sys->i_mode = MODE_VIDEO_MEM;
676 p_vout->p_sys->i_img_type = minfo.type;
677 p_vout->p_sys->screen_dim.w = minfo.width;
678 p_vout->p_sys->screen_dim.h = minfo.height;
679 p_vout->i_screen_depth = minfo.bits_per_pixel;
683 case Pg_IMAGE_PALETTE_BYTE:
684 p_vout->i_bytes_per_pixel = 1;
687 case Pg_IMAGE_DIRECT_555:
688 case Pg_IMAGE_DIRECT_565:
689 p_vout->i_bytes_per_pixel = 2;
692 case Pg_IMAGE_DIRECT_8888:
693 p_vout->i_bytes_per_pixel = 4;
697 switch( p_vout->i_screen_depth )
700 p_vout->i_red_mask = 0x7c00;
701 p_vout->i_green_mask = 0x03e0;
702 p_vout->i_blue_mask = 0x001f;
706 p_vout->i_red_mask = 0xf800;
707 p_vout->i_green_mask = 0x07e0;
708 p_vout->i_blue_mask = 0x001f;
714 p_vout->i_red_mask = 0xff0000;
715 p_vout->i_green_mask = 0x00ff00;
716 p_vout->i_blue_mask = 0x0000ff;
723 /*****************************************************************************
724 * QNXCreateWnd: create and realize the main window
725 *****************************************************************************/
726 static int QNXCreateWnd( p_vout_thread_t p_vout )
729 PhPoint_t pos = { 0, 0 };
730 PgColor_t color = Pg_BLACK;
732 /* correct way to check for overlay support:
734 1. call PgGetGraphicsHWCaps and check
735 the results for Pg_VIDEO_OVERLAY
736 2. check if the current graphics mode
737 has PgVM_MODE_CAP1_VIDEO_OVERLAY set
738 3. call PgGetScalerCapabilities for info
742 1. Pg_VIDEO_OVERLAY is not defined in any
744 2. PgVM_MODE_CAP1_VIDEO_OVERLAY is not set
745 even if the current mode supports overlay
746 3. the flags (chroma, etc) do not reflect
747 the actual capabilities
750 if( p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY )
752 if( ( p_vout->p_sys->p_channel =
753 PgCreateVideoChannel( Pg_VIDEO_CHANNEL_SCALER, 0 ) ) == NULL )
755 intf_ErrMsg( "vout error: unable to create video channel" );
761 PgScalerCaps_t vcaps;
763 vcaps.size = sizeof( vcaps );
764 while( PgGetScalerCapabilities( p_vout->p_sys->p_channel,
767 if( vcaps.format == Pg_VIDEO_FORMAT_YV12 ||
768 vcaps.format == Pg_VIDEO_FORMAT_RGB8888 )
770 p_vout->p_sys->i_vc_flags = vcaps.flags;
771 p_vout->p_sys->i_vc_format = vcaps.format;
774 vcaps.size = sizeof( vcaps );
777 if( p_vout->p_sys->i_vc_format == 0 )
779 intf_ErrMsg( "vout error: need YV12 or RGB8888 overlay" );
782 else if( vcaps.flags & Pg_SCALER_CAP_DST_CHROMA_KEY )
784 color = PgGetOverlayChromaColor();
789 /* fullscreen, set dimension */
790 if( p_vout->b_fullscreen )
792 p_vout->p_sys->old_dim.w = p_vout->p_sys->dim.w;
793 p_vout->p_sys->old_dim.h = p_vout->p_sys->dim.h;
794 p_vout->i_width = p_vout->p_sys->dim.w = p_vout->p_sys->screen_dim.w;
795 p_vout->i_height = p_vout->p_sys->dim.h = p_vout->p_sys->screen_dim.h;
798 /* set window parameters */
799 PtSetArg( &args[0], Pt_ARG_POS, &pos, 0 );
800 PtSetArg( &args[1], Pt_ARG_DIM, &p_vout->p_sys->dim, 0 );
801 PtSetArg( &args[2], Pt_ARG_FILL_COLOR, color, 0 );
802 PtSetArg( &args[3], Pt_ARG_WINDOW_TITLE, "VideoLan Client", 0 );
803 PtSetArg( &args[4], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_FALSE, Ph_WM_CLOSE );
804 PtSetArg( &args[5], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_TRUE,
805 Ph_WM_MOVE | Ph_WM_RESIZE | Ph_WM_CLOSE );
806 PtSetArg( &args[6], Pt_ARG_WINDOW_RENDER_FLAGS,
807 p_vout->b_fullscreen ? Pt_FALSE : Pt_TRUE,
808 Ph_WM_RENDER_BORDER | Ph_WM_RENDER_TITLE );
811 p_vout->p_sys->p_window = PtCreateWidget( PtWindow, Pt_NO_PARENT, 7, args);
812 if( p_vout->p_sys->p_window == NULL )
814 intf_ErrMsg( "vout error: unable to create window" );
818 /* realize the window widget */
819 if( PtRealizeWidget( p_vout->p_sys->p_window ) != 0 )
821 intf_ErrMsg( "vout error: unable to realize window widget" );
822 PtDestroyWidget( p_vout->p_sys->p_window );
829 /*****************************************************************************
830 * QNXDestroyWnd: unrealize and destroy the main window
831 *****************************************************************************/
832 static int QNXDestroyWnd( p_vout_thread_t p_vout )
834 /* destroy the window widget */
835 PtUnrealizeWidget( p_vout->p_sys->p_window );
836 PtDestroyWidget( p_vout->p_sys->p_window );
838 /* destroy video channel */
839 if( p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY )
841 PgDestroyVideoChannel( p_vout->p_sys->p_channel );