/*
MPlayer video driver for DirectFramebuffer device
(C) 2001
Written by Jiri Svoboda <Jiri.Svoboda@seznam.cz>
Inspired by vo_sdl and vo_fbdev.
To get second head working delete line 120
from fbdev.c (from DirectFB sources version 0.9.7)
Line contains following:
fbdev->fd = open( "/dev/fb0", O_RDWR );
Parts of this code taken from DirectFB examples:
(c) Copyright 2000 convergence integrated media GmbH.
All rights reserved.
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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
// directfb includes
#include <directfb.h>
// other things
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.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 "aspect.h"
#ifndef min
#define min(x,y) (((x)<(y))?(x):(y))
#endif
LIBVO_EXTERN(directfb)
static vo_info_t vo_info = {
"Direct Framebuffer Device",
"directfb",
"Jiri Svoboda Jiri.Svoboda@seznam.cz",
""
};
extern int verbose;
/******************************
* directfb *
******************************/
/*
* (Globals)
*/
static IDirectFB *dfb = NULL;
static IDirectFBSurface *primary = NULL;
static IDirectFBInputDevice *keyboard = NULL;
static IDirectFBDisplayLayer *videolayer = NULL;
static DFBDisplayLayerConfig dlc;
static unsigned int screen_width = 0;
static unsigned int screen_height = 0;
static DFBSurfacePixelFormat frame_format;
static unsigned int frame_pixel_size = 0;
static unsigned int source_pixel_size = 0;
static int xoffset=0,yoffset=0;
#define DFBCHECK(x...) \
{ \
DFBResult err = x; \
\
if (err != DFB_OK) \
{ \
fprintf( stderr, "%s <%d>:\n\t", __FILE__, __LINE__ ); \
DirectFBErrorFatal( #x, err ); \
} \
}
/*
* The frame is to be loaded into a surface that we can blit from.
*/
static IDirectFBSurface *frame = NULL;
/*
* A buffer for input events.
*/
#ifdef HAVE_DIRECTFB099
static IDirectFBEventBuffer *buffer = NULL;
#else
static IDirectFBInputBuffer *buffer = NULL;
#endif
/******************************
* vo_directfb *
******************************/
/* command line/config file options */
#ifdef HAVE_FBDEV
extern char *fb_dev_name;
#else
char *fb_dev_name;
#endif
static void (*draw_alpha_p)(int w, int h, unsigned char *src,
unsigned char *srca, int stride, unsigned char *dst,
int dstride);
static uint32_t in_width;
static uint32_t in_height;
static uint32_t out_width=1;
static uint32_t out_height=1;
static uint32_t pixel_format;
static int fs;
static int flip;
static int stretch=0;
struct modes_t {
int valid;
unsigned int width;
unsigned int height;
int overx,overy;
} modes [4];
static unsigned int best_bpp=5;
// videolayer stuff
static int videolayeractive=0;
static int videolayerpresent=0;
//some info about videolayer - filled on preinit
struct vlayer_t {
int iv12;
int i420;
int yuy2;
int uyvy;
int brightness;
int saturation;
int contrast;
int hue;
} videolayercaps;
// workabout for DirectFB bug
static int buggyYV12BitBlt=0;
static int memcpyBitBlt=0;
#define DIRECTRENDER
#ifdef DIRECTRENDER
static int dr_enabled=0;
static int framelocked=0;
#endif
// primary & frame stuff
static int frameallocated=0;
static int primaryallocated=0;
DFBEnumerationResult enum_modes_callback( unsigned int width,unsigned int height,unsigned int bpp, void *data)
{
int overx=0,overy=0;
unsigned int index=bpp/8-1;
int allow_under=0;
if (verbose) printf("DirectFB: Validator entered %i %i %i\n",width,height,bpp);
overx=width-out_width;
overy=height-out_height;
if (!modes[index].valid) {
modes[index].valid=1;
modes[index].width=width;
modes[index].height=height;
modes[index].overx=overx;
modes[index].overy=overy;
}
if ((modes[index].overy<0)||(modes[index].overx<0)) allow_under=1;
if (abs(overx*overy)<abs(modes[index].overx * modes[index].overy)) {
if (((overx>=0)&&(overy>=0)) || allow_under) {
modes[index].valid=1;
modes[index].width=width;
modes[index].height=height;
modes[index].overx=overx;
modes[index].overy=overy;
if (verbose) printf("DirectFB:Better mode added %i %i %i\n",width,height,bpp);
};
};
return DFENUM_OK;
}
DFBEnumerationResult enum_layers_callback( unsigned int id,
DFBDisplayLayerCapabilities caps,
void *data )
{
IDirectFBDisplayLayer **layer = (IDirectFBDisplayLayer **)data;
if (verbose) {
printf("\nDirectFB: Layer %d:\n", id );
if (caps & DLCAPS_SURFACE)
printf( " - Has a surface.\n" );
if (caps & DLCAPS_ALPHACHANNEL)
printf( " - Supports blending based on alpha channel.\n" );
#ifdef HAVE_DIRECTFB0910
if (caps & DLCAPS_SRC_COLORKEY)
printf( " - Supports source based color keying.\n" );
if (caps & DLCAPS_DST_COLORKEY)
printf( " - Supports destination based color keying.\n" );
#else
if (caps & DLCAPS_COLORKEYING)
printf( " - Supports color keying.\n" );
#endif
if (caps & DLCAPS_FLICKER_FILTERING)
printf( " - Supports flicker filtering.\n" );
if (caps & DLCAPS_INTERLACED_VIDEO)
printf( " - Can natively display interlaced video.\n" );
if (caps & DLCAPS_OPACITY)
printf( " - Supports blending based on global alpha factor.\n" );
if (caps & DLCAPS_SCREEN_LOCATION)
printf( " - Can be positioned on the screen.\n" );
if (caps & DLCAPS_BRIGHTNESS)
printf( " - Brightness can be adjusted.\n" );
if (caps & DLCAPS_CONTRAST)
printf( " - Contrast can be adjusted.\n" );
if (caps & DLCAPS_HUE)
printf( " - Hue can be adjusted.\n" );
if (caps & DLCAPS_SATURATION)
printf( " - Saturation can be adjusted.\n" );
printf("\n");
}
/* We take the first layer not being the primary */
if (id != DLID_PRIMARY) {
DFBResult ret;
ret = dfb->GetDisplayLayer( dfb, id, layer );
if (ret)
DirectFBError( "dfb->GetDisplayLayer failed", ret );
else
return DFENUM_CANCEL;
}
return DFENUM_OK;
}
static uint32_t preinit(const char *arg)
{
DFBSurfaceDescription dsc;
DFBResult ret;
DFBDisplayLayerConfigFlags failed;
/*
* (Initialize)
*/
if (verbose) printf("DirectFB: Preinit entered\n");
DFBCHECK (DirectFBInit (NULL,NULL));
if ((directfb_major_version >= 0) &&
(directfb_minor_version >= 9) &&
(directfb_micro_version >= 7))
{
if (!fb_dev_name && !(fb_dev_name = getenv("FRAMEBUFFER"))) fb_dev_name = "/dev/fb0";
DFBCHECK (DirectFBSetOption ("fbdev",fb_dev_name));
}
// disable YV12 for dfb until 0.9.10 - there is a bug in dfb! should be revised with every dfb version until bug is fixed in dfb.
if ((directfb_major_version <= 0) &&
(directfb_minor_version <= 9) &&
(d
|