Skip to content

Commit 697fef3

Browse files
committed
added scaling
1 parent a9a62e3 commit 697fef3

File tree

10 files changed

+2566
-0
lines changed

10 files changed

+2566
-0
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ set(CMAKE_C_VISIBILITY_PRESET hidden)
4444
add_executable(ppuc-pinmame
4545
src/ppuc.cpp
4646
src/VirtualDMD.cpp
47+
src/xbrz/xbrz.cpp
4748
)
4849

4950
target_include_directories(ppuc-pinmame PUBLIC
@@ -94,6 +95,7 @@ endif()
9495
add_executable(ppuc-backbox
9596
src/backbox.cpp
9697
src/VirtualDMD.cpp
98+
src/xbrz/xbrz.cpp
9799
)
98100

99101
target_include_directories(ppuc-backbox PUBLIC

src/VirtualDMD.cpp

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,28 @@
11
#include "VirtualDMD.h"
22

3+
#include <vector>
4+
5+
#include "xbrz/xbrz.h"
6+
37
void VirtualDMD::Update(uint8_t* pData)
8+
{
9+
switch (m_renderingMode)
10+
{
11+
case RenderingMode::SmoothScaling:
12+
RenderSmoothScaling(pData);
13+
break;
14+
15+
case RenderingMode::XBRZ:
16+
RenderXBRZ(pData);
17+
break;
18+
19+
default:
20+
RenderDots(pData);
21+
break;
22+
}
23+
}
24+
25+
void VirtualDMD::RenderDots(uint8_t* pData)
426
{
527
// Get window size to calculate scaling
628
int windowWidth, windowHeight;
@@ -56,3 +78,95 @@ void VirtualDMD::Update(uint8_t* pData)
5678

5779
SDL_RenderPresent(m_pRenderer);
5880
}
81+
82+
void VirtualDMD::RenderSmoothScaling(uint8_t* pData)
83+
{
84+
int windowWidth, windowHeight;
85+
SDL_GetRenderOutputSize(m_pRenderer, &windowWidth, &windowHeight);
86+
87+
// Create source texture
88+
SDL_Texture* srcTexture =
89+
SDL_CreateTexture(m_pRenderer, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STATIC, m_width, m_height);
90+
SDL_UpdateTexture(srcTexture, NULL, pData, m_width * 3);
91+
92+
// Create intermediate texture at 4x resolution
93+
int intermediateW = m_width * 4;
94+
int intermediateH = m_height * 4;
95+
SDL_Texture* intermediate =
96+
SDL_CreateTexture(m_pRenderer, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_TARGET, intermediateW, intermediateH);
97+
98+
// First scale pass (nearest neighbor to 4x)
99+
SDL_SetRenderTarget(m_pRenderer, intermediate);
100+
SDL_SetTextureScaleMode(srcTexture, SDL_SCALEMODE_NEAREST);
101+
SDL_RenderTexture(m_pRenderer, srcTexture, NULL, NULL);
102+
103+
// Second scale pass (linear to final size)
104+
SDL_SetRenderTarget(m_pRenderer, NULL);
105+
SDL_SetTextureScaleMode(intermediate, SDL_SCALEMODE_LINEAR);
106+
SDL_FRect dest = {0, 0, (float)windowWidth, (float)windowHeight};
107+
SDL_RenderTexture(m_pRenderer, intermediate, NULL, &dest);
108+
109+
SDL_RenderPresent(m_pRenderer);
110+
111+
// Cleanup
112+
SDL_DestroyTexture(srcTexture);
113+
SDL_DestroyTexture(intermediate);
114+
}
115+
116+
void VirtualDMD::RenderXBRZ(uint8_t* pData)
117+
{
118+
// Get the window size
119+
int windowWidth, windowHeight;
120+
SDL_GetRenderOutputSize(m_pRenderer, &windowWidth, &windowHeight);
121+
122+
// Prepare source ARGB buffer
123+
const int srcWidth = m_width;
124+
const int srcHeight = m_height;
125+
std::vector<uint32_t> srcImage(srcWidth * srcHeight);
126+
127+
for (int y = 0; y < srcHeight; ++y)
128+
{
129+
for (int x = 0; x < srcWidth; ++x)
130+
{
131+
int i = y * srcWidth + x;
132+
int j = i * 3;
133+
uint8_t r = pData[j];
134+
uint8_t g = pData[j + 1];
135+
uint8_t b = pData[j + 2];
136+
srcImage[i] = (255u << 24) | (r << 16) | (g << 8) | b; // ARGB format
137+
}
138+
}
139+
140+
// Set up xBRZ scaler configuration
141+
xbrz::ScalerCfg cfg;
142+
cfg.luminanceWeight = 1.0;
143+
cfg.equalColorTolerance = 30.0;
144+
cfg.centerDirectionBias = 4.0;
145+
cfg.dominantDirectionThreshold = 3.6;
146+
cfg.steepDirectionThreshold = 2.2;
147+
148+
// xBRZ upscale (max factor: 6)
149+
const size_t scaleFactor = 6;
150+
const int scaledWidth = srcWidth * scaleFactor;
151+
const int scaledHeight = srcHeight * scaleFactor;
152+
std::vector<uint32_t> dstImage(scaledWidth * scaledHeight);
153+
154+
xbrz::scale(scaleFactor, srcImage.data(), dstImage.data(), srcWidth, srcHeight, xbrz::ColorFormat::ARGB, cfg, 0,
155+
srcHeight);
156+
157+
// Create an SDL texture from the scaled buffer
158+
SDL_Texture* texture =
159+
SDL_CreateTexture(m_pRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, scaledWidth, scaledHeight);
160+
161+
SDL_UpdateTexture(texture, nullptr, dstImage.data(), scaledWidth * sizeof(uint32_t));
162+
163+
// Clear and render the texture
164+
SDL_RenderClear(m_pRenderer);
165+
166+
SDL_FRect dstRect = {0.0f, 0.0f, (float)windowWidth, (float)windowHeight};
167+
SDL_RenderTexture(m_pRenderer, texture, nullptr, &dstRect);
168+
169+
SDL_RenderPresent(m_pRenderer);
170+
171+
SDL_DestroyTexture(texture);
172+
}

src/VirtualDMD.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,22 @@ class DMDUTILAPI VirtualDMD : public DMDUtil::RGB24DMD
1313

1414
~VirtualDMD() { m_pRenderer = nullptr; }
1515

16+
enum RenderingMode : int
17+
{
18+
Dots = 0,
19+
SmoothScaling = 1,
20+
XBRZ = 2,
21+
};
22+
1623
virtual void Update(uint8_t* pData) override;
1724

25+
void SetRenderingMode(RenderingMode mode) { m_renderingMode = mode; }
26+
1827
private:
1928
SDL_Renderer* m_pRenderer;
29+
int m_renderingMode = RenderingMode::Dots;
30+
31+
void RenderDots(uint8_t* pData);
32+
void RenderSmoothScaling(uint8_t* pData);
33+
void RenderXBRZ(uint8_t* pData);
2034
};

src/backbox.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ static struct cag_option options[] = {
107107
.access_name = "virtual-dmd-screen",
108108
.value_name = "VALUE",
109109
.description = "Show virtual DMD on a specific screen"},
110+
{.identifier = 'S',
111+
.access_name = "virtual-dmd-scale",
112+
.value_name = NULL,
113+
.description = "Scale virtual DMD instead or rendering dots."},
110114
{.identifier = 'h', .access_letters = "h", .access_name = "help", .description = "Show help"}};
111115

