Skip to content
Snippets Groups Projects
Commit 767cbb9a authored by Deucе's avatar Deucе :ok_hand_tone4:
Browse files

Many X11 scaling improvements...

1) Initialize the r2y array for xBR so it actually works.
2) Add a vertical (only) interpolation scaler for aspect ratio enforcement
3) Add a simple muliplier scaler, so that can be removed from x_event.c
4) Use a new graphics buffer free list, which allows tracking last
   drawn screen instead of last bitmap rectangle, removing various hacks
5) Share the Y'CbCr <-> R'dG'dB'd tables between xBR and scale.c
parent 26def071
No related branches found
No related tags found
1 merge request!463MRC mods by Codefenix (2024-10-20)
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "genwrap.h" #include "genwrap.h"
#include "dirwrap.h" #include "dirwrap.h"
#include "xpbeep.h" #include "xpbeep.h"
#include "scale.h"
#if (defined CIOLIB_IMPORTS) #if (defined CIOLIB_IMPORTS)
#undef CIOLIB_IMPORTS #undef CIOLIB_IMPORTS
...@@ -1664,6 +1665,7 @@ int bitmap_drv_init(void (*drawrect_cb) (struct rectlist *data) ...@@ -1664,6 +1665,7 @@ int bitmap_drv_init(void (*drawrect_cb) (struct rectlist *data)
pthread_mutex_init(&screenb.screenlock, NULL); pthread_mutex_init(&screenb.screenlock, NULL);
pthread_mutex_init(&free_rect_lock, NULL); pthread_mutex_init(&free_rect_lock, NULL);
pthread_mutex_lock(&vstatlock); pthread_mutex_lock(&vstatlock);
init_r2y();
vstat.vmem=NULL; vstat.vmem=NULL;
vstat.flags = VIDMODES_FLAG_PALETTE_VMEM; vstat.flags = VIDMODES_FLAG_PALETTE_VMEM;
pthread_mutex_lock(&screena.screenlock); pthread_mutex_lock(&screena.screenlock);
......
#include "scale.h" #include "scale.h"
#include "xbr.h" #include "xbr.h"
uint32_t r2y[1<<24];
uint32_t y2r[1<<24];
static int r2y_inited;
static void pointy_scale3(uint32_t* src, uint32_t* dest, int width, int height); 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_scale5(uint32_t* src, uint32_t* dest, int width, int height);
static void interpolate_height(uint32_t* src, uint32_t* dst, int width, int height, int newheight);
static void multiply_scale(uint32_t* src, uint32_t* dst, int width, int height, int xmult, int ymult);
static struct graphics_buffer *free_list;
#define CLAMP(x) do { \
if (x < 0) \
x = 0; \
else if (x > 255) \
x = 255; \
} while(0)
void
init_r2y(void)
{
int r, g, b;
int y, u, v;
const double luma = 255.0 / 219;
const double col = 255.0 / 224;
if (r2y_inited)
return;
for (r = 0; r < 256; r++) {
for (g = 0; g < 256; g++) {
for (b = 0; b < 256; b++) {
y = 16 + ( 65.738 * r + 129.057 * g + 25.064 * b + 128) / 256;
CLAMP(y);
u = 128 + (-37.945 * r - 74.494 * g + 112.439 * b + 128) / 256;
CLAMP(u);
v = 128 + (112.439 * r - 94.154 * g - 18.285 * b + 128) / 256;
CLAMP(v);
r2y[(r<<16) | (g<<8) | b] = (y<<16)|(u<<8)|v;
}
}
}
for (y = 0; y < 256; y++) {
for (u = 0; u < 256; u++) {
for (v = 0; v < 256; v++) {
const int c = y - 16;
const int d = u - 128;
const int e = v - 128;
r = luma * c + col * 1.402 * e;
CLAMP(r);
g = luma * c - col * 1.772 * (0.114 / 0.587) * d - col * 1.402 * (0.299 / 0.587) * e;
CLAMP(g);
b = luma * c + col * 1.772 * d;
CLAMP(b);
uint32_t* y2r[(y<<16) | (u<<8) | v] = (r<<16)|(g<<8)|b;
do_scale(struct rectlist* rect, uint32_t **target, size_t *targetsz, int* xscale, int* yscale, int* w, int* h) }
}
}
r2y_inited = 1;
}
struct graphics_buffer *
get_buffer(void)
{ {
struct graphics_buffer* ret = NULL;
if (free_list) {
ret = free_list;
free_list = free_list->next;
ret->next = NULL;
return ret;
}
ret = calloc(1, sizeof(struct graphics_buffer));
return ret;
}
void
release_buffer(struct graphics_buffer *buf)
{
buf->next = free_list;
free_list = buf;
}
struct graphics_buffer *
do_scale(struct rectlist* rect, int* xscale, int* yscale, double ratio)
{
struct graphics_buffer* ret1 = get_buffer();
struct graphics_buffer* ret2 = get_buffer();
int pointy5 = 0; int pointy5 = 0;
int pointy3 = 0; int pointy3 = 0;
int xbr2 = 0; int xbr2 = 0;
int xbr4 = 0; int xbr4 = 0;
int ymult = 1;
int xmult = 1;
int newscale = 1; int newscale = 1;
int total_scaling = 1; int total_xscaling = 1;
static uint32_t *tmptarget = NULL; int total_yscaling = 1;
static size_t tmptargetsz = 0; struct graphics_buffer *ctarget;
uint32_t *ctarget; struct graphics_buffer *csrc;
uint32_t *csrc = rect->data;
uint32_t* nt; uint32_t* nt;
int swidth = rect->rect.width; int fheight;
int sheight = rect->rect.height;
*w = rect->rect.width;
*h = rect->rect.height;
// As a first pass, only do equal integer scaling
if (*xscale != *yscale)
return rect->data;
switch (*xscale) { switch (*xscale) {
case 1: case 1:
return rect->data; break;
case 2: case 2:
xbr2 = 1; xbr2 = 1;
break; break;
...@@ -45,105 +124,155 @@ do_scale(struct rectlist* rect, uint32_t **target, size_t *targetsz, int* xscale ...@@ -45,105 +124,155 @@ do_scale(struct rectlist* rect, uint32_t **target, size_t *targetsz, int* xscale
pointy3 = 1; pointy3 = 1;
xbr2 = 1; xbr2 = 1;
break; break;
case 7: // TODO: Do we want a pointy7 and pointy11?
xmult = 7;
ymult = 7;
break;
default: default:
total_scaling = *xscale; total_xscaling = *xscale;
*xscale = 1; *xscale = 1;
while (total_scaling > 1 && ((total_scaling % 5) == 0)) { total_yscaling = *yscale;
*yscale = 1;
while (total_xscaling > 1 && ((total_xscaling % 5) == 0) && ((total_yscaling % 5) == 0)) {
pointy5++; pointy5++;
total_scaling /= 5; total_xscaling /= 5;
*xscale *= 5; *xscale *= 5;
total_yscaling /= 5;
*yscale *= 5;
} }
while (total_scaling > 1 && ((total_scaling % 3) == 0)) { while (total_xscaling > 1 && ((total_xscaling % 3) == 0) && ((total_yscaling % 3) == 0)) {
pointy3++; pointy3++;
total_scaling /= 3; total_xscaling /= 3;
*xscale *= 3; *xscale *= 3;
total_yscaling /= 3;
*yscale *= 3;
} }
while (total_scaling > 1 && ((total_scaling % 4) == 0)) { while (total_xscaling > 1 && ((total_xscaling % 4) == 0) && ((total_yscaling % 4) == 0)) {
xbr4++; xbr4++;
total_scaling /= 4; total_xscaling /= 4;
*xscale *= 4; *xscale *= 4;
total_yscaling /= 4;
*yscale *= 4;
} }
while (total_scaling > 1 && ((total_scaling % 2) == 0)) { while (total_xscaling > 1 && ((total_xscaling % 2) == 0) && ((total_yscaling % 2) == 0)) {
xbr2++; xbr2++;
total_scaling /= 2; total_xscaling /= 2;
*xscale *= 2; *xscale *= 2;
total_yscaling /= 2;
*yscale *= 2;
} }
if (*xscale == 1)
return rect->data;
break; break;
} }
if (*xscale != *yscale) {
if (*yscale == *xscale * 2)
ymult *= 2;
else
return NULL;
}
// Calculate the scaled height from ratio...
fheight = lround((double)(rect->rect.height * (*yscale)) / ratio);
// Now make sure target is big enough... // Now make sure target is big enough...
size_t needsz = rect->rect.width * rect->rect.height * (*xscale) * (*xscale) * sizeof(uint32_t); size_t needsz = rect->rect.width * (*xscale) * fheight * sizeof(uint32_t);
if (needsz > *targetsz) { if (needsz > ret1->sz) {
nt = realloc(*target, needsz); nt = realloc(ret1->data, needsz);
if (nt == NULL) if (nt == NULL)
return rect->data; return NULL;
*target = nt; ret1->data = nt;
*targetsz = needsz; ret1->sz = needsz;
} }
ctarget = *target;
if (needsz > ret2->sz) {
// And if we need an extra target, do the same there... nt = realloc(ret2->data, needsz);
if (pointy3 + pointy5 + xbr4 + xbr2 > 1) { if (nt == NULL)
if (needsz > tmptargetsz) { return NULL;
nt = realloc(tmptarget, needsz); ret2->data = nt;
if (nt == NULL) ret2->sz = needsz;
return rect->data;
tmptarget = nt;
tmptargetsz = needsz;
}
} }
// And finally, scale... // Copy rect into first buffer
// TODO: Unify bitmap rects and scaling buffers so this can just whomp on over.
csrc = ret1;
ctarget = ret2;
memcpy(csrc->data, rect->data, rect->rect.width * rect->rect.height * sizeof(rect->data[0]));
csrc->w = rect->rect.width;
csrc->h = rect->rect.height;
// And scale...
if (ymult != 1 || xmult != 1) {
multiply_scale(csrc->data, ctarget->data, csrc->w, csrc->h, xmult, ymult);
ctarget->w = csrc->w * xmult;
ctarget->h = csrc->h * ymult;
ymult = 1;
xmult = 1;
csrc = ctarget;
if (ctarget == ret1)
ctarget = ret2;
else
ctarget = ret1;
}
while (xbr4 > 0) { while (xbr4 > 0) {
xbr_filter(csrc, ctarget, swidth, sheight, 4); xbr_filter(csrc->data, ctarget->data, csrc->w, csrc->h, 4);
xbr4--; xbr4--;
swidth *= 4; ctarget->w = csrc->w * 4;
sheight *= 4; ctarget->h = csrc->h * 4;
csrc = ctarget; csrc = ctarget;
if (ctarget == tmptarget) if (ctarget == ret1)
ctarget = *target; ctarget = ret2;
else else
ctarget = tmptarget; ctarget = ret1;
} }
while (xbr2 > 0) { while (xbr2 > 0) {
xbr_filter(csrc, ctarget, swidth, sheight, 2); xbr_filter(csrc->data, ctarget->data, csrc->w, csrc->h, 2);
xbr2--; xbr2--;
swidth *= 2; ctarget->w = csrc->w * 2;
sheight *= 2; ctarget->h = csrc->h * 2;
csrc = ctarget; csrc = ctarget;
if (ctarget == tmptarget) if (ctarget == ret1)
ctarget = *target; ctarget = ret2;
else else
ctarget = tmptarget; ctarget = ret1;
} }
while (pointy5 > 0) { while (pointy5 > 0) {
pointy_scale5(csrc, ctarget, swidth, sheight); pointy_scale5(csrc->data, ctarget->data, csrc->w, csrc->h);
pointy5--; pointy5--;
swidth *= 5; ctarget->w = csrc->w * 5;
sheight *= 5; ctarget->h = csrc->h * 5;
csrc = ctarget; csrc = ctarget;
if (ctarget == tmptarget) if (ctarget == ret1)
ctarget = *target; ctarget = ret2;
else else
ctarget = tmptarget; ctarget = ret1;
} }
while (pointy3 > 0) { while (pointy3 > 0) {
pointy_scale3(csrc, ctarget, swidth, sheight); pointy_scale3(csrc->data, ctarget->data, csrc->w, csrc->h);
pointy3--; pointy3--;
swidth *= 3; ctarget->w = csrc->w * 3;
sheight *= 3; ctarget->h = csrc->h * 3;
csrc = ctarget; csrc = ctarget;
if (ctarget == tmptarget) if (ctarget == ret1)
ctarget = *target; ctarget = ret2;
else else
ctarget = tmptarget; ctarget = ret1;
} }
*w *= *xscale;
*h *= *xscale; // And finally, interpolate if needed
if (ratio != 1) {
interpolate_height(csrc->data, ctarget->data, csrc->w, csrc->h, fheight);
ctarget->h = fheight;
ctarget->w = csrc->w;
csrc = ctarget;
if (ctarget == ret1)
ctarget = ret2;
else
ctarget = ret1;
}
*xscale = newscale; *xscale = newscale;
*yscale = newscale; *yscale = newscale;
release_buffer(ctarget);
return csrc; return csrc;
} }
...@@ -339,3 +468,93 @@ pointy_scale3(uint32_t* src, uint32_t* dest, int width, int height) ...@@ -339,3 +468,93 @@ pointy_scale3(uint32_t* src, uint32_t* dest, int width, int height)
prevline = -width; prevline = -width;
} }
} }
static __attribute__((always_inline))
uint32_t blend(const uint32_t c1, const uint32_t c2, const double weight)
{
uint8_t yuv1[4];
uint8_t yuv2[4];
int y, u, v;
const double iw = 1.0 - weight;
*(uint32_t *)yuv1 = r2y[c1];
*(uint32_t *)yuv2 = r2y[c2];
#ifdef __BIG_ENDIAN__
y = yuv1[1] * iw + yuv2[1] * weight;
u = yuv1[2] * iw + yuv2[2] * weight;
v = yuv1[3] * iw + yuv2[3] * weight;
#else
y = yuv1[2] * iw + yuv2[2] * weight;
u = yuv1[1] * iw + yuv2[1] * weight;
v = yuv1[0] * iw + yuv2[0] * weight;
#endif
CLAMP(y);
CLAMP(u);
CLAMP(v);
return y2r[(y<<16)|(u<<8)|v];
}
/*
* This does non-integer *height* scaling. It does not scale in the other
* direction. This does the interpolation using Y'UV to prevent dimming of
* pixels.
*/
static void
interpolate_height(uint32_t* src, uint32_t* dst, int width, int height, int newheight)
{
int x, y;
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;
// 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;
if (pix1 == pix2)
*dst = pix1;
else {
*dst = blend(pix1, pix2, weight);
}
}
dst++;
}
}
}
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;
for (y = 0; y < height; y++) {
slstart = src;
for (my = 0; my < ymult; my++) {
src = slstart;
for (x = 0; x < width; x++) {
for (mx = 0; mx < xmult; mx++) {
*dst = *src;
dst++;
}
src++;
}
}
}
}
#include "bitmap_con.h" #include "bitmap_con.h"
uint32_t* do_scale(struct rectlist* rect, uint32_t **target, size_t *targetsz, int* xscale, int* yscale, int* w, int* h); struct graphics_buffer {
uint32_t* data;
size_t sz;
size_t w;
size_t h;
struct graphics_buffer *next;
};
extern uint32_t r2y[1<<24];
extern uint32_t y2r[1<<24];
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);
...@@ -85,7 +85,7 @@ static unsigned long base_pixel; ...@@ -85,7 +85,7 @@ static unsigned long base_pixel;
static int r_shift; static int r_shift;
static int g_shift; static int g_shift;
static int b_shift; static int b_shift;
static struct rectlist *last = NULL; static struct graphics_buffer *last = NULL;
/* Array of Graphics Contexts */ /* Array of Graphics Contexts */
static GC gc; static GC gc;
...@@ -208,9 +208,13 @@ static struct { ...@@ -208,9 +208,13 @@ static struct {
static void resize_xim(void) static void resize_xim(void)
{ {
int width = bitmap_width * x_cvstat.scaling;
double ratio = (double)x_cvstat.scale_numerator / x_cvstat.scale_denominator;
int height = lround((double)(bitmap_height * x_cvstat.scaling * x_cvstat.vmultiplier) / ratio);
if (xim) { if (xim) {
if (bitmap_width*x_cvstat.scaling == xim->width if (width == xim->width
&& bitmap_height*x_cvstat.scaling*x_cvstat.vmultiplier == xim->height) { && height == xim->height) {
return; return;
} }
#ifdef XDestroyImage #ifdef XDestroyImage
...@@ -220,11 +224,11 @@ static void resize_xim(void) ...@@ -220,11 +224,11 @@ static void resize_xim(void)
#endif #endif
} }
if (last) { if (last) {
bitmap_drv_free_rect(last); release_buffer(last);
last = NULL; last = NULL;
} }
xim=x11.XCreateImage(dpy,&visual,depth,ZPixmap,0,NULL,bitmap_width*x_cvstat.scaling,bitmap_height*x_cvstat.scaling*x_cvstat.vmultiplier,32,0); xim = x11.XCreateImage(dpy, &visual, depth, ZPixmap, 0, NULL, width, height, 32, 0);
xim->data=(char *)malloc(xim->bytes_per_line*xim->height); xim->data=(char *)calloc(1, xim->bytes_per_line*xim->height);
} }
/* Swiped from FreeBSD libc */ /* Swiped from FreeBSD libc */
...@@ -346,6 +350,7 @@ static int init_window() ...@@ -346,6 +350,7 @@ static int init_window()
static void map_window() static void map_window()
{ {
XSizeHints *sh; XSizeHints *sh;
int scaled_height;
sh = x11.XAllocSizeHints(); sh = x11.XAllocSizeHints();
if (sh == NULL) { if (sh == NULL) {
...@@ -357,7 +362,9 @@ static void map_window() ...@@ -357,7 +362,9 @@ static void map_window()
sh->base_height = bitmap_height*x_cvstat.scaling*x_cvstat.vmultiplier; sh->base_height = bitmap_height*x_cvstat.scaling*x_cvstat.vmultiplier;
sh->min_width = sh->width_inc = sh->min_aspect.x = sh->max_aspect.x = bitmap_width; sh->min_width = sh->width_inc = sh->min_aspect.x = sh->max_aspect.x = bitmap_width;
sh->min_height = sh->height_inc = sh->min_aspect.y = sh->max_aspect.y = bitmap_height;
scaled_height = ceil((double)bitmap_height*x_cvstat.vmultiplier / ((double)x_cvstat.scale_numerator / x_cvstat.scale_denominator));
sh->min_height = sh->height_inc = sh->min_aspect.y = sh->max_aspect.y = scaled_height;
sh->flags = USSize | PMinSize | PSize | PResizeInc | PAspect; sh->flags = USSize | PMinSize | PSize | PResizeInc | PAspect;
x11.XSetWMNormalHints(dpy, win, sh); x11.XSetWMNormalHints(dpy, win, sh);
...@@ -371,10 +378,11 @@ static void map_window() ...@@ -371,10 +378,11 @@ static void map_window()
/* Resize the window. This function is called after a mode change. */ /* Resize the window. This function is called after a mode change. */
static void resize_window() static void resize_window()
{ {
x11.XResizeWindow(dpy, win, bitmap_width*x_cvstat.scaling, bitmap_height*x_cvstat.scaling*x_cvstat.vmultiplier); int scaled_height = ceil((double)bitmap_height*x_cvstat.scaling*x_cvstat.vmultiplier / ((double)x_cvstat.scale_numerator / x_cvstat.scale_denominator));
resize_xim(); x11.XResizeWindow(dpy, win, bitmap_width*x_cvstat.scaling, scaled_height);
resize_xim();
return; return;
} }
static void init_mode_internal(int mode) static void init_mode_internal(int mode)
...@@ -386,7 +394,7 @@ static void init_mode_internal(int mode) ...@@ -386,7 +394,7 @@ static void init_mode_internal(int mode)
pthread_mutex_lock(&blinker_lock); pthread_mutex_lock(&blinker_lock);
pthread_mutex_lock(&vstatlock); pthread_mutex_lock(&vstatlock);
if (last) { if (last) {
bitmap_drv_free_rect(last); release_buffer(last);
last = NULL; last = NULL;
} }
bitmap_drv_init_mode(mode, &bitmap_width, &bitmap_height); bitmap_drv_init_mode(mode, &bitmap_width, &bitmap_height);
...@@ -451,7 +459,6 @@ static void local_draw_rect(struct rectlist *rect) ...@@ -451,7 +459,6 @@ static void local_draw_rect(struct rectlist *rect)
{ {
int x,y,xscale,yscale,xoff=0,yoff=0; int x,y,xscale,yscale,xoff=0,yoff=0;
int xscaling, yscaling; int xscaling, yscaling;
int rxscaling, ryscaling;
unsigned int r, g, b; unsigned int r, g, b;
unsigned long pixel; unsigned long pixel;
int cleft; int cleft;
...@@ -459,14 +466,9 @@ static void local_draw_rect(struct rectlist *rect) ...@@ -459,14 +466,9 @@ static void local_draw_rect(struct rectlist *rect)
int ctop; int ctop;
int cbottom = -1; int cbottom = -1;
int idx; int idx;
int ridx;
int ridx_part;
uint32_t last_pixel = 0x55555555; uint32_t last_pixel = 0x55555555;
static uint32_t* target = NULL; struct graphics_buffer *source;
size_t targetsz = 0; int lines;
uint32_t* source;
int width, height;
int lheight, lines;
if (bitmap_width != rect->rect.width || bitmap_height != rect->rect.height) if (bitmap_width != rect->rect.width || bitmap_height != rect->rect.height)
return; return;
...@@ -481,23 +483,32 @@ static void local_draw_rect(struct rectlist *rect) ...@@ -481,23 +483,32 @@ static void local_draw_rect(struct rectlist *rect)
// Scale... // Scale...
xscaling = x_cvstat.scaling; xscaling = x_cvstat.scaling;
yscaling = x_cvstat.scaling*x_cvstat.vmultiplier; yscaling = x_cvstat.scaling*x_cvstat.vmultiplier;
source = do_scale(rect, &target, &targetsz, &xscaling, &yscaling, &width, &height); source = do_scale(rect, &xscaling, &yscaling, (double)x_cvstat.scale_numerator / x_cvstat.scale_denominator);
rxscaling = width / rect->rect.width; bitmap_drv_free_rect(rect);
ryscaling = height / rect->rect.height; if (source == NULL)
cleft = width; return;
ctop = height; cleft = source->w;
ctop = source->h;
lines = 0; lines = 0;
lheight = x_cvstat.charheight * ryscaling;
xoff = (x11_window_width - source->w) / 2;
if (xoff < 0)
xoff = 0;
yoff = (x11_window_height - source->h) / 2;
if (yoff < 0)
yoff = 0;
if (last && (last->w != source->w || last->h != source->h)) {
release_buffer(last);
last = NULL;
}
/* TODO: Translate into local colour depth */ /* TODO: Translate into local colour depth */
for(y=0;y<height;y++) { idx = 0;
idx = y * width; for (y = 0; y < source->h; y++) {
ridx = y / ryscaling * rect->rect.width; for (x = 0; x < source->w; x++) {
ridx_part = 0;
for(x=0; x<width; x++) {
if (last) { if (last) {
// TODO: Based on source pixel, not target pixel. :( if (last->data[idx] != source->data[idx]) {
if (last->data[ridx] != rect->data[ridx]) {
if (x < cleft) if (x < cleft)
cleft = x; cleft = x;
if (x > cright) if (x > cright)
...@@ -508,29 +519,15 @@ static void local_draw_rect(struct rectlist *rect) ...@@ -508,29 +519,15 @@ static void local_draw_rect(struct rectlist *rect)
cbottom = y; cbottom = y;
} }
else { else {
if (source == rect->data) { idx++;
idx += (rxscaling); continue;
x += (rxscaling - 1);
ridx++;
continue;
}
else {
if (cright < x - rxscaling * 2
&& (x >= width - (rxscaling * 3)
|| last->data[ridx + 1] == rect->data[ridx + 1])) {
idx += (rxscaling);
x += (rxscaling - 1);
ridx++;
continue;
}
}
} }
} }
if (last_pixel != source[idx]) { if (last_pixel != source->data[idx]) {
last_pixel = source[idx]; last_pixel = source->data[idx];
r = source[idx] >> 16 & 0xff; r = source->data[idx] >> 16 & 0xff;
g = source[idx] >> 8 & 0xff; g = source->data[idx] >> 8 & 0xff;
b = source[idx] & 0xff; b = source->data[idx] & 0xff;
r = (r<<8)|r; r = (r<<8)|r;
g = (g<<8)|g; g = (g<<8)|g;
b = (b<<8)|b; b = (b<<8)|b;
...@@ -560,54 +557,36 @@ static void local_draw_rect(struct rectlist *rect) ...@@ -560,54 +557,36 @@ static void local_draw_rect(struct rectlist *rect)
} }
} }
idx++; idx++;
ridx_part++;
if (ridx_part >= rxscaling) {
ridx_part = 0;
ridx++;
}
} }
lines++; lines++;
/* This line was changed */ /* This line was changed */
if (last && ((lines == lheight) || (y == height - 1)) && cright >= 0) { // TODO: Previously this did one update per display line...
#ifdef USE_XBRZ if (last && (cbottom != y || y == source->h - 1) && cright >= 0) {
if (source != rect->data) {
cleft -= 2 * rxscaling;
if (cleft < 0)
cleft = 0;
cright += 2 * rxscaling;
if (cright >= width)
cright = width - 1;
}
#endif
lines = 0; lines = 0;
x11.XPutImage(dpy, win, gc, xim, cleft * xscaling, ctop * yscaling x11.XPutImage(dpy, win, gc, xim, cleft * xscaling, ctop * yscaling
, cleft * xscaling + xoff, ctop * yscaling + yoff , cleft * xscaling + xoff, ctop * yscaling + yoff
, (cright - cleft + 1) * xscaling, (cbottom - ctop + 1) * yscaling); , (cright - cleft + 1) * xscaling, (cbottom - ctop + 1) * yscaling);
cleft = width; cleft = source->w;
cright = cbottom = -100; cright = cbottom = -100;
ctop = height; ctop = source->h;
} }
} }
if (last == NULL) 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, width * xscaling, height * yscaling); 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);
else else
bitmap_drv_free_rect(last); release_buffer(last);
last = rect; last = source;
} }
static void handle_resize_event(int width, int height) static void handle_resize_event(int width, int height)
{ {
int newFSH=1; int newFSH=1;
int newFSW=1; int newFSW=1;
double ratio = (double)x_cvstat.scale_numerator / x_cvstat.scale_denominator;
// No change
if((width == x_cvstat.charwidth * x_cvstat.cols * x_cvstat.scaling)
&& (height == x_cvstat.charheight * x_cvstat.rows * x_cvstat.scaling*x_cvstat.vmultiplier))
return;
newFSH=width/bitmap_width; newFSH=width/bitmap_width;
newFSW=height/bitmap_height; newFSW=floor((double)height / bitmap_height * ratio);
if(newFSW<1) if(newFSW<1)
newFSW=1; newFSW=1;
if(newFSH<1) if(newFSH<1)
...@@ -627,9 +606,11 @@ static void handle_resize_event(int width, int height) ...@@ -627,9 +606,11 @@ static void handle_resize_event(int width, int height)
*/ */
if (newFSH != newFSW) if (newFSH != newFSW)
resize_window(); resize_window();
#if 0 // TODO: Is this even worth looking at?
else if((width % (x_cvstat.charwidth * x_cvstat.cols) != 0) else if((width % (x_cvstat.charwidth * x_cvstat.cols) != 0)
|| (height % (x_cvstat.charheight * x_cvstat.rows) != 0)) || (height % (x_cvstat.charheight * x_cvstat.rows) != 0))
resize_window(); resize_window();
#endif
else else
resize_xim(); resize_xim();
bitmap_drv_request_pixels(); bitmap_drv_request_pixels();
...@@ -680,7 +661,7 @@ static void expose_rect(int x, int y, int width, int height) ...@@ -680,7 +661,7 @@ static void expose_rect(int x, int y, int width, int height)
/* Since we're exposing, we *have* to redraw */ /* Since we're exposing, we *have* to redraw */
if (last) { if (last) {
bitmap_drv_free_rect(last); release_buffer(last);
last = NULL; last = NULL;
bitmap_drv_request_some_pixels(sx, sy, ex-sx+1, ey-sy+1); bitmap_drv_request_some_pixels(sx, sy, ex-sx+1, ey-sy+1);
} }
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <inttypes.h> #include <inttypes.h>
#include <stdlib.h> #include <stdlib.h>
#include "scale.h"
#define LB_MASK 0x00FEFEFE #define LB_MASK 0x00FEFEFE
#define RED_BLUE_MASK 0x00FF00FF #define RED_BLUE_MASK 0x00FF00FF
...@@ -39,8 +40,6 @@ ...@@ -39,8 +40,6 @@
#undef PI #undef PI
#endif #endif
uint32_t r2y[1<<24];
static uint32_t pixel_diff(uint32_t x, uint32_t y) static uint32_t pixel_diff(uint32_t x, uint32_t y)
{ {
#define YMASK 0xff0000 #define YMASK 0xff0000
...@@ -190,6 +189,13 @@ static uint32_t pixel_diff(uint32_t x, uint32_t y) ...@@ -190,6 +189,13 @@ static uint32_t pixel_diff(uint32_t x, uint32_t y)
} \ } \
} while (0) } while (0)
#define CLAMP(x) do { \
if (x < 0) \
x = 0; \
else if (x > 255) \
x = 255; \
} while(0)
void void
xbr_filter(uint32_t *data, uint32_t *out, int width, int height, int n) xbr_filter(uint32_t *data, uint32_t *out, int width, int height, int n)
{ {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment