/*
* vo_sdl.c
*
* (was video_out_sdl.c from OMS project/mpeg2dec -> http://linuxvideo.org)
*
* Copyright (C) Ryan C. Gordon <icculus@lokigames.com> - April 22, 2000
*
* Copyright (C) Felix Buenemann <atmosfear@users.sourceforge.net> - 2001
*
* (for extensive code enhancements)
*
* Current maintainer for MPlayer project (report bugs to that address):
* Felix Buenemann <atmosfear@users.sourceforge.net>
*
* This file is a video out driver using the SDL library (http://libsdl.org/),
* to be used with MPlayer, further info from http://www.mplayerhq.hu
*
* -- old disclaimer --
*
* A mpeg2dec display driver that does output through the
* Simple DirectMedia Layer (SDL) library. This effectively gives us all
* sorts of output options: X11, SVGAlib, fbcon, AAlib, GGI. Win32, MacOS
* and BeOS support, too. Yay. SDL info, source, and binaries can be found
* at http://slouken.devolution.com/SDL/
*
* -- end old disclaimer --
*
* This file is part of MPlayer.
*
* MPlayer is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* MPlayer 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* define to force software-surface (video surface stored in system memory)*/
#undef SDL_NOHWSURFACE
/* define to enable surface locks, this might be needed on SMP machines */
#undef SDL_ENABLE_LOCKS
/* MONITOR_ASPECT MUST BE FLOAT */
#define MONITOR_ASPECT 4.0/3.0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "config.h"
#include "mp_msg.h"
#include "mp_msg.h"
#include "video_out.h"
#include "video_out_internal.h"
#include "fastmemcpy.h"
#include "sub/sub.h"
#include "aspect.h"
#include "libmpcodecs/vfcap.h"
#include "mpbswap.h"
#ifdef CONFIG_X11
#include <X11/Xlib.h>
#include "x11_common.h"
#endif
#include "subopt-helper.h"
static const vo_info_t info =
{
"SDL YUV/RGB/BGR renderer (SDL v1.1.7+ only!)",
"sdl",
"Ryan C. Gordon <icculus@lokigames.com>, Felix Buenemann <atmosfear@users.sourceforge.net>",
""
};
const LIBVO_EXTERN(sdl)
#include "sdl_common.h"
//#include <SDL/SDL_syswm.h>
#ifdef SDL_ENABLE_LOCKS
#define SDL_OVR_LOCK(x) if (SDL_LockYUVOverlay (priv->overlay)) { \
mp_msg(MSGT_VO,MSGL_V, "SDL: Couldn't lock YUV overlay\n"); \
return x; \
}
#define SDL_OVR_UNLOCK SDL_UnlockYUVOverlay (priv->overlay);
#define SDL_SRF_LOCK(srf, x) if(SDL_MUSTLOCK(srf)) { \
if(SDL_LockSurface (srf)) { \
mp_msg(MSGT_VO,MSGL_V, "SDL: Couldn't lock RGB surface\n"); \
return x; \
} \
}
#define SDL_SRF_UNLOCK(srf) if(SDL_MUSTLOCK(srf)) \
SDL_UnlockSurface (srf);
#else
#define SDL_OVR_LOCK(x)
#define SDL_OVR_UNLOCK
#define SDL_SRF_LOCK(srf, x)
#define SDL_SRF_UNLOCK(srf)
#endif
/** Private SDL Data structure **/
static struct sdl_priv_s {
/* output driver used by sdl */
char driver[8];
/* SDL display surface */
SDL_Surface *surface;
/* SDL RGB surface */
SDL_Surface *rgbsurface;
/* SDL YUV overlay */
SDL_Overlay *overlay;
/* available fullscreen modes */
SDL_Rect **fullmodes;
/* surface attributes for fullscreen and windowed mode */
Uint32 sdlflags, sdlfullflags;
/* save the windowed output extents */
SDL_Rect windowsize;
/* Bits per Pixel */
Uint8 bpp;
/* RGB or YUV? */
Uint8 mode;
#define YUV 0
#define RGB 1
#define BGR 2
/* use direct blitting to surface */
int dblit;
/* current fullscreen mode, 0 = highest available fullscreen mode */
int fullmode;
/* YUV ints */
int framePlaneY, framePlaneUV, framePlaneYUY;
int stridePlaneY, stridePlaneUV, stridePlaneYUY;
/* RGB ints */
int framePlaneRGB;
int stridePlaneRGB;
/* Flip image */
int flip;
/* fullscreen behaviour; see init */
int fulltype;
/* is X running (0/1) */
int X;
/* X11 Resolution */
int XWidth, XHeight;
/* original image dimensions */
int width, height;
/* destination dimensions */
int dstwidth, dstheight;
/* Draw image at coordinate y on the SDL surfaces */
int y;
/* The image is displayed between those y coordinates in priv->surface */
int y_screen_top, y_screen_bottom;
/* 1 if the OSD has changed otherwise 0 */
int osd_has_changed;
/* source image format (YUV/RGB/...) */
uint32_t format;
/* dirty_off_frame[0] contains a bounding box around the osd contents drawn above the image
dirty_off_frame[1] is the corresponding thing for OSD contents drawn below the image
*/
SDL_Rect dirty_off_frame[2];
} sdl_priv;
static void erase_area_4(int x_start, int width, int height, int pitch, uint32_t color, uint8_t* pixels);
static void erase_area_1(int x_start, int width, int height, int pitch, uint8_t color, uint8_t* pixels);
static int setup_surfaces(void);
static void set_video_mode(int width, int height, int bpp, uint32_t sdlflags);
static void erase_rectangle(int x, int y, int w, int h);
/* Expand 'rect' to contain the rectangle specified by x, y, w and h */
static void expand_rect(SDL_Rect* rect, int x, int y, int w, int h)
{
if(rect->x < 0 || rect->y < 0) {
rect->x = x;
rect->y = y;
rect->w = w;
rect->h = h;
return;
}
if(rect->x > x)
rect->x = x;
if(rect->y > y)
rect->y = y;
if(rect->x + rect->w < x + w)
rect->w = x + w - rect->x;
if(rect->y + rect->h < y + h)
rect->h = y + h - rect->y;
}
/** libvo Plugin functions **/
/**
* draw_alpha is used for osd and subtitle display.
*
**/
static void draw_alpha(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){
struct sdl_priv_s *priv = &sdl_priv;
if(priv->osd_has_changed) {
/* OSD did change. Store a bounding box of everything drawn into the OSD */
if(priv->y >= y0) {
/* Make sure we don't mark part of the frame area dirty */
if(h + y0 > priv->y)
expand_rect(&priv->dirty_off_frame[0], x0, y0, w, priv->y - y0);
else
expand_rect(&priv->dirty_off_frame[0], x0, y0, w, h);
}
else if(priv->y + priv->height <= y0 + h) {
/* Make sure we don't mark part of the frame area dirty */
|