Synchronet now requires the libarchive development package (e.g. libarchive-dev on Debian-based Linux distros, libarchive.org for more info) to build successfully.

Commits (1)
......@@ -120,41 +120,44 @@ do_scale(struct rectlist* rect, int xscale, int yscale, double ratio)
xscale = 1;
total_yscaling = yscale;
yscale = 1;
if (!(cio_api.options & CONIO_OPT_BLOCKY_SCALING)) {
if ((total_xscaling & 1) == 1 && (total_xscaling == total_yscaling || (total_yscaling % total_xscaling == 0))) {
pointymult = total_xscaling;
total_xscaling /= pointymult;
xscale *= pointymult;
total_yscaling /= pointymult;
yscale *= pointymult;
}
while (total_xscaling > 1 && ((total_xscaling % 5) == 0) && ((total_yscaling % 5) == 0)) {
pointy5++;
total_xscaling /= 5;
xscale *= 5;
total_yscaling /= 5;
yscale *= 5;
}
while (total_xscaling > 1 && ((total_xscaling % 3) == 0) && ((total_yscaling % 3) == 0)) {
pointy3++;
total_xscaling /= 3;
xscale *= 3;
total_yscaling /= 3;
yscale *= 3;
}
while (total_xscaling > 1 && ((total_xscaling % 4) == 0) && ((total_yscaling % 4) == 0)) {
xbr4++;
total_xscaling /= 4;
xscale *= 4;
total_yscaling /= 4;
yscale *= 4;
}
while (total_xscaling > 1 && ((total_xscaling % 2) == 0) && ((total_yscaling % 2) == 0)) {
xbr2++;
total_xscaling /= 2;
xscale *= 2;
total_yscaling /= 2;
yscale *= 2;
// If x/y scaling isn't a simple multiple, block scale everything...
if ((total_yscaling % total_xscaling) == 0) {
if (!(cio_api.options & CONIO_OPT_BLOCKY_SCALING)) {
if ((total_xscaling & 1) == 1 && total_xscaling > 5) {
pointymult = total_xscaling;
total_xscaling /= pointymult;
xscale *= pointymult;
total_yscaling /= pointymult;
yscale *= pointymult;
}
while (total_xscaling > 1 && ((total_xscaling % 5) == 0) && ((total_yscaling % 5) == 0)) {
pointy5++;
total_xscaling /= 5;
xscale *= 5;
total_yscaling /= 5;
yscale *= 5;
}
while (total_xscaling > 1 && ((total_xscaling % 3) == 0) && ((total_yscaling % 3) == 0)) {
pointy3++;
total_xscaling /= 3;
xscale *= 3;
total_yscaling /= 3;
yscale *= 3;
}
while (total_xscaling > 1 && ((total_xscaling % 4) == 0) && ((total_yscaling % 4) == 0)) {
xbr4++;
total_xscaling /= 4;
xscale *= 4;
total_yscaling /= 4;
yscale *= 4;
}
while (total_xscaling > 1 && ((total_xscaling % 2) == 0) && ((total_yscaling % 2) == 0)) {
xbr2++;
total_xscaling /= 2;
xscale *= 2;
total_yscaling /= 2;
yscale *= 2;
}
}
}
......@@ -215,6 +218,18 @@ do_scale(struct rectlist* rect, int xscale, int yscale, double ratio)
csrc->w = rect->rect.width;
csrc->h = rect->rect.height;
#if 0
fprintf(stderr, "Plan:\n"
"pointymulti: %d\n"
"pointy5: %d\n"
"pointy3: %d\n"
"xBR4: %d\n"
"xBR2: %d\n"
"Multiply: %dx%d\n"
"hinterp: %zu -> %zu\n"
"winterp: %zu -> %zu\n",
pointymult, pointy5, pointy3, xbr4, xbr2, xmult, ymult, csrc->h * yscale, ratio < 1 ? fheight : csrc->h * yscale, csrc->w * xscale, ratio > 1 ? fwidth : csrc->w * xscale);
#endif
// And scale...
if (ymult != 1 || xmult != 1) {
multiply_scale(csrc->data, ctarget->data, csrc->w, csrc->h, xmult, ymult);
......@@ -683,33 +698,29 @@ static void
interpolate_height(uint32_t* src, uint32_t* dst, int width, int height, int newheight)
{
int x, y;
bool em = false;
const double mult = (double)height / newheight;
for (y = 0; y < newheight; y++) {
for (x = 0; x < width; x++) {
// First, calculate which two pixels this is between.
const double ypos = mult * y;
const int yposi = ypos;
if (y == ypos) {
// Exact match!
*dst = src[width * yposi + x];
}
else {
const double weight = ypos - yposi;
const double ypos = mult * y;
const int yposi = ypos;
em = (y == ypos || yposi >= height - 1);
if (em) {
memcpy(dst, &src[yposi * width], width * sizeof(dst[0]));
dst += width;
}
else {
const double weight = ypos - yposi;
for (x = 0; x < width; x++) {
// Now pick the two pixels
const uint32_t pix1 = src[yposi * width + x] & 0xffffff;
uint32_t pix2;
if (yposi < height - 1)
pix2 = src[(yposi + 1) * width + x] & 0xffffff;
else
pix2 = src[yposi * width + x] & 0xffffff;
const uint32_t pix2 = src[(yposi + 1) * width + x] & 0xffffff;
if (pix1 == pix2)
*dst = pix1;
else {
else
*dst = blend(pix1, pix2, weight);
}
dst++;
}
dst++;
}
}
}
......@@ -717,8 +728,6 @@ interpolate_height(uint32_t* src, uint32_t* dst, int width, int height, int newh
static void
multiply_scale(uint32_t* src, uint32_t* dst, int width, int height, int xmult, int ymult)
{
int nheight = height * ymult;
int nwidth = width * xmult;
int x, y;
int mx, my;
uint32_t* slstart;
......
......@@ -24,6 +24,7 @@
#include "vidmodes.h"
#define BITMAP_CIOLIB_DRIVER
#include "bitmap_con.h"
#include "scale.h"
#include "SDL.h"
......@@ -38,6 +39,8 @@ unsigned char sdl_keynext=0; /* Index into keybuf for next free position */
int sdl_exitcode=0;
bool internal_scaling = true; // Protected by the win mutex
SDL_Window *win=NULL;
SDL_Cursor *curs=NULL;
SDL_Renderer *renderer=NULL;
......@@ -565,12 +568,14 @@ static void setup_surfaces_locked(void)
vmultiplier = cvstat.vmultiplier;
idealh = roundl((long double)cvstat.winwidth * cvstat.scale_denominator / cvstat.scale_numerator * cvstat.scrnheight / cvstat.scrnwidth);
idealmh = roundl((long double)cvstat.scrnwidth * cvstat.scale_denominator / cvstat.scale_numerator * cvstat.scrnheight / cvstat.scrnwidth);
internal_scaling = true;
sdl.SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0");
if (win == NULL) {
// SDL2: This is slow sometimes... not sure why.
if (sdl.CreateWindowAndRenderer(cvstat.winwidth, idealh, flags, &win, &renderer) == 0) {
sdl.RenderClear(renderer);
newtexture = sdl.CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, cvstat.scrnwidth, cvstat.scrnheight);
newtexture = sdl.CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, cvstat.winwidth, idealh);
if (texture)
sdl.DestroyTexture(texture);
......@@ -582,9 +587,9 @@ static void setup_surfaces_locked(void)
}
}
else {
sdl.SetWindowMinimumSize(win, cvstat.scrnwidth, idealh);
sdl.SetWindowMinimumSize(win, cvstat.scrnwidth, idealmh);
sdl.SetWindowSize(win, cvstat.winwidth, idealh);
newtexture = sdl.CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, cvstat.scrnwidth, cvstat.scrnheight);
newtexture = sdl.CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, cvstat.winwidth, idealh);
sdl.RenderClear(renderer);
if (texture)
sdl.DestroyTexture(texture);
......@@ -969,16 +974,23 @@ void sdl_video_event_thread(void *data)
const char *newh;
pthread_mutex_lock(&vstatlock);
if ((ev.window.data1 % cvstat.scrnwidth) || (ev.window.data2 % cvstat.scrnheight))
pthread_mutex_lock(&win_mutex);
if ((ev.window.data1 % cvstat.scrnwidth) && (ev.window.data2 % cvstat.scrnheight)) {
newh = "2";
else
internal_scaling = false;
}
else {
newh = "0";
pthread_mutex_lock(&win_mutex);
internal_scaling = true;
}
sdl.GetWindowSize(win, &cvstat.winwidth, &cvstat.winheight);
if (strcmp(newh, sdl.GetHint(SDL_HINT_RENDER_SCALE_QUALITY))) {
SDL_Texture *newtexture;
sdl.SetHint(SDL_HINT_RENDER_SCALE_QUALITY, newh);
newtexture = sdl.CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, cvstat.scrnwidth, cvstat.scrnheight);
if (internal_scaling)
newtexture = sdl.CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, cvstat.winwidth, cvstat.winheight);
else
newtexture = sdl.CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, cvstat.scrnwidth, cvstat.scrnheight);
sdl.RenderClear(renderer);
if (texture)
sdl.DestroyTexture(texture);
......@@ -1025,43 +1037,78 @@ void sdl_video_event_thread(void *data)
int row;
int tw, th;
src.x = 0;
src.y = 0;
src.w = list->rect.width;
src.h = list->rect.height;
sdl.QueryTexture(texture, NULL, NULL, &tw, &th);
sdl.LockTexture(texture, &src, &pixels, &pitch);
if (pitch != list->rect.width * sizeof(list->data[0])) {
// If this happens, we need to copy a row at a time...
for (row = 0; row < list->rect.height && row < th; row++) {
if (pitch < list->rect.width * sizeof(list->data[0]))
memcpy(pixels, &list->data[list->rect.width * row], pitch);
else
memcpy(pixels, &list->data[list->rect.width * row], list->rect.width * sizeof(list->data[0]));
pixels = (void *)((char*)pixels + pitch);
if (internal_scaling) {
struct graphics_buffer *gb;
gb = do_scale(list, cvstat.winwidth / cvstat.scrnwidth, cvstat.winheight / cvstat.scrnheight,
(double)cvstat.scale_numerator / cvstat.scale_denominator);
src.x = 0;
src.y = 0;
src.w = gb->w;
src.h = gb->h;
sdl.QueryTexture(texture, NULL, NULL, &tw, &th);
sdl.LockTexture(texture, &src, &pixels, &pitch);
if (pitch != gb->w * sizeof(gb->data[0])) {
// If this happens, we need to copy a row at a time...
for (row = 0; row < gb->h && row < th; row++) {
if (pitch < gb->w * sizeof(gb->data[0]))
memcpy(pixels, &gb->data[gb->w * row], pitch);
else
memcpy(pixels, &gb->data[gb->w * row], gb->w * sizeof(gb->data[0]));
pixels = (void *)((char*)pixels + pitch);
}
}
else {
int ch = gb->h;
if (ch > th)
ch = th;
memcpy(pixels, gb->data, gb->w * ch * sizeof(gb->data[0]));
}
sdl.UnlockTexture(texture);
dst.x = 0;
dst.y = 0;
dst.w = gb->w;
dst.h = gb->h;
release_buffer(gb);
}
else {
int ch = list->rect.height;
if (ch > th)
ch = th;
memcpy(pixels, list->data, list->rect.width * ch * sizeof(list->data[0]));
}
sdl.UnlockTexture(texture);
dst.x = 0;
dst.y = 0;
dst.w = cvstat.winwidth;
dst.h = cvstat.winheight;
// Get correct aspect ratio for dst...
idealw = roundl((long double)dst.h * cvstat.scale_numerator / cvstat.scale_denominator * cvstat.scrnwidth / cvstat.scrnheight);
idealh = roundl((long double)dst.w * cvstat.scale_denominator / cvstat.scale_numerator * cvstat.scrnheight / cvstat.scrnwidth);
if (idealw < cvstat.winwidth) {
dst.x = (cvstat.winwidth - idealw) / 2;
dst.w = idealw;
}
else if(idealh < cvstat.winheight) {
dst.y = (cvstat.winheight - idealh) / 2;
dst.h = idealh;
src.x = 0;
src.y = 0;
src.w = list->rect.width;
src.h = list->rect.height;
sdl.QueryTexture(texture, NULL, NULL, &tw, &th);
sdl.LockTexture(texture, &src, &pixels, &pitch);
if (pitch != list->rect.width * sizeof(list->data[0])) {
// If this happens, we need to copy a row at a time...
for (row = 0; row < list->rect.height && row < th; row++) {
if (pitch < list->rect.width * sizeof(list->data[0]))
memcpy(pixels, &list->data[list->rect.width * row], pitch);
else
memcpy(pixels, &list->data[list->rect.width * row], list->rect.width * sizeof(list->data[0]));
pixels = (void *)((char*)pixels + pitch);
}
}
else {
int ch = list->rect.height;
if (ch > th)
ch = th;
memcpy(pixels, list->data, list->rect.width * ch * sizeof(list->data[0]));
}
sdl.UnlockTexture(texture);
dst.x = 0;
dst.y = 0;
dst.w = cvstat.winwidth;
dst.h = cvstat.winheight;
// Get correct aspect ratio for dst...
idealw = roundl((long double)dst.h * cvstat.scale_numerator / cvstat.scale_denominator * cvstat.scrnwidth / cvstat.scrnheight);
idealh = roundl((long double)dst.w * cvstat.scale_denominator / cvstat.scale_numerator * cvstat.scrnheight / cvstat.scrnwidth);
if (idealw < cvstat.winwidth) {
dst.x = (cvstat.winwidth - idealw) / 2;
dst.w = idealw;
}
else if(idealh < cvstat.winheight) {
dst.y = (cvstat.winheight - idealh) / 2;
dst.h = idealh;
}
}
sdl.RenderCopy(renderer, texture, &src, &dst);
}
......
......@@ -1816,7 +1816,7 @@ int main(int argc, char **argv)
// Save changed settings
gettextinfo(&txtinfo);
// Only save window info if we're in the startup mode...
if (txtinfo.currmode == settings.startup_mode || (settings.startup_mode == SCREEN_MODE_CURRENT && txtinfo.currmode == C80)) {
if (txtinfo.currmode == screen_to_ciolib(settings.startup_mode) || (settings.startup_mode == SCREEN_MODE_CURRENT && txtinfo.currmode == C80)) {
ww = wh = sf = -1;
get_window_info(&ww, &wh, NULL, NULL);
sf = getscaling();
......