/*
MPlayer video driver for DirectFB / Matrox G200/G400/G450/G550
Copyright (C) 2002-2005 Ville Syrjala <syrjala@sci.fi>
Originally based on vo_directfb.c by
Jiri Svoboda <Jiri.Svoboda@seznam.cz>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA.
*/
/* directfb includes */
#include <directfb.h>
#define DFB_VERSION(a,b,c) (((a)<<16)|((b)<<8)|(c))
/* other things */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "video_out.h"
#include "video_out_internal.h"
#include "fastmemcpy.h"
#include "sub.h"
#include "mp_msg.h"
#include "aspect.h"
#include "mp_fifo.h"
static const vo_info_t info = {
"DirectFB / Matrox G200/G400/G450/G550",
"dfbmga",
"Ville Syrjala <syrjala@sci.fi>",
""
};
const LIBVO_EXTERN(dfbmga)
/******************************
* directfb *
******************************/
/*
* (Globals)
*/
static IDirectFB *dfb;
static IDirectFBDisplayLayer *primary;
static IDirectFBDisplayLayer *bes;
static IDirectFBDisplayLayer *crtc2;
static IDirectFBDisplayLayer *spic;
static int num_bufs;
static int current_buf;
static int current_ip_buf;
static IDirectFBSurface *bufs[3];
static IDirectFBSurface *frame;
static IDirectFBSurface *subframe;
static IDirectFBSurface *besframe;
static IDirectFBSurface *c2frame;
static IDirectFBSurface *spicframe;
static DFBSurfacePixelFormat frame_format;
static DFBSurfacePixelFormat subframe_format;
static DFBRectangle besrect;
static DFBRectangle c2rect;
static DFBRectangle *subrect;
static IDirectFBInputDevice *keyboard;
static IDirectFBInputDevice *remote;
static IDirectFBEventBuffer *buffer;
static int blit_done;
static int stretch;
static int use_bes;
static int use_crtc2;
static int use_spic;
static int use_input;
static int use_remote;
static int field_parity;
static int flipping;
static DFBDisplayLayerBufferMode buffermode;
static int tvnorm;
static int osd_changed;
static int osd_dirty;
static int osd_current;
static int osd_max;
static int is_g200;
/******************************
* vo_dfbmga *
******************************/
#if DIRECTFBVERSION < DFB_VERSION(0,9,18)
#define DSPF_ALUT44 DSPF_LUT8
#define DLBM_TRIPLE ~0
#define DSFLIP_ONSYNC 0
#endif
#if DIRECTFBVERSION < DFB_VERSION(0,9,16)
#define DSPF_ARGB1555 DSPF_RGB15
#endif
static uint32_t in_width;
static uint32_t in_height;
static uint32_t buf_height;
static uint32_t screen_width;
static uint32_t screen_height;
static uint32_t sub_width;
static uint32_t sub_height;
static char *
pixelformat_name( DFBSurfacePixelFormat format )
{
switch(format) {
case DSPF_ARGB:
return "ARGB";
case DSPF_RGB32:
return "RGB32";
case DSPF_RGB24:
return "RGB24";
case DSPF_RGB16:
return "RGB16";
case DSPF_ARGB1555:
return "ARGB1555";
case DSPF_YUY2:
return "YUY2";
case DSPF_UYVY:
return "UYVY";
case DSPF_YV12:
return "YV12";
case DSPF_I420:
return "I420";
case DSPF_ALUT44:
return "ALUT44";
#if DIRECTFBVERSION > DFB_VERSION(0,9,21)
case DSPF_NV12:
return "NV12";
case DSPF_NV21:
return "NV21";
#endif
default:
return "Unknown pixel format";
}
}
static DFBSurfacePixelFormat
imgfmt_to_pixelformat( uint32_t format )
{
switch (format) {
case IMGFMT_BGR32:
return DSPF_RGB32;
case IMGFMT_BGR24:
return DSPF_RGB24;
case IMGFMT_BGR16:
return DSPF_RGB16;
case IMGFMT_BGR15:
return DSPF_ARGB1555;
case IMGFMT_YUY2:
return DSPF_YUY2;
case IMGFMT_UYVY:
return DSPF_UYVY;
case IMGFMT_YV12:
return DSPF_YV12;
case IMGFMT_I420:
case IMGFMT_IYUV:
return DSPF_I420;
#if DIRECTFBVERSION > DFB_VERSION(0,9,21)
case IMGFMT_NV12:
return DSPF_NV12;
case IMGFMT_NV21:
return DSPF_NV21;
#endif
default:
return DSPF_UNKNOWN;
}
}
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 > DFB_VERSION(0,9,15)
/* 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 == 0 && !strcmp( l->name, "FBDev Primary Layer" )) ||
(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 int
preinit( const char *arg )
{
DFBResult res;
int force_input = -1;
/* Some defaults */
use_bes = 0;
use_crtc2 = 1;
use_spic = 1;
field_parity = -1;
#if DIRECTFBVERSION > DFB_VERSION(0,9,17)
buffermode = DLBM_TRIPLE;
osd_max = 4;
#else
buffermode = DLBM_BACKVIDEO;
osd_max = 2;
#endif
flipping = 1;
tvnorm = -1;
use_input = !getenv( "DISPLAY" );
if (vo_subdevice) {
int show_help = 0;
int opt_no = 0;
while (*vo_subdevice != '\0') {
if (!strncmp(vo_subdevice, "bes", 3)) {
use_bes = !opt_no;
vo_subdevice += 3;
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)) {
force_input = !opt_no;
vo_subdevice += 5;
opt_no = 0;
} else if (!strncmp(vo_subdevice, "remote", 6)) {
use_remote = !opt_no;
vo_subdevice += 6;
opt_no = 0;
} else if (!strncmp(vo_su
|