From 618e0aaa31b4728eb4df78ec4de6c2b873908eda Mon Sep 17 00:00:00 2001 From: William McBrine Date: Sat, 21 Dec 2019 17:12:00 -0500 Subject: [PATCH] Partial reversal of 6e6962. Issue #61 remains fixed. I couldn't get the "new style" stable under Linux. Other fixes still applied. --- sdl2/README.md | 1 + sdl2/pdcdisp.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++---- sdl2/pdckbd.c | 3 +- sdl2/pdcscrn.c | 54 ++++++++++++++-------------- sdl2/pdcsdl.h | 5 +-- sdl2/sdltest.c | 5 +-- 6 files changed, 123 insertions(+), 41 deletions(-) diff --git a/sdl2/README.md b/sdl2/README.md index 5a8a5da8..aefe4e2d 100644 --- a/sdl2/README.md +++ b/sdl2/README.md @@ -134,6 +134,7 @@ include pdcsdl.h, or just add the declarations you need in your code: PDCEX SDL_Surface *pdc_screen, *pdc_font, *pdc_icon, *pdc_back; PDCEX int pdc_sheight, pdc_swidth, pdc_yoffset, pdc_xoffset; + PDCEX void PDC_update_rects(void); PDCEX void PDC_retile(void); pdc_window is the main window, created by SDL_CreateWindow(), unless diff --git a/sdl2/pdcdisp.c b/sdl2/pdcdisp.c index 52c266f1..a3c27163 100644 --- a/sdl2/pdcdisp.c +++ b/sdl2/pdcdisp.c @@ -11,10 +11,65 @@ # include "../common/acs437.h" #endif +#define MAXRECT 200 /* maximum number of rects to queue up before + an update is forced; the number was chosen + arbitrarily */ + +static SDL_Rect uprect[MAXRECT]; /* table of rects to update */ static chtype oldch = (chtype)(-1); /* current attribute */ +static int rectcount = 0; /* index into uprect */ static short foregr = -2, backgr = -2; /* current foreground, background */ static bool blinked_off = FALSE; +/* do the real updates on a delay */ + +void PDC_update_rects(void) +{ + int i; + + if (rectcount) + { + /* if the maximum number of rects has been reached, we're + probably better off doing a full screen update */ + + if (rectcount == MAXRECT) + SDL_UpdateWindowSurface(pdc_window); + else + { + int w = pdc_screen->w; + int h = pdc_screen->h; + + for (i = 0; i < rectcount; i++) + { + if (uprect[i].x > w || + uprect[i].y > h || + !uprect[i].w || !uprect[i].h) + { + if (i + 1 < rectcount) + { + memmove(uprect + i, uprect + i + 1, + (rectcount - i + 1) * sizeof(*uprect)); + --i; + } + rectcount--; + continue; + } + + if (uprect[i].x + uprect[i].w > w) + uprect[i].w = min(w, w - uprect[i].x); + + if (uprect[i].y + uprect[i].h > h) + uprect[i].h = min(h, h - uprect[i].y); + } + + if (rectcount > 0) + SDL_UpdateWindowSurfaceRects(pdc_window, uprect, rectcount); + } + + rectcount = 0; + } +} + /* set the font colors to match the chtype's attribute */ static void _set_attr(chtype ch) @@ -267,11 +322,19 @@ void PDC_gotoyx(int row, int col) SDL_BlitSurface(pdc_font, &src, pdc_screen, &dest); #endif + + if (oldrow != row || oldcol != col) + { + if (rectcount == MAXRECT) + PDC_update_rects(); + + uprect[rectcount++] = dest; + } } void _new_packet(attr_t attr, int lineno, int x, int len, const chtype *srcp) { - SDL_Rect src, dest; + SDL_Rect src, dest, lastrect; int j; #ifdef PDC_WIDE Uint16 chstr[2] = {0, 0}; @@ -280,6 +343,9 @@ void _new_packet(attr_t attr, int lineno, int x, int len, const chtype *srcp) short hcol = SP->line_color; bool blink = blinked_off && (attr & A_BLINK) && (sysattrs & A_BLINK); + if (rectcount == MAXRECT) + PDC_update_rects(); + #ifdef PDC_WIDE src.x = 0; src.y = 0; @@ -292,6 +358,24 @@ void _new_packet(attr_t attr, int lineno, int x, int len, const chtype *srcp) dest.h = pdc_fheight; dest.w = pdc_fwidth * len; + /* if the previous rect was just above this one, with the same width + and horizontal position, then merge the new one with it instead + of adding a new entry */ + + if (rectcount) + lastrect = uprect[rectcount - 1]; + + if (rectcount && lastrect.x == dest.x && lastrect.w == dest.w) + { + if (lastrect.y + lastrect.h == dest.y) + uprect[rectcount - 1].h = lastrect.h + pdc_fheight; + else + if (lastrect.y != dest.y) + uprect[rectcount++] = dest; + } + else + uprect[rectcount++] = dest; + _set_attr(attr); if (backgr == -1) @@ -474,10 +558,7 @@ void PDC_blink_text(void) void PDC_doupdate(void) { - SDL_UpdateTexture(pdc_texture, NULL, pdc_screen->pixels, pdc_screen->pitch); - SDL_RenderClear(pdc_renderer); - SDL_RenderCopy(pdc_renderer, pdc_texture, NULL, NULL); - SDL_RenderPresent(pdc_renderer); + PDC_update_rects(); } void PDC_pump_and_peep(void) @@ -489,7 +570,10 @@ void PDC_pump_and_peep(void) if (SDL_WINDOWEVENT == event.type && (SDL_WINDOWEVENT_RESTORED == event.window.event || SDL_WINDOWEVENT_EXPOSED == event.window.event)) - PDC_doupdate(); + { + SDL_UpdateWindowSurface(pdc_window); + rectcount = 0; + } else SDL_PushEvent(&event); } diff --git a/sdl2/pdckbd.c b/sdl2/pdckbd.c index 1047da2d..b069a028 100644 --- a/sdl2/pdckbd.c +++ b/sdl2/pdckbd.c @@ -412,8 +412,7 @@ int PDC_get_key(void) case SDL_WINDOWEVENT: if (SDL_WINDOWEVENT_SIZE_CHANGED == event.window.event) { - PDC_oldscreen(); - PDC_newscreen(); + pdc_screen = SDL_GetWindowSurface(pdc_window); pdc_sheight = pdc_screen->h - pdc_xoffset; pdc_swidth = pdc_screen->w - pdc_yoffset; touchwin(curscr); diff --git a/sdl2/pdcscrn.c b/sdl2/pdcscrn.c index fe53dd57..a368c444 100644 --- a/sdl2/pdcscrn.c +++ b/sdl2/pdcscrn.c @@ -28,8 +28,6 @@ int pdc_font_size = #endif SDL_Window *pdc_window = NULL; -SDL_Renderer *pdc_renderer = NULL; -SDL_Texture *pdc_texture = NULL; SDL_Surface *pdc_screen = NULL, *pdc_font = NULL, *pdc_icon = NULL, *pdc_back = NULL, *pdc_tileback = NULL; int pdc_sheight = 0, pdc_swidth = 0, pdc_yoffset = 0, pdc_xoffset = 0; @@ -132,24 +130,6 @@ static void _initialize_colors(void) pdc_color[i].g, pdc_color[i].b); } -void PDC_oldscreen(void) -{ - SDL_FreeSurface(pdc_screen); - SDL_DestroyTexture(pdc_texture); - SDL_DestroyRenderer(pdc_renderer); -} - -void PDC_newscreen(void) -{ - SDL_GetWindowSize(pdc_window, &pdc_swidth, &pdc_sheight); - pdc_renderer = SDL_CreateRenderer(pdc_window, -1, 0); - pdc_texture = SDL_CreateTexture(pdc_renderer, SDL_PIXELFORMAT_ARGB8888, - SDL_TEXTUREACCESS_STREAMING, - pdc_swidth, pdc_sheight); - pdc_screen = SDL_CreateRGBSurface(0, pdc_swidth, pdc_sheight, 32, - 0, 0, 0, 0); -} - /* find the display where the mouse pointer is */ int _get_displaynum(void) @@ -306,14 +286,35 @@ int PDC_scr_open(void) } SDL_SetWindowIcon(pdc_window, pdc_icon); + + /* Events must be pumped before calling SDL_GetWindowSurface, or + initial modifiers (e.g. numlock) will be ignored and out-of-sync. */ + + SDL_PumpEvents(); + + pdc_screen = SDL_GetWindowSurface(pdc_window); + + if (pdc_screen == NULL) + { + fprintf(stderr, "Could not open SDL window surface: %s\n", + SDL_GetError()); + return ERR; + } + + pdc_sheight = pdc_screen->h; + pdc_swidth = pdc_screen->w; } + else + { + if (!pdc_screen) + pdc_screen = SDL_GetWindowSurface(pdc_window); - SDL_PumpEvents(); + if (!pdc_sheight) + pdc_sheight = pdc_screen->h - pdc_yoffset; - PDC_newscreen(); - - pdc_sheight -= pdc_yoffset; - pdc_swidth -= pdc_xoffset; + if (!pdc_swidth) + pdc_swidth = pdc_screen->w - pdc_xoffset; + } if (!pdc_screen) { @@ -370,8 +371,7 @@ int PDC_resize_screen(int nlines, int ncols) pdc_swidth = ncols * pdc_fwidth; SDL_SetWindowSize(pdc_window, pdc_swidth, pdc_sheight); - PDC_oldscreen(); - PDC_newscreen(); + pdc_screen = SDL_GetWindowSurface(pdc_window); } if (pdc_tileback) diff --git a/sdl2/pdcsdl.h b/sdl2/pdcsdl.h index 79989cdb..d2e1f3c8 100644 --- a/sdl2/pdcsdl.h +++ b/sdl2/pdcsdl.h @@ -12,8 +12,6 @@ PDCEX TTF_Font *pdc_ttffont; PDCEX int pdc_font_size; #endif PDCEX SDL_Window *pdc_window; -PDCEX SDL_Renderer *pdc_renderer; -PDCEX SDL_Texture *pdc_texture; PDCEX SDL_Surface *pdc_screen, *pdc_font, *pdc_icon, *pdc_back; PDCEX int pdc_sheight, pdc_swidth, pdc_yoffset, pdc_xoffset; @@ -31,9 +29,8 @@ extern bool pdc_own_window; /* if pdc_window was not set before initscr(), PDCurses is responsible for (owns) it */ +PDCEX void PDC_update_rects(void); PDCEX void PDC_retile(void); -extern void PDC_oldscreen(void); -extern void PDC_newscreen(void); extern void PDC_pump_and_peep(void); extern void PDC_blink_text(void); diff --git a/sdl2/sdltest.c b/sdl2/sdltest.c index 58d7265a..9dc0c2c1 100644 --- a/sdl2/sdltest.c +++ b/sdl2/sdltest.c @@ -34,12 +34,13 @@ int main(int argc, char **argv) pdc_window = SDL_CreateWindow("PDCurses for SDL", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0); + pdc_screen = SDL_GetWindowSurface(pdc_window); /* Initialize PDCurses */ pdc_yoffset = 416; /* 480 - 4 * 16 */ - initscr(); /* creates pdc_screen */ + initscr(); start_color(); scrollok(stdscr, TRUE); @@ -61,7 +62,7 @@ int main(int argc, char **argv) rand() % 256, rand() % 256)); } - doupdate(); /* updates pdc_screen */ + SDL_UpdateWindowSurface(pdc_window); /* Do some curses stuff */