mirror of https://github.com/stella-emu/stella.git
Add HQ blitter.
This commit is contained in:
parent
62af272020
commit
f6eb86b9bb
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include "ThreadDebugging.hxx"
|
#include "ThreadDebugging.hxx"
|
||||||
#include "sdl_blitter/BilinearBlitter.hxx"
|
#include "sdl_blitter/BilinearBlitter.hxx"
|
||||||
|
#include "sdl_blitter/HqBlitter.hxx"
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
FBSurfaceSDL2::FBSurfaceSDL2(FrameBufferSDL2& buffer,
|
FBSurfaceSDL2::FBSurfaceSDL2(FrameBufferSDL2& buffer,
|
||||||
|
@ -28,7 +29,7 @@ FBSurfaceSDL2::FBSurfaceSDL2(FrameBufferSDL2& buffer,
|
||||||
myIsVisible(true),
|
myIsVisible(true),
|
||||||
myIsStatic(false)
|
myIsStatic(false)
|
||||||
{
|
{
|
||||||
myBlitter = make_unique<BilinearBlitter>(buffer);
|
myBlitter = make_unique<HqBlitter>(buffer);
|
||||||
createSurface(width, height, data);
|
createSurface(width, height, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,23 +137,8 @@ void FBSurfaceSDL2::translateCoords(Int32& x, Int32& y) const
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool FBSurfaceSDL2::render()
|
bool FBSurfaceSDL2::render()
|
||||||
{
|
{
|
||||||
// ASSERT_MAIN_THREAD;
|
|
||||||
|
|
||||||
if(myIsVisible)
|
if(myIsVisible)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
SDL_Texture* texture = myTexture;
|
|
||||||
|
|
||||||
if(myTexAccess == SDL_TEXTUREACCESS_STREAMING) {
|
|
||||||
SDL_UpdateTexture(myTexture, &mySrcR, mySurface->pixels, mySurface->pitch);
|
|
||||||
myTexture = mySecondaryTexture;
|
|
||||||
mySecondaryTexture = texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_RenderCopy(myFB.myRenderer, texture, &mySrcR, &myDstR);
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
myBlitter->blit(*mySurface);
|
myBlitter->blit(*mySurface);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -170,53 +156,13 @@ void FBSurfaceSDL2::invalidate()
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FBSurfaceSDL2::free()
|
void FBSurfaceSDL2::free()
|
||||||
{/*
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
|
||||||
|
|
||||||
SDL_Texture* textures[] = {myTexture, mySecondaryTexture};
|
|
||||||
for (SDL_Texture* texture: textures) {
|
|
||||||
if (!texture) continue;
|
|
||||||
|
|
||||||
SDL_DestroyTexture(myTexture);
|
|
||||||
myTexture = nullptr;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
myBlitter->free();
|
myBlitter->free();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FBSurfaceSDL2::reload()
|
void FBSurfaceSDL2::reload()
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
ASSERT_MAIN_THREAD;
|
|
||||||
|
|
||||||
// Re-create texture; the underlying SDL_Surface is fine as-is
|
|
||||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, myInterpolate ? "1" : "0");
|
|
||||||
myTexture = SDL_CreateTexture(myFB.myRenderer, myFB.myPixelFormat->format,
|
|
||||||
myTexAccess, mySurface->w, mySurface->h);
|
|
||||||
|
|
||||||
if (myTexAccess == SDL_TEXTUREACCESS_STREAMING)
|
|
||||||
mySecondaryTexture = SDL_CreateTexture(myFB.myRenderer, myFB.myPixelFormat->format,
|
|
||||||
myTexAccess, mySurface->w, mySurface->h);
|
|
||||||
|
|
||||||
// If the data is static, we only upload it once
|
|
||||||
if(myTexAccess == SDL_TEXTUREACCESS_STATIC)
|
|
||||||
SDL_UpdateTexture(myTexture, nullptr, myStaticData.get(), myStaticPitch);
|
|
||||||
|
|
||||||
SDL_Texture* textures[] = {myTexture, mySecondaryTexture};
|
|
||||||
for (SDL_Texture* texture: textures) {
|
|
||||||
if (!texture) continue;
|
|
||||||
|
|
||||||
// Blending enabled?
|
|
||||||
if(myBlendEnabled)
|
|
||||||
{
|
|
||||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
|
||||||
SDL_SetTextureAlphaMod(texture, myBlendAlpha);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
reinitializeBlitter();
|
reinitializeBlitter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,14 +171,6 @@ void FBSurfaceSDL2::resize(uInt32 width, uInt32 height)
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
/*
|
|
||||||
// We will only resize when necessary, and not using static textures
|
|
||||||
if((myTexAccess == SDL_TEXTUREACCESS_STATIC) || (mySurface &&
|
|
||||||
int(width) <= mySurface->w && int(height) <= mySurface->h))
|
|
||||||
return; // don't need to resize at all
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
if(mySurface)
|
if(mySurface)
|
||||||
SDL_FreeSurface(mySurface);
|
SDL_FreeSurface(mySurface);
|
||||||
free();
|
free();
|
||||||
|
@ -271,10 +209,6 @@ void FBSurfaceSDL2::createSurface(uInt32 width, uInt32 height,
|
||||||
SDL_memcpy(mySurface->pixels, data, mySurface->w * mySurface->h * 4);
|
SDL_memcpy(mySurface->pixels, data, mySurface->w * mySurface->h * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
// applyAttributes(false);
|
|
||||||
|
|
||||||
// To generate texture
|
|
||||||
// reload();
|
|
||||||
reinitializeBlitter();
|
reinitializeBlitter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,16 +222,4 @@ void FBSurfaceSDL2::reinitializeBlitter()
|
||||||
void FBSurfaceSDL2::applyAttributes(bool immediate)
|
void FBSurfaceSDL2::applyAttributes(bool immediate)
|
||||||
{
|
{
|
||||||
reinitializeBlitter();
|
reinitializeBlitter();
|
||||||
/*
|
|
||||||
myInterpolate = myAttributes.smoothing;
|
|
||||||
myBlendEnabled = myAttributes.blending;
|
|
||||||
myBlendAlpha = uInt8(myAttributes.blendalpha * 2.55);
|
|
||||||
|
|
||||||
if(immediate)
|
|
||||||
{
|
|
||||||
// Re-create the texture with the new settings
|
|
||||||
free();
|
|
||||||
reload();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,8 @@ MODULE_OBJS := \
|
||||||
src/common/ThreadDebugging.o \
|
src/common/ThreadDebugging.o \
|
||||||
src/common/StaggeredLogger.o \
|
src/common/StaggeredLogger.o \
|
||||||
src/common/repository/KeyValueRepositoryConfigfile.o \
|
src/common/repository/KeyValueRepositoryConfigfile.o \
|
||||||
src/common/sdl_blitter/BilinearBlitter.o
|
src/common/sdl_blitter/BilinearBlitter.o \
|
||||||
|
src/common/sdl_blitter/HqBlitter.o
|
||||||
|
|
||||||
MODULE_DIRS += \
|
MODULE_DIRS += \
|
||||||
src/common
|
src/common
|
||||||
|
|
|
@ -0,0 +1,170 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// SSSS tt lll lll
|
||||||
|
// SS SS tt ll ll
|
||||||
|
// SS tttttt eeee ll ll aaaa
|
||||||
|
// SSSS tt ee ee ll ll aa
|
||||||
|
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||||
|
// SS SS tt ee ll ll aa aa
|
||||||
|
// SSSS ttt eeeee llll llll aaaaa
|
||||||
|
//
|
||||||
|
// Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony
|
||||||
|
// and the Stella Team
|
||||||
|
//
|
||||||
|
// See the file "License.txt" for information on usage and redistribution of
|
||||||
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
#include "HqBlitter.hxx"
|
||||||
|
|
||||||
|
#include "ThreadDebugging.hxx"
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
HqBlitter::HqBlitter(FrameBufferSDL2& fb) :
|
||||||
|
mySrcTexture(nullptr),
|
||||||
|
myIntermediateTexture(nullptr),
|
||||||
|
mySecondaryIntermedateTexture(nullptr),
|
||||||
|
myTexturesAreAllocated(false),
|
||||||
|
myRecreateTextures(false),
|
||||||
|
myStaticData(nullptr),
|
||||||
|
myFB(fb)
|
||||||
|
{}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
HqBlitter::~HqBlitter()
|
||||||
|
{
|
||||||
|
free();
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void HqBlitter::reinitialize(
|
||||||
|
SDL_Rect srcRect,
|
||||||
|
SDL_Rect destRect,
|
||||||
|
FBSurface::Attributes attributes,
|
||||||
|
SDL_Surface* staticData
|
||||||
|
)
|
||||||
|
{
|
||||||
|
myRecreateTextures = !(
|
||||||
|
mySrcRect.w == srcRect.w &&
|
||||||
|
mySrcRect.h == srcRect.h &&
|
||||||
|
myDstRect.w == destRect.w &&
|
||||||
|
myDstRect.h == destRect.h &&
|
||||||
|
attributes == myAttributes &&
|
||||||
|
myStaticData == staticData
|
||||||
|
);
|
||||||
|
|
||||||
|
myStaticData = staticData;
|
||||||
|
mySrcRect = srcRect;
|
||||||
|
myDstRect = destRect;
|
||||||
|
myAttributes = attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void HqBlitter::free()
|
||||||
|
{
|
||||||
|
if (!myTexturesAreAllocated) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
SDL_Texture* textures[] = {mySrcTexture, myIntermediateTexture, mySecondaryIntermedateTexture};
|
||||||
|
for (SDL_Texture* texture: textures) {
|
||||||
|
if (!texture) continue;
|
||||||
|
|
||||||
|
SDL_DestroyTexture(texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
myTexturesAreAllocated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void HqBlitter::blit(SDL_Surface& surface)
|
||||||
|
{
|
||||||
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
recreateTexturesIfNecessary();
|
||||||
|
|
||||||
|
SDL_Texture* texture = myIntermediateTexture;
|
||||||
|
|
||||||
|
if(myStaticData == nullptr) {
|
||||||
|
SDL_UpdateTexture(mySrcTexture, &mySrcRect, surface.pixels, surface.pitch);
|
||||||
|
|
||||||
|
blitToIntermediate();
|
||||||
|
|
||||||
|
myIntermediateTexture = mySecondaryIntermedateTexture;
|
||||||
|
mySecondaryIntermedateTexture = texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_RenderCopy(myFB.renderer(), texture, &myIntermediateRect, &myDstRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void HqBlitter::blitToIntermediate()
|
||||||
|
{
|
||||||
|
SDL_Rect r = mySrcRect;
|
||||||
|
r.x = r.y = 0;
|
||||||
|
|
||||||
|
SDL_SetRenderTarget(myFB.renderer(), myIntermediateTexture);
|
||||||
|
SDL_RenderCopy(myFB.renderer(), mySrcTexture, &r, &myIntermediateRect);
|
||||||
|
|
||||||
|
SDL_SetRenderTarget(myFB.renderer(), nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void HqBlitter::recreateTexturesIfNecessary()
|
||||||
|
{
|
||||||
|
if (myTexturesAreAllocated && !myRecreateTextures) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
if (myTexturesAreAllocated) {
|
||||||
|
free();
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_TextureAccess texAccess = myStaticData == nullptr ? SDL_TEXTUREACCESS_STREAMING : SDL_TEXTUREACCESS_STATIC;
|
||||||
|
|
||||||
|
myIntermediateRect.w = (myDstRect.w / mySrcRect.w) * mySrcRect.w;
|
||||||
|
myIntermediateRect.h = (myDstRect.h / mySrcRect.h) * mySrcRect.h;
|
||||||
|
myIntermediateRect.x = 0;
|
||||||
|
myIntermediateRect.y = 0;
|
||||||
|
|
||||||
|
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0");
|
||||||
|
|
||||||
|
mySrcTexture = SDL_CreateTexture(myFB.renderer(), myFB.pixelFormat().format,
|
||||||
|
texAccess, mySrcRect.w, mySrcRect.h);
|
||||||
|
|
||||||
|
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, myAttributes.smoothing ? "1" : "0");
|
||||||
|
|
||||||
|
myIntermediateTexture = SDL_CreateTexture(myFB.renderer(), myFB.pixelFormat().format,
|
||||||
|
SDL_TEXTUREACCESS_TARGET, myIntermediateRect.w, myIntermediateRect.h);
|
||||||
|
|
||||||
|
if (myStaticData == nullptr) {
|
||||||
|
mySecondaryIntermedateTexture = SDL_CreateTexture(myFB.renderer(), myFB.pixelFormat().format,
|
||||||
|
SDL_TEXTUREACCESS_TARGET, myIntermediateRect.w, myIntermediateRect.h);
|
||||||
|
} else {
|
||||||
|
mySecondaryIntermedateTexture = nullptr;
|
||||||
|
SDL_UpdateTexture(mySrcTexture, nullptr, myStaticData->pixels, myStaticData->pitch);
|
||||||
|
|
||||||
|
blitToIntermediate();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (myAttributes.blending) {
|
||||||
|
uInt8 blendAlpha = uInt8(myAttributes.blendalpha * 2.55);
|
||||||
|
|
||||||
|
SDL_Texture* textures[] = {mySrcTexture, myIntermediateTexture, mySecondaryIntermedateTexture};
|
||||||
|
for (SDL_Texture* texture: textures) {
|
||||||
|
if (!texture) continue;
|
||||||
|
|
||||||
|
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||||
|
SDL_SetTextureAlphaMod(texture, blendAlpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
myRecreateTextures = false;
|
||||||
|
myTexturesAreAllocated = true;
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// SSSS tt lll lll
|
||||||
|
// SS SS tt ll ll
|
||||||
|
// SS tttttt eeee ll ll aaaa
|
||||||
|
// SSSS tt ee ee ll ll aa
|
||||||
|
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||||
|
// SS SS tt ee ll ll aa aa
|
||||||
|
// SSSS ttt eeeee llll llll aaaaa
|
||||||
|
//
|
||||||
|
// Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony
|
||||||
|
// and the Stella Team
|
||||||
|
//
|
||||||
|
// See the file "License.txt" for information on usage and redistribution of
|
||||||
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
#ifndef HQ_BLITTER_HXX
|
||||||
|
#define HQ_BLITTER_HXX
|
||||||
|
|
||||||
|
#include "Blitter.hxx"
|
||||||
|
#include "FrameBufferSDL2.hxx"
|
||||||
|
#include "SDL_lib.hxx"
|
||||||
|
|
||||||
|
class HqBlitter : public Blitter {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
HqBlitter(FrameBufferSDL2& fb);
|
||||||
|
|
||||||
|
virtual ~HqBlitter();
|
||||||
|
|
||||||
|
virtual void reinitialize(
|
||||||
|
SDL_Rect srcRect,
|
||||||
|
SDL_Rect destRect,
|
||||||
|
FBSurface::Attributes attributes,
|
||||||
|
SDL_Surface* staticData = nullptr
|
||||||
|
) override;
|
||||||
|
|
||||||
|
virtual void blit(SDL_Surface& surface) override;
|
||||||
|
|
||||||
|
virtual void free() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
SDL_Texture* mySrcTexture;
|
||||||
|
SDL_Texture* myIntermediateTexture;
|
||||||
|
SDL_Texture* mySecondaryIntermedateTexture;
|
||||||
|
|
||||||
|
SDL_Rect mySrcRect, myIntermediateRect, myDstRect;
|
||||||
|
FBSurface::Attributes myAttributes;
|
||||||
|
|
||||||
|
bool myTexturesAreAllocated;
|
||||||
|
bool myRecreateTextures;
|
||||||
|
|
||||||
|
SDL_Surface* myStaticData;
|
||||||
|
|
||||||
|
FrameBufferSDL2& myFB;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void recreateTexturesIfNecessary();
|
||||||
|
|
||||||
|
void blitToIntermediate();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
HqBlitter(const HqBlitter&) = delete;
|
||||||
|
|
||||||
|
HqBlitter(HqBlitter&&) = delete;
|
||||||
|
|
||||||
|
HqBlitter& operator=(const HqBlitter&) = delete;
|
||||||
|
|
||||||
|
HqBlitter& operator=(HqBlitter&&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // HQ_BLITTER_CXX
|
Loading…
Reference in New Issue