diff --git a/src/conio/bitmap_con.c b/src/conio/bitmap_con.c index 16c3cd593d952b9a7ef1a9b2c3c48069af3f3092..fac505333714f21383175bf7c4d2ffc2b0087877 100644 --- a/src/conio/bitmap_con.c +++ b/src/conio/bitmap_con.c @@ -267,6 +267,7 @@ int bitmap_getvideoflags(void) { int flags=0; + pthread_mutex_lock(&vstatlock); if(vstat.bright_background) flags |= CIOLIB_VIDEO_BGBRIGHT; if(vstat.no_bright) @@ -277,11 +278,13 @@ int bitmap_getvideoflags(void) flags |= CIOLIB_VIDEO_NOBLINK; if(vstat.blink_altcharset) flags |= CIOLIB_VIDEO_BLINKALTCHARS; + pthread_mutex_unlock(&vstatlock); return(flags); } void bitmap_setvideoflags(int flags) { + pthread_mutex_lock(&vstatlock); if(flags & CIOLIB_VIDEO_BGBRIGHT) vstat.bright_background=1; else @@ -306,6 +309,7 @@ void bitmap_setvideoflags(int flags) vstat.blink_altcharset=1; else vstat.blink_altcharset=0; + pthread_mutex_unlock(&vstatlock); } int bitmap_movetext(int x, int y, int ex, int ey, int tox, int toy) @@ -601,13 +605,20 @@ int bitmap_getfont(void) void bitmap_setscaling(int new_value) { + pthread_mutex_lock(&vstatlock); if(new_value > 0) vstat.scaling = new_value; + pthread_mutex_unlock(&vstatlock); } int bitmap_getscaling(void) { - return vstat.scaling; + int ret; + + pthread_mutex_lock(&vstatlock); + ret = vstat.scaling; + pthread_mutex_unlock(&vstatlock); + return ret; } /* Called from event thread only */ diff --git a/src/conio/sdl_con.c b/src/conio/sdl_con.c index 80cbf48d7f7484fbf12b0e59118930f9f44a017e..9e880eeeca1c61dc47b647c6c11d5f852c0dc22b 100644 --- a/src/conio/sdl_con.c +++ b/src/conio/sdl_con.c @@ -626,13 +626,18 @@ void sdl_flush(void) int sdl_init_mode(int mode) { - int oldcols=vstat.cols; + int oldcols; + + pthread_mutex_lock(&vstatlock); + oldcols = vstat.cols; + pthread_mutex_unlock(&vstatlock); sdl_user_func_ret(SDL_USEREVENT_FLUSH); bitmap_init_mode(mode, &bitmap_width, &bitmap_height); /* Deal with 40 col doubling */ + pthread_mutex_lock(&vstatlock); if(yuv.enabled) { vstat.scaling=2; } @@ -649,6 +654,7 @@ int sdl_init_mode(int mode) vstat.scaling = 1; if(vstat.vmultiplier < 1) vstat.vmultiplier = 1; + pthread_mutex_unlock(&vstatlock); sdl_user_func_ret(SDL_USEREVENT_SETVIDMODE); @@ -881,8 +887,8 @@ int sdl_setup_yuv_colours(void) void setup_surfaces(void) { - int char_width=vstat.charwidth*vstat.cols*vstat.scaling; - int char_height=vstat.charheight*vstat.rows*vstat.scaling*vstat.vmultiplier; + int char_width; + int char_height; int flags=SDL_HWSURFACE|SDL_ANYFORMAT; SDL_Surface *tmp_rect; SDL_Event ev; @@ -893,6 +899,10 @@ void setup_surfaces(void) flags |= SDL_RESIZABLE; 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; + if(yuv.enabled) { if(!yuv.win_width) yuv.win_width=vstat.charwidth*vstat.cols; @@ -905,6 +915,7 @@ 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) { @@ -1466,41 +1477,58 @@ int sdl_mouse_thread(void *data) int win_to_text_xpos(int winpos) { + int ret; + if(yuv.enabled) { - int ret; sdl.mutexP(win_mutex); + pthread_mutex_lock(&vstatlock); ret = winpos*vstat.cols/win->w+1; + pthread_mutex_unlock(&vstatlock); sdl.mutexV(win_mutex); return(ret); } - else - return(winpos/(vstat.charwidth*vstat.scaling)+1); + else { + pthread_mutex_lock(&vstatlock); + ret = winpos/(vstat.charwidth*vstat.scaling)+1; + pthread_mutex_unlock(&vstatlock); + return ret; + } } int win_to_text_ypos(int winpos) { - if(yuv.enabled) { - int ret; + int ret; + if(yuv.enabled) { sdl.mutexP(win_mutex); + pthread_mutex_lock(&vstatlock); ret = winpos*vstat.rows/win->h+1; + pthread_mutex_unlock(&vstatlock); sdl.mutexV(win_mutex); return(ret); } - else - return(winpos/(vstat.charheight*vstat.scaling*vstat.vmultiplier)+1); + else { + pthread_mutex_lock(&vstatlock); + ret = winpos/(vstat.charheight*vstat.scaling*vstat.vmultiplier)+1; + pthread_mutex_unlock(&vstatlock); + return ret; + } } int sdl_video_event_thread(void *data) { SDL_Event ev; int new_scaling = -1; - int old_scaling = vstat.scaling; + int old_scaling; SDL_Rect *upd_rects=NULL; int rectspace=0; int rectsused=0; + pthread_mutex_lock(&vstatlock); + old_scaling = vstat.scaling; + pthread_mutex_unlock(&vstatlock); + if(!init_sdl_video()) { char driver[16]; if(sdl.VideoDriverName(driver, sizeof(driver))!=NULL) { @@ -1522,6 +1550,7 @@ int sdl_video_event_thread(void *data) while(1) { if(sdl.PollEvent(&ev)!=1) { + // TODO: Still accessing vstat without holding the lock... if (new_scaling != -1 || vstat.scaling != old_scaling) { if (new_scaling == -1) new_scaling = vstat.scaling; @@ -1594,8 +1623,11 @@ int sdl_video_event_thread(void *data) yuv.win_height=ev.resize.h; new_scaling = 2; } - else + else { + pthread_mutex_lock(&vstatlock); new_scaling = (int)(ev.resize.w/(vstat.charwidth*vstat.cols)); + pthread_mutex_unlock(&vstatlock); + } } break; case SDL_VIDEOEXPOSE: @@ -1644,6 +1676,7 @@ int sdl_video_event_thread(void *data) break; } sdl.mutexP(newrect_mutex); + pthread_mutex_lock(&vstatlock); for(y=0; y<rect->height; y++) { offset=y*rect->width; for(x=0; x<rect->width; x++) { @@ -1676,6 +1709,7 @@ int sdl_video_event_thread(void *data) rectsused=0; } } + pthread_mutex_unlock(&vstatlock); sdl.mutexV(newrect_mutex); sdl.mutexV(win_mutex); free(rect->data); @@ -1735,6 +1769,7 @@ int sdl_video_event_thread(void *data) free(ev.user.data1); break; case SDL_USEREVENT_SETVIDMODE: + pthread_mutex_lock(&vstatlock); if(!yuv.enabled) { rectspace=vstat.cols*vstat.rows+vstat.cols; rectsused=0; @@ -1749,6 +1784,7 @@ int sdl_video_event_thread(void *data) } new_scaling = -1; old_scaling = vstat.scaling; + pthread_mutex_unlock(&vstatlock); setup_surfaces(); sdl_ufunc_retval=0; sdl.SemPost(sdl_ufunc_ret); diff --git a/src/conio/x_cio.c b/src/conio/x_cio.c index 1a13dabef0d066ee9f1aa7cf0adc41edcc52820a..12baa80636c2cce850e4308b04876eeb06ae8ae6 100644 --- a/src/conio/x_cio.c +++ b/src/conio/x_cio.c @@ -268,6 +268,10 @@ int x_init(void) xp_dlclose(dl); return(-1); } + if((x11.XCloseDisplay=xp_dlsym(dl,XCloseDisplay))==NULL) { + xp_dlclose(dl); + return(-1); + } if((x11.XCreateSimpleWindow=xp_dlsym(dl,XCreateSimpleWindow))==NULL) { xp_dlclose(dl); return(-1); diff --git a/src/conio/x_events.c b/src/conio/x_events.c index 164319fc704a0179f1b5aa4fb9f5f4fe25b2f78d..77998c7e376e5a230e49d0e92145b49db1824e97 100644 --- a/src/conio/x_events.c +++ b/src/conio/x_events.c @@ -48,6 +48,8 @@ int x11_window_ypos; int x11_window_width; int x11_window_height; int x11_initialized=0; +sem_t event_thread_complete; +int terminate = 0; /* * Local variables */ @@ -210,8 +212,10 @@ static int init_window() white=WhitePixel(dpy, DefaultScreen(dpy)); /* Create window, but defer setting a size and GC. */ + pthread_mutex_lock(&vstatlock); win = x11.XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, 640*vstat.scaling, 400*vstat.scaling*vstat.vmultiplier, 2, black, black); + pthread_mutex_unlock(&vstatlock); wmhints=x11.XAllocWMHints(); if(wmhints) { @@ -265,8 +269,10 @@ static void map_window() exit(1); } + pthread_mutex_lock(&vstatlock); sh->base_width = bitmap_width*vstat.scaling; sh->base_height = bitmap_height*vstat.scaling*vstat.vmultiplier; + pthread_mutex_unlock(&vstatlock); sh->min_width = sh->width_inc = sh->min_aspect.x = sh->max_aspect.x = bitmap_width; sh->min_height = sh->height_inc = sh->min_aspect.y = sh->max_aspect.y = bitmap_height; @@ -285,18 +291,26 @@ static void map_window() /* Resize the window. This function is called after a mode change. */ static void resize_window() { + pthread_mutex_lock(&vstatlock); x11.XResizeWindow(dpy, win, bitmap_width*vstat.scaling, bitmap_height*vstat.scaling*vstat.vmultiplier); + pthread_mutex_unlock(&vstatlock); + return; } static int init_mode(int mode) { - int oldcols=vstat.cols; + int oldcols; int oldwidth=bitmap_width; int oldheight=bitmap_height; + pthread_mutex_lock(&vstatlock); + oldcols=vstat.cols; + pthread_mutex_unlock(&vstatlock); + bitmap_init_mode(mode, &bitmap_width, &bitmap_height); + pthread_mutex_lock(&vstatlock); /* Deal with 40 col doubling */ if(oldcols != vstat.cols) { if(oldcols == 40) @@ -307,6 +321,7 @@ static int init_mode(int mode) if(vstat.scaling < 1) vstat.scaling = 1; + pthread_mutex_unlock(&vstatlock); map_window(); /* Resize window if necessary. */ @@ -323,10 +338,12 @@ static int video_init() /* If we are running under X, get a connection to the X server and create an empty window of size (1, 1). It makes a couple of init functions a lot easier. */ + pthread_mutex_lock(&vstatlock); if(vstat.scaling<1) vstat.scaling=1; if(vstat.vmultiplier<1) vstat.vmultiplier=1; + pthread_mutex_unlock(&vstatlock); if(init_window()) return(-1); @@ -349,6 +366,8 @@ static void local_draw_rect(struct update_rect *rect) #if 0 /* Draw solid colour rectangles... */ int rectw, recth, rectc, y2; + + pthread_mutex_lock(&vstatlock); for(y=0; y<rect->height; y++) { for(x=0; x<rect->width; x++) { rectc=rect->data[y*rect->width+x]; @@ -376,8 +395,10 @@ static void local_draw_rect(struct update_rect *rect) x11.XFillRectangle(dpy, win, gca[rectc], (rect->x+x)*vstat.scaling, (rect->y+y)*vstat.scaling*vstat.vmultiplier, rectw*vstat.scaling, recth*vstat.scaling*vstat.vmultiplier); } } + pthread_mutex_unlock(&vstatlock); #else #if 1 /* XImage */ + pthread_mutex_lock(&vstatlock); xim=x11.XCreateImage(dpy,&visual,depth,ZPixmap,0,NULL,rect->width*vstat.scaling,rect->height*vstat.scaling*vstat.vmultiplier,32,0); xim->data=(char *)malloc(xim->bytes_per_line*rect->height*vstat.scaling*vstat.vmultiplier); for(y=0;y<rect->height;y++) { @@ -395,6 +416,7 @@ static void local_draw_rect(struct update_rect *rect) } x11.XPutImage(dpy,win,gca[0],xim,0,0,rect->x*vstat.scaling,rect->y*vstat.scaling*vstat.vmultiplier,rect->width*vstat.scaling,rect->height*vstat.scaling*vstat.vmultiplier); + pthread_mutex_unlock(&vstatlock); #ifdef XDestroyImage XDestroyImage(xim); #else @@ -402,11 +424,13 @@ static void local_draw_rect(struct update_rect *rect) #endif #else /* XFillRectangle */ + pthread_mutex_lock(&vstatlock); for(y=0;y<rect->height;y++) { for(x=0; x<rect->width; x++) { x11.XFillRectangle(dpy, win, gca[rect->data[y*rect->width+x]], (rect->x+x)*vstat.scaling, (rect->y+y)*vstat.scaling*vstat.vmultiplier, vstat.scaling, vstat.scaling*vstat.vmultiplier); } } + pthread_mutex_unlock(&vstatlock); #endif #endif free(rect->data); @@ -418,9 +442,12 @@ static void handle_resize_event(int width, int height) int newFSW=1; // No change + pthread_mutex_lock(&vstatlock); if((width == vstat.charwidth * vstat.cols * vstat.scaling) - && (height == vstat.charheight * vstat.rows * vstat.scaling*vstat.vmultiplier)) + && (height == vstat.charheight * vstat.rows * vstat.scaling*vstat.vmultiplier)) { + pthread_mutex_unlock(&vstatlock); return; + } newFSH=width/bitmap_width; newFSW=height/bitmap_height; @@ -440,15 +467,20 @@ static void handle_resize_event(int width, int height) * Otherwise, we can simply resend everything */ if((width % (vstat.charwidth * vstat.cols) != 0) - || (height % (vstat.charheight * vstat.rows) != 0)) + || (height % (vstat.charheight * vstat.rows) != 0)) { + pthread_mutex_unlock(&vstatlock); resize_window(); + } + else + pthread_mutex_unlock(&vstatlock); send_rectangle(0,0,bitmap_width,bitmap_height,TRUE); } -static void expose_rect(x,y,width,height) +static void expose_rect(int x, int y, int width, int height) { int sx,sy,ex,ey; + pthread_mutex_lock(&vstatlock); sx=x/vstat.scaling; sy=y/(vstat.scaling*vstat.vmultiplier); @@ -462,6 +494,7 @@ static void expose_rect(x,y,width,height) } ex=ex/vstat.scaling; ey=ey/(vstat.scaling*vstat.vmultiplier); + pthread_mutex_unlock(&vstatlock); send_rectangle(sx, sy, ex-sx+1, ey-sy+1, TRUE); } @@ -565,6 +598,7 @@ static int x11_event(XEvent *ev) { XMotionEvent *me = (XMotionEvent *)ev; + pthread_mutex_lock(&vstatlock); me->x/=vstat.scaling; me->x/=vstat.charwidth; me->y/=vstat.scaling; @@ -580,6 +614,7 @@ static int x11_event(XEvent *ev) me->x=vstat.cols; if(me->y>vstat.rows+1) me->y=vstat.rows+1; + pthread_mutex_unlock(&vstatlock); ciomouse_gotevent(CIOLIB_MOUSE_MOVE,me->x,me->y); } break; @@ -587,6 +622,7 @@ static int x11_event(XEvent *ev) { XButtonEvent *be = (XButtonEvent *)ev; + pthread_mutex_lock(&vstatlock); be->x/=vstat.scaling; be->x/=vstat.charwidth; be->y/=vstat.scaling; @@ -602,6 +638,7 @@ static int x11_event(XEvent *ev) be->x=vstat.cols; if(be->y>vstat.rows+1) be->y=vstat.rows+1; + pthread_mutex_unlock(&vstatlock); if (be->button <= 3) { ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(be->button),be->x,be->y); } @@ -611,6 +648,7 @@ static int x11_event(XEvent *ev) { XButtonEvent *be = (XButtonEvent *)ev; + pthread_mutex_lock(&vstatlock); be->x/=vstat.scaling; be->x/=vstat.charwidth; be->y/=vstat.scaling; @@ -626,6 +664,7 @@ static int x11_event(XEvent *ev) be->x=vstat.cols; if(be->y>vstat.rows+1) be->y=vstat.rows+1; + pthread_mutex_unlock(&vstatlock); if (be->button <= 3) { ciomouse_gotevent(CIOLIB_BUTTON_PRESS(be->button),be->x,be->y); } @@ -824,10 +863,20 @@ static int x11_event(XEvent *ev) void check_scaling(void) { + pthread_mutex_lock(&vstatlock); if (old_scaling != vstat.scaling) { + pthread_mutex_unlock(&vstatlock); resize_window(); + pthread_mutex_lock(&vstatlock); old_scaling = vstat.scaling; } + pthread_mutex_unlock(&vstatlock); +} + +static void x11_terminate_event_thread(void) +{ + terminate = 1; + sem_wait(&event_thread_complete); } void x11_event_thread(void *args) @@ -844,6 +893,8 @@ void x11_event_thread(void *args) return; } x11_initialized=1; + sem_init(&event_thread_complete, 0, 0); + atexit(x11_terminate_event_thread); sem_post(&init_complete); if(local_pipe[0] > xfd) @@ -851,7 +902,7 @@ void x11_event_thread(void *args) else high_fd=xfd; - for (;;) { + for (;!terminate;) { check_scaling(); tv.tv_sec=0; @@ -956,4 +1007,6 @@ void x11_event_thread(void *args) } } } + x11.XCloseDisplay(dpy); + sem_post(&event_thread_complete); } diff --git a/src/conio/x_events.h b/src/conio/x_events.h index 366aa51a3fb592f3931e2035434393b79a22b724..6e55daf6192e19c1d276cea3cf0cfd03f2dc016f 100644 --- a/src/conio/x_events.h +++ b/src/conio/x_events.h @@ -57,6 +57,7 @@ struct x11 { Pixmap (*XCreateBitmapFromData) (Display*, Drawable, _Xconst char*, unsigned int, unsigned int); Status (*XAllocColor) (Display*, Colormap, XColor*); Display*(*XOpenDisplay) (_Xconst char*); + int (*XCloseDisplay) (Display*); Window (*XCreateSimpleWindow) (Display*, Window, int, int, unsigned int, unsigned int, unsigned int, unsigned long, unsigned long); GC (*XCreateGC) (Display*, Drawable, unsigned long, XGCValues*); int (*XSelectInput) (Display*, Window, long); @@ -98,6 +99,8 @@ extern sem_t pastebuf_set; extern sem_t pastebuf_used; extern sem_t init_complete; extern sem_t mode_set; +extern sem_t event_thread_complete; +extern int terminate; extern int x11_window_xpos; extern int x11_window_ypos; extern int x11_window_width;