Mercurial > mplayer.hg
changeset 9021:070b91093606
* Remove unneeded includes & macros
* Get layers by name rather that fixed ID. Only works for DirectFB >=
0.9.16 so fall back to ID based stuff for older releases.
* New option "noinput" (useful in X)
* Add some NULL pointer checks to uninit()
* Improve error messages and use mp_msg()
* Direct rendering fix (at least IPB was broken)
* Use 0xff for alpha component in all colors
* Blit from temp surface to screen was only done in draw_osd() which
doesn't always get called. Do the blit in flip_page() in this case.
* Add GUI support to control()
* Change the driver name to include G450/G550 ;)
patch by Ville Syrj¸«£l¸«£ <syrjala@sci.fi>
author | arpi |
---|---|
date | Sun, 19 Jan 2003 15:41:26 +0000 |
parents | 721a7b3dde59 |
children | b345f92422b4 |
files | libvo/vo_dfbmga.c |
diffstat | 1 files changed, 218 insertions(+), 87 deletions(-) [+] |
line wrap: on
line diff
--- a/libvo/vo_dfbmga.c Sun Jan 19 15:28:29 2003 +0000 +++ b/libvo/vo_dfbmga.c Sun Jan 19 15:41:26 2003 +0000 @@ -1,7 +1,7 @@ /* - MPlayer video driver for DirectFB / Matrox G400 + MPlayer video driver for DirectFB / Matrox G400/G450/G550 - Copyright (C) 2002 Ville Syrjala <syrjala@sci.fi> + Copyright (C) 2002,2003 Ville Syrjala <syrjala@sci.fi> Originally based on vo_directfb.c by Jiri Svoboda <Jiri.Svoboda@seznam.cz> @@ -29,31 +29,17 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <fcntl.h> -#include <unistd.h> -#include <errno.h> -#include <assert.h> - -#include <sys/mman.h> -#include <sys/ioctl.h> -#include <sys/kd.h> -#include <linux/fb.h> #include "config.h" #include "video_out.h" #include "video_out_internal.h" #include "fastmemcpy.h" #include "sub.h" -#include "../postproc/rgb2rgb.h" - +#include "mp_msg.h" #include "aspect.h" -#ifndef min -#define min(x,y) (((x)<(y))?(x):(y)) -#endif - static vo_info_t info = { - "DirectFB / Matrox G400", + "DirectFB / Matrox G400/G450/G550", "dfbmga", "Ville Syrjala <syrjala@sci.fi>", "" @@ -98,11 +84,13 @@ static int inited = 0; -static int stretch = 0; +static int blit_done; +static int stretch; -static int use_bes = 0; -static int use_crtc2 = 1; -static int use_spic = 1; +static int use_bes; +static int use_crtc2; +static int use_spic; +static int use_input; static int osd_changed; static int osd_dirty; @@ -194,32 +182,88 @@ } } +struct layer_enum +{ + const char *name; + IDirectFBDisplayLayer **layer; + DFBResult res; +}; + +static DFBEnumerationResult +get_layer_by_name( DFBDisplayLayerID id, + DFBDisplayLayerDescription desc, + void *data ) +{ + struct layer_enum *l = (struct layer_enum *) data; + +#if DIRECTFBVERSION > 915 + /* We have desc.name so use it */ + if (!strcmp( l->name, desc.name )) + if ((l->res = dfb->GetDisplayLayer( dfb, id, l->layer )) == DFB_OK) + return DFENUM_CANCEL; +#else + /* Fake it according to id */ + if ((id == 1 && !strcmp( l->name, "Matrox Backend Scaler" )) || + (id == 2 && !strcmp( l->name, "Matrox CRTC2" )) || + (id == 3 && !strcmp( l->name, "Matrox CRTC2 Sub-Picture" ))) + if ((l->res = dfb->GetDisplayLayer( dfb, id, l->layer )) == DFB_OK) + return DFENUM_CANCEL; +#endif + + return DFENUM_OK; +} + static uint32_t preinit( const char *arg ) { + DFBResult res; + + /* Some defaults */ + use_bes = 0; + use_crtc2 = 1; + use_spic = 1; + use_input = 1; + if (vo_subdevice) { + int opt_no = 0; while (*vo_subdevice != '\0') { if (!strncmp(vo_subdevice, "bes", 3)) { - use_bes = 1; + use_bes = !opt_no; vo_subdevice += 3; - } else if (!strncmp(vo_subdevice, "nocrtc2", 7)) { - use_crtc2 = 0; - vo_subdevice += 7; - } else if (!strncmp(vo_subdevice, "nospic", 6)) { - use_spic = 0; - vo_subdevice += 6; - } else + opt_no = 0; + } else if (!strncmp(vo_subdevice, "crtc2", 5)) { + use_crtc2 = !opt_no; + vo_subdevice += 5; + opt_no = 0; + } else if (!strncmp(vo_subdevice, "spic", 4)) { + use_spic = !opt_no; + vo_subdevice += 4; + opt_no = 0; + } else if (!strncmp(vo_subdevice, "input", 5)) { + use_spic = !opt_no; + vo_subdevice += 5; + opt_no = 0; + } else if (!strncmp(vo_subdevice, "no", 2)) { + vo_subdevice += 2; + opt_no = 1; + } else { vo_subdevice++; + opt_no = 0; + } } } if (!use_bes && !use_crtc2) { - fprintf( stderr, "vo_dfbmga: No output selected\n" ); + mp_msg( MSGT_VO, MSGL_ERR, "vo_dfbmga: No output selected\n" ); return -1; } if (!inited) { - if (DirectFBInit( NULL, NULL ) != DFB_OK) + if ((res = DirectFBInit( NULL, NULL )) != DFB_OK) { + mp_msg( MSGT_VO, MSGL_ERR, + "vo_dfbmga: DirectFBInit() failed - %s\n", + DirectFBErrorString( res ) ); return -1; + } if (!fb_dev_name && !(fb_dev_name = getenv( "FRAMEBUFFER" ))) fb_dev_name = "/dev/fb0"; @@ -227,30 +271,60 @@ DirectFBSetOption( "no-cursor", "" ); DirectFBSetOption( "bg-color", "00000000" ); - if (DirectFBCreate( &dfb ) != DFB_OK) + if ((res = DirectFBCreate( &dfb )) != DFB_OK) { + mp_msg( MSGT_VO, MSGL_ERR, + "vo_dfbmga: DirectFBCreate() failed - %s\n", + DirectFBErrorString( res ) ); return -1; + } inited = 1; } if (use_bes) { - if (dfb->GetDisplayLayer( dfb, 1, &bes ) != DFB_OK) + struct layer_enum l = { + "Matrox Backend Scaler", + &bes, + DFB_UNSUPPORTED + }; + + dfb->EnumDisplayLayers( dfb, get_layer_by_name, &l ); + if (l.res != DFB_OK) { + mp_msg( MSGT_VO, MSGL_ERR, "Can't get BES layer - %s\n", + DirectFBErrorString( l.res ) ); return -1; + } bes->SetCooperativeLevel( bes, DLSCL_EXCLUSIVE ); bes->SetOpacity( bes, 0 ); } if (use_crtc2) { - if (dfb->GetDisplayLayer( dfb, 2, &crtc2 ) != DFB_OK) + struct layer_enum l = { + "Matrox CRTC2", + &crtc2, + DFB_UNSUPPORTED + }; + + dfb->EnumDisplayLayers( dfb, get_layer_by_name, &l ); + if (l.res != DFB_OK) { + mp_msg( MSGT_VO, MSGL_ERR, "Can't get CRTC2 layer - %s\n", + DirectFBErrorString( l.res ) ); return -1; + } crtc2->SetCooperativeLevel( crtc2, DLSCL_EXCLUSIVE ); crtc2->SetOpacity( crtc2, 0 ); } - if (dfb->GetInputDevice( dfb, DIDID_KEYBOARD, &keyboard ) != DFB_OK) - return -1; - keyboard->CreateEventBuffer( keyboard, &buffer ); - buffer->Reset( buffer ); + if (use_input) { + if ((res = dfb->GetInputDevice( dfb, DIDID_KEYBOARD, &keyboard )) != DFB_OK) { + mp_msg( MSGT_VO, MSGL_ERR, + "vo_dfbmga: Can't get keyboard - %s\n", + DirectFBErrorString( res ) ); + return -1; + } + keyboard->CreateEventBuffer( keyboard, &buffer ); + buffer->Reset( buffer ); + } return 0; } @@ -262,12 +336,19 @@ char *title, uint32_t format ) { + DFBResult res; + DFBDisplayLayerConfig dlc; DFBDisplayLayerConfigFlags failed; uint32_t out_width; uint32_t out_height; + c2frame = NULL; + spic = NULL; + subframe = NULL; + bufs[0] = bufs[1] = bufs[2] = NULL; + in_width = width; in_height = height; @@ -283,8 +364,11 @@ dlc.height = in_height; dlc.buffermode = DLBM_BACKVIDEO; - if (bes->TestConfiguration( bes, &dlc, &failed ) != DFB_OK) + if (bes->TestConfiguration( bes, &dlc, &failed ) != DFB_OK) { + mp_msg( MSGT_VO, MSGL_ERR, + "vo_dfbmga: Invalid BES configuration!\n" ); return -1; + } bes->SetConfiguration( bes, &dlc ); bes->GetSurface( bes, &frame ); @@ -308,9 +392,13 @@ dsc.pixelformat = dlc.pixelformat; for (num_bufs = 0; num_bufs < 3; num_bufs++) { - if (dfb->CreateSurface( dfb, &dsc, &bufs[num_bufs] ) != DFB_OK) { - if (num_bufs == 0) + if ((res = dfb->CreateSurface( dfb, &dsc, &bufs[num_bufs] )) != DFB_OK) { + if (num_bufs == 0) { + mp_msg( MSGT_VO, MSGL_ERR, + "vo_dfbmga: Can't create surfaces - %s!\n", + DirectFBErrorString( res ) ); return -1; + } } } frame = bufs[0]; @@ -339,8 +427,11 @@ use_spic = 0; } - if (crtc2->TestConfiguration( crtc2, &dlc, &failed ) != DFB_OK) + if (crtc2->TestConfiguration( crtc2, &dlc, &failed ) != DFB_OK) { + mp_msg( MSGT_VO, MSGL_ERR, + "vo_dfbmga: Invalid CRTC2 configuration!\n" ); return -1; + } crtc2->SetConfiguration( crtc2, &dlc ); crtc2->GetSurface( crtc2, &c2frame ); @@ -372,11 +463,11 @@ drect.w = out_width; drect.h = out_height; - c2frame->Clear( c2frame, 0, 0, 0, 0 ); + c2frame->Clear( c2frame, 0, 0, 0, 0xff ); c2frame->Flip( c2frame, NULL, 0 ); - c2frame->Clear( c2frame, 0, 0, 0, 0 ); + c2frame->Clear( c2frame, 0, 0, 0, 0xff ); - printf( "vo_dfbmga: CRTC2 surface %dx%d %s\n", dlc.width, dlc.height, pixelformat_name( dlc.pixelformat ) ); + mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: CRTC2 surface %dx%d %s\n", dlc.width, dlc.height, pixelformat_name( dlc.pixelformat ) ); } else { screen_width = in_width; screen_height = in_height; @@ -385,7 +476,7 @@ frame->GetPixelFormat( frame, &frame_format ); frame_pixel_size = DFB_BYTES_PER_PIXEL( frame_format ); - printf( "vo_dfbmga: Video surface %dx%d %s (%s)\n", + mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: Video surface %dx%d %s (%s)\n", in_width, in_height, pixelformat_name( frame_format ), use_bes ? "BES" : "offscreen" ); @@ -395,23 +486,33 @@ IDirectFBPalette *palette; DFBColor color; int i; - - if (dfb->GetDisplayLayer( dfb, 3, &spic ) != DFB_OK) + struct layer_enum l = { + "Matrox CRTC2 Sub-Picture", + &spic, + DFB_UNSUPPORTED + }; + dfb->EnumDisplayLayers( dfb, get_layer_by_name, &l ); + if (l.res != DFB_OK) { + mp_msg( MSGT_VO, MSGL_ERR, "vo_dfbmga: Can't get sub-picture layer - %s\n", DirectFBErrorString( l.res ) ); return -1; + } spic->SetCooperativeLevel( spic, DLSCL_EXCLUSIVE ); spic->SetOpacity( spic, 0 ); dlc.flags = DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE; dlc.pixelformat = DSPF_LUT8; dlc.buffermode = DLBM_BACKVIDEO; - if (spic->TestConfiguration( spic, &dlc, &failed ) != DFB_OK) + if (spic->TestConfiguration( spic, &dlc, &failed ) != DFB_OK) { + mp_msg( MSGT_VO, MSGL_ERR, + "vo_dfbmga: Invalid sub-picture configuration!\n" ); return -1; + } spic->SetConfiguration( spic, &dlc ); spic->GetSurface( spic, &subframe ); subframe->GetPalette( subframe, &palette ); - color.a = 0; + color.a = 0xff; for (i = 0; i < 16; i++) { color.r = i * 17; color.g = i * 17; @@ -420,9 +521,9 @@ } palette->Release( palette ); - subframe->Clear( subframe, 0, 0, 0, 0 ); + subframe->Clear( subframe, 0, 0, 0, 0xff ); subframe->Flip( subframe, NULL, 0 ); - subframe->Clear( subframe, 0, 0, 0, 0 ); + subframe->Clear( subframe, 0, 0, 0, 0xff ); } else if (use_crtc2) { /* Draw OSD to CRTC2 surface */ subframe = c2frame; @@ -434,7 +535,7 @@ subframe->GetSize( subframe, &sub_width, &sub_height ); subframe->GetPixelFormat( subframe, &subframe_format ); subframe_pixel_size = DFB_BYTES_PER_PIXEL( subframe_format ); - printf( "vo_dfbmga: Sub-picture surface %dx%d %s (%s)\n", + mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: Sub-picture surface %dx%d %s (%s)\n", sub_width, sub_height, pixelformat_name( subframe_format ), use_crtc2 ? (use_spic ? "Sub-picture layer" : "CRTC2") : "BES" ); @@ -449,6 +550,7 @@ osd_dirty = 0; osd_current = 1; + blit_done = 0; return 0; } @@ -591,9 +693,6 @@ void *dst; int pitch; - if (vo_directrendering) - frame->Unlock( frame ); - if (frame->Lock( frame, DSLF_WRITE, &dst, &pitch ) != DFB_OK) return VO_FALSE; @@ -628,19 +727,34 @@ } static void +blit_to_screen( void ) +{ + /* Flip BES */ + if (use_bes) + frame->Flip( frame, NULL, 0 ); + + /* Blit from BES/temp to CRTC2 */ + c2frame->SetBlittingFlags( c2frame, DSBLIT_NOFX ); + if (stretch) + c2frame->StretchBlit( c2frame, frame, NULL, &drect ); + else + c2frame->Blit( c2frame, frame, NULL, drect.x, drect.y ); +} + +static void draw_osd( void ) { - if (vo_directrendering) - frame->Unlock( frame ); + frame = bufs[current_buf]; + frame->Unlock( frame ); osd_changed = vo_osd_changed( 0 ); - + if (osd_dirty & osd_current) { if (use_spic) { - subframe->Clear( subframe, 0, 0, 0, 0 ); + subframe->Clear( subframe, 0, 0, 0, 0xff ); } else if (use_crtc2) { /* Clear black bars around the picture */ - subframe->SetColor( subframe, 0, 0, 0, 0 ); + subframe->SetColor( subframe, 0, 0, 0, 0xff ); subframe->FillRectangle( subframe, 0, 0, screen_width, drect.y ); @@ -658,16 +772,8 @@ } if (use_crtc2) { - /* Flip BES */ - if (use_bes) - frame->Flip( frame, NULL, 0 ); - - /* Blit from BES/temp to CRTC2 */ - c2frame->SetBlittingFlags( c2frame, DSBLIT_NOFX ); - if (stretch) - c2frame->StretchBlit( c2frame, frame, NULL, &drect ); - else - c2frame->Blit( c2frame, frame, NULL, drect.x, drect.y ); + blit_to_screen(); + blit_done = 1; } vo_draw_text( sub_width, sub_height, draw_alpha ); @@ -685,38 +791,51 @@ /* Flip BES */ frame->Flip( frame, NULL, vo_vsync ? DSFLIP_WAITFORSYNC : 0 ); } else { + if (!blit_done) + blit_to_screen(); + /* Flip CRTC2 */ c2frame->Flip( c2frame, NULL, vo_vsync ? DSFLIP_WAITFORSYNC : 0 ); if (!use_spic) osd_current ^= 3; + blit_done = 0; } - current_buf = 0; + current_buf = vo_directrendering ? 0 : (current_buf + 1) % num_bufs; } static void uninit( void ) { - buffer->Release( buffer ); - keyboard->Release( keyboard ); + if (use_input) { + buffer->Release( buffer ); + keyboard->Release( keyboard ); + } while (num_bufs--) { frame = bufs[num_bufs]; - frame->Release( frame ); + if (frame) + frame->Release( frame ); + bufs[num_bufs] = NULL; } if (use_bes) { bes->SetOpacity( bes, 0 ); bes->Release( bes ); } if (use_crtc2) { - c2frame->Release( c2frame ); + if (c2frame) + c2frame->Release( c2frame ); crtc2->SetOpacity( crtc2, 0 ); crtc2->Release( crtc2 ); + c2frame = NULL; } - if (use_spic) { - subframe->Release( subframe ); + if (use_spic && spic) { + if (subframe) + subframe->Release( subframe ); spic->SetOpacity( spic, 0 ); spic->Release( spic ); + subframe = NULL; + spic = NULL; } /* @@ -730,6 +849,7 @@ static uint32_t get_image( mp_image_t *mpi ) { + int buf = current_buf; void *dst; int pitch; @@ -740,8 +860,6 @@ if (mpi->flags & MP_IMGFLAG_READABLE && (mpi->type == MP_IMGTYPE_IPB || mpi->type == MP_IMGTYPE_IP)) { - int buf = current_buf; - if (num_bufs < 2) return VO_FALSE; @@ -754,12 +872,12 @@ if (mpi->type == MP_IMGTYPE_IPB) buf++; + } + frame = bufs[buf]; + frame->Unlock( frame ); - current_buf = buf; - frame = bufs[current_buf]; - } - - if (frame->Lock( frame, DSLF_WRITE | (mpi->flags & MP_IMGFLAG_READABLE ? DSLF_READ : 0), + /* Always use DSLF_READ to preserve system memory copy */ + if (frame->Lock( frame, DSLF_WRITE | DSLF_READ, &dst, &pitch ) != DFB_OK) return VO_FALSE; @@ -783,6 +901,8 @@ } mpi->flags |= MP_IMGFLAG_DIRECT; + mpi->priv = (void *) buf; + current_buf = buf; return VO_TRUE; } @@ -797,7 +917,11 @@ static uint32_t draw_image( mp_image_t *mpi ) { - if (mpi->flags & (MP_IMGFLAG_DIRECT | MP_IMGFLAG_DRAW_CALLBACK)) + if (mpi->flags & MP_IMGFLAG_DIRECT) { + current_buf = (int) mpi->priv; + return VO_TRUE; + } + if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK) return VO_TRUE; if (mpi->flags & MP_IMGFLAG_PLANAR) @@ -892,6 +1016,10 @@ control( uint32_t request, void *data, ... ) { switch (request) { + case VOCTRL_GUISUPPORT: + case VOCTRL_GUI_NOWINDOW: + return VO_TRUE; + case VOCTRL_QUERY_FORMAT: return query_format( *((uint32_t *) data) ); @@ -937,6 +1065,9 @@ { DFBInputEvent event; + if (!use_input) + return; + if (buffer->GetEvent( buffer, DFB_EVENT( &event )) == DFB_OK) { if (event.type == DIET_KEYPRESS) { switch (event.key_symbol) {