diff --git a/src/conio/bitmap_con.c b/src/conio/bitmap_con.c index c98473510dca96eab50b8c11c7780ce893da9e33..89094f26c76cadb8f834f2fb39166b8ad10c80cd 100644 --- a/src/conio/bitmap_con.c +++ b/src/conio/bitmap_con.c @@ -35,6 +35,7 @@ struct video_stats vstat; struct bitmap_callbacks { void (*drawrect) (int xpos, int ypos, int width, int height, unsigned char *data); + void (*flush) (void); }; pthread_mutex_t vstatlock; @@ -66,7 +67,8 @@ static void blinker_thread(void *data) } } -int bitmap_init(void (*drawrect_cb) (int xpos, int ypos, int width, int height, unsigned char *data)) +int bitmap_init(void (*drawrect_cb) (int xpos, int ypos, int width, int height, unsigned char *data) + ,void (*flush_cb) (void)) { pthread_mutex_init(&vstatlock, NULL); pthread_mutex_init(&screenlock, NULL); @@ -75,6 +77,7 @@ int bitmap_init(void (*drawrect_cb) (int xpos, int ypos, int width, int height, pthread_mutex_unlock(&vstatlock); callbacks.drawrect=drawrect_cb; + callbacks.flush=flush_cb; _beginthread(blinker_thread,0,NULL); return(0); @@ -89,10 +92,12 @@ void send_rectangle(int xoffset, int yoffset, int width, int height, int force) pthread_mutex_lock(&screenlock); if(callbacks.drawrect) { +#ifdef PARANOIA if(xoffset < 0 || xoffset >= screenwidth || yoffset < 0 || yoffset >= screenheight || width <= 0 || width > screenwidth || height <=0 || height >screenheight) { pthread_mutex_unlock(&screenlock); return; } +#endif rect=(unsigned char *)malloc(width*height*sizeof(unsigned char)); if(!rect) { @@ -203,14 +208,8 @@ int bitmap_puttext(int sx, int sy, int ex, int ey, void *fill) vstat.vmem[y*cio_textinfo.screenwidth+x]=sch; } } -#ifdef SEPARATE_SEND_RECTANGLE - update_rect(sx,sy,ex-sx+1,ey-sy+1,FALSE,FALSE); - pthread_mutex_unlock(&vstatlock); - send_rectangle((sx-1)*vstat.charwidth, (sy-1)*vstat.charheight, (ex-sx+1)*vstat.charwidth, (ey-sy+1)*vstat.charheight, FALSE); -#else update_rect(sx,sy,ex-sx+1,ey-sy+1,FALSE,TRUE); pthread_mutex_unlock(&vstatlock); -#endif return(1); } @@ -227,8 +226,6 @@ int bitmap_gettext(int sx, int sy, int ex, int ey, void *fill) || sy < 1 || ex < 1 || ey < 1 - || sx > cio_textinfo.screenwidth - || sy > cio_textinfo.screenheight || sx > ex || sy > ey || ex > cio_textinfo.screenwidth @@ -486,7 +483,7 @@ int bitmap_loadfont(char *filename) } /* Called from events thread only */ -static void bitmap_draw_cursor(void) +static void bitmap_draw_cursor(int flush) { int x; int y; @@ -513,6 +510,8 @@ static void bitmap_draw_cursor(void) } pthread_mutex_unlock(&screenlock); send_rectangle(xoffset, yoffset+vstat.curs_start, vstat.charwidth, vstat.curs_end-vstat.curs_start+1,FALSE); + if(flush && callbacks.flush) + callbacks.flush(); } } } @@ -534,7 +533,7 @@ void bitmap_gotoxy(int x, int y) if(lx != vstat.curs_col || ly != vstat.curs_row) update_rect(lx,ly,1,1,TRUE,TRUE); /* Draw new cursor */ - bitmap_draw_cursor(); + bitmap_draw_cursor(TRUE); lx=vstat.curs_col; ly=vstat.curs_row; } @@ -597,6 +596,7 @@ static int update_rect(int sx, int sy, int width, int height, int force, int cal int this_rect_used=0; struct rectangle last_rect; int last_rect_used=0; + int sent=FALSE; if(sx==0 && sy==0 && width==0 && height==0) fullredraw=1; @@ -634,8 +634,8 @@ static int update_rect(int sx, int sy, int width, int height, int force, int cal redraw_cursor=1; for(y=0;y<height;y++) { + pos=(sy+y-1)*vstat.cols+(sx-1); for(x=0;x<width;x++) { - pos=(sy+y-1)*vstat.cols+(sx+x-1); if(force || (last_vmem[pos] != vstat.vmem[pos]) /* Different char */ || (vstat.blink != vs.blink && vstat.vmem[pos]>>15) /* Blinking char */ @@ -643,6 +643,7 @@ static int update_rect(int sx, int sy, int width, int height, int force, int cal ) { last_vmem[pos] = vstat.vmem[pos]; bitmap_draw_one_char(sx+x,sy+y); + sent=TRUE; if(calls_send) { if(lastcharupdated) { @@ -653,7 +654,7 @@ static int update_rect(int sx, int sy, int width, int height, int force, int cal if(this_rect_used) { send_rectangle(this_rect.x, this_rect.y, this_rect.width, this_rect.height,FALSE); } - + this_rect.x=(sx+x-1)*vstat.charwidth; this_rect.y=(sy+y-1)*vstat.charheight; this_rect.width=vstat.charwidth; @@ -731,7 +732,10 @@ static int update_rect(int sx, int sy, int width, int height, int force, int cal } if(redraw_cursor) - bitmap_draw_cursor(); + bitmap_draw_cursor(FALSE); + + if(sent && callbacks.flush) + callbacks.flush(); return(0); } diff --git a/src/conio/bitmap_con.h b/src/conio/bitmap_con.h index 58859654c30d2ecb7d5df6f1152d1eaa3ee5b4be..d6c47b7f65c4fc29f1606b29a6bdabe2ac628272 100644 --- a/src/conio/bitmap_con.h +++ b/src/conio/bitmap_con.h @@ -18,6 +18,7 @@ int bitmap_loadfont(char *filename); void send_rectangle(int xoffset, int yoffset, int width, int height, int force); int bitmap_init_mode(int mode, int *width, int *height); -int bitmap_init(void (*drawrect_cb) (int xpos, int ypos, int width, int height, unsigned char *data)); +int bitmap_init(void (*drawrect_cb) (int xpos, int ypos, int width, int height, unsigned char *data) + ,void (*flush) (void)); #endif diff --git a/src/conio/sdl_con.c b/src/conio/sdl_con.c index 12df516f3b94736e445b5ad9601f9cf7428bbcb5..3a0b898a2ff8609abd17af3bad19bb24e3821f56 100644 --- a/src/conio/sdl_con.c +++ b/src/conio/sdl_con.c @@ -61,12 +61,14 @@ int sdl_ufunc_retval; int fullscreen=0; -SDL_sem *sdl_init_complete; int sdl_init_good=0; SDL_mutex *sdl_keylock; SDL_sem *sdl_key_pending; static unsigned int sdl_pending_mousekeys=0; Uint32 sdl_dac_default[sizeof(dac_default)/sizeof(struct dac_colors)]; +SDL_Rect *upd_rects=NULL; +int rectspace=0; +int rectsused=0; struct sdl_keyvals { int keysym @@ -86,6 +88,7 @@ struct update_rect { enum { SDL_USEREVENT_UPDATERECT + ,SDL_USEREVENT_FLUSH ,SDL_USEREVENT_SETTITLE ,SDL_USEREVENT_SETNAME ,SDL_USEREVENT_SETICON @@ -258,25 +261,11 @@ void sdl_user_func(int func, ...) } while(sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff)!=1); break; - case SDL_USEREVENT_SETVIDMODE: - if((ev.user.data1=(void *)malloc(sizeof(int)))==NULL) { - va_end(argptr); - return; - } - *((int *)ev.user.data1)=va_arg(argptr, int); - if((ev.user.data2=(void *)malloc(sizeof(int)))==NULL) { - free(ev.user.data1); - va_end(argptr); - return; - } - *((int *)ev.user.data2)=va_arg(argptr, int); - while(sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff)!=1); - break; case SDL_USEREVENT_COPY: case SDL_USEREVENT_PASTE: case SDL_USEREVENT_SHOWMOUSE: case SDL_USEREVENT_HIDEMOUSE: - case SDL_USEREVENT_INIT: + case SDL_USEREVENT_FLUSH: while(sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff)!=1); break; } @@ -300,6 +289,8 @@ int sdl_user_func_ret(int func, ...) ev.user.code=func; va_start(argptr, func); switch(func) { + case SDL_USEREVENT_SETVIDMODE: + case SDL_USEREVENT_INIT: case SDL_USEREVENT_QUIT: while(sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff)!=1); passed=TRUE; @@ -435,6 +426,11 @@ void sdl_drawrect(int xoffset,int yoffset,int width,int height,unsigned char *da } } +void sdl_flush(void) +{ + sdl_user_func(SDL_USEREVENT_FLUSH); +} + int sdl_init_mode(int mode) { struct video_params vmode; @@ -455,7 +451,7 @@ int sdl_init_mode(int mode) if(vstat.scaling < 1) vstat.scaling = 1; - sdl_user_func(SDL_USEREVENT_SETVIDMODE,vstat.charwidth*vstat.cols*vstat.scaling, vstat.charheight*vstat.rows*vstat.scaling); + sdl_user_func_ret(SDL_USEREVENT_SETVIDMODE); return(0); } @@ -470,14 +466,13 @@ int sdl_init(int mode) if(init_sdl_video()) return(-1); - bitmap_init(sdl_drawrect); + bitmap_init(sdl_drawrect, sdl_flush); if(mode==CIOLIB_MODE_SDL_FULLSCREEN) fullscreen=1; sdl_init_mode(3); - sdl_user_func(SDL_USEREVENT_INIT); + sdl_user_func_ret(SDL_USEREVENT_INIT); - sdl.SemWait(sdl_init_complete); if(sdl_init_good) { cio_api.mode=fullscreen?CIOLIB_MODE_SDL_FULLSCREEN:CIOLIB_MODE_SDL; #ifdef _WIN32 @@ -621,7 +616,7 @@ void sdl_add_key(unsigned int keyval) if(keyval==0xa600) { fullscreen=!fullscreen; cio_api.mode=fullscreen?CIOLIB_MODE_SDL_FULLSCREEN:CIOLIB_MODE_SDL; - sdl_user_func(SDL_USEREVENT_SETVIDMODE,vstat.charwidth*vstat.cols, vstat.charheight*vstat.rows); + sdl_user_func_ret(SDL_USEREVENT_SETVIDMODE); return; } if(keyval <= 0xffff) { @@ -1164,6 +1159,9 @@ int sdl_video_event_thread(void *data) SDL_Rect r; SDL_Rect dst; int x,y,offset; + + if(!win) + break; #ifndef DOUBLE_BUFFER for(y=0; y<rect->height; y++) { offset=y*rect->width; @@ -1175,7 +1173,15 @@ int sdl_video_event_thread(void *data) sdl.FillRect(win, &r, sdl_dac_default[rect->data[offset++]]); } } - sdl.UpdateRect(win,rect->x*vstat.scaling,rect->y*vstat.scaling,rect->width*vstat.scaling,rect->height*vstat.scaling); + upd_rects[rectsused].x=rect->x*vstat.scaling; + upd_rects[rectsused].y=rect->y*vstat.scaling; + upd_rects[rectsused].w=rect->width*vstat.scaling; + upd_rects[rectsused].h=rect->height*vstat.scaling; + rectsused++; + if(rectsused==rectspace) { + sdl.UpdateRects(win,rectsused,upd_rects); + rectsused=0; + } #else for(y=0; y<rect->height; y++) { for(x=0; x<rect->width; x++) { @@ -1197,12 +1203,22 @@ int sdl_video_event_thread(void *data) dst.w=rect->width*vstat.scaling; dst.h=rect->height*vstat.scaling; sdl.BlitSurface(new_rect, &r, win, &dst); - sdl.UpdateRects(win,1,&dst); + upd_rects[rectsused++]=dst; + if(rectsused==rectspace) { + sdl.UpdateRects(win,rectsused,upd_rects); + rectsused=0; + } #endif free(rect->data); free(rect); break; } + case SDL_USEREVENT_FLUSH: + if(win && upd_rects) { + sdl.UpdateRects(win,rectsused,upd_rects); + rectsused=0; + } + break; case SDL_USEREVENT_SETNAME: sdl.WM_SetCaption((char *)ev.user.data1,(char *)ev.user.data1); free(ev.user.data1); @@ -1229,6 +1245,15 @@ int sdl_video_event_thread(void *data) break; case SDL_USEREVENT_SETVIDMODE: pthread_mutex_lock(&vstatlock); + rectspace=vstat.cols*vstat.rows+vstat.cols; + rectsused=0; + upd_rects=(SDL_Rect *)malloc(sizeof(SDL_Rect)*rectspace); + if(upd_rects==NULL) { + pthread_mutex_unlock(&vstatlock); + ev.type=SDL_QUIT; + sdl_exitcode=1; + sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff); + } if(fullscreen) win=sdl.SetVideoMode( vstat.charwidth*vstat.cols*vstat.scaling @@ -1278,8 +1303,8 @@ int sdl_video_event_thread(void *data) } else pthread_mutex_unlock(&vstatlock); - free(ev.user.data1); - free(ev.user.data2); + sdl_ufunc_retval=0; + sdl.SemPost(sdl_ufunc_ret); break; case SDL_USEREVENT_HIDEMOUSE: sdl.ShowCursor(SDL_DISABLE); @@ -1298,7 +1323,8 @@ int sdl_video_event_thread(void *data) } } } - sdl.SemPost(sdl_init_complete); + sdl_ufunc_retval=0; + sdl.SemPost(sdl_ufunc_ret); break; case SDL_USEREVENT_COPY: #if (defined(__MACH__) && defined(__APPLE__)) @@ -1493,7 +1519,6 @@ int sdl_initciolib(int mode) if(init_sdl_video()==-1) return(-1); sdl_key_pending=sdl.SDL_CreateSemaphore(0); - sdl_init_complete=sdl.SDL_CreateSemaphore(0); sdl_ufunc_ret=sdl.SDL_CreateSemaphore(0); sdl_keylock=sdl.SDL_CreateMutex(); sdl_ufunc_lock=sdl.SDL_CreateMutex();