On Mon, Jan 06, 2003 at 03:51:46PM -0600, Billy Biggs wrote:
> I'm more worried about whether GetCurrentOutputField() is accurate or
> not.
That's really up to the hardware. Have you had any problems?
> In tvtime I work in single buffered mode, so I never need to call
> flip. All I do is, while the top field is being shown, draw the bottom
> field, repeat.
Would you believe I just grabbed the tvtime tarball a few days ago and
after noticing there isn't a DirectFB output driver I wrote one. I knew I
should've been using the CVS sources :) Well actually what I have is for
overlays (w/ window & colorkeying) so it's not exactly what you have in
CVS. I've attached the file in case you want to use it somehow.
--
Ville Syrj�l�
[EMAIL PROTECTED]
http://www.sci.fi/~syrjala/
#include "config.h"
#include "dfboutput.h"
#ifdef HAVE_DIRECTFB
#include <directfb.h>
#include "input.h"
static void *image_data;
static int image_pitch;
static IDirectFB *dfb;
static IDirectFBDisplayLayer *primary;
static IDirectFBDisplayLayer *video;
static IDirectFBWindow *window;
static IDirectFBSurface *wsurface;
static IDirectFBSurface *surface;
static IDirectFBEventBuffer *buffer;
static DFBColor colorkey = { 0xff, 0x00, 0x00, 0xff };
static int output_width, output_height;
static int input_width, input_height;
static int output_aspect = 0;
static int output_fullscreen = 0;
typedef struct {
int x;
int y;
unsigned int width;
unsigned int height;
} area_t;
area_t video_area;
static void resize_video( void )
{
int x, y, w, h;
DFBDisplayLayerConfig dlc;
primary->GetConfiguration( primary, &dlc );
x = video_area.x;
y = video_area.y;
w = video_area.width;
h = video_area.height;
if (x < 0) {
w = w + x;
x = 0;
}
if (y < 0) {
h = h + y;
y = 0;
}
if (x + w > dlc.width)
w = dlc.width - x;
if (y + h > dlc.height)
h = dlc.height - y;
video->SetScreenLocation( video,
(float) x / (float) dlc.width,
(float) y / (float) dlc.height,
(float) w / (float) dlc.width,
(float) h / (float) dlc.height );
wsurface->Clear( wsurface, colorkey.r, colorkey.g, colorkey.b, 0xff );
wsurface->Flip( wsurface, NULL, 0 );
}
static int open_display( void )
{
DFBWindowDescription wd;
DFBDisplayLayerConfig dlc;
DirectFBCreate( &dfb );
/* Get the primary layer */
dfb->GetDisplayLayer( dfb, DLID_PRIMARY, &primary );
primary->SetCooperativeLevel( primary, DLSCL_SHARED );
/* Create a window to house the video layer */
wd.flags = DWDESC_POSX | DWDESC_POSY | DWDESC_WIDTH | DWDESC_HEIGHT;
wd.posx = 0;
wd.posy = 0;
wd.width = output_width;
wd.height = output_height;
primary->CreateWindow( primary, &wd, &window );
video_area.x = 0;
video_area.y = 0;
video_area.width = output_width;
video_area.height = output_height;
window->GetSurface( window, &wsurface );
window->SetOpacity( window, 0xff );
/* Select events */
window->DisableEvents( window, DWET_ALL );
window->EnableEvents( window, DWET_BUTTONDOWN | DWET_KEYDOWN | DWET_WHEEL |
DWET_POSITION | DWET_SIZE );
window->CreateEventBuffer( window, &buffer );
/* Get the video layer */
dfb->GetDisplayLayer( dfb, 1, &video );
video->SetCooperativeLevel( video, DLSCL_EXCLUSIVE );
/* Set configuration accroding to input data */
dlc.flags = DLCONF_BUFFERMODE | DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT
| DLCONF_OPTIONS;
dlc.buffermode = DLBM_BACKVIDEO;
dlc.width = input_width;
dlc.height = input_height;
dlc.pixelformat = DSPF_YUY2;
dlc.options = DLOP_DST_COLORKEY;
video->SetConfiguration( video, &dlc );
video->SetDstColorKey( video, colorkey.r, colorkey.g, colorkey.b );
video->SetOpacity( video, 0xff );
return 1;
}
static void dfb_alloc_frame( void )
{
video->GetSurface( video, &surface );
}
static void dfb_clear_screen( void )
{
surface->Clear( surface, 0, 0, 0, 0xff );
}
int dfb_init( int inputwidth, int inputheight, int outputwidth, int aspect )
{
output_aspect = aspect;
input_width = inputwidth;
input_height = inputheight;
output_width = outputwidth;
output_height = ( output_width * 3 ) / 4;
open_display();
dfb_alloc_frame();
dfb_clear_screen();
resize_video();
return 1;
}
int dfb_toggle_fullscreen( int fullscreen_width, int fullscreen_height )
{
output_fullscreen = !output_fullscreen;
if( output_fullscreen ) {
DFBDisplayLayerConfig dlc;
primary->GetConfiguration( primary, &dlc );
window->SetOptions( window,
DWOP_KEEP_POSITION | DWOP_KEEP_SIZE | DWOP_KEEP_STACKING
);
/* Raise the window to the top */
window->RaiseToTop( window );
/* Maximize the window */
window->MoveTo( window, 0, 0 );
window->Resize( window, dlc.width, dlc.height );
window->GrabPointer( window );
window->GrabKeyboard( window );
/* Hide the mouse cursor */
primary->SetCursorOpacity( primary, 0 );
} else {
window->SetOptions( window, DWOP_NONE );
/* Resize the window to normal size */
window->MoveTo( window, 0, 0 );
window->Resize( window, output_width, output_height );
window->UngrabPointer( window );
window->UngrabKeyboard( window );
/* Show the mouse cursor */
primary->SetCursorOpacity( primary, 0xff );
}
return output_fullscreen;
}
int dfb_toggle_aspect( void )
{
output_aspect = !output_aspect;
dfb_clear_screen();
return output_aspect;
}
void dfb_show_frame( void )
{
surface->Flip( surface, NULL, DSFLIP_WAITFORSYNC );
}
void dfb_poll_events( input_t *in )
{
DFBWindowEvent event;
int arg = 0;
int reconfigure = 0;
while (buffer->HasEvent( buffer ) == DFB_OK) {
if (buffer->GetEvent( buffer, DFB_EVENT( &event ) ) != DFB_OK)
continue;
if (event.clazz != DFEC_WINDOW)
continue;
switch( event.type ) {
case DWET_KEYDOWN:
if( event.modifiers & DIMM_SHIFT ) arg |= I_SHIFT;
if( event.modifiers & DIMM_CONTROL ) arg |= I_CTRL;
if( event.modifiers & DIMM_META ) arg |= I_META;
if( event.key_symbol >= DIKS_SMALL_A &&
event.key_symbol <= DIKS_SMALL_Z ) {
arg |= event.key_symbol - DIKS_SMALL_A + 'a';
} else if( event.key_symbol >= DIKS_CAPITAL_A &&
event.key_symbol <= DIKS_CAPITAL_Z ) {
arg |= event.key_symbol - DIKS_CAPITAL_A + 'a';
} else if( event.key_symbol >= DIKS_0 &&
event.key_symbol <= DIKS_9 ) {
arg |= event.key_symbol - DIKS_0 + '0';
}
switch( event.key_symbol ) {
case DIKS_ESCAPE: arg |= I_ESCAPE; break;
case DIKS_HOME: arg |= I_HOME; break;
case DIKS_END: arg |= I_END; break;
case DIKS_CURSOR_LEFT: arg |= I_LEFT; break;
case DIKS_CURSOR_UP: arg |= I_UP; break;
case DIKS_CURSOR_RIGHT: arg |= I_RIGHT; break;
case DIKS_CURSOR_DOWN: arg |= I_DOWN; break;
case DIKS_PAGE_UP: arg |= I_PGUP; break;
case DIKS_PAGE_DOWN: arg |= I_PGDN; break;
case DIKS_F1: arg |= I_F1; break;
case DIKS_F2: arg |= I_F2; break;
case DIKS_F3: arg |= I_F3; break;
case DIKS_F4: arg |= I_F4; break;
case DIKS_F5: arg |= I_F5; break;
case DIKS_F6: arg |= I_F6; break;
case DIKS_F7: arg |= I_F7; break;
case DIKS_F8: arg |= I_F8; break;
case DIKS_F9: arg |= I_F9; break;
case DIKS_F10: arg |= I_F10; break;
case DIKS_F11: arg |= I_F11; break;
case DIKS_F12: arg |= I_F12; break;
case DIKS_ENTER: arg |= I_ENTER; break;
case DIKS_APOSTROPHE: arg |= '*'; break;
case DIKS_MINUS_SIGN: arg |= '-'; break;
case DIKS_PLUS_SIGN: arg |= '+'; break;
case DIKS_SLASH: arg |= '/'; break;
default: break;
}
input_callback( in, I_KEYDOWN, arg );
break;
case DWET_BUTTONDOWN:
input_callback( in, I_BUTTONPRESS, event.button );
break;
case DWET_WHEEL:
input_callback( in, I_BUTTONPRESS, event.step > 0 ? 4 : 5 );
break;
case DWET_POSITION:
video_area.x = event.x;
video_area.y = event.y;
reconfigure = 1;
break;
case DWET_SIZE:
video_area.width = event.w;
video_area.height = event.h;
reconfigure = 1;
break;
default: break;
}
}
if (reconfigure)
resize_video();
}
void dfb_quit( void )
{
/* Hide the video layer */
video->SetOpacity( video, 0 );
buffer->Release( buffer );
surface->Release( surface );
wsurface->Release( wsurface );
window->Release( window );
video->Release( video );
primary->Release( primary );
dfb->Release( dfb );
}
int dfb_get_stride( void )
{
return image_pitch;
}
int dfb_is_interlaced( void )
{
return 0;
}
void dfb_wait_for_sync( int field )
{
}
void dfb_lock_output( void )
{
surface->Lock( surface, DSLF_READ | DSLF_WRITE,
&image_data, &image_pitch );
}
void dfb_unlock_output( void )
{
surface->Unlock( surface );
}
void dfb_set_window_caption( const char *caption )
{
}
unsigned char *dfb_get_output( void )
{
return image_data;
}
static output_api_t dfboutput =
{
dfb_init,
dfb_lock_output,
dfb_get_output,
dfb_get_stride,
dfb_unlock_output,
dfb_is_interlaced,
dfb_wait_for_sync,
dfb_show_frame,
dfb_toggle_aspect,
dfb_toggle_fullscreen,
dfb_set_window_caption,
dfb_poll_events,
dfb_quit
};
output_api_t *get_dfb_output( void )
{
return &dfboutput;
}
#else
output_api_t *get_dfb_output( void )
{
return 0;
}
#endif