Added video special scaler functionality to Qt GUI.

This commit is contained in:
Matthew Budd 2020-11-11 20:14:00 -05:00
parent 0b5c73bd23
commit 4c94acf68a
7 changed files with 241 additions and 68 deletions

View File

@ -39,6 +39,29 @@ ConsoleVideoConfDialog_t::ConsoleVideoConfDialog_t(QWidget *parent)
main_vbox->addLayout( hbox1 );
// Video Driver Select
lbl = new QLabel( tr("Scaler:") );
scalerSelect = new QComboBox();
scalerSelect->addItem( tr("None"), 0 );
scalerSelect->addItem( tr("hq2x"), 1 );
scalerSelect->addItem( tr("scale2x"), 2 );
scalerSelect->addItem( tr("NTSC 2x"), 3 );
scalerSelect->addItem( tr("hq3x"), 4 );
scalerSelect->addItem( tr("scale3x"), 5 );
scalerSelect->addItem( tr("Prescale 2x"), 6 );
scalerSelect->addItem( tr("Prescale 3x"), 7 );
scalerSelect->addItem( tr("Prescale 4x"), 8 );
scalerSelect->addItem( tr("PAL"), 9 );
hbox1 = new QHBoxLayout();
hbox1->addWidget( lbl );
hbox1->addWidget( scalerSelect );
main_vbox->addLayout( hbox1 );
// Enable OpenGL Linear Filter Checkbox
gl_LF_chkBox = new QCheckBox( tr("Enable OpenGL Linear Filter") );
@ -59,9 +82,11 @@ ConsoleVideoConfDialog_t::ConsoleVideoConfDialog_t(QWidget *parent)
setComboBoxFromProperty( regionSelect, "SDL.PAL");
setComboBoxFromProperty( driverSelect, "SDL.VideoDriver");
setComboBoxFromProperty( scalerSelect, "SDL.SpecialFilter");
connect(regionSelect, SIGNAL(currentIndexChanged(int)), this, SLOT(regionChanged(int)) );
connect(driverSelect, SIGNAL(currentIndexChanged(int)), this, SLOT(driverChanged(int)) );
connect(scalerSelect, SIGNAL(currentIndexChanged(int)), this, SLOT(scalerChanged(int)) );
hbox1 = new QHBoxLayout();
@ -214,8 +239,10 @@ void ConsoleVideoConfDialog_t::closeWindow(void)
//----------------------------------------------------
void ConsoleVideoConfDialog_t::resetVideo(void)
{
fceuWrapperLock();
KillVideo ();
InitVideo (GameInfo);
fceuWrapperUnLock();
}
//----------------------------------------------------
void ConsoleVideoConfDialog_t::setCheckBoxFromProperty( QCheckBox *cbx, const char *property )
@ -348,6 +375,18 @@ void ConsoleVideoConfDialog_t::driverChanged(int index)
printf("Note: A restart of the application is needed for video driver change to take effect...\n");
}
//----------------------------------------------------
void ConsoleVideoConfDialog_t::scalerChanged(int index)
{
int scaler;
//printf("Scaler: %i : %i \n", index, scalerSelect->itemData(index).toInt() );
scaler = scalerSelect->itemData(index).toInt();
g_config->setOption ("SDL.SpecialFilter", scaler);
g_config->save ();
}
//----------------------------------------------------
void ConsoleVideoConfDialog_t::regionChanged(int index)
{
int region;
@ -373,8 +412,8 @@ QSize ConsoleVideoConfDialog_t::calcNewScreenSize(void)
{
QSize w, v;
double xscale, yscale;
int texture_width = nes_shm->ncol;
int texture_height = nes_shm->nrow;
int texture_width = nes_shm->video.ncol;
int texture_height = nes_shm->video.nrow;
int l=0, r=texture_width;
int t=0, b=texture_height;
int dw=0, dh=0, rw, rh;
@ -395,7 +434,9 @@ QSize ConsoleVideoConfDialog_t::calcNewScreenSize(void)
if ( sqrPixCbx->isChecked() )
{
yscale = xscale = xScaleBox->value();
xscale = xScaleBox->value();
yscale = xscale * (double)nes_shm->video.xyRatio;
}
else
{

View File

@ -29,6 +29,7 @@ class ConsoleVideoConfDialog_t : public QDialog
void closeEvent(QCloseEvent *bar);
QComboBox *driverSelect;
QComboBox *scalerSelect;
QComboBox *regionSelect;
QCheckBox *gl_LF_chkBox;
QCheckBox *new_PPU_ena;
@ -63,6 +64,7 @@ class ConsoleVideoConfDialog_t : public QDialog
void showFPSChanged( int value );
void regionChanged(int index);
void driverChanged(int index);
void scalerChanged(int index);
void applyChanges( void );
};

View File

@ -38,7 +38,7 @@ ConsoleViewGL_t::ConsoleViewGL_t(QWidget *parent)
devPixRatio = screen->devicePixelRatio();
//printf("Ratio: %f \n", screen->devicePixelRatio() );
}
localBufSize = GL_NES_WIDTH * GL_NES_HEIGHT * sizeof(uint32_t);
localBufSize = (4 * GL_NES_WIDTH) * (4 * GL_NES_HEIGHT) * sizeof(uint32_t);
localBuf = (uint32_t*)malloc( localBufSize );
@ -87,6 +87,7 @@ int ConsoleViewGL_t::init( void )
void ConsoleViewGL_t::buildTextures(void)
{
int w, h;
glEnable(GL_TEXTURE_RECTANGLE);
if ( gltexture )
@ -105,8 +106,11 @@ void ConsoleViewGL_t::buildTextures(void)
glTexParameteri( GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
w = nes_shm->video.ncol;
h = nes_shm->video.nrow;
glTexImage2D( GL_TEXTURE_RECTANGLE, 0,
GL_RGBA8, GL_NES_WIDTH, GL_NES_HEIGHT, 0,
GL_RGBA8, w, h, 0,
GL_BGRA, GL_UNSIGNED_BYTE, 0 );
}
@ -152,46 +156,78 @@ void ConsoleViewGL_t::setLinearFilterEnable( bool ena )
void ConsoleViewGL_t::setScaleXY( double xs, double ys )
{
float xyRatio = (float)nes_shm->video.xyRatio;
xscale = xs;
yscale = ys;
if ( sqrPixels )
{
if (xscale < yscale )
if ( (xscale*xyRatio) < yscale )
{
yscale = xscale;
yscale = (xscale*xyRatio);
}
else
{
xscale = yscale;
xscale = (yscale/xyRatio);
}
}
}
void ConsoleViewGL_t::transfer2LocalBuffer(void)
{
memcpy( localBuf, nes_shm->pixbuf, localBufSize );
int i=0, hq = 0;
int numPixels = nes_shm->video.ncol * nes_shm->video.nrow;
int cpSize = numPixels * 4;
uint8_t *src, *dest;
if ( cpSize > localBufSize )
{
cpSize = localBufSize;
}
src = (uint8_t*)nes_shm->pixbuf;
dest = (uint8_t*)localBuf;
hq = (nes_shm->video.preScaler == 1) || (nes_shm->video.preScaler == 4); // hq2x and hq3x
if ( hq )
{
for (i=0; i<numPixels; i++)
{
dest[3] = 0xFF;
dest[1] = src[1];
dest[2] = src[2];
dest[0] = src[0];
src += 4; dest += 4;
}
}
else
{
memcpy( localBuf, nes_shm->pixbuf, cpSize );
}
}
void ConsoleViewGL_t::paintGL(void)
{
int texture_width = nes_shm->ncol;
int texture_height = nes_shm->nrow;
int texture_width = nes_shm->video.ncol;
int texture_height = nes_shm->video.nrow;
int l=0, r=texture_width;
int t=0, b=texture_height;
float xscaleTmp = (float)view_width / (float)texture_width;
float yscaleTmp = (float)view_height / (float)texture_height;
float xyRatio = (float)nes_shm->video.xyRatio;
float xscaleTmp = (float)(view_width) / (float)(texture_width);
float yscaleTmp = (float)(view_height) / (float)(texture_height);
if ( sqrPixels )
{
if (xscaleTmp < yscaleTmp )
if ( (xscaleTmp*xyRatio) < yscaleTmp )
{
yscaleTmp = xscaleTmp;
yscaleTmp = (xscaleTmp*xyRatio);
}
else
{
xscaleTmp = yscaleTmp;
xscaleTmp = (yscaleTmp/xyRatio);
}
}
@ -232,7 +268,7 @@ void ConsoleViewGL_t::paintGL(void)
glBindTexture(GL_TEXTURE_RECTANGLE, gltexture);
glTexSubImage2D(GL_TEXTURE_RECTANGLE, 0,
0, 0, GL_NES_WIDTH, GL_NES_HEIGHT,
0, 0, texture_width, texture_height,
GL_BGRA, GL_UNSIGNED_BYTE, localBuf );
glBegin(GL_QUADS);

View File

@ -43,7 +43,7 @@ ConsoleViewSDL_t::ConsoleViewSDL_t(QWidget *parent)
vsyncEnabled = false;
localBufSize = GL_NES_WIDTH * GL_NES_HEIGHT * sizeof(uint32_t);
localBufSize = (4 * GL_NES_WIDTH) * (4 * GL_NES_HEIGHT) * sizeof(uint32_t);
localBuf = (uint32_t*)malloc( localBufSize );
@ -85,25 +85,56 @@ void ConsoleViewSDL_t::setLinearFilterEnable( bool ena )
void ConsoleViewSDL_t::setScaleXY( double xs, double ys )
{
float xyRatio = (float)nes_shm->video.xyRatio;
xscale = xs;
yscale = ys;
if ( sqrPixels )
{
if (xscale < yscale )
if ( (xscale*xyRatio) < yscale )
{
yscale = xscale;
yscale = (xscale*xyRatio);
}
else
{
xscale = yscale;
xscale = (yscale/xyRatio);
}
}
}
void ConsoleViewSDL_t::transfer2LocalBuffer(void)
{
memcpy( localBuf, nes_shm->pixbuf, localBufSize );
int i=0, hq = 0;
int numPixels = nes_shm->video.ncol * nes_shm->video.nrow;
int cpSize = numPixels * 4;
uint8_t *src, *dest;
if ( cpSize > localBufSize )
{
cpSize = localBufSize;
}
src = (uint8_t*)nes_shm->pixbuf;
dest = (uint8_t*)localBuf;
hq = (nes_shm->video.preScaler == 1) || (nes_shm->video.preScaler == 4); // hq2x and hq3x
if ( hq )
{
for (i=0; i<numPixels; i++)
{
dest[3] = 0xFF;
dest[1] = src[1];
dest[2] = src[2];
dest[0] = src[0];
src += 4; dest += 4;
}
}
else
{
memcpy( localBuf, nes_shm->pixbuf, cpSize );
}
}
int ConsoleViewSDL_t::init(void)
@ -171,11 +202,11 @@ int ConsoleViewSDL_t::init(void)
printf("[SDL] Renderer Output Size: %i x %i \n", sdlRendW, sdlRendH );
sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, GL_NES_WIDTH, GL_NES_HEIGHT);
sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, nes_shm->video.ncol, nes_shm->video.nrow);
if (sdlTexture == NULL)
{
printf("[SDL] Failed to create texture: %i x %i", GL_NES_WIDTH, GL_NES_HEIGHT );
printf("[SDL] Failed to create texture: %i x %i", nes_shm->video.ncol, nes_shm->video.nrow );
return -1;
}
@ -201,7 +232,7 @@ void ConsoleViewSDL_t::reset(void)
cleanup();
if ( init() == 0 )
{
//console->GetVideoRenderer()->RegisterRenderingDevice(this);
}
else
{
@ -219,23 +250,19 @@ void ConsoleViewSDL_t::resizeEvent(QResizeEvent *event)
printf("SDL Resize: %i x %i \n", view_width, view_height);
reset();
//sdlViewport.x = sdlRendW - view_width;
//sdlViewport.y = sdlRendH - view_height;
//sdlViewport.w = view_width;
//sdlViewport.h = view_height;
}
//void ConsoleViewSDL_t::paintEvent( QPaintEvent *event )
void ConsoleViewSDL_t::render(void)
{
int nesWidth = GL_NES_WIDTH;
int nesHeight = GL_NES_HEIGHT;
float xyRatio = 1.0;
if ( nes_shm != NULL )
{
nesWidth = nes_shm->ncol;
nesHeight = nes_shm->nrow;
nesWidth = nes_shm->video.ncol;
nesHeight = nes_shm->video.nrow;
xyRatio = (float)nes_shm->video.xyRatio;
}
//printf(" %i x %i \n", nesWidth, nesHeight );
float xscaleTmp = (float)view_width / (float)nesWidth;
@ -243,13 +270,13 @@ void ConsoleViewSDL_t::render(void)
if ( sqrPixels )
{
if (xscaleTmp < yscaleTmp )
if ( (xscaleTmp*xyRatio) < yscaleTmp )
{
yscaleTmp = xscaleTmp;
yscaleTmp = (xscaleTmp*xyRatio);
}
else
{
xscaleTmp = yscaleTmp;
xscaleTmp = (yscaleTmp/xyRatio);
}
}
@ -288,12 +315,10 @@ void ConsoleViewSDL_t::render(void)
int rowPitch;
SDL_LockTexture( sdlTexture, nullptr, (void**)&textureBuffer, &rowPitch);
{
memcpy( textureBuffer, localBuf, GL_NES_HEIGHT*GL_NES_WIDTH*sizeof(uint32_t) );
memcpy( textureBuffer, localBuf, nesWidth*nesHeight*sizeof(uint32_t) );
}
SDL_UnlockTexture(sdlTexture);
//SDL_RenderSetViewport( sdlRenderer, &sdlViewport );
SDL_Rect source = {0, 0, nesWidth, nesHeight };
SDL_Rect dest = { sx, sy, rw, rh };
SDL_RenderCopy(sdlRenderer, sdlTexture, &source, &dest);

View File

@ -45,9 +45,12 @@ nes_shm_t *open_nes_shm(void)
//sem_init( &vaddr->sem, 1, 1 );
vaddr->ncol = 256;
vaddr->nrow = 256;
vaddr->pitch = 256 * 4;
vaddr->video.ncol = 256;
vaddr->video.nrow = 256;
vaddr->video.pitch = 256 * 4;
vaddr->video.scale = 1;
vaddr->video.xyRatio = 1;
vaddr->video.preScaler = 0;
return vaddr;
}

View File

@ -20,9 +20,15 @@ struct nes_shm_t
uint32_t render_count;
uint32_t blit_count;
struct
{
int ncol;
int nrow;
int pitch;
int scale;
int xyRatio;
int preScaler;
} video;
char runEmulator;
char blitUpdated;
@ -57,7 +63,7 @@ struct nes_shm_t
} cmd[64];
} guiEvent;
uint32_t pixbuf[65536]; // 256 x 256
uint32_t pixbuf[1048576]; // 1024 x 1024
void clear_pixbuf(void)
{

View File

@ -96,18 +96,19 @@ KillVideo()
nes_shm->clear_pixbuf();
}
//destroy_gui_video();
// if the rest of the system has been initialized, shut it down
// shut down the system that converts from 8 to 16/32 bpp
if (initBlitToHighDone)
{
KillBlitToHigh();
initBlitToHighDone = 0;
}
// return failure if the video system was not initialized
if (s_inited == 0)
return -1;
// if the rest of the system has been initialized, shut it down
// // shut down the system that converts from 8 to 16/32 bpp
// if (s_curbpp > 8)
// {
// KillBlitToHigh();
// }
// SDL Video system is not used.
// shut down the SDL video sub-system
@ -154,7 +155,7 @@ int InitVideo(FCEUGI *gi)
//#ifdef OPENGL
// g_config->getOption("SDL.OpenGL", &s_useOpenGL);
//#endif
//g_config->getOption("SDL.SpecialFilter", &s_sponge);
g_config->getOption("SDL.SpecialFilter", &s_sponge);
g_config->getOption("SDL.XStretch", &xstretch);
g_config->getOption("SDL.YStretch", &ystretch);
//g_config->getOption("SDL.LastXRes", &xres);
@ -166,7 +167,6 @@ int InitVideo(FCEUGI *gi)
//g_config->getOption("SDL.YScale", &s_eys);
uint32_t rmask, gmask, bmask;
s_sponge = 0;
s_exs = 1.0;
s_eys = 1.0;
xres = gui_draw_area_width;
@ -176,16 +176,57 @@ int InitVideo(FCEUGI *gi)
FCEUI_GetCurrentVidSystem(&s_srendline, &s_erendline);
s_tlines = s_erendline - s_srendline + 1;
//init_gui_video( s_useOpenGL );
nes_shm->video.preScaler = s_sponge;
switch ( s_sponge )
{
case 0: // None
nes_shm->video.scale = 1;
break;
case 1: // hq2x
case 2: // Scale2x
case 3: // NTSC 2x
case 6: // Prescale2x
nes_shm->video.scale = 2;
break;
case 4: // hq3x
case 5: // Scale3x
case 7: // Prescale3x
nes_shm->video.scale = 3;
break;
case 8: // Prescale4x
nes_shm->video.scale = 4;
break;
case 9: // PAL
nes_shm->video.scale = 3;
break;
}
s_inited = 1;
// check to see if we are showing FPS
FCEUI_SetShowFPS(show_fps);
nes_shm->ncol = NWIDTH;
nes_shm->nrow = s_tlines;
nes_shm->pitch = GL_NES_WIDTH * 4;
int iScale = nes_shm->video.scale;
if ( s_sponge == 3 )
{
nes_shm->video.ncol = iScale*301;
}
else
{
nes_shm->video.ncol = iScale*NWIDTH;
}
if ( s_sponge == 9 )
{
nes_shm->video.nrow = 1*s_tlines;
nes_shm->video.xyRatio = 3;
}
else
{
nes_shm->video.nrow = iScale*s_tlines;
nes_shm->video.xyRatio = 1;
}
nes_shm->video.pitch = nes_shm->video.ncol * 4;
#ifdef LSB_FIRST
rmask = 0x00FF0000;
@ -221,6 +262,8 @@ int InitVideo(FCEUGI *gi)
initBlitToHighDone = 1;
}
s_paletterefresh = 1;
return 0;
}
@ -329,7 +372,7 @@ void
BlitScreen(uint8 *XBuf)
{
uint8 *dest;
int w, h, pitch;
int w, h, pitch, iScale;
// refresh the palette if required
if (s_paletterefresh)
@ -342,13 +385,30 @@ BlitScreen(uint8 *XBuf)
XBuf += s_srendline * 256;
dest = (uint8*)nes_shm->pixbuf;
w = GL_NES_WIDTH;
h = GL_NES_HEIGHT;
iScale = nes_shm->video.scale;
if ( s_sponge == 3 )
{
w = iScale*301;
}
else
{
w = iScale*NWIDTH;
}
if ( s_sponge == 9 )
{
h = 1*s_tlines;
}
else
{
h = iScale*s_tlines;
}
pitch = w*4;
nes_shm->ncol = NWIDTH;
nes_shm->nrow = s_tlines;
nes_shm->pitch = pitch;
nes_shm->video.ncol = w;
nes_shm->video.nrow = h;
nes_shm->video.pitch = pitch;
nes_shm->video.preScaler = s_sponge;
if ( dest == NULL ) return;
@ -358,7 +418,7 @@ BlitScreen(uint8 *XBuf)
}
else
{
Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines, pitch, 1, 1);
Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines, pitch, iScale, iScale);
}
nes_shm->blitUpdated = 1;