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 (2)
  • Deucе's avatar
    Make a generic odd pointy scaler. · 519520da
    Deucе authored
    Since we have all odd numbers thanks to the pointy scaler, and we
    have 2x thanks to xBR, we should now be able to build any integer
    scaling from a combination of those two scalers.
    
    This, of course, assumes you have enough CPU and RAM to actually
    do the scaling you want... powers of two will likely be the worst
    case for scaling.
    
    Also, do pointy scaling before xBR.
    519520da
  • Deucе's avatar
    Now that we have scaling sorted out, the X11 driver doesn't need it · d5808927
    Deucе authored
    Also, we don't need to use pointers for the scaling.
    d5808927
......@@ -7,6 +7,7 @@ static int r2y_inited;
static void pointy_scale3(uint32_t* src, uint32_t* dest, int width, int height);
static void pointy_scale5(uint32_t* src, uint32_t* dest, int width, int height);
static void pointy_scale_odd(uint32_t* src, uint32_t* dest, int width, int height, int mult);
static void interpolate_height(uint32_t* src, uint32_t* dst, int width, int height, int newheight);
static void interpolate_width(uint32_t* src, uint32_t* dst, int width, int height, int newwidth);
static void multiply_scale(uint32_t* src, uint32_t* dst, int width, int height, int xmult, int ymult);
......@@ -88,17 +89,17 @@ release_buffer(struct graphics_buffer *buf)
}
struct graphics_buffer *
do_scale(struct rectlist* rect, int* xscale, int* yscale, double ratio)
do_scale(struct rectlist* rect, int xscale, int yscale, double ratio)
{
struct graphics_buffer* ret1 = get_buffer();
struct graphics_buffer* ret2 = get_buffer();
int pointymult = 1;
int pointy5 = 0;
int pointy3 = 0;
int xbr2 = 0;
int xbr4 = 0;
int ymult = 1;
int xmult = 1;
int newscale = 1;
int total_xscaling = 1;
int total_yscaling = 1;
struct graphics_buffer *ctarget;
......@@ -106,83 +107,84 @@ do_scale(struct rectlist* rect, int* xscale, int* yscale, double ratio)
uint32_t* nt;
int fheight;
int fwidth;
bool swapxy = false;
switch (*xscale) {
case 1:
break;
case 2:
xbr2 = 1;
break;
case 3:
pointy3 = 1;
break;
case 4:
xbr4 = 1;
break;
case 5:
pointy5 = 1;
break;
case 6:
pointy3 = 1;
xbr2 = 1;
break;
case 7: // TODO: Do we want a pointy7 and pointy11?
xmult = 7;
ymult = 7;
break;
default:
total_xscaling = *xscale;
*xscale = 1;
total_yscaling = *yscale;
*yscale = 1;
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;
}
break;
if (xscale > yscale) {
swapxy = true;
total_xscaling = xscale;
xscale = yscale;
yscale = total_xscaling;
}
total_xscaling = xscale;
xscale = 1;
total_yscaling = yscale;
yscale = 1;
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 (*xscale != *yscale) {
if (*yscale == *xscale * 2)
ymult *= 2;
else
return NULL;
xmult = total_xscaling;
xscale *= xmult;
total_xscaling = 1;
ymult = total_yscaling;
yscale *= ymult;
total_yscaling = 1;
if (swapxy) {
int tmp;
tmp = ymult;
ymult = xmult;
xmult = tmp;
tmp = xscale;
xscale = yscale;
yscale = tmp;
}
// Calculate the scaled height from ratio...
if (ratio < 1)
fheight = lround((double)(rect->rect.height * (*yscale)) / ratio);
fheight = lround((double)(rect->rect.height * (yscale)) / ratio);
else
fheight = rect->rect.height * *yscale;
fheight = rect->rect.height * yscale;
if (ratio > 1)
fwidth = lround((double)(rect->rect.width * (*xscale)) / ratio);
fwidth = lround((double)(rect->rect.width * (xscale)) / ratio);
else
fwidth = rect->rect.width * *xscale;
fwidth = rect->rect.width * xscale;
// Now make sure target is big enough...
size_t needsz = fwidth * fheight * sizeof(uint32_t);
......@@ -223,22 +225,11 @@ do_scale(struct rectlist* rect, int* xscale, int* yscale, double ratio)
else
ctarget = ret1;
}
while (xbr4 > 0) {
xbr_filter(csrc->data, ctarget->data, csrc->w, csrc->h, 4);
xbr4--;
ctarget->w = csrc->w * 4;
ctarget->h = csrc->h * 4;
csrc = ctarget;
if (ctarget == ret1)
ctarget = ret2;
else
ctarget = ret1;
}
while (xbr2 > 0) {
xbr_filter(csrc->data, ctarget->data, csrc->w, csrc->h, 2);
xbr2--;
ctarget->w = csrc->w * 2;
ctarget->h = csrc->h * 2;
if (pointymult > 1 && pointymult & 1) {
pointy_scale_odd(csrc->data, ctarget->data, csrc->w, csrc->h, pointymult);
ctarget->w = csrc->w * pointymult;
ctarget->h = csrc->h * pointymult;
pointymult = 1;
csrc = ctarget;
if (ctarget == ret1)
ctarget = ret2;
......@@ -267,6 +258,28 @@ do_scale(struct rectlist* rect, int* xscale, int* yscale, double ratio)
else
ctarget = ret1;
}
while (xbr4 > 0) {
xbr_filter(csrc->data, ctarget->data, csrc->w, csrc->h, 4);
xbr4--;
ctarget->w = csrc->w * 4;
ctarget->h = csrc->h * 4;
csrc = ctarget;
if (ctarget == ret1)
ctarget = ret2;
else
ctarget = ret1;
}
while (xbr2 > 0) {
xbr_filter(csrc->data, ctarget->data, csrc->w, csrc->h, 2);
xbr2--;
ctarget->w = csrc->w * 2;
ctarget->h = csrc->h * 2;
csrc = ctarget;
if (ctarget == ret1)
ctarget = ret2;
else
ctarget = ret1;
}
// And finally, interpolate if needed
if (ratio < 1) {
......@@ -291,12 +304,114 @@ do_scale(struct rectlist* rect, int* xscale, int* yscale, double ratio)
ctarget = ret1;
}
*xscale = newscale;
*yscale = newscale;
release_buffer(ctarget);
return csrc;
}
static void
pointy_scale_odd(uint32_t* src, uint32_t* dest, int width, int height, int mult)
{
int x, y;
uint32_t* s;
uint32_t* d;
int prevline, prevcol, nextline, nextcol;
int i, j;
int mid = mult / 2;
int multoff = mult - 1;
int dline = width * mult;
int dbott;
int dstripe = dline * mult;
s = src;
d = dest;
prevline = 0;
nextline = width;
for (y = 0; y < height; y++) {
if (y == height - 1)
nextline = 0;
prevcol = 0;
nextcol = 1;
for (x = 0; x < width; x++) {
if (x == width - 1)
nextcol = 0;
for (i = 0; i < mid; i++) {
d = &dest[dstripe * y + dline * i + x * mult];
dbott = dline * (multoff - i * 2);
for (j = 0; j < mid - i; j++) {
if (s[prevline + prevcol] == s[0]) {
d[j] = s[0];
}
else if (s[prevline] == s[prevcol]) {
d[j] = s[prevcol];
}
else {
d[j] = s[0];
}
if (s[prevline + nextcol] == s[0]) {
d[multoff - j] = s[0];
}
else if (s[prevline] == s[nextcol]) {
d[multoff - j] = s[nextcol];
}
else {
d[multoff - j] = s[0];
}
if (s[prevcol + nextline] == s[0]) {
d[dbott + j] = s[0];
}
else if(s[prevcol] == s[nextline]) {
d[dbott + j] = s[prevcol];
}
else {
d[dbott + j] = s[0];
}
if (s[nextcol + nextline] == s[0]) {
d[dbott + multoff - j] = s[0];
}
else if (s[nextcol] == s[nextline]) {
d[dbott + multoff - j] = s[nextcol];
}
else {
d[dbott + multoff - j] = s[0];
}
}
// And the rest is always kept the same
for (; j < mid; j++) {
d[j] = s[0];
d[multoff - j] = s[0];
d[dbott + j] = s[0];
d[dbott + multoff - j] = s[0];
}
// And the middle dot.
d[j] = s[0];
d[dbott + j] = s[0];
}
d = &dest[dstripe * y + dline * i + x * mult];
for (j = 0; j < mid; j++) {
d[j] = s[0];
d[multoff - j] = s[0];
}
d[j] = s[0];
s++;
if (x == 0)
prevcol = -1;
}
if (y == 0)
prevline = -width;
}
}
static void
pointy_scale5(uint32_t* src, uint32_t* dest, int width, int height)
{
......
......@@ -15,4 +15,4 @@ struct graphics_buffer * get_buffer(void);
void release_buffer(struct graphics_buffer *);
void init_r2y(void);
struct graphics_buffer * do_scale(struct rectlist* rect, int* xscale, int* yscale, double ratio);
struct graphics_buffer * do_scale(struct rectlist* rect, int xscale, int yscale, double ratio);
......@@ -457,8 +457,7 @@ static int video_init()
static void local_draw_rect(struct rectlist *rect)
{
int x,y,xscale,yscale,xoff=0,yoff=0;
int xscaling, yscaling;
int x, y, xoff = 0, yoff = 0;
unsigned int r, g, b;
unsigned long pixel;
int cleft;
......@@ -481,9 +480,7 @@ static void local_draw_rect(struct rectlist *rect)
yoff = 0;
// Scale...
xscaling = x_cvstat.scaling;
yscaling = x_cvstat.scaling*x_cvstat.vmultiplier;
source = do_scale(rect, &xscaling, &yscaling, (double)x_cvstat.scale_numerator / x_cvstat.scale_denominator);
source = do_scale(rect, x_cvstat.scaling, x_cvstat.scaling * x_cvstat.vmultiplier, (double)x_cvstat.scale_numerator / x_cvstat.scale_denominator);
bitmap_drv_free_rect(rect);
if (source == NULL)
return;
......@@ -545,18 +542,11 @@ static void local_draw_rect(struct rectlist *rect)
else
pixel |= (b >> (0-b_shift)) & visual.blue_mask;
}
// TODO: These loops shouldn't be necessary anymore...
for(yscale=0; yscale<yscaling; yscale++) {
for(xscale=0; xscale<xscaling; xscale++) {
#ifdef XPutPixel
XPutPixel(xim, (x + rect->rect.x) * xscaling + xscale
, (y + rect->rect.y) * yscaling + yscale, pixel);
XPutPixel(xim, (x + rect->rect.x), (y + rect->rect.y), pixel);
#else
x11.XPutPixel(xim, (x + rect->rect.x) * xscaling + xscale
, (y + rect->rect.y) * yscaling + yscale, pixel);
x11.XPutPixel(xim, (x + rect->rect.x), (y + rect->rect.y), pixel);
#endif
}
}
idx++;
}
lines++;
......@@ -564,9 +554,9 @@ static void local_draw_rect(struct rectlist *rect)
// TODO: Previously this did one update per display line...
if (last && (cbottom != y || y == source->h - 1) && cright >= 0) {
lines = 0;
x11.XPutImage(dpy, win, gc, xim, cleft * xscaling, ctop * yscaling
, cleft * xscaling + xoff, ctop * yscaling + yoff
, (cright - cleft + 1) * xscaling, (cbottom - ctop + 1) * yscaling);
x11.XPutImage(dpy, win, gc, xim, cleft, ctop
, cleft + xoff, ctop + yoff
, (cright - cleft + 1), (cbottom - ctop + 1));
cleft = source->w;
cright = cbottom = -100;
ctop = source->h;
......@@ -574,7 +564,7 @@ static void local_draw_rect(struct rectlist *rect)
}
if (last == NULL)
x11.XPutImage(dpy, win, gc, xim, rect->rect.x*xscaling, rect->rect.y*yscaling, rect->rect.x*xscaling + xoff, rect->rect.y*yscaling + yoff, source->w * xscaling, source->h * yscaling);
x11.XPutImage(dpy, win, gc, xim, rect->rect.x, rect->rect.y, rect->rect.x + xoff, rect->rect.y + yoff, source->w, source->h);
else
release_buffer(last);
last = source;
......