mirror of https://github.com/stella-emu/stella.git
Blargg effects now work, but the scanlines aren't quite right yet.
git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2855 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
parent
a1ea1b0c96
commit
6c562f49b8
|
@ -31,9 +31,10 @@ FBSurfaceTIA::FBSurfaceTIA(FrameBufferSDL2& buffer)
|
||||||
: myFB(buffer),
|
: myFB(buffer),
|
||||||
mySurface(NULL),
|
mySurface(NULL),
|
||||||
myTexture(NULL),
|
myTexture(NULL),
|
||||||
myScanlinesEnabled(false)
|
myScanlines(NULL),
|
||||||
// myScanlineIntensityI(50),
|
myScanlinesEnabled(false),
|
||||||
// myScanlineIntensityF(0.5)
|
myScanlineIntensityI(50),
|
||||||
|
myScanlineIntensityF(0.5)
|
||||||
{
|
{
|
||||||
// Texture width is set to contain all possible sizes for a TIA image,
|
// Texture width is set to contain all possible sizes for a TIA image,
|
||||||
// including Blargg filtering
|
// including Blargg filtering
|
||||||
|
@ -52,7 +53,7 @@ FBSurfaceTIA::FBSurfaceTIA(FrameBufferSDL2& buffer)
|
||||||
|
|
||||||
myPitch = mySurface->pitch / pf.BytesPerPixel;
|
myPitch = mySurface->pitch / pf.BytesPerPixel;
|
||||||
|
|
||||||
// To generate texture
|
// To generate textures
|
||||||
reload();
|
reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,67 +144,13 @@ void FBSurfaceTIA::update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Rect tmp;
|
// Draw TIA image
|
||||||
tmp.x = tmp.y = 0;
|
SDL_UpdateTexture(myTexture, &mySrc, mySurface->pixels, mySurface->pitch);
|
||||||
tmp.w = 160; tmp.h = 210;
|
|
||||||
SDL_UpdateTexture(myTexture, NULL, mySurface->pixels, mySurface->pitch);
|
|
||||||
SDL_RenderCopy(myFB.myRenderer, myTexture, &mySrc, &myDst);
|
SDL_RenderCopy(myFB.myRenderer, myTexture, &mySrc, &myDst);
|
||||||
|
|
||||||
|
// Draw overlaying scanlines
|
||||||
#if 0
|
if(myScanlinesEnabled)
|
||||||
myGL.EnableClientState(GL_VERTEX_ARRAY);
|
SDL_RenderCopy(myFB.myRenderer, myScanlines, NULL, &myDst);
|
||||||
myGL.EnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
||||||
|
|
||||||
// Update TIA image (texture 0), then blend scanlines (texture 1)
|
|
||||||
myGL.ActiveTexture(GL_TEXTURE0);
|
|
||||||
myGL.BindTexture(GL_TEXTURE_2D, myTexID[0]);
|
|
||||||
myGL.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
|
||||||
myGL.PixelStorei(GL_UNPACK_ROW_LENGTH, myPitch);
|
|
||||||
myGL.TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, myBaseW, myBaseH,
|
|
||||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
|
||||||
mySurface->pixels);
|
|
||||||
|
|
||||||
if(myFB.myVBOAvailable)
|
|
||||||
{
|
|
||||||
myGL.BindBuffer(GL_ARRAY_BUFFER, myVBOID);
|
|
||||||
myGL.VertexPointer(2, GL_FLOAT, 0, (const GLvoid*)0);
|
|
||||||
myGL.TexCoordPointer(2, GL_FLOAT, 0, (const GLvoid*)(8*sizeof(GLfloat)));
|
|
||||||
myGL.DrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
|
||||||
|
|
||||||
if(myScanlinesEnabled)
|
|
||||||
{
|
|
||||||
myGL.Enable(GL_BLEND);
|
|
||||||
myGL.Color4f(1.0f, 1.0f, 1.0f, myScanlineIntensityF);
|
|
||||||
myGL.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
myGL.BindTexture(GL_TEXTURE_2D, myTexID[1]);
|
|
||||||
myGL.VertexPointer(2, GL_FLOAT, 0, (const GLvoid*)(16*sizeof(GLfloat)));
|
|
||||||
myGL.TexCoordPointer(2, GL_FLOAT, 0, (const GLvoid*)(24*sizeof(GLfloat)));
|
|
||||||
myGL.DrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
|
||||||
myGL.Disable(GL_BLEND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
myGL.VertexPointer(2, GL_FLOAT, 0, myCoord);
|
|
||||||
myGL.TexCoordPointer(2, GL_FLOAT, 0, myCoord+8);
|
|
||||||
myGL.DrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
|
||||||
|
|
||||||
if(myScanlinesEnabled)
|
|
||||||
{
|
|
||||||
myGL.Enable(GL_BLEND);
|
|
||||||
myGL.Color4f(1.0f, 1.0f, 1.0f, myScanlineIntensityF);
|
|
||||||
myGL.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
myGL.BindTexture(GL_TEXTURE_2D, myTexID[1]);
|
|
||||||
myGL.VertexPointer(2, GL_FLOAT, 0, myCoord+16);
|
|
||||||
myGL.TexCoordPointer(2, GL_FLOAT, 0, myCoord+24);
|
|
||||||
myGL.DrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
|
||||||
myGL.Disable(GL_BLEND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
myGL.DisableClientState(GL_VERTEX_ARRAY);
|
|
||||||
myGL.DisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Let postFrameUpdate() know that a change has been made
|
// Let postFrameUpdate() know that a change has been made
|
||||||
myFB.myDirtyFlag = true;
|
myFB.myDirtyFlag = true;
|
||||||
|
@ -223,6 +170,11 @@ void FBSurfaceTIA::free()
|
||||||
SDL_DestroyTexture(myTexture);
|
SDL_DestroyTexture(myTexture);
|
||||||
myTexture = NULL;
|
myTexture = NULL;
|
||||||
}
|
}
|
||||||
|
if(myScanlines)
|
||||||
|
{
|
||||||
|
SDL_DestroyTexture(myScanlines);
|
||||||
|
myScanlines = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -232,67 +184,21 @@ void FBSurfaceTIA::reload()
|
||||||
myTexture = SDL_CreateTexture(myFB.myRenderer,
|
myTexture = SDL_CreateTexture(myFB.myRenderer,
|
||||||
SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING,
|
SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING,
|
||||||
mySurface->w, mySurface->h);
|
mySurface->w, mySurface->h);
|
||||||
#if 0
|
|
||||||
// This does a 'soft' reset of the surface
|
|
||||||
// It seems that on some system (notably, OSX), creating a new SDL window
|
|
||||||
// destroys the GL context, requiring a reload of all textures
|
|
||||||
// However, destroying the entire FBSurfaceGL object is wasteful, since
|
|
||||||
// it will also regenerate SDL software surfaces (which are not required
|
|
||||||
// to be regenerated)
|
|
||||||
// Basically, all that needs to be done is to re-call glTexImage2D with a
|
|
||||||
// new texture ID, so that's what we do here
|
|
||||||
|
|
||||||
myGL.ActiveTexture(GL_TEXTURE0);
|
// Re-create scanline texture (contents don't change)
|
||||||
myGL.Enable(GL_TEXTURE_2D);
|
myScanlines = SDL_CreateTexture(myFB.myRenderer,
|
||||||
|
SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC,
|
||||||
// TIA surfaces also use a scanline texture
|
1, 2);
|
||||||
myGL.GenTextures(2, myTexID);
|
SDL_SetTextureBlendMode(myScanlines, SDL_BLENDMODE_BLEND);
|
||||||
|
SDL_SetTextureAlphaMod(myScanlines, myScanlineIntensityF*255);
|
||||||
// Base texture (@ index 0)
|
SDL_UpdateTexture(myScanlines, NULL, ourScanData, 1);
|
||||||
myGL.BindTexture(GL_TEXTURE_2D, myTexID[0]);
|
|
||||||
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myTexFilter[0]);
|
|
||||||
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myTexFilter[0]);
|
|
||||||
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
|
|
||||||
// Create the texture in the most optimal format
|
|
||||||
myGL.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
|
||||||
myGL.PixelStorei(GL_UNPACK_ROW_LENGTH, myPitch);
|
|
||||||
myGL.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, myTexWidth, myTexHeight, 0,
|
|
||||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
|
||||||
mySurface->pixels);
|
|
||||||
|
|
||||||
// Scanline texture (@ index 1)
|
|
||||||
myGL.BindTexture(GL_TEXTURE_2D, myTexID[1]);
|
|
||||||
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myTexFilter[1]);
|
|
||||||
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myTexFilter[1]);
|
|
||||||
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
||||||
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
||||||
|
|
||||||
static uInt32 const scanline[2] = { 0x00000000, 0xff000000 };
|
|
||||||
myGL.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
|
||||||
myGL.PixelStorei(GL_UNPACK_ROW_LENGTH, 1);
|
|
||||||
myGL.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 2, 0,
|
|
||||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
|
||||||
scanline);
|
|
||||||
|
|
||||||
// Cache vertex and texture coordinates using vertex buffer object
|
|
||||||
if(myFB.myVBOAvailable)
|
|
||||||
{
|
|
||||||
myGL.GenBuffers(1, &myVBOID);
|
|
||||||
myGL.BindBuffer(GL_ARRAY_BUFFER, myVBOID);
|
|
||||||
myGL.BufferData(GL_ARRAY_BUFFER, 32*sizeof(GLfloat), myCoord, GL_STATIC_DRAW);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FBSurfaceTIA::setScanIntensity(uInt32 intensity)
|
void FBSurfaceTIA::setScanIntensity(uInt32 intensity)
|
||||||
{
|
{
|
||||||
#if 0
|
myScanlineIntensityI = intensity;
|
||||||
myScanlineIntensityI = (GLuint)intensity;
|
myScanlineIntensityF = intensity / 100.0;
|
||||||
myScanlineIntensityF = (GLfloat)intensity / 100;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -325,29 +231,19 @@ void FBSurfaceTIA::setScanInterpolation(bool enable)
|
||||||
void FBSurfaceTIA::updateCoords(uInt32 baseH,
|
void FBSurfaceTIA::updateCoords(uInt32 baseH,
|
||||||
uInt32 imgX, uInt32 imgY, uInt32 imgW, uInt32 imgH)
|
uInt32 imgX, uInt32 imgY, uInt32 imgW, uInt32 imgH)
|
||||||
{
|
{
|
||||||
//cerr << "baseH=" << baseH << ", x=" << imgX << ", y=" << imgY << ", w=" << imgW << ", h=" << imgH << endl;
|
|
||||||
|
|
||||||
mySrc.w = myFB.ntscEnabled() ? ATARI_NTSC_OUT_WIDTH(160) : 160;
|
|
||||||
mySrc.h = baseH;
|
mySrc.h = baseH;
|
||||||
|
|
||||||
myDst.w = imgW;
|
myDst.w = imgW;
|
||||||
myDst.h = imgH;
|
myDst.h = imgH;
|
||||||
|
|
||||||
//cerr << "src: x=" << mySrc.x << ", y=" << mySrc.y << ", w=" << mySrc.w << ", h=" << mySrc.h << endl;
|
|
||||||
//cerr << "dst: x=" << myDst.x << ", y=" << myDst.y << ", w=" << myDst.w << ", h=" << myDst.h << endl;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
myBaseH = baseH;
|
|
||||||
myImageX = imgX; myImageY = imgY;
|
|
||||||
myImageW = imgW; myImageH = imgH;
|
|
||||||
|
|
||||||
updateCoords();
|
updateCoords();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FBSurfaceTIA::updateCoords()
|
void FBSurfaceTIA::updateCoords()
|
||||||
{
|
{
|
||||||
|
// For a TIA surface, only the width can possibly change
|
||||||
|
mySrc.w = myFB.ntscEnabled() ? ATARI_NTSC_OUT_WIDTH(160) : 160;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// Normal TIA rendering and TV effects use different widths
|
// Normal TIA rendering and TV effects use different widths
|
||||||
// We use the same buffer, and only pick the width we need
|
// We use the same buffer, and only pick the width we need
|
||||||
|
@ -430,3 +326,6 @@ void FBSurfaceTIA::setTIAPalette(const uInt32* palette)
|
||||||
{
|
{
|
||||||
myFB.myNTSCFilter.setTIAPalette(myFB, palette);
|
myFB.myNTSCFilter.setTIAPalette(myFB, palette);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
uInt32 const FBSurfaceTIA::ourScanData[2] = { 0x00000000, 0xff000000 };
|
||||||
|
|
|
@ -67,10 +67,15 @@ class FBSurfaceTIA : public FBSurface
|
||||||
|
|
||||||
SDL_Surface* mySurface;
|
SDL_Surface* mySurface;
|
||||||
SDL_Texture* myTexture;
|
SDL_Texture* myTexture;
|
||||||
|
SDL_Texture* myScanlines;
|
||||||
SDL_Rect mySrc, myDst;
|
SDL_Rect mySrc, myDst;
|
||||||
uInt32 myPitch;
|
uInt32 myPitch;
|
||||||
|
|
||||||
bool myScanlinesEnabled;
|
bool myScanlinesEnabled;
|
||||||
|
uInt32 myScanlineIntensityI;
|
||||||
|
float myScanlineIntensityF;
|
||||||
|
|
||||||
|
static uInt32 const ourScanData[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -69,8 +69,16 @@ FrameBufferSDL2::FrameBufferSDL2(OSystem* osystem)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
FrameBufferSDL2::~FrameBufferSDL2()
|
FrameBufferSDL2::~FrameBufferSDL2()
|
||||||
{
|
{
|
||||||
// if(myWindow)
|
if(myRenderer)
|
||||||
// SDL_DestroyWindow(myWindow);
|
{
|
||||||
|
SDL_DestroyRenderer(myRenderer);
|
||||||
|
myRenderer = NULL;
|
||||||
|
}
|
||||||
|
if(myWindow)
|
||||||
|
{
|
||||||
|
SDL_DestroyWindow(myWindow);
|
||||||
|
myWindow = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// We're taking responsibility for this surface
|
// We're taking responsibility for this surface
|
||||||
delete myTiaSurface;
|
delete myTiaSurface;
|
||||||
|
@ -469,7 +477,7 @@ void FrameBufferSDL2::enableNTSC(bool enable)
|
||||||
if(myTiaSurface)
|
if(myTiaSurface)
|
||||||
{
|
{
|
||||||
myFilterType = FilterType(enable ? myFilterType | 0x10 : myFilterType & 0x01);
|
myFilterType = FilterType(enable ? myFilterType | 0x10 : myFilterType & 0x01);
|
||||||
//FIXSDL myTiaSurface->updateCoords();
|
myTiaSurface->updateCoords();
|
||||||
|
|
||||||
myTiaSurface->enableScanlines(ntscEnabled());
|
myTiaSurface->enableScanlines(ntscEnabled());
|
||||||
myTiaSurface->setScanIntensity(myOSystem->settings().getInt("tv_scanlines"));
|
myTiaSurface->setScanIntensity(myOSystem->settings().getInt("tv_scanlines"));
|
||||||
|
@ -483,7 +491,6 @@ void FrameBufferSDL2::enableNTSC(bool enable)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
uInt32 FrameBufferSDL2::enableScanlines(int relative, int absolute)
|
uInt32 FrameBufferSDL2::enableScanlines(int relative, int absolute)
|
||||||
{
|
{
|
||||||
#if 0//FIXSDL
|
|
||||||
int intensity = myTiaSurface->myScanlineIntensityI;
|
int intensity = myTiaSurface->myScanlineIntensityI;
|
||||||
if(myTiaSurface)
|
if(myTiaSurface)
|
||||||
{
|
{
|
||||||
|
@ -496,8 +503,6 @@ uInt32 FrameBufferSDL2::enableScanlines(int relative, int absolute)
|
||||||
myRedrawEntireFrame = true;
|
myRedrawEntireFrame = true;
|
||||||
}
|
}
|
||||||
return intensity;
|
return intensity;
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -529,7 +534,7 @@ FBSurface* FrameBufferSDL2::createSurface(int w, int h, bool isBase) const
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameBufferSDL2::scanline(uInt32 row, uInt8* data) const
|
void FrameBufferSDL2::scanline(uInt32 row, uInt8* data) const
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0 //FIXSDL
|
||||||
// Invert the row, since OpenGL rows start at the bottom
|
// Invert the row, since OpenGL rows start at the bottom
|
||||||
// of the framebuffer
|
// of the framebuffer
|
||||||
const GUI::Rect& image = imageRect();
|
const GUI::Rect& image = imageRect();
|
||||||
|
@ -554,16 +559,16 @@ string FrameBufferSDL2::effectsInfo() const
|
||||||
break;
|
break;
|
||||||
case kBlarggNormal:
|
case kBlarggNormal:
|
||||||
buf << myNTSCFilter.getPreset() << ", scanlines="
|
buf << myNTSCFilter.getPreset() << ", scanlines="
|
||||||
#if 0
|
|
||||||
<< myTiaSurface->myScanlineIntensityI << "/"
|
<< myTiaSurface->myScanlineIntensityI << "/"
|
||||||
|
#if 0
|
||||||
<< (myTiaSurface->myTexFilter[1] == GL_LINEAR ? "inter" : "nointer");
|
<< (myTiaSurface->myTexFilter[1] == GL_LINEAR ? "inter" : "nointer");
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
break;
|
break;
|
||||||
case kBlarggPhosphor:
|
case kBlarggPhosphor:
|
||||||
buf << myNTSCFilter.getPreset() << ", phosphor, scanlines="
|
buf << myNTSCFilter.getPreset() << ", phosphor, scanlines="
|
||||||
#if 0
|
|
||||||
<< myTiaSurface->myScanlineIntensityI << "/"
|
<< myTiaSurface->myScanlineIntensityI << "/"
|
||||||
|
#if 0
|
||||||
<< (myTiaSurface->myTexFilter[1] == GL_LINEAR ? "inter" : "nointer");
|
<< (myTiaSurface->myTexFilter[1] == GL_LINEAR ? "inter" : "nointer");
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
|
|
Loading…
Reference in New Issue