mirror of
https://github.com/Interlisp/maiko.git
synced 2026-01-14 23:46:14 +00:00
Implement bitblt to texture at bit level rather than word level, some cleanup
sdl_bitblt_to_texture2 is an experiment, parallel to sdl_bitblt_to_texture that only moves as many bits as are required, rather than rounding down(up) to the nearest (16-bit) word boundary for the start(end) of the line. Introduces some name changes to make things a little clearer.
This commit is contained in:
parent
78bcb188a8
commit
878168f4f5
176
src/sdl.c
176
src/sdl.c
@ -19,6 +19,8 @@ static SDL_Texture *sdl_texture = NULL;
|
||||
#else
|
||||
static SDL_Surface *sdl_windowsurface = NULL;
|
||||
static SDL_Surface *sdl_buffersurface = NULL;
|
||||
static int buffer_size = 0;
|
||||
static void *buffer = NULL;
|
||||
#endif
|
||||
static Uint32 sdl_white;
|
||||
static Uint32 sdl_black;
|
||||
@ -26,8 +28,6 @@ static Uint32 sdl_foreground;
|
||||
static Uint32 sdl_background;
|
||||
static int sdl_bytesperpixel;
|
||||
static SDL_PixelFormat *sdl_pixelformat;
|
||||
static int buffer_size = 0;
|
||||
static void *buffer = NULL;
|
||||
|
||||
extern void kb_trans(u_short keycode, u_short upflg);
|
||||
extern int error(const char *s);
|
||||
@ -216,7 +216,7 @@ static int min(int a, int b) {
|
||||
return b;
|
||||
}
|
||||
|
||||
static int should_update_texture = 0;
|
||||
static int display_update_needed = 0;
|
||||
|
||||
static int min_x = 0;
|
||||
static int min_y = 0;
|
||||
@ -231,7 +231,7 @@ void sdl_notify_damage(int x, int y, int w, int h) {
|
||||
max_x = min(x + w, sdl_displaywidth - 1);
|
||||
if(y + h > max_y)
|
||||
max_y = min(y + h, sdl_displayheight - 1);
|
||||
should_update_texture = 1;
|
||||
display_update_needed = 1;
|
||||
}
|
||||
|
||||
/* a simple linked list to remember generated cursors
|
||||
@ -286,6 +286,7 @@ static SDL_Cursor *sdl_getOrAllocateCursor(Uint8 cursor[32], int hot_x, int hot_
|
||||
/*
|
||||
* Read a cursor bitmap from lisp. Try to find a cached cursor, then use that.
|
||||
* Use HOT_X and HOT_Y as the cursor hotspot.
|
||||
* XXX: needs to deal with sdl_pixelscale > 1, and where is the hotspot?
|
||||
*/
|
||||
void sdl_setCursor(int hot_x, int hot_y) {
|
||||
DLword *newbm = ((DLword *)(IOPage->dlcursorbitmap));
|
||||
@ -310,51 +311,86 @@ void sdl_setCursor(int hot_x, int hot_y) {
|
||||
#if defined(SDLRENDERING)
|
||||
void sdl_bitblt_to_texture(int _x, int _y, int _w, int _h) {
|
||||
// printf("bitblt(%d, %d, %d, %d)\n", _x, _y, _w, _h);
|
||||
// Uint32 *dr = (Uint32 *)DisplayRegion68k;
|
||||
// Uint32 *src = (Uint32 *)DisplayRegion68k;
|
||||
static const DLword mask[16] = {1<<15, 1<<14, 1<<13, 1<<12, 1<<11, 1<<10, 1<<9, 1<<8,
|
||||
1<<7, 1<<6, 1<<5, 1<<4, 1<<3, 1<<2, 1<<1, 1<<0};
|
||||
DLword *dr = DisplayRegion68k;
|
||||
void *destbuffer;
|
||||
int destpitchbytes;
|
||||
int destpitchpixels;
|
||||
// const int bitsperword = 8 * sizeof(Uint32);
|
||||
DLword *src = DisplayRegion68k;
|
||||
void *dst;
|
||||
int dstpitchbytes;
|
||||
int dstpitchpixels;
|
||||
const int bitsperword = 8 * sizeof(DLword);
|
||||
int sourcepitchwords = sdl_displaywidth / bitsperword;
|
||||
int xstart = _x / bitsperword;
|
||||
int xlimit = (_x + _w + bitsperword - 1) / bitsperword;
|
||||
int ystart = _y * sourcepitchwords;
|
||||
int ylimit = (_y + _h) * sourcepitchwords;
|
||||
SDL_Rect destrect;
|
||||
SDL_Rect dstrect;
|
||||
/* printf("_x %d _y %d _w %d _h %d; xstart %d xlimit %d ystart %d ylimit %d sourcepitchwords %d\n",
|
||||
_x, _y, _w, _h, xstart, xlimit, ystart, ylimit, sourcepitchwords); */
|
||||
// Avoid dealing with partial words in the update by stretching the source rectangle
|
||||
// left and right to cover complete units (32-bit words) and lock the corresponding
|
||||
// left and right to cover complete units and lock the corresponding
|
||||
// region in the texture
|
||||
destrect.x = (_x / bitsperword) * bitsperword;
|
||||
destrect.w = ((_x + _w + bitsperword - 1) / bitsperword * bitsperword) - destrect.x;
|
||||
destrect.y = _y;
|
||||
destrect.h = _h;
|
||||
SDL_LockTexture(sdl_texture, &destrect, &destbuffer, &destpitchbytes);
|
||||
destpitchpixels = destpitchbytes / sdl_bytesperpixel;
|
||||
dstrect.x = (_x / bitsperword) * bitsperword;
|
||||
dstrect.w = ((_x + _w + bitsperword - 1) / bitsperword * bitsperword) - dstrect.x;
|
||||
dstrect.y = _y;
|
||||
dstrect.h = _h;
|
||||
SDL_LockTexture(sdl_texture, &dstrect, &dst, &dstpitchbytes);
|
||||
dstpitchpixels = dstpitchbytes / sdl_bytesperpixel;
|
||||
int dy = 0;
|
||||
// for each line in the source image
|
||||
for(int sy = ystart; sy < ylimit ; sy += sourcepitchwords, dy += destpitchpixels) {
|
||||
for(int sy = ystart; sy < ylimit ; sy += sourcepitchwords, dy += dstpitchpixels) {
|
||||
// for each word in the line
|
||||
int dx = 0;
|
||||
for(int sx = xstart; sx < xlimit; sx++, dx += bitsperword) {
|
||||
int w = GETBASEWORD(dr, sy + sx);
|
||||
int srcw = GETBASEWORD(src, sy + sx);
|
||||
// for each bit in the word
|
||||
for(int b = 0; b < bitsperword; b++) {
|
||||
((Uint32 *)destbuffer)[dy + dx + b] = (w & mask[b]) ? sdl_foreground : sdl_background;
|
||||
((Uint32 *)dst)[dy + dx + b] = (srcw & mask[b]) ? sdl_foreground : sdl_background;
|
||||
}
|
||||
}
|
||||
}
|
||||
SDL_UnlockTexture(sdl_texture);
|
||||
}
|
||||
void sdl_bitblt_to_texture2(int _x, int _y, int _w, int _h) {
|
||||
static const int mask[16] = {1<<15, 1<<14, 1<<13, 1<<12, 1<<11, 1<<10, 1<<9, 1<<8,
|
||||
1<<7, 1<<6, 1<<5, 1<<4, 1<<3, 1<<2, 1<<1, 1<<0};
|
||||
DLword *src = DisplayRegion68k;
|
||||
void *dst;
|
||||
int dstpitchbytes;
|
||||
int dstpitchpixels;
|
||||
const int bitsperword = 8 * sizeof(DLword);
|
||||
int sourcepitchwords = sdl_displaywidth / bitsperword;
|
||||
int xstart = _x / bitsperword; // "word" index of first accessed word in line
|
||||
int xstartb = _x % bitsperword; // bit within word
|
||||
int xlimit = (_x + _w + bitsperword - 1) / bitsperword; // word index
|
||||
int ystart = _y * sourcepitchwords;
|
||||
int ylimit = (_y + _h) * sourcepitchwords;
|
||||
SDL_Rect dstrect = {.x = _x, .y = _y, .w = _w, .h = _h};
|
||||
SDL_LockTexture(sdl_texture, &dstrect, &dst, &dstpitchbytes);
|
||||
dstpitchpixels = dstpitchbytes / sdl_bytesperpixel;
|
||||
int dy = 0;
|
||||
// for each line in the source image
|
||||
for(int sy = ystart; sy < ylimit ; sy += sourcepitchwords, dy += dstpitchpixels) {
|
||||
int dx = 0;
|
||||
int sx = xstart;
|
||||
int b = xstartb;
|
||||
int srcw = GETBASEWORD(src, sy + sx);
|
||||
// for each pixel within the dstination region line
|
||||
for (int dx = 0; dx < _w; dx++) {
|
||||
((Uint32 *)dst)[dy + dx] = (srcw & mask[b]) ? sdl_foreground : sdl_background;
|
||||
if (++b == bitsperword) {
|
||||
b = 0;
|
||||
sx++;
|
||||
srcw = GETBASEWORD(src, sy + sx);
|
||||
}
|
||||
}
|
||||
}
|
||||
SDL_UnlockTexture(sdl_texture);
|
||||
}
|
||||
#else
|
||||
void sdl_bitblt_to_screen(int _x, int _y, int _w, int _h) {
|
||||
void sdl_bitblt_to_buffer(int _x, int _y, int _w, int _h) {
|
||||
// printf("bitblt(%d, %d, %d, %d)\n", _x, _y, _w, _h);
|
||||
Uint32 *dr = (Uint32*)DisplayRegion68k;
|
||||
Uint32 *src = (Uint32*)DisplayRegion68k;
|
||||
|
||||
int before = SDL_GetTicks();
|
||||
int width = sdl_displaywidth;
|
||||
@ -366,12 +402,12 @@ void sdl_bitblt_to_screen(int _x, int _y, int _w, int _h) {
|
||||
for(int y = _y; y < ylimit; y++) {
|
||||
int they = y * sdl_displaywidth;
|
||||
for(int x = _x / bpw; x < xlimit; x++) {
|
||||
int w = dr[y * pitch + x];
|
||||
int srcw = src[y * pitch + x];
|
||||
int thex = x * bpw;
|
||||
for(int b = 0; b < bpw; b++) {
|
||||
//printf("%d/%d %d\n", x, y, b);
|
||||
uint32_t px = 0;
|
||||
if(w & (1 << (bpw - 1 - b))) {
|
||||
if(srcw & (1 << (bpw - 1 - b))) {
|
||||
px = sdl_foreground;
|
||||
} else {
|
||||
px = sdl_background;
|
||||
@ -387,37 +423,31 @@ void sdl_bitblt_to_screen(int _x, int _y, int _w, int _h) {
|
||||
// printf("bitblting took %dms\n", after - before);
|
||||
}
|
||||
void sdl_bitblt_to_window_surface(int _x, int _y, int _w, int _h) {
|
||||
// printf("bitblt(%d, %d, %d, %d)\n", _x, _y, _w, _h);
|
||||
Uint32 *dr = (Uint32*)DisplayRegion68k;
|
||||
|
||||
int before = SDL_GetTicks();
|
||||
int width = sdl_displaywidth;
|
||||
int height = sdl_displayheight;
|
||||
int bpw = 8 * sizeof(Uint32);
|
||||
int pitch = sdl_displaywidth / bpw;
|
||||
int xlimit = (_x + _w + bpw - 1) / bpw;
|
||||
int ylimit = _y + _h;
|
||||
for(int y = _y; y < ylimit; y++) {
|
||||
int they = y * sdl_displaywidth;
|
||||
for(int x = _x / bpw; x < xlimit; x++) {
|
||||
int w = dr[y * pitch + x];
|
||||
int thex = x * bpw;
|
||||
for(int b = 0; b < bpw; b++) {
|
||||
//printf("%d/%d %d\n", x, y, b);
|
||||
uint32_t px = 0;
|
||||
if(w & (1 << (bpw - 1 - b))) {
|
||||
px = sdl_foreground;
|
||||
} else {
|
||||
px = sdl_background;
|
||||
}
|
||||
//printf("px is %x\n", px);
|
||||
int pxindex = they + thex + b;
|
||||
assert(pxindex >= 0 && pxindex < buffer_size);
|
||||
((Uint32 *)sdl_windowsurface->pixels)[pxindex] = px;
|
||||
static const DLword mask[16] = {1<<15, 1<<14, 1<<13, 1<<12, 1<<11, 1<<10, 1<<9, 1<<8,
|
||||
1<<7, 1<<6, 1<<5, 1<<4, 1<<3, 1<<2, 1<<1, 1<<0};
|
||||
DLword *src = DisplayRegion68k;
|
||||
Uint32 *dst = (Uint32 *)sdl_windowsurface->pixels;
|
||||
int dstpitchbytes = sdl_windowsurface->pitch;
|
||||
int dstpitchpixels = dstpitchbytes / sdl_bytesperpixel;
|
||||
const int bitsperword = 8 * sizeof(DLword);
|
||||
int sourcepitchwords = sdl_displaywidth / bitsperword;
|
||||
int xstart = _x / bitsperword;
|
||||
int xlimit = (_x + _w + bitsperword - 1) / bitsperword;
|
||||
int ystart = _y * sourcepitchwords;
|
||||
int ylimit = (_y + _h) * sourcepitchwords;
|
||||
int dy = _y * dstpitchpixels;
|
||||
// for each line in the source image
|
||||
for(int sy = ystart; sy < ylimit ; sy += sourcepitchwords, dy += dstpitchpixels) {
|
||||
// for each word in the line
|
||||
int dx = (_x / bitsperword) * bitsperword;
|
||||
for(int sx = xstart; sx < xlimit; sx++, dx+=bitsperword) {
|
||||
int srcw = GETBASEWORD(src, sy + sx);
|
||||
// for each bit in the word
|
||||
for(int b = 0; b < bitsperword; b++) {
|
||||
((Uint32 *)dst)[dy + dx + b] = (srcw & mask[b]) ? sdl_foreground : sdl_background;
|
||||
}
|
||||
}
|
||||
}
|
||||
int after = SDL_GetTicks();
|
||||
// printf("bitblting took %dms\n", after - before);
|
||||
}
|
||||
#endif
|
||||
@ -520,25 +550,24 @@ void sdl_setMousePosition(int x, int y) {
|
||||
SDL_WarpMouseInWindow(sdl_window, x * sdl_pixelscale, y * sdl_pixelscale);
|
||||
}
|
||||
#if defined(SDLRENDERING)
|
||||
void sdl_update_display_rendering() {
|
||||
void sdl_update_display() {
|
||||
int before = 0;
|
||||
int after = 0;
|
||||
|
||||
if(should_update_texture) {
|
||||
before = SDL_GetTicks();
|
||||
sdl_bitblt_to_texture(min_x, min_y, max_x - min_x, max_y - min_y);
|
||||
after = SDL_GetTicks();
|
||||
// printf("UpdateTexture took %dms\n", after - before);
|
||||
should_update_texture = 0;
|
||||
min_x = sdl_displaywidth;
|
||||
min_y = sdl_displayheight;
|
||||
max_x = max_y = 0;
|
||||
}
|
||||
int this_draw = SDL_GetTicks();
|
||||
if(this_draw - last_draw <= 16) return;
|
||||
|
||||
sdl_bitblt_to_texture2(min_x, min_y, max_x - min_x, max_y - min_y);
|
||||
after = SDL_GetTicks();
|
||||
// printf("UpdateTexture took %dms\n", after - before);
|
||||
display_update_needed = 0;
|
||||
min_x = sdl_displaywidth;
|
||||
min_y = sdl_displayheight;
|
||||
max_x = max_y = 0;
|
||||
|
||||
before = SDL_GetTicks();
|
||||
|
||||
|
||||
if(this_draw - last_draw > 10) {
|
||||
before = SDL_GetTicks();
|
||||
//SDL_RenderClear(sdl_renderer);
|
||||
SDL_Rect r;
|
||||
@ -557,16 +586,15 @@ void sdl_update_display_rendering() {
|
||||
last_draw = this_draw;
|
||||
after = SDL_GetTicks();
|
||||
// printf("rendering took %dms\n", after - before);
|
||||
}
|
||||
}
|
||||
#else
|
||||
void sdl_update_display_surfaces() {
|
||||
void sdl_update_display() {
|
||||
int before = 0;
|
||||
int after = 0;
|
||||
int this_draw = SDL_GetTicks();
|
||||
|
||||
/* check if there's anything to do and sufficient time has elapsed */
|
||||
if (!should_update_texture || this_draw - last_draw <= 16) {
|
||||
if (!display_update_needed || this_draw - last_draw <= 16) {
|
||||
return;
|
||||
}
|
||||
SDL_Rect r;
|
||||
@ -583,7 +611,7 @@ void sdl_update_display_surfaces() {
|
||||
s.y = r.y * sdl_pixelscale;
|
||||
s.w = r.w * sdl_pixelscale;
|
||||
s.h = r.h * sdl_pixelscale;
|
||||
sdl_bitblt_to_screen(r.x, r.y, r.w, r.h);
|
||||
sdl_bitblt_to_buffer(r.x, r.y, r.w, r.h);
|
||||
SDL_BlitScaled(sdl_buffersurface, &r, sdl_windowsurface, &s);
|
||||
SDL_UpdateWindowSurfaceRects(sdl_window, &s, 1);
|
||||
}
|
||||
@ -591,7 +619,7 @@ void sdl_update_display_surfaces() {
|
||||
max_x = 0;
|
||||
min_y = sdl_displayheight;
|
||||
max_y = 0;
|
||||
should_update_texture = 0;
|
||||
display_update_needed = 0;
|
||||
after = SDL_GetTicks();
|
||||
last_draw = this_draw;
|
||||
// printf("surface update took %dms\n", after - before);
|
||||
@ -685,11 +713,9 @@ void process_SDLevents() {
|
||||
printf("other event type: %d\n", event.type);
|
||||
}
|
||||
}
|
||||
#if defined(SDLRENDERING)
|
||||
sdl_update_display_rendering();
|
||||
#else
|
||||
sdl_update_display_surfaces();
|
||||
#endif
|
||||
if (display_update_needed) {
|
||||
sdl_update_display();
|
||||
}
|
||||
}
|
||||
|
||||
int init_SDL(char *windowtitle, int w, int h, int s) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user