Skip to content
Snippets Groups Projects
Commit 5ad4150e authored by deuce's avatar deuce
Browse files

bitmap_con.c overhaul with extra care on locking.

parent 7f744b55
Branches
Tags
No related merge requests found
...@@ -31,6 +31,7 @@ int screenheight; ...@@ -31,6 +31,7 @@ int screenheight;
#define PIXEL_OFFSET(x,y) ( (y)*screenwidth+(x) ) #define PIXEL_OFFSET(x,y) ( (y)*screenwidth+(x) )
static int current_font=-99; static int current_font=-99;
static int bitmap_initialized=0;
struct video_stats vstat; struct video_stats vstat;
struct bitmap_callbacks { struct bitmap_callbacks {
...@@ -78,9 +79,14 @@ static void blinker_thread(void *data) ...@@ -78,9 +79,14 @@ static void blinker_thread(void *data)
} }
} }
/*
* MUST be called only once and before any other bitmap functions
*/
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)) ,void (*flush_cb) (void))
{ {
if(bitmap_initialized)
return(-1);
pthread_mutex_init(&vstatlock, NULL); pthread_mutex_init(&vstatlock, NULL);
pthread_mutex_init(&screenlock, NULL); pthread_mutex_init(&screenlock, NULL);
pthread_mutex_lock(&vstatlock); pthread_mutex_lock(&vstatlock);
...@@ -89,49 +95,26 @@ int bitmap_init(void (*drawrect_cb) (int xpos, int ypos, int width, int height, ...@@ -89,49 +95,26 @@ int bitmap_init(void (*drawrect_cb) (int xpos, int ypos, int width, int height,
callbacks.drawrect=drawrect_cb; callbacks.drawrect=drawrect_cb;
callbacks.flush=flush_cb; callbacks.flush=flush_cb;
bitmap_initialized=1;
_beginthread(blinker_thread,0,NULL); _beginthread(blinker_thread,0,NULL);
return(0); return(0);
} }
void send_rectangle(int xoffset, int yoffset, int width, int height, int force) /*
{ * This function is intended to be called from the driver.
unsigned char *rect; * as a result, it cannot block waiting for driver status
int pixel=0; *
int inpixel; * Care MUST be taken to avoid deadlocks...
int x,y; */
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) {
pthread_mutex_unlock(&screenlock);
return;
}
for(y=0; y<height; y++) {
inpixel=PIXEL_OFFSET(xoffset, yoffset+y);
for(x=0; x<width; x++) {
rect[pixel++]=vstat.palette[screen[inpixel++]];
}
}
callbacks.drawrect(xoffset,yoffset,width,height,rect);
}
pthread_mutex_unlock(&screenlock);
}
int bitmap_init_mode(int mode, int *width, int *height) int bitmap_init_mode(int mode, int *width, int *height)
{ {
int i; int i;
char *newscreen; char *newscreen;
if(!bitmap_initialized)
return(-1);
pthread_mutex_lock(&vstatlock); pthread_mutex_lock(&vstatlock);
if(load_vmode(&vstat, mode)) { if(load_vmode(&vstat, mode)) {
...@@ -177,6 +160,40 @@ int bitmap_init_mode(int mode, int *width, int *height) ...@@ -177,6 +160,40 @@ int bitmap_init_mode(int mode, int *width, int *height)
return(0); return(0);
} }
/*
* Send by ciolib side, should not block in driver
* Generally, if the driver may block on a rectangle draw, the updates
* should be cached until flush is called.
*/
void send_rectangle(int xoffset, int yoffset, int width, int height, int force)
{
unsigned char *rect;
int pixel=0;
int inpixel;
int x,y;
if(!bitmap_initialized)
return;
pthread_mutex_lock(&screenlock);
if(callbacks.drawrect) {
if(xoffset < 0 || xoffset >= screenwidth || yoffset < 0 || yoffset >= screenheight || width <= 0 || width > screenwidth || height <=0 || height >screenheight)
goto end;
rect=(unsigned char *)malloc(width*height*sizeof(unsigned char));
if(!rect)
goto end;
for(y=0; y<height; y++) {
inpixel=PIXEL_OFFSET(xoffset, yoffset+y);
for(x=0; x<width; x++)
rect[pixel++]=vstat.palette[screen[inpixel++]];
}
callbacks.drawrect(xoffset,yoffset,width,height,rect);
}
end:
pthread_mutex_unlock(&screenlock);
}
/********************************************************/ /********************************************************/
/* High Level Stuff */ /* High Level Stuff */
/********************************************************/ /********************************************************/
...@@ -188,7 +205,8 @@ int bitmap_puttext(int sx, int sy, int ex, int ey, void *fill) ...@@ -188,7 +205,8 @@ int bitmap_puttext(int sx, int sy, int ex, int ey, void *fill)
unsigned char *out; unsigned char *out;
WORD sch; WORD sch;
pthread_mutex_lock(&vstatlock); if(!bitmap_initialized)
return(0);
if( sx < 1 if( sx < 1
|| sy < 1 || sy < 1
|| ex < 1 || ex < 1
...@@ -199,11 +217,10 @@ int bitmap_puttext(int sx, int sy, int ex, int ey, void *fill) ...@@ -199,11 +217,10 @@ int bitmap_puttext(int sx, int sy, int ex, int ey, void *fill)
|| sy > ey || sy > ey
|| ex > cio_textinfo.screenwidth || ex > cio_textinfo.screenwidth
|| ey > cio_textinfo.screenheight || ey > cio_textinfo.screenheight
|| fill==NULL) { || fill==NULL)
pthread_mutex_unlock(&vstatlock);
return(0); return(0);
}
pthread_mutex_lock(&vstatlock);
out=fill; out=fill;
for(y=sy-1;y<ey;y++) { for(y=sy-1;y<ey;y++) {
for(x=sx-1;x<ex;x++) { for(x=sx-1;x<ex;x++) {
...@@ -223,7 +240,8 @@ int bitmap_gettext(int sx, int sy, int ex, int ey, void *fill) ...@@ -223,7 +240,8 @@ int bitmap_gettext(int sx, int sy, int ex, int ey, void *fill)
unsigned char *out; unsigned char *out;
WORD sch; WORD sch;
pthread_mutex_lock(&vstatlock); if(!bitmap_initialized)
return(0);
if( sx < 1 if( sx < 1
|| sy < 1 || sy < 1
...@@ -233,11 +251,10 @@ int bitmap_gettext(int sx, int sy, int ex, int ey, void *fill) ...@@ -233,11 +251,10 @@ int bitmap_gettext(int sx, int sy, int ex, int ey, void *fill)
|| sy > ey || sy > ey
|| ex > cio_textinfo.screenwidth || ex > cio_textinfo.screenwidth
|| ey > cio_textinfo.screenheight || ey > cio_textinfo.screenheight
|| fill==NULL) { || fill==NULL)
pthread_mutex_unlock(&vstatlock);
return(0); return(0);
}
pthread_mutex_lock(&vstatlock);
out=fill; out=fill;
for(y=sy-1;y<ey;y++) { for(y=sy-1;y<ey;y++) {
for(x=sx-1;x<ex;x++) { for(x=sx-1;x<ex;x++) {
...@@ -250,9 +267,11 @@ int bitmap_gettext(int sx, int sy, int ex, int ey, void *fill) ...@@ -250,9 +267,11 @@ int bitmap_gettext(int sx, int sy, int ex, int ey, void *fill)
return(1); return(1);
} }
/* Called from main thread only */ /* Called from ciolib thread only */
void bitmap_setcursortype(int type) void bitmap_setcursortype(int type)
{ {
if(!bitmap_initialized)
return;
pthread_mutex_lock(&vstatlock); pthread_mutex_lock(&vstatlock);
switch(type) { switch(type) {
case _NOCURSOR: case _NOCURSOR:
...@@ -268,7 +287,6 @@ void bitmap_setcursortype(int type) ...@@ -268,7 +287,6 @@ void bitmap_setcursortype(int type)
vstat.curs_end = vstat.default_curs_end; vstat.curs_end = vstat.default_curs_end;
break; break;
} }
update_rect(cio_textinfo.curx+cio_textinfo.winleft-1,cio_textinfo.cury+cio_textinfo.wintop-1,1,1,TRUE,TRUE);
pthread_mutex_unlock(&vstatlock); pthread_mutex_unlock(&vstatlock);
} }
...@@ -285,6 +303,8 @@ int bitmap_setfont(int font, int force) ...@@ -285,6 +303,8 @@ int bitmap_setfont(int font, int force)
char *pold; char *pold;
char *pnew; char *pnew;
if(!bitmap_initialized)
return(-1);
if(font < 0 || font>(sizeof(conio_fontdata)/sizeof(struct conio_font_data_struct)-2)) if(font < 0 || font>(sizeof(conio_fontdata)/sizeof(struct conio_font_data_struct)-2))
return(-1); return(-1);
...@@ -295,11 +315,12 @@ int bitmap_setfont(int font, int force) ...@@ -295,11 +315,12 @@ int bitmap_setfont(int font, int force)
else if(conio_fontdata[font].eight_by_eight!=NULL) else if(conio_fontdata[font].eight_by_eight!=NULL)
newmode=C80X50; newmode=C80X50;
pthread_mutex_lock(&vstatlock);
switch(vstat.charheight) { switch(vstat.charheight) {
case 8: case 8:
if(conio_fontdata[font].eight_by_eight==NULL) { if(conio_fontdata[font].eight_by_eight==NULL) {
if(force) if(force)
return(-1); goto error_return;
else else
changemode=1; changemode=1;
} }
...@@ -307,7 +328,7 @@ int bitmap_setfont(int font, int force) ...@@ -307,7 +328,7 @@ int bitmap_setfont(int font, int force)
case 14: case 14:
if(conio_fontdata[font].eight_by_fourteen==NULL) { if(conio_fontdata[font].eight_by_fourteen==NULL) {
if(force) if(force)
return(-1); goto error_return;
else else
changemode=1; changemode=1;
} }
...@@ -315,18 +336,20 @@ int bitmap_setfont(int font, int force) ...@@ -315,18 +336,20 @@ int bitmap_setfont(int font, int force)
case 16: case 16:
if(conio_fontdata[font].eight_by_sixteen==NULL) { if(conio_fontdata[font].eight_by_sixteen==NULL) {
if(force) if(force)
return(-1); goto error_return;
else else
changemode=1; changemode=1;
} }
break; break;
} }
if(changemode && newmode==-1) if(changemode && newmode==-1)
return(-1); goto error_return;
current_font=font; current_font=font;
pthread_mutex_unlock(&vstatlock);
if(changemode) { if(changemode) {
gettextinfo(&ti); gettextinfo(&ti);
attr=ti.attribute; attr=ti.attribute;
ow=ti.screenwidth; ow=ti.screenwidth;
oh=ti.screenheight; oh=ti.screenheight;
...@@ -369,6 +392,10 @@ int bitmap_setfont(int font, int force) ...@@ -369,6 +392,10 @@ int bitmap_setfont(int font, int force)
} }
bitmap_loadfont(NULL); bitmap_loadfont(NULL);
return(0); return(0);
error_return:
pthread_mutex_unlock(&vstatlock);
return(-1);
} }
int bitmap_getfont(void) int bitmap_getfont(void)
...@@ -384,8 +411,10 @@ int bitmap_loadfont(char *filename) ...@@ -384,8 +411,10 @@ int bitmap_loadfont(char *filename)
int fw; int fw;
int fh; int fh;
int i; int i;
FILE *fontfile; FILE *fontfile=NULL;
if(!bitmap_initialized)
return(-1);
if(current_font==-99 || current_font>(sizeof(conio_fontdata)/sizeof(struct conio_font_data_struct)-2)) { if(current_font==-99 || current_font>(sizeof(conio_fontdata)/sizeof(struct conio_font_data_struct)-2)) {
for(i=0; conio_fontdata[i].desc != NULL; i++) { for(i=0; conio_fontdata[i].desc != NULL; i++) {
if(!strcmp(conio_fontdata[i].desc, "Codepage 437 English")) { if(!strcmp(conio_fontdata[i].desc, "Codepage 437 English")) {
...@@ -408,30 +437,19 @@ int bitmap_loadfont(char *filename) ...@@ -408,30 +437,19 @@ int bitmap_loadfont(char *filename)
fontsize=fw*fh*256*sizeof(unsigned char); fontsize=fw*fh*256*sizeof(unsigned char);
if(font) if(font)
free(font); FREE_AND_NULL(font);
if((font=(unsigned char *)malloc(fontsize))==NULL) { if((font=(unsigned char *)malloc(fontsize))==NULL)
pthread_mutex_unlock(&vstatlock); goto error_return;
return(-1);
}
if(filename != NULL) { if(filename != NULL) {
if(flength(filename)!=fontsize) { if(flength(filename)!=fontsize)
pthread_mutex_unlock(&vstatlock); goto error_return;
free(font); if((fontfile=fopen(filename,"rb"))==NULL)
return(-1); goto error_return;
} if(fread(font, 1, fontsize, fontfile)!=fontsize)
if((fontfile=fopen(filename,"rb"))==NULL) { goto error_return;
pthread_mutex_unlock(&vstatlock);
free(font);
return(-1);
}
if(fread(font, 1, fontsize, fontfile)!=fontsize) {
pthread_mutex_unlock(&vstatlock);
free(font);
fclose(fontfile);
return(-1);
}
fclose(fontfile); fclose(fontfile);
fontfile=NULL;
current_font=-1; current_font=-1;
if(filename != current_filename) if(filename != current_filename)
SAFECOPY(current_filename,filename); SAFECOPY(current_filename,filename);
...@@ -441,48 +459,42 @@ int bitmap_loadfont(char *filename) ...@@ -441,48 +459,42 @@ int bitmap_loadfont(char *filename)
case 8: case 8:
switch(vstat.charheight) { switch(vstat.charheight) {
case 8: case 8:
if(conio_fontdata[current_font].eight_by_eight==NULL) { if(conio_fontdata[current_font].eight_by_eight==NULL)
pthread_mutex_unlock(&vstatlock); goto error_return;
free(font);
return(-1);
}
memcpy(font, conio_fontdata[current_font].eight_by_eight, fontsize); memcpy(font, conio_fontdata[current_font].eight_by_eight, fontsize);
break; break;
case 14: case 14:
if(conio_fontdata[current_font].eight_by_fourteen==NULL) { if(conio_fontdata[current_font].eight_by_fourteen==NULL)
pthread_mutex_unlock(&vstatlock); goto error_return;
free(font);
return(-1);
}
memcpy(font, conio_fontdata[current_font].eight_by_fourteen, fontsize); memcpy(font, conio_fontdata[current_font].eight_by_fourteen, fontsize);
break; break;
case 16: case 16:
if(conio_fontdata[current_font].eight_by_sixteen==NULL) { if(conio_fontdata[current_font].eight_by_sixteen==NULL)
pthread_mutex_unlock(&vstatlock); goto error_return;
free(font);
return(-1);
}
memcpy(font, conio_fontdata[current_font].eight_by_sixteen, fontsize); memcpy(font, conio_fontdata[current_font].eight_by_sixteen, fontsize);
break; break;
default: default:
pthread_mutex_unlock(&vstatlock); goto error_return;
free(font);
return(-1);
} }
break; break;
default: default:
pthread_mutex_unlock(&vstatlock); goto error_return;
free(font);
return(-1);
} }
} }
force_redraws++; force_redraws++;
pthread_mutex_unlock(&vstatlock); pthread_mutex_unlock(&vstatlock);
return(0); return(0);
error_return:
FREE_AND_NULL(font);
if(fontfile)
fclose(fontfile);
pthread_mutex_unlock(&vstatlock);
return(-1);
} }
/* Called from events thread only */ /* vstatlock is held */
static void bitmap_draw_cursor(int flush) static void bitmap_draw_cursor(int flush)
{ {
int x; int x;
...@@ -493,6 +505,8 @@ static void bitmap_draw_cursor(int flush) ...@@ -493,6 +505,8 @@ static void bitmap_draw_cursor(int flush)
int start,end; int start,end;
int width; int width;
if(!bitmap_initialized)
return;
if(vstat.blink && !hold_update) { if(vstat.blink && !hold_update) {
if(vstat.curs_start<=vstat.curs_end) { if(vstat.curs_start<=vstat.curs_end) {
xoffset=(cio_textinfo.curx+cio_textinfo.winleft-2)*vstat.charwidth; xoffset=(cio_textinfo.curx+cio_textinfo.winleft-2)*vstat.charwidth;
...@@ -521,6 +535,8 @@ void bitmap_gotoxy(int x, int y) ...@@ -521,6 +535,8 @@ void bitmap_gotoxy(int x, int y)
{ {
static int lx=-1,ly=-1; static int lx=-1,ly=-1;
if(!bitmap_initialized)
return;
pthread_mutex_lock(&vstatlock); pthread_mutex_lock(&vstatlock);
if((x != cio_textinfo.curx) || (y != cio_textinfo.cury)) { if((x != cio_textinfo.curx) || (y != cio_textinfo.cury)) {
vstat.curs_col=x+cio_textinfo.winleft-1; vstat.curs_col=x+cio_textinfo.winleft-1;
...@@ -530,16 +546,17 @@ void bitmap_gotoxy(int x, int y) ...@@ -530,16 +546,17 @@ void bitmap_gotoxy(int x, int y)
} }
if(!hold_update) { if(!hold_update) {
/* Erase old cursor */ /* Erase old cursor */
if(lx != vstat.curs_col || ly != vstat.curs_row) // if(lx != vstat.curs_col || ly != vstat.curs_row)
update_rect(lx,ly,1,1,TRUE,TRUE); // update_rect(lx,ly,1,1,TRUE,TRUE);
/* Draw new cursor */ /* Draw new cursor */
bitmap_draw_cursor(TRUE); // bitmap_draw_cursor(TRUE);
lx=vstat.curs_col; lx=vstat.curs_col;
ly=vstat.curs_row; ly=vstat.curs_row;
} }
pthread_mutex_unlock(&vstatlock); pthread_mutex_unlock(&vstatlock);
} }
/* vstatlock is held */
static int bitmap_draw_one_char(unsigned int xpos, unsigned int ypos) static int bitmap_draw_one_char(unsigned int xpos, unsigned int ypos)
{ {
int fg; int fg;
...@@ -551,6 +568,9 @@ static int bitmap_draw_one_char(unsigned int xpos, unsigned int ypos) ...@@ -551,6 +568,9 @@ static int bitmap_draw_one_char(unsigned int xpos, unsigned int ypos)
int fontoffset; int fontoffset;
WORD sch; WORD sch;
if(!bitmap_initialized)
return(-1);
if(!screen) if(!screen)
return(-1); return(-1);
...@@ -583,6 +603,7 @@ static int bitmap_draw_one_char(unsigned int xpos, unsigned int ypos) ...@@ -583,6 +603,7 @@ static int bitmap_draw_one_char(unsigned int xpos, unsigned int ypos)
return(0); return(0);
} }
/* vstatlock is held */
static int update_rect(int sx, int sy, int width, int height, int force, int calls_send) static int update_rect(int sx, int sy, int width, int height, int force, int calls_send)
{ {
int x,y; int x,y;
...@@ -597,6 +618,9 @@ static int update_rect(int sx, int sy, int width, int height, int force, int cal ...@@ -597,6 +618,9 @@ static int update_rect(int sx, int sy, int width, int height, int force, int cal
struct rectangle last_rect; struct rectangle last_rect;
int last_rect_used=0; int last_rect_used=0;
if(!bitmap_initialized)
return(-1);
if(sx==0 && sy==0 && width==0 && height==0) if(sx==0 && sy==0 && width==0 && height==0)
fullredraw=1; fullredraw=1;
...@@ -629,7 +653,9 @@ static int update_rect(int sx, int sy, int width, int height, int force, int cal ...@@ -629,7 +653,9 @@ static int update_rect(int sx, int sy, int width, int height, int force, int cal
/* Redraw all chars */ /* Redraw all chars */
if(vstat.blink != vs.blink if(vstat.blink != vs.blink
|| vstat.curs_col!=vs.curs_col || vstat.curs_col!=vs.curs_col
|| vstat.curs_row!=vs.curs_row) || vstat.curs_row!=vs.curs_row
|| vstat.curs_start!=vs.curs_start
|| vstat.curs_end!=vs.curs_end)
redraw_cursor=1; redraw_cursor=1;
for(y=0;y<height;y++) { for(y=0;y<height;y++) {
...@@ -718,10 +744,13 @@ static int update_rect(int sx, int sy, int width, int height, int force, int cal ...@@ -718,10 +744,13 @@ static int update_rect(int sx, int sy, int width, int height, int force, int cal
} }
} }
/* Did we redraw the cursor? If so, update position */ /* Did we redraw the cursor? If so, update cursor info */
if(redraw_cursor) { if(redraw_cursor) {
vs.curs_col=vstat.curs_col; vs.curs_col=vstat.curs_col;
vs.curs_row=vstat.curs_row; vs.curs_row=vstat.curs_row;
vs.blink=vstat.blink;
vs.curs_start=vstat.curs_start;
vs.curs_end=vstat.curs_end;
} }
/* On full redraws, save the last blink value */ /* On full redraws, save the last blink value */
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment