Move the scaling, streaming and blending options directly into FBSurfaceSDL2,

making this class more robust, and enabling it to be used for either UI
surfaces or TIA surfaces.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2884 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2014-05-04 20:21:16 +00:00
parent b418d5a4f5
commit 68df6fe891
7 changed files with 97 additions and 15 deletions

View File

@ -25,7 +25,12 @@ FBSurfaceSDL2::FBSurfaceSDL2(FrameBufferSDL2& buffer, uInt32 width, uInt32 heigh
myFB(buffer),
mySurface(NULL),
myTexture(NULL),
mySurfaceIsDirty(true)
mySurfaceIsDirty(true),
myDataIsStatic(false),
myInterpolate(false),
myBlendEnabled(false),
myBlendAlpha(255),
myStaticData(NULL)
{
// Create a surface in the same format as the parent GL class
const SDL_PixelFormat* pf = myFB.myPixelFormat;
@ -56,6 +61,12 @@ FBSurfaceSDL2::~FBSurfaceSDL2()
SDL_FreeSurface(mySurface);
free();
if(myStaticData)
{
delete[] myStaticData;
myStaticData = NULL;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -92,8 +103,31 @@ void FBSurfaceSDL2::addDirtyRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceSDL2::basePtr(uInt32*& pixels, uInt32& pitch)
void FBSurfaceSDL2::setStaticContents(const uInt32* pixels, uInt32 pitch)
{
myDataIsStatic = true;
myStaticPitch = pitch * 4; // we need pitch in 'bytes'
if(!myStaticData)
myStaticData = new uInt32[mySurface->w * mySurface->h];
SDL_memcpy(myStaticData, pixels, mySurface->w * mySurface->h);
// Re-create the texture with the new settings
free();
reload();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceSDL2::setInterpolationAndBlending(
bool smoothScale, bool useBlend, uInt32 blendAlpha)
{
myInterpolate = smoothScale;
myBlendEnabled = useBlend;
myBlendAlpha = blendAlpha * 2.55;
// Re-create the texture with the new settings
free();
reload();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -147,7 +181,8 @@ void FBSurfaceSDL2::render()
//cerr << "src: x=" << mySrcR.x << ", y=" << mySrcR.y << ", w=" << mySrcR.w << ", h=" << mySrcR.h << endl;
//cerr << "dst: x=" << myDstR.x << ", y=" << myDstR.y << ", w=" << myDstR.w << ", h=" << myDstR.h << endl;
SDL_UpdateTexture(myTexture, &mySrcR, mySurface->pixels, mySurface->pitch);
if(!myDataIsStatic)
SDL_UpdateTexture(myTexture, &mySrcR, mySurface->pixels, mySurface->pitch);
SDL_RenderCopy(myFB.myRenderer, myTexture, &mySrcR, &myDstR);
mySurfaceIsDirty = false;
@ -177,7 +212,19 @@ void FBSurfaceSDL2::free()
void FBSurfaceSDL2::reload()
{
// Re-create texture; the underlying SDL_Surface is fine as-is
myTexture = SDL_CreateTexture(myFB.myRenderer,
SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING,
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, myInterpolate ? "1" : "0");
myTexture = SDL_CreateTexture(myFB.myRenderer, myFB.myPixelFormat->format,
myDataIsStatic ? SDL_TEXTUREACCESS_STATIC : SDL_TEXTUREACCESS_STREAMING,
mySurface->w, mySurface->h);
// If the data is static, we only upload it once
if(myDataIsStatic)
SDL_UpdateTexture(myTexture, NULL, myStaticData, myStaticPitch);
// Blending enabled?
if(myBlendEnabled)
{
SDL_SetTextureBlendMode(myTexture, SDL_BLENDMODE_BLEND);
SDL_SetTextureAlphaMod(myTexture, myBlendAlpha);
}
}

View File

@ -33,6 +33,7 @@ class FBSurfaceSDL2 : public FBSurface
{
public:
FBSurfaceSDL2(FrameBufferSDL2& buffer, uInt32 width, uInt32 height);
virtual ~FBSurfaceSDL2();
// Most of the surface drawing primitives are implemented in FBSurface;
@ -42,7 +43,9 @@ class FBSurfaceSDL2 : public FBSurface
void drawSurface(const FBSurface* surface, uInt32 x, uInt32 y);
void addDirtyRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h);
void basePtr(uInt32*& pixels, uInt32& pitch);
void setStaticContents(const uInt32* pixels, uInt32 pitch);
void setInterpolationAndBlending(bool smoothScale, bool useBlend,
uInt32 blendAlpha);
GUI::Rect srcRect();
GUI::Rect dstRect();
@ -65,6 +68,14 @@ class FBSurfaceSDL2 : public FBSurface
SDL_Rect mySrcR, myDstR;
bool mySurfaceIsDirty;
bool myDataIsStatic; // Is pixel data constant or can it change?
bool myInterpolate; // Scaling is smoothed or blocky
bool myBlendEnabled; // Blending is enabled
uInt8 myBlendAlpha; // Alpha to use in blending mode
uInt32* myStaticData; // The data to use when the buffer contents are static
uInt32 myStaticPitch; // The number of bytes in a row of static data
};
#endif

View File

@ -48,7 +48,9 @@ class FBSurfaceTIA : public FBSurface
void free();
void reload();
void basePtr(uInt32*& pixels, uInt32& pitch) { }
void setStaticContents(const uInt32* pixels, uInt32 pitch) { }
void setInterpolationAndBlending(bool smoothScale, bool useBlend,
uInt32 blendAlpha) { }
GUI::Rect srcRect() { return GUI::Rect(); }
GUI::Rect dstRect() { return GUI::Rect(); }

View File

@ -336,7 +336,7 @@ void FrameBufferSDL2::setTIAPalette(const uInt32* palette)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FBSurface* FrameBufferSDL2::createSurface(int w, int h) const
FBSurface* FrameBufferSDL2::createSurface(uInt32 w, uInt32 h) const
{
return new FBSurfaceSDL2((FrameBufferSDL2&)*this, w, h);
}

View File

@ -165,13 +165,12 @@ class FrameBufferSDL2 : public FrameBuffer
void invalidate();
/**
This method is called to create a surface compatible with the one
currently in use, but having the given dimensions.
This method is called to create a surface with the given attributes.
@param w The requested width of the new surface.
@param h The requested height of the new surface.
*/
FBSurface* createSurface(int w, int h) const;
FBSurface* createSurface(uInt32 w, uInt32 h) const;
/**
Grabs or ungrabs the mouse based on the given boolean value.

View File

@ -219,7 +219,7 @@ class FBSurface
// implemented in child classes.
//
// For the following, 'src' indicates the actual data buffer area
// (non-scaled) and 'dst' indicates the rendered area (possibly scaled).
// (non-scaled) and 'dst' indicates the rendered area (possibly scaled).
//////////////////////////////////////////////////////////////////////////
/**
@ -238,6 +238,30 @@ class FBSurface
virtual void setDstPos(uInt32 x, uInt32 y) = 0;
virtual void setDstSize(uInt32 w, uInt32 h) = 0;
/**
This method should be called to indicate that the surface contains
static data that will never change. Some rendering toolkits can
use this information to optimize how the data is rendered.
Note that once this method is called, all other drawing primitives
will not work.
@param pixels The static data to use
@param pitch The number of pixels in a row
*/
virtual void setStaticContents(const uInt32* pixels, uInt32 pitch) = 0;
/**
This method should be called to modify the interpolation and
blending effects to be applied to this surface.
@param smoothScale Whether to use interpolation during scaling
@param useBlend Whether the surface should use alpha blending
@param blendAlpha The alpha to use during blending (if used)
*/
virtual void setInterpolationAndBlending(bool smoothScale,
bool useBlend, uInt32 blendAlpha) = 0;
/**
This method should be called to translate the given coordinates
to the (destination) surface coordinates.

View File

@ -437,13 +437,12 @@ class FrameBuffer
virtual void invalidate() = 0;
/**
This method is called to create a surface compatible with the one
currently in use, but having the given dimensions.
This method is called to create a surface with the given attributes.
@param w The requested width of the new surface.
@param h The requested height of the new surface.
*/
virtual FBSurface* createSurface(int w, int h) const = 0;
virtual FBSurface* createSurface(uInt32 w, uInt32 h) const = 0;
/**
Change scanline intensity and interpolation.