112116
void DMDUTILCALLBACK LogCallback(DMDUtil_LogLevel logLevel, const char* format, va_list args)
@@ -257,6 +261,7 @@ int main(int argc, char** argv)
257261
bool opt_virtual_dmd = false;
258262
bool opt_virtual_dmd_hd = false;
259263
bool opt_virtual_dmd_window = false;
264+
bool opt_virtual_dmd_scale = false;
260265
uint16_t opt_virtual_dmd_width = 1280;
261266
uint16_t opt_virtual_dmd_height = 320;
262267
int8_t opt_virtual_dmd_screen = -1;
@@ -318,6 +323,9 @@ int main(int argc, char** argv)
318323
case 'R':
319324
opt_virtual_dmd_screen = atoi(cag_option_get_value(&cag_context));
320325
break;
326+
case 'S':
327+
opt_virtual_dmd_scale = true;
328+
break;
321329
case 'h':
322330
printf("Usage: ppuc [OPTION]...\n");
323331
cag_option_print(options, CAG_ARRAY_SIZE(options), stdout);
@@ -445,6 +453,11 @@ int main(int argc, char** argv)
445453
pVirtualDMD = new VirtualDMD(pVirtualDMDRenderer, 128, 32);
446454
}
447455

456+
if (opt_virtual_dmd_scale)
457+
{
458+
pVirtualDMD->SetRenderingMode(VirtualDMD::RenderingMode::XBRZ);
459+
}
460+
448461
pDmd->AddRGB24DMD((DMDUtil::RGB24DMD* const)pVirtualDMD);
449462
}
450463

src/xbrz/Changelog.txt

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
xBRZ 1.8 [2019-11-28]
2+
---------------------
3+
Consider ARGB outside area as transparent
4+
Fixed ARGB scaling issue on image borders
5+
6+
7+
xBRZ 1.7 [2019-07-04]
8+
---------------------
9+
Fixed asymmetric color distance
10+
New parameter: "Center direction bias"
11+
12+
13+
xBRZ 1.6 [2018-02-27]
14+
---------------------
15+
Added bilinear scaling
16+
Option to skip color buffer creation
17+
Updated license info
18+
19+
20+
xBRZ 1.5 [2017-08-07]
21+
---------------------
22+
Added RGB conversion routines
23+
24+
25+
xBRZ 1.4 [2015-07-25]
26+
---------------------
27+
Added 6xBRZ scaler
28+
Create color distance buffer lazily
29+
30+
31+
xBRZ 1.3 [2015-04-03]
32+
---------------------
33+
Improved ARGB performance by 15%
34+
Fixed alpha channel gradient bug
35+
36+
37+
xBRZ 1.2 [2014-11-21]
38+
---------------------
39+
Further improved performance by over 30%
40+
41+
42+
xBRZ 1.1 [2014-11-02]
43+
---------------------
44+
Support images with alpha channel
45+
Improved color analysis
46+
47+
48+
xBRZ 1.0 [2013-02-11]
49+
---------------------
50+
Fixed xBRZ scaler compiler issues for GCC
51+
52+
53+
xBRZ 0.2 [2012-12-11]
54+
---------------------
55+
Added 5xBRZ scaler
56+
Optimized xBRZ scaler performance by factor 3
57+
Further improved image quality of xBRZ scaler
58+
59+
60+
xBRZ 0.1 [2012-09-26]
61+
---------------------
62+
Initial release:
63+
- scale while preserving small image features
64+
- support multithreading
65+
- support 64-bit architectures
66+
- support processing image slices

0 commit comments

Comments
 (0)