diff --git a/src/conio/bitmap_con.c b/src/conio/bitmap_con.c index c194aaf1f0bcf9014fa51c85f511c9768100672e..c6adeebe9bd97f7a8574138d65068bdb62850e0c 100644 --- a/src/conio/bitmap_con.c +++ b/src/conio/bitmap_con.c @@ -31,6 +31,7 @@ int screenheight=0; static int default_font=-99; static int current_font[4]={-99, -99, -99, -99}; static int bitmap_initialized=0; +pthread_mutex_t vmem_lock; struct video_stats vstat; static int *damaged=NULL; @@ -64,6 +65,22 @@ static __inline void *locked_screen_check(void) return(ret); } +static struct vstat_vmem *lock_vmem(struct video_stats *vs) +{ + struct vstat_vmem *ret; + pthread_mutex_lock(&vstatlock); + ret = get_vmem(vs); + pthread_mutex_unlock(&vstatlock); + pthread_mutex_lock(&vmem_lock); + return ret; +} + +static void unlock_vmem(struct vstat_vmem *vm) +{ + pthread_mutex_unlock(&vmem_lock); + release_vmem(vm); +} + /* Blinker Thread */ static void blinker_thread(void *data) { @@ -75,15 +92,15 @@ static void blinker_thread(void *data) SLEEP(10); } while(locked_screen_check()==NULL); count++; - pthread_mutex_lock(&vstatlock); if(count==50) { + pthread_mutex_lock(&vstatlock); if(vstat.blink) vstat.blink=FALSE; else vstat.blink=TRUE; count=0; + pthread_mutex_unlock(&vstatlock); } - pthread_mutex_unlock(&vstatlock); if(force_redraws) update_rect(0,0,0,0,force_redraws--); else @@ -100,11 +117,12 @@ int bitmap_init(void (*drawrect_cb) (int xpos, int ypos, int width, int height, { if(bitmap_initialized) return(-1); + pthread_mutex_init(&vmem_lock, NULL); pthread_mutex_init(&vstatlock, NULL); pthread_mutex_init(&screenlock, NULL); - pthread_mutex_lock(&vstatlock); + pthread_mutex_lock(&vmem_lock); vstat.vmem=NULL; - pthread_mutex_unlock(&vstatlock); + pthread_mutex_unlock(&vmem_lock); callbacks.drawrect=drawrect_cb; callbacks.flush=flush_cb; @@ -150,8 +168,10 @@ int bitmap_init_mode(int mode, int *width, int *height) damaged=newdamaged; /* Initialize video memory with black background, white foreground */ + pthread_mutex_lock(&vmem_lock); for (i = 0; i < vstat.cols*vstat.rows; ++i) - vstat.vmem[i] = 0x0700; + vstat.vmem->vmem[i] = 0x0700; + pthread_mutex_unlock(&vmem_lock); screenwidth=vstat.charwidth*vstat.cols; if(width) @@ -323,6 +343,7 @@ int bitmap_movetext(int x, int y, int ex, int ey, int tox, int toy) int sourcepos; int width=ex-x+1; int height=ey-y+1; + struct vstat_vmem *vmem_ptr; if( x<1 || y<1 @@ -344,13 +365,13 @@ int bitmap_movetext(int x, int y, int ex, int ey, int tox, int toy) sourcepos=(y-1)*cio_textinfo.screenwidth+(x-1); destoffset=(((toy-1)*cio_textinfo.screenwidth+(tox-1))-sourcepos); - pthread_mutex_lock(&vstatlock); + vmem_ptr = lock_vmem(&vstat); for(cy=(direction==-1?(height-1):0); cy<height && cy>=0; cy+=direction) { damaged[toy+cy-1]=1; sourcepos=((y-1)+cy)*cio_textinfo.screenwidth+(x-1); - memmove(&(vstat.vmem[sourcepos+destoffset]), &(vstat.vmem[sourcepos]), sizeof(vstat.vmem[0])*width); + memmove(&(vmem_ptr->vmem[sourcepos+destoffset]), &(vmem_ptr->vmem[sourcepos]), sizeof(vmem_ptr->vmem[0])*width); } - pthread_mutex_unlock(&vstatlock); + unlock_vmem(vmem_ptr); return(1); } @@ -358,27 +379,29 @@ void bitmap_clreol(void) { int pos,x; WORD fill=(cio_textinfo.attribute<<8)|space; + struct vstat_vmem *vmem_ptr; pos=(cio_textinfo.cury+cio_textinfo.wintop-2)*cio_textinfo.screenwidth; - pthread_mutex_lock(&vstatlock); + vmem_ptr = lock_vmem(&vstat); damaged[cio_textinfo.cury-1]=1; for(x=cio_textinfo.curx+cio_textinfo.winleft-2; x<cio_textinfo.winright; x++) - vstat.vmem[pos+x]=fill; - pthread_mutex_unlock(&vstatlock); + vmem_ptr->vmem[pos+x]=fill; + unlock_vmem(vmem_ptr); } void bitmap_clrscr(void) { int x,y; WORD fill=(cio_textinfo.attribute<<8)|space; + struct vstat_vmem *vmem_ptr; - pthread_mutex_lock(&vstatlock); + vmem_ptr = lock_vmem(&vstat); for(y=cio_textinfo.wintop-1; y<cio_textinfo.winbottom; y++) { damaged[y]=1; for(x=cio_textinfo.winleft-1; x<cio_textinfo.winright; x++) - vstat.vmem[y*cio_textinfo.screenwidth+x]=fill; + vmem_ptr->vmem[y*cio_textinfo.screenwidth+x]=fill; } - pthread_mutex_unlock(&vstatlock); + unlock_vmem(vmem_ptr); } int bitmap_puttext(int sx, int sy, int ex, int ey, void *fill) @@ -386,6 +409,7 @@ int bitmap_puttext(int sx, int sy, int ex, int ey, void *fill) int x,y; unsigned char *out; WORD sch; + struct vstat_vmem *vmem_ptr; if(!bitmap_initialized) return(0); @@ -402,17 +426,17 @@ int bitmap_puttext(int sx, int sy, int ex, int ey, void *fill) || fill==NULL) return(0); - pthread_mutex_lock(&vstatlock); + vmem_ptr = lock_vmem(&vstat); out=fill; for(y=sy-1;y<ey;y++) { damaged[y]=1; for(x=sx-1;x<ex;x++) { sch=*(out++); sch |= (*(out++))<<8; - vstat.vmem[y*cio_textinfo.screenwidth+x]=sch; + vmem_ptr->vmem[y*cio_textinfo.screenwidth+x]=sch; } } - pthread_mutex_unlock(&vstatlock); + unlock_vmem(vmem_ptr); return(1); } @@ -422,6 +446,7 @@ int bitmap_gettext(int sx, int sy, int ex, int ey, void *fill) int x,y; unsigned char *out; WORD sch; + struct vstat_vmem *vmem_ptr; if(!bitmap_initialized) return(0); @@ -437,16 +462,16 @@ int bitmap_gettext(int sx, int sy, int ex, int ey, void *fill) || fill==NULL) return(0); - pthread_mutex_lock(&vstatlock); + vmem_ptr = lock_vmem(&vstat); out=fill; for(y=sy-1;y<ey;y++) { for(x=sx-1;x<ex;x++) { - sch=vstat.vmem[y*cio_textinfo.screenwidth+x]; + sch=vmem_ptr->vmem[y*cio_textinfo.screenwidth+x]; *(out++)=sch & 0xff; *(out++)=sch >> 8; } } - pthread_mutex_unlock(&vstatlock); + unlock_vmem(vmem_ptr); return(1); } @@ -823,6 +848,7 @@ static int bitmap_draw_one_char(struct video_stats *vs, unsigned int xpos, unsig int altfont; unsigned char *this_font; WORD sch; + struct vstat_vmem *vmem_ptr; if(!bitmap_initialized) return(-1); @@ -838,7 +864,11 @@ static int bitmap_draw_one_char(struct video_stats *vs, unsigned int xpos, unsig return(-1); } - sch=vs->vmem[(ypos-1)*cio_textinfo.screenwidth+(xpos-1)]; + vmem_ptr = lock_vmem(vs); + + sch=vmem_ptr->vmem[(ypos-1)*cio_textinfo.screenwidth+(xpos-1)]; + + unlock_vmem(vmem_ptr); altfont = (sch>>11 & 0x01) | ((sch>>14) & 0x02); if(vs->bright_background) { @@ -887,10 +917,12 @@ static int update_rect(int sx, int sy, int width, int height, int force) static unsigned short *this_vmem=NULL; static struct video_stats vs; struct video_stats cvstat; + struct vstat_vmem cvmem; struct rectangle this_rect; int this_rect_used=0; struct rectangle last_rect; int last_rect_used=0; + struct vstat_vmem *vmem_ptr; if(!bitmap_initialized) return(-1); @@ -937,9 +969,14 @@ static int update_rect(int sx, int sy, int width, int height, int force) || vstat.curs_end!=vs.curs_end) redraw_cursor=1; cvstat = vstat; - cvstat.vmem = this_vmem; - memcpy(cvstat.vmem, vstat.vmem, vstat.cols*vstat.rows*sizeof(unsigned short)); + vmem_ptr = get_vmem(&vstat); pthread_mutex_unlock(&vstatlock); + pthread_mutex_lock(&vmem_lock); + cvstat.vmem = &cvmem; + cvstat.vmem->refcount = 1; + cvstat.vmem->vmem = this_vmem; + memcpy(cvstat.vmem->vmem, vmem_ptr->vmem, vstat.cols*vstat.rows*sizeof(unsigned short)); + pthread_mutex_unlock(&vmem_lock); for(y=0;y<height;y++) { if(force @@ -950,11 +987,11 @@ static int update_rect(int sx, int sy, int width, int height, int force) pos=(sy+y-1)*cvstat.cols+(sx-1); for(x=0;x<width;x++) { if(force - || (last_vmem[pos] != cvstat.vmem[pos]) /* Different char */ - || ((cvstat.blink != vs.blink) && (cvstat.vmem[pos]>>15) && (!cvstat.no_blink)) /* Blinking char */ + || (last_vmem[pos] != cvstat.vmem->vmem[pos]) /* Different char */ + || ((cvstat.blink != vs.blink) && (cvstat.vmem->vmem[pos]>>15) && (!cvstat.no_blink)) /* Blinking char */ || (redraw_cursor && ((vs.curs_col==sx+x && vs.curs_row==sy+y) || (cvstat.curs_col==sx+x && cvstat.curs_row==sy+y))) /* Cursor */ ) { - last_vmem[pos] = cvstat.vmem[pos]; + last_vmem[pos] = cvstat.vmem->vmem[pos]; bitmap_draw_one_char(&cvstat, sx+x,sy+y); if(!redraw_cursor && sx+x==cvstat.curs_col && sy+y==cvstat.curs_row) diff --git a/src/conio/sdl_con.c b/src/conio/sdl_con.c index 3389807b5dea51910fd8ac569477ce32240b9c33..536c8058cffb9a3ce73b517d028945f9623f347c 100644 --- a/src/conio/sdl_con.c +++ b/src/conio/sdl_con.c @@ -892,6 +892,7 @@ void setup_surfaces(void) int flags=SDL_HWSURFACE|SDL_ANYFORMAT; SDL_Surface *tmp_rect; SDL_Event ev; + int charwidth, charheight, cols, scaling, rows, vmultiplier; if(fullscreen) flags |= SDL_FULLSCREEN; @@ -900,14 +901,22 @@ void setup_surfaces(void) sdl.mutexP(win_mutex); pthread_mutex_lock(&vstatlock); - char_width=vstat.charwidth*vstat.cols*vstat.scaling; - char_height=vstat.charheight*vstat.rows*vstat.scaling*vstat.vmultiplier; + charwidth = vstat.charwidth; + charheight = vstat.charheight; + cols = vstat.cols; + scaling = vstat.scaling; + rows = vstat.rows; + vmultiplier = vstat.vmultiplier; + pthread_mutex_unlock(&vstatlock); + + char_width=charwidth*cols*scaling; + char_height=charheight*rows*scaling*vmultiplier; if(yuv.enabled) { if(!yuv.win_width) - yuv.win_width=vstat.charwidth*vstat.cols; + yuv.win_width=charwidth*cols; if(!yuv.win_height) - yuv.win_height=vstat.charheight*vstat.rows; + yuv.win_height=charheight*rows; if(fullscreen && yuv.screen_width && yuv.screen_height) win=sdl.SetVideoMode(yuv.screen_width,yuv.screen_height,0,flags); else @@ -915,7 +924,6 @@ void setup_surfaces(void) } else win=sdl.SetVideoMode(char_width,char_height,8,flags); - pthread_mutex_unlock(&vstatlock); #if !defined(NO_X) && defined(__unix__) if(sdl_x11available && sdl_using_x11) { @@ -1668,6 +1676,7 @@ int sdl_video_event_thread(void *data) struct update_rect *rect=(struct update_rect *)ev.user.data1; SDL_Rect r; int x,y,offset; + int scaling, vmultiplier; sdl.mutexP(win_mutex); if(!win) { @@ -1678,13 +1687,16 @@ int sdl_video_event_thread(void *data) } sdl.mutexP(newrect_mutex); pthread_mutex_lock(&vstatlock); + scaling = vstat.scaling; + vmultiplier = vstat.vmultiplier; + pthread_mutex_unlock(&vstatlock); for(y=0; y<rect->height; y++) { offset=y*rect->width; for(x=0; x<rect->width; x++) { - r.w=vstat.scaling; - r.h=vstat.scaling*vstat.vmultiplier; - r.x=(rect->x+x)*vstat.scaling; - r.y=(rect->y+y)*vstat.scaling*vstat.vmultiplier; + r.w=scaling; + r.h=scaling*vmultiplier; + r.x=(rect->x+x)*scaling; + r.y=(rect->y+y)*scaling*vmultiplier; if(yuv.enabled) yuv_fillrect(yuv.overlay, &r, rect->data[offset++]); else @@ -1700,10 +1712,10 @@ int sdl_video_event_thread(void *data) pthread_mutex_unlock(&vstatlock); break; } - upd_rects[rectsused].x=rect->x*vstat.scaling; - upd_rects[rectsused].y=rect->y*vstat.scaling*vstat.vmultiplier; - upd_rects[rectsused].w=rect->width*vstat.scaling; - upd_rects[rectsused].h=rect->height*vstat.scaling*vstat.vmultiplier; + upd_rects[rectsused].x=rect->x*scaling; + upd_rects[rectsused].y=rect->y*scaling*vmultiplier; + upd_rects[rectsused].w=rect->width*scaling; + upd_rects[rectsused].h=rect->height*scaling*vmultiplier; sdl.BlitSurface(new_rect, &(upd_rects[rectsused]), win, &(upd_rects[rectsused])); rectsused++; if(rectsused==rectspace) { @@ -1711,7 +1723,6 @@ int sdl_video_event_thread(void *data) rectsused=0; } } - pthread_mutex_unlock(&vstatlock); sdl.mutexV(newrect_mutex); sdl.mutexV(win_mutex); free(rect->data); diff --git a/src/conio/vidmodes.c b/src/conio/vidmodes.c index 1fe79318cd587ea31eb4a08b277074ad5e4d94af..0c673ab8c2b2a06ba327335770f08b6ec9e341a8 100644 --- a/src/conio/vidmodes.c +++ b/src/conio/vidmodes.c @@ -158,18 +158,49 @@ int find_vmode(int mode) return -1; } +struct vstat_vmem *get_vmem(struct video_stats *vs) +{ + vs->vmem->refcount++; + return vs->vmem; +} + +void release_vmem(struct vstat_vmem *vm) +{ + if (vm == NULL) + return; + vm->refcount--; + if (vm->refcount == 0) { + FREE_AND_NULL(vm->vmem); + FREE_AND_NULL(vm); + } +} + +static struct vstat_vmem *new_vmem(int cols, int rows) +{ + struct vstat_vmem *ret = malloc(sizeof(struct vstat_vmem)); + + if (ret == NULL) + return ret; + ret->refcount = 1; + ret->vmem = (unsigned short *)malloc(cols*rows*sizeof(unsigned short)); + if (ret->vmem == NULL) { + free(ret); + return NULL; + } + return ret; +} + int load_vmode(struct video_stats *vs, int mode) { int i; - unsigned short *newvmem; i=find_vmode(mode); if(i==-1) return(-1); - newvmem=(unsigned short *)realloc(vs->vmem, vparams[i].cols*vparams[i].rows*sizeof(unsigned short)); - if(newvmem==NULL) - return(-1); - vs->vmem=newvmem; + release_vmem(vs->vmem); + vs->vmem=new_vmem(vparams[i].cols, vparams[i].rows); + if (vs->vmem == NULL) + return -1; vs->rows=vparams[i].rows; vs->cols=vparams[i].cols; vs->curs_start=vparams[i].curs_start; diff --git a/src/conio/vidmodes.h b/src/conio/vidmodes.h index 968366a4e84799f96c07927db64951992ee60d1a..0d6425308460ba54c2518a5f29eebd8fc9ecbf6e 100644 --- a/src/conio/vidmodes.h +++ b/src/conio/vidmodes.h @@ -64,6 +64,11 @@ struct video_params { int vmultiplier; }; +struct vstat_vmem { + unsigned refcount; + unsigned short *vmem; +}; + struct video_stats { int rows; int cols; @@ -89,7 +94,7 @@ struct video_stats { int vmultiplier; struct dac_colors dac_colors[256]; unsigned char palette[16]; - unsigned short *vmem; + struct vstat_vmem *vmem; }; enum { @@ -112,6 +117,8 @@ extern char vga_font_bitmap8[2048]; extern "C" { #endif int find_vmode(int mode); +struct vstat_vmem *get_vmem(struct video_stats *vs); +void release_vmem(struct vstat_vmem *vm); int load_vmode(struct video_stats *vs, int mode); #ifdef __cplusplus }