mirror of https://github.com/snes9xgit/snes9x.git
Add I420 Xvideo image format support, with both libyuv hardware acceleration and software conversion support.
This commit is contained in:
parent
d65789edc4
commit
bd996da4af
|
@ -445,6 +445,22 @@ if test "x$enable_xvideo" = "xyes"; then
|
||||||
])
|
])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Check if we can build with libyuv hardware acceleration I420 conversion support
|
||||||
|
AC_ARG_ENABLE([libyuv],
|
||||||
|
[AS_HELP_STRING([--enable-libyuv],
|
||||||
|
[enable libyuv I420 conversion support if available (default: yes)])],
|
||||||
|
[], [enable_libyuv="yes"])
|
||||||
|
|
||||||
|
if test "x$enable_libyuv" = "xyes"; then
|
||||||
|
enable_libyuv="no"
|
||||||
|
AC_CHECK_HEADER([libyuv.h],
|
||||||
|
[
|
||||||
|
enable_libyuv="yes"
|
||||||
|
S9XLIBS="$S9XLIBS -lyuv"
|
||||||
|
S9XDEFS="$S9XDEFS -DUSE_LIBYUV"
|
||||||
|
])
|
||||||
|
fi
|
||||||
|
|
||||||
# Check if we can build with Xinerama multi-monitor support
|
# Check if we can build with Xinerama multi-monitor support
|
||||||
AC_ARG_ENABLE([xinerama],
|
AC_ARG_ENABLE([xinerama],
|
||||||
[AS_HELP_STRING([--enable-xinerama],
|
[AS_HELP_STRING([--enable-xinerama],
|
||||||
|
@ -545,6 +561,7 @@ libs................. $S9XLIBS
|
||||||
|
|
||||||
features:
|
features:
|
||||||
Xvideo support....... $enable_xvideo
|
Xvideo support....... $enable_xvideo
|
||||||
|
libyuv support....... $enable_libyuv
|
||||||
Xinerama support..... $enable_xinerama
|
Xinerama support..... $enable_xinerama
|
||||||
sound support........ $enable_sound
|
sound support........ $enable_sound
|
||||||
alsa support......... $enable_sound_alsa
|
alsa support......... $enable_sound_alsa
|
||||||
|
|
96
unix/x11.cpp
96
unix/x11.cpp
|
@ -25,7 +25,12 @@
|
||||||
#ifdef USE_XVIDEO
|
#ifdef USE_XVIDEO
|
||||||
#include <X11/extensions/Xvlib.h>
|
#include <X11/extensions/Xvlib.h>
|
||||||
|
|
||||||
|
#ifdef USE_LIBYUV
|
||||||
|
#include <libyuv.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define FOURCC_YUY2 0x32595559
|
#define FOURCC_YUY2 0x32595559
|
||||||
|
#define FOURCC_I420 0x30323449
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_XINERAMA
|
#ifdef USE_XINERAMA
|
||||||
|
@ -585,6 +590,12 @@ static bool8 SetupXvideo()
|
||||||
|
|
||||||
for (int i = 0; i < formats; i++)
|
for (int i = 0; i < formats; i++)
|
||||||
{
|
{
|
||||||
|
//prefer I420
|
||||||
|
if (fo[i].id == FOURCC_I420) {
|
||||||
|
GUI.xv_format = FOURCC_I420;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (fo[i].id == 0x3 || fo[i].type == XvRGB)
|
if (fo[i].id == 0x3 || fo[i].type == XvRGB)
|
||||||
{
|
{
|
||||||
if (fo[i].bits_per_pixel < GUI.xv_bpp)
|
if (fo[i].bits_per_pixel < GUI.xv_bpp)
|
||||||
|
@ -617,12 +628,14 @@ static bool8 SetupXvideo()
|
||||||
}
|
}
|
||||||
free (fo);
|
free (fo);
|
||||||
|
|
||||||
if (GUI.xv_format != FOURCC_YUY2)
|
if (GUI.xv_format != FOURCC_YUY2 && GUI.xv_format != FOURCC_I420) {
|
||||||
{
|
|
||||||
printf("Selected XvRGB format: %d bpp\n",GUI.xv_bpp);
|
printf("Selected XvRGB format: %d bpp\n",GUI.xv_bpp);
|
||||||
} else {
|
} else {
|
||||||
// use YUY2
|
// use I420 or YUY2
|
||||||
printf("Fallback to YUY2 format.\n");
|
if(GUI.xv_format == FOURCC_I420) {
|
||||||
|
printf("Xvideo I420 image format.\n");
|
||||||
|
} else {
|
||||||
|
printf("Xvideo YUY2 image format.\n");
|
||||||
GUI.depth = 15;
|
GUI.depth = 15;
|
||||||
|
|
||||||
/* Build a table for yuv conversion */
|
/* Build a table for yuv conversion */
|
||||||
|
@ -644,6 +657,7 @@ static bool8 SetupXvideo()
|
||||||
GUI.v_table[color] = CLAMP (v, 0, 255);
|
GUI.v_table[color] = CLAMP (v, 0, 255);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -939,7 +953,7 @@ static void SetupImage (void)
|
||||||
FatalError("Failed to allocate GUI.filter_buffer.");
|
FatalError("Failed to allocate GUI.filter_buffer.");
|
||||||
|
|
||||||
#ifdef USE_XVIDEO
|
#ifdef USE_XVIDEO
|
||||||
if ((GUI.depth == 15 || GUI.depth == 16) && GUI.xv_format != FOURCC_YUY2)
|
if ((GUI.depth == 15 || GUI.depth == 16) && GUI.xv_format != FOURCC_YUY2 && GUI.xv_format != FOURCC_I420)
|
||||||
#else
|
#else
|
||||||
if (GUI.depth == 15 || GUI.depth == 16)
|
if (GUI.depth == 15 || GUI.depth == 16)
|
||||||
#endif
|
#endif
|
||||||
|
@ -1209,6 +1223,55 @@ static void TakedownXvImage (void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(USE_XVIDEO) && !defined(USE_LIBYUV)
|
||||||
|
void rgb565ToRgb24(uint8 *dest, uint8 *s, int width, int height) {
|
||||||
|
for (int i=0, j=0; i< width * height * 2 ; i+=2) {
|
||||||
|
uint16 c = s[i] + (s[i+1]<<8);
|
||||||
|
uint8 r = uint8(((c & 0xF800) >> 11) << 3);
|
||||||
|
uint8 g = uint8(((c & 0x7E0) >> 5) << 2);
|
||||||
|
uint8 b = uint8(((c & 0x1F)) << 3);
|
||||||
|
dest[j++]=r;
|
||||||
|
dest[j++]=g;
|
||||||
|
dest[j++]=b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rgb24ToI420(uint8 *dest, uint8 *rgb, int width, int height) {
|
||||||
|
int image_size = width * height;
|
||||||
|
int upos = image_size;
|
||||||
|
int vpos = upos + upos / 4;
|
||||||
|
int i = 0;
|
||||||
|
for (int line = 0; line < height; ++line) {
|
||||||
|
if( !(line % 2) ) {
|
||||||
|
for ( int x = 0; x < width; x += 2 ) {
|
||||||
|
uint8 r = rgb[3 * i];
|
||||||
|
uint8 g = rgb[3 * i + 1];
|
||||||
|
uint8 b = rgb[3 * i + 2];
|
||||||
|
|
||||||
|
dest[i++] = ((66*r + 129*g + 25*b) >> 8) + 16;
|
||||||
|
|
||||||
|
dest[upos++] = ((-38*r + -74*g + 112*b) >> 8) + 128;
|
||||||
|
dest[vpos++] = ((112*r + -94*g + -18*b) >> 8) + 128;
|
||||||
|
|
||||||
|
r = rgb[3 * i];
|
||||||
|
g = rgb[3 * i + 1];
|
||||||
|
b = rgb[3 * i + 2];
|
||||||
|
|
||||||
|
dest[i++] = ((66*r + 129*g + 25*b) >> 8) + 16;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int x = 0; x < width; x += 1) {
|
||||||
|
uint8 r = rgb[3 * i];
|
||||||
|
uint8 g = rgb[3 * i + 1];
|
||||||
|
uint8 b = rgb[3 * i + 2];
|
||||||
|
|
||||||
|
dest[i++] = ((66*r + 129*g + 25*b) >> 8) + 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void S9xPutImage (int width, int height)
|
void S9xPutImage (int width, int height)
|
||||||
{
|
{
|
||||||
static int prevWidth = 0, prevHeight = 0;
|
static int prevWidth = 0, prevHeight = 0;
|
||||||
|
@ -1307,6 +1370,29 @@ void S9xPutImage (int width, int height)
|
||||||
*d = (GUI.v_table[rgb1] + GUI.v_table[rgb2]) / 2; d++;
|
*d = (GUI.v_table[rgb1] + GUI.v_table[rgb2]) / 2; d++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (GUI.use_xvideo && (GUI.xv_format == FOURCC_I420)) {
|
||||||
|
uint8 *s = (uint8 *)GUI.blit_screen;
|
||||||
|
uint8 *d = (uint8 *)GUI.image->data;
|
||||||
|
|
||||||
|
int tw = SNES_WIDTH * 2;
|
||||||
|
int th = SNES_HEIGHT_EXTENDED * 2;
|
||||||
|
|
||||||
|
#ifdef USE_LIBYUV
|
||||||
|
libyuv::RGB565ToI420(
|
||||||
|
s, tw*2,
|
||||||
|
d, tw,
|
||||||
|
d + tw*th, tw/2,
|
||||||
|
d + tw*th + tw*th/4, tw/2,
|
||||||
|
tw, th);
|
||||||
|
#else
|
||||||
|
uint8 *ns = (uint8 *) calloc(tw*th*3, 1);
|
||||||
|
//convert to RGB24
|
||||||
|
rgb565ToRgb24(ns, s, tw, th);
|
||||||
|
//convert to I420
|
||||||
|
rgb24ToI420(d, ns, tw, th);
|
||||||
|
free(ns);
|
||||||
|
#endif
|
||||||
|
GUI.need_convert =0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue