GTK GUI :

Added a Xvideo renderer to get hardware accelerated scaling and filtering. It is about 10x faster than the GTK+ renderer. No filters yet.


git-svn-id: https://svn.code.sf.net/p/vbam/code/trunk@490 a31d4220-a93d-0410-bf67-fe4944624d44
This commit is contained in:
bgk 2008-04-22 10:39:23 +00:00
parent 3090c69c7b
commit bd07f02a0d
6 changed files with 333 additions and 12 deletions

View File

@ -15,14 +15,15 @@ PKG_CHECK_MODULES ( GLIBMM glibmm-2.4 )
PKG_CHECK_MODULES ( GLADEMM libglademm-2.4 )
PKG_CHECK_MODULES ( PORTAUDIO portaudio-2.0 )
PKG_CHECK_MODULES ( SDL sdl )
PKG_CHECK_MODULES ( XV xv )
IF( SDL_FOUND )
SET( CAN_BUILD_VBAM 1 )
ENDIF( SDL_FOUND )
IF( GLIBMM_FOUND AND GTKMM_FOUND AND GLADEMM_FOUND AND PORTAUDIO_FOUND )
IF( GLIBMM_FOUND AND GTKMM_FOUND AND GLADEMM_FOUND AND PORTAUDIO_FOUND AND XV_FOUND )
SET( CAN_BUILD_GVBAM 1 )
ENDIF( GLIBMM_FOUND AND GTKMM_FOUND AND GLADEMM_FOUND AND PORTAUDIO_FOUND )
ENDIF( GLIBMM_FOUND AND GTKMM_FOUND AND GLADEMM_FOUND AND PORTAUDIO_FOUND AND XV_FOUND )
IF( NOT DATA_INSTALL_DIR )
SET( DATA_INSTALL_DIR "src/gtk" )
@ -141,6 +142,7 @@ SET(SRC_GTK
src/gtk/joypadconfig.cpp
src/gtk/screenarea.cpp
src/gtk/screenarea-gtk.cpp
src/gtk/screenarea-xvideo.cpp
src/gtk/tools.cpp
src/gtk/window.cpp
src/gtk/sndPortAudio.cpp
@ -207,6 +209,7 @@ IF( CAN_BUILD_GVBAM )
${PNG_LIBRARY}
${GLADEMM_LIBRARIES}
${PORTAUDIO_LIBRARIES}
${XV_LIBRARIES}
)
INSTALL(PROGRAMS gvbam DESTINATION bin)

View File

@ -0,0 +1,226 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "screenarea-xvideo.h"
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <X11/extensions/Xvlib.h>
#define FOURCC_YUY2 0x32595559
namespace VBA
{
ScreenAreaXv::ScreenAreaXv(int _iWidth, int _iHeight, int _iScale) :
ScreenArea(_iWidth, _iHeight, _iScale)
{
XvAdaptorInfo *pAdaptors;
unsigned int iNumAdaptors;
XvImageFormatValues *pFormats;
int iNumFormats;
GdkWindow *pRoot;
memset(&m_oShm, 0, sizeof(m_oShm));
// Ugly bit of GTK+ to get the X display
Glib::RefPtr<Gdk::Window> poWindow = get_root_window();
GdkWindow *pWindow = poWindow->gobj();
m_pDisplay = gdk_x11_drawable_get_xdisplay(GDK_DRAWABLE(pWindow));
Glib::RefPtr<Gdk::Screen> poScreen = get_screen();
Glib::RefPtr<Gdk::Window> poRoot = poScreen->get_root_window();
pRoot = poRoot->gobj();
m_iXvPortId = -1;
XvQueryAdaptors(m_pDisplay,
GDK_WINDOW_XWINDOW(pRoot),
&iNumAdaptors,
&pAdaptors);
for (unsigned int i = 0; i < iNumAdaptors; i++)
{
if (pAdaptors[i].type & XvInputMask &&
pAdaptors[i].type & XvImageMask)
{
m_iXvPortId = pAdaptors[i].base_id;
}
}
XvFreeAdaptorInfo(pAdaptors);
if (m_iXvPortId < 0)
{
fprintf (stderr, "Could not open Xv output port.\n");
throw std::exception();
}
/* Try to find an RGB format */
pFormats = XvListImageFormats(m_pDisplay, m_iXvPortId, &iNumFormats);
m_iFormat = FOURCC_YUY2;
for (int i = 0; i < iNumFormats; i++)
{
if (pFormats[i].id == 0x3 || pFormats[i].type == XvRGB)
{
/* Try to find a 32-bit mode */
if (pFormats[i].bits_per_pixel == 32)
{
m_iFormat = pFormats[i].id;
}
}
}
Atom oAtom = XInternAtom(m_pDisplay, "XV_AUTOPAINT_COLORKEY", True);
if (oAtom != None)
XvSetPortAttribute (m_pDisplay, m_iXvPortId, oAtom, 1);
vUpdateSize();
}
ScreenAreaXv::~ScreenAreaXv()
{
XShmDetach(m_pDisplay, &m_oShm);
}
void ScreenAreaXv::vDrawPixels(u8 * _puiData)
{
GtkWidget *pDrawingArea = GTK_WIDGET(this->gobj());
GdkGC *gc = pDrawingArea->style->bg_gc[GTK_WIDGET_STATE (pDrawingArea)];
const int iSrcPitch = (m_iWidth + 4) * sizeof(u16);
const int iDstPitch = m_iWidth * sizeof(u32) + 4;
vRGB32toYUY2((unsigned char*)m_pXvImage->data, m_iWidth, m_iHeight, iSrcPitch,
_puiData + iDstPitch, m_iWidth + 4, m_iHeight + 4, iDstPitch);
gdk_display_sync(gtk_widget_get_display(pDrawingArea));
XvShmPutImage(m_pDisplay,
m_iXvPortId,
GDK_WINDOW_XWINDOW (pDrawingArea->window),
GDK_GC_XGC (gc),
m_pXvImage,
0, 0,
m_iWidth, m_iHeight,
0, 0,
m_iAreaWidth, m_iAreaHeight,
True);
gdk_display_sync(gtk_widget_get_display(pDrawingArea));
}
void ScreenAreaXv::vDrawColor(u32 _uiColor)
{
}
void ScreenAreaXv::vUpdateSize()
{
if (m_oShm.shmid)
{
XShmDetach(m_pDisplay, &m_oShm);
}
m_iAreaWidth = m_iScale * m_iWidth;
m_iAreaHeight = m_iScale * m_iHeight;
m_pXvImage = XvShmCreateImage(m_pDisplay,
m_iXvPortId,
m_iFormat,
0,
m_iWidth + 4,
m_iHeight + 4,
&m_oShm);
m_oShm.shmid = shmget(IPC_PRIVATE, m_pXvImage->data_size, IPC_CREAT | 0777);
m_oShm.shmaddr = (char *) shmat(m_oShm.shmid, 0, 0);
m_oShm.readOnly = FALSE;
m_pXvImage->data = m_oShm.shmaddr;
XShmAttach(m_pDisplay, &m_oShm);
set_size_request(m_iAreaWidth, m_iAreaHeight);
}
void ScreenAreaXv::vRGB32toYUY2 (unsigned char* dest_ptr,
int dest_width,
int dest_height,
int dest_pitch,
unsigned char* src_ptr,
int src_width,
int src_height,
int src_pitch)
{
unsigned char* pSrc = NULL;
unsigned char* pDst = NULL;
int iR = 0;
int iG = 0;
int iB = 0;
int iY = 0;
int iU = 0;
int iV = 0;
/* Run through each row */
for (int y = 0; y < src_height; y++)
{
/* Get the src and dst row pointers */
pSrc = src_ptr + y * src_pitch;
pDst = dest_ptr + y * dest_pitch;
/* Loop along each row */
for (int x = 0; x < src_width; x++)
{
/* Convert RGB to YUV, using the following fixed-point formula:
*
* Y = (r * 2104 + g * 4130 + b * 802 + 4096 + 131072) >> 13
* U = (r * -1214 + g * -2384 + b * 3598 + 4096 + 1048576) >> 13
* V = (r * 3598 + g * -3013 + b * -585 + 4096 + 1048576) >> 13
*/
#if defined(_WINDOWS)
iR = pSrc[2];
iG = pSrc[1];
iB = pSrc[0];
#else
iR = pSrc[0];
iG = pSrc[1];
iB = pSrc[2];
#endif
iY = (iR * 2104 + iG * 4130 + iB * 802 + 4096 + 131072) >> 13;
iU = (iR * -1214 - iG * 2384 + iB * 3598 + 4096 + 1048576) >> 13;
iV = (iR * 3598 - iG * 3013 - iB * 585 + 4096 + 1048576) >> 13;
/* Write out the Y */
pDst[0] = (unsigned char) iY;
/* If we are even, write out U. If odd, write V */
pDst[1] = (unsigned char) ((x & 1) ? iV : iU);
/* Advance the src pointer */
pSrc += 4;
/* Advance the dst pointer */
pDst += 2;
}
}
}
} // namespace VBA

View File

@ -0,0 +1,64 @@
// -*- C++ -*-
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program 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, or(at your option)
// any later version.
//
// This program 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 this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef __VBA_SCREENAREA_XVIDEO_H__
#define __VBA_SCREENAREA_XVIDEO_H__
#include "screenarea.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/Xv.h>
#include <X11/extensions/XShm.h>
#include <X11/extensions/Xvlib.h>
namespace VBA
{
class ScreenAreaXv : public ScreenArea
{
public:
ScreenAreaXv(int _iWidth, int _iHeight, int _iScale = 1);
virtual ~ScreenAreaXv();
void vDrawPixels(u8 * _puiData);
void vDrawColor(u32 _uiColor); // 0xRRGGBB
private:
Display *m_pDisplay;
XvImage *m_pXvImage;
int m_iXvPortId;
int m_iFormat;
u16* m_paYUY;
XShmSegmentInfo m_oShm;
void vUpdateSize();
void vRGB32toYUY2 (unsigned char* dest_ptr,
int dest_width,
int dest_height,
int dest_pitch,
unsigned char* src_ptr,
int src_width,
int src_height,
int src_pitch);
};
} // namespace VBA
#endif // __VBA_SCREENAREA_XVIDEO_H__

View File

@ -42,7 +42,6 @@ public:
virtual void vDrawColor(u32 _uiColor) = 0; // 0xRRGGBB
protected:
virtual bool on_expose_event(GdkEventExpose * _pstEvent) = 0;
virtual bool on_motion_notify_event(GdkEventMotion * _pstEvent);
virtual bool on_enter_notify_event(GdkEventCrossing * _pstEvent);
virtual bool on_leave_notify_event(GdkEventCrossing * _pstEvent);

View File

@ -33,6 +33,8 @@
#include "menuitem.h"
#include "tools.h"
#include "intl.h"
#include "screenarea-gtk.h"
#include "screenarea-xvideo.h"
extern int systemRenderedFrames;
extern int systemFPS;
@ -95,13 +97,6 @@ Window::Window(GtkWindow * _pstWindow, const Glib::RefPtr<Xml> & _poXml) :
vSetDefaultTitle();
Gtk::Container * poC;
poC = dynamic_cast<Gtk::Container *>(_poXml->get_widget("ScreenContainer"));
m_poScreenArea = Gtk::manage(new ScreenAreaGtk(m_iScreenWidth, m_iScreenHeight));
poC->add(*m_poScreenArea);
vDrawDefaultScreen();
m_poScreenArea->show();
// Get config
//
vInitConfig();
@ -123,6 +118,8 @@ Window::Window(GtkWindow * _pstWindow, const Glib::RefPtr<Xml> & _poXml) :
vSaveConfig(m_sConfigFile);
}
vInitScreenArea();
vCreateFileOpenDialog();
vLoadHistoryFromConfig();
vLoadJoypadsFromConfig();
@ -857,6 +854,36 @@ Window::~Window()
m_poInstance = NULL;
}
void Window::vInitScreenArea()
{
Gtk::Container * poC;
bool bUseXv;
poC = dynamic_cast<Gtk::Container *>(m_poXml->get_widget("ScreenContainer"));
bUseXv = m_poDisplayConfig->oGetKey<bool>("use_Xv");
if (bUseXv)
{
try
{
m_poScreenArea = Gtk::manage(new ScreenAreaXv(m_iScreenWidth, m_iScreenHeight));
}
catch (std::exception e)
{
fprintf(stderr, "Unable to initialise Xv output, falling back to GTK+\n");
m_poScreenArea = Gtk::manage(new ScreenAreaGtk(m_iScreenWidth, m_iScreenHeight));
}
}
else
{
m_poScreenArea = Gtk::manage(new ScreenAreaGtk(m_iScreenWidth, m_iScreenHeight));
}
poC->add(*m_poScreenArea);
vDrawDefaultScreen();
m_poScreenArea->show();
}
void Window::vInitSystem()
{
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
@ -963,6 +990,7 @@ void Window::vInitConfig()
m_poDisplayConfig->vSetKey("pause_when_inactive", true );
m_poDisplayConfig->vSetKey("filter2x", FilterNone );
m_poDisplayConfig->vSetKey("filterIB", FilterIBNone );
m_poDisplayConfig->vSetKey("use_Xv", false );
// Sound section
//

View File

@ -33,7 +33,7 @@
#include "../System.h"
#include "configfile.h"
#include "screenarea-gtk.h"
#include "screenarea.h"
#include "filters.h"
#include "input.h"
#include "joypadconfig.h"
@ -232,7 +232,7 @@ private:
Gtk::FileChooserDialog * m_poFileOpenDialog;
ScreenAreaGtk * m_poScreenArea;
ScreenArea * m_poScreenArea;
Gtk::Menu * m_poRecentMenu;
Gtk::MenuItem * m_poRecentResetItem;
Gtk::CheckMenuItem * m_poFilePauseItem;
@ -281,6 +281,7 @@ private:
void vInitSystem();
void vInitConfig();
void vCheckConfig();
void vInitScreenArea();
void vLoadConfig(const std::string & _rsFile);
void vSaveConfig(const std::string & _rsFile);
void vLoadHistoryFromConfig();