From c914a00fb8b2257cc827d1d0b41ce5ee496b9289 Mon Sep 17 00:00:00 2001 From: lecoanet Date: Mon, 13 Nov 2000 10:17:36 +0000 Subject: * (WidgetObjCmd): Dans les commandes raise/lower les items n'appartenant pas au m�me groupe que le premier item ou l'item de r�f�rence, sont ignor�s. * Ajout du rendu local et de l'option -localrender. * Utilisation du module perfos pour la mesure de perf (monitor). --- generic/tkZinc.c | 287 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 211 insertions(+), 76 deletions(-) (limited to 'generic') diff --git a/generic/tkZinc.c b/generic/tkZinc.c index f3bdd67..f620c93 100644 --- a/generic/tkZinc.c +++ b/generic/tkZinc.c @@ -50,6 +50,7 @@ static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " #include "Track.h" #include "Transfo.h" #include "Image.h" +#include "perfos.h" #ifdef GPC #include "gpc/gpc.h" #endif @@ -59,8 +60,6 @@ static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " #include #include #include -#include -#include #include #ifdef SHM #include @@ -174,6 +173,8 @@ static Tk_ConfigSpec config_specs[] = { "600", Tk_Offset(WidgetInfo, insert_on_time), 0}, {TK_CONFIG_PIXELS, "-insertwidth", "insertWidth", "InsertWidth", "2", Tk_Offset(WidgetInfo, text_info.insert_width), 0}, + {TK_CONFIG_BOOLEAN, "-localrender", "localRender", "LocalRender", + "0", Tk_Offset(WidgetInfo, local_render), 0}, {TK_CONFIG_BITMAP, "-mapdistancesymbol", "mapDistanceSymbol", "MapDistanceSymbol", "AtcSymbol19", Tk_Offset(WidgetInfo, map_distance_symbol), TK_CONFIG_NULL_OK}, {TK_CONFIG_FONT, "-maptextfont", "mapTextFont", "MapTextFont", @@ -233,22 +234,23 @@ static Tk_ConfigSpec config_specs[] = { #define INSERT_OFF_TIME_SPEC 11 #define INSERT_ON_TIME_SPEC 12 #define INSERT_WIDTH_SPEC 13 -#define MAP_DISTANCE_SYMBOL_SPEC 14 -#define MAP_TEXT_FONT_SPEC 15 -#define OVERLAP_MANAGER_SPEC 16 -#define PICK_APERTURE_SPEC 17 -#define RELIEF_SPEC 18 -#define RESHAPE_SPEC 19 -#define SELECT_COLOR_SPEC 20 -#define SPEED_VECTOR_LENGTH_SPEC 21 -#define TAKE_FOCUS_SPEC 22 -#define TILE_SPEC 23 -#define MANAGE_HISTORY_SPEC 24 -#define MANAGED_HISTORY_SIZE_SPEC 25 -#define WIDTH_SPEC 26 -#define BBOXES_SPEC 27 -#define BBOXES_COLOR_SPEC 28 -#define LIGHT_ANGLE_SPEC 29 +#define LOCAL_RENDER_SPEC 14 +#define MAP_DISTANCE_SYMBOL_SPEC 15 +#define MAP_TEXT_FONT_SPEC 16 +#define OVERLAP_MANAGER_SPEC 17 +#define PICK_APERTURE_SPEC 18 +#define RELIEF_SPEC 19 +#define RESHAPE_SPEC 20 +#define SELECT_COLOR_SPEC 21 +#define SPEED_VECTOR_LENGTH_SPEC 22 +#define TAKE_FOCUS_SPEC 23 +#define TILE_SPEC 24 +#define MANAGE_HISTORY_SPEC 25 +#define MANAGED_HISTORY_SIZE_SPEC 26 +#define WIDTH_SPEC 27 +#define BBOXES_SPEC 28 +#define BBOXES_COLOR_SPEC 29 +#define LIGHT_ANGLE_SPEC 30 static void CmdDeleted _ANSI_ARGS_((ClientData client_data)); @@ -371,6 +373,73 @@ ZnNeedRedisplay(WidgetInfo *wi) /* *---------------------------------------------------------------------- * + * CreateSharedImageBuffer -- + * + *---------------------------------------------------------------------- + */ +#ifdef SHM +void +CreateSharedImageBuffer(WidgetInfo *wi) +{ + /* + * Allocate a shared image to be used as the back buffer. + * The sequence is extracted from gdk image. + */ + wi->draw_buffer_im = XShmCreateImage(wi->dpy, Tk_Visual(wi->win), Tk_Depth(wi->win), + ZPixmap, NULL, &wi->x_shm_info, + wi->width, wi->height); + if (wi->draw_buffer_im == NULL) { + ZnWarning("XShmCreateImage failed, unable to use local rendering"); + wi->local_render = False; + } + else { + wi->x_shm_info.shmid = shmget(IPC_PRIVATE, + wi->draw_buffer_im->bytes_per_line * + wi->draw_buffer_im->height, + IPC_CREAT | 0777); + if (wi->x_shm_info.shmid == -1) { + XDestroyImage(wi->draw_buffer_im); + wi->draw_buffer_im = NULL; + ZnWarning("shmget failed, unable to use local rendering"); + wi->local_render = False; + } + else { + wi->x_shm_info.readOnly = False; + wi->x_shm_info.shmaddr = shmat(wi->x_shm_info.shmid, 0, 0); + wi->draw_buffer_im->data = wi->x_shm_info.shmaddr; + if (wi->x_shm_info.shmaddr == (char *) -1) { + shmctl(wi->x_shm_info.shmid, IPC_RMID, 0); + XDestroyImage(wi->draw_buffer_im); + wi->draw_buffer_im = NULL; + ZnWarning("shmat failed, unable to use local rendering"); + wi->local_render = False; + } + else { + wi->buf.buf = ZnMalloc(wi->draw_buffer_im->bytes_per_line * + wi->draw_buffer_im->height * 3); + wi->buf.rowstride = wi->draw_buffer_im->bytes_per_line * 3; + wi->buf.ox = wi->buf.oy = 0; + wi->buf.cx = wi->width; + wi->buf.cy = wi->height; + XShmAttach(wi->dpy, &wi->x_shm_info); + XSync(wi->dpy, False); + /* We mark the segment as destroyed so that when + * the last process detaches, it will be deleted. + * There is a small possibility of leaking if + * we die in XShmAttach. In theory, a signal handler + * could be set up. + */ + shmctl(wi->x_shm_info.shmid, IPC_RMID, 0); + } + } + } +} +#endif + + +/* + *---------------------------------------------------------------------- + * * ZincObjCmd -- * * This procedure is invoked to process the "zinc" Tcl @@ -419,16 +488,12 @@ ZincObjCmd(ClientData client_data, /* Main window associated with wi->interp = interp; wi->dpy = Tk_Display(tkwin); wi->screen = Tk_Screen(tkwin); - wi->has_z_pixmap = False; wi->has_x_shm = False; #ifdef SHM if (XQueryExtension(wi->dpy, "MIT-SHM", &major_op, &first_evt, &first_err)) { ZnBool pixmaps; if (XShmQueryVersion(wi->dpy, &major_op, &minor_op, &pixmaps) == True) { wi->has_x_shm = True; - if ((pixmaps == True) && (XShmPixmapFormat(wi->dpy) == ZPixmap)) { - wi->has_z_pixmap = True; - } } } #endif @@ -441,6 +506,7 @@ ZincObjCmd(ClientData client_data, /* Main window associated with wi->has_x_input = XQueryExtension(wi->dpy, "XInputExtension", &major_op, &first_evt, &first_err); wi->reshape = wi->full_reshape = True; + wi->local_render = False; wi->real_top = None; #ifdef PTK @@ -493,15 +559,17 @@ ZincObjCmd(ClientData client_data, /* Main window associated with #endif wi->gc = 0; wi->draw_buffer = 0; + wi->draw_buffer_im = 0; wi->events_flags = 0; wi->pick_aperture = 0; wi->new_item = wi->current_item = ZN_NO_ITEM; wi->new_part = wi->current_part = ZN_NO_PART; wi->monitoring = False; - wi->num_updates = 0; - wi->last_time = wi->total_time = 0; - + wi->total_draw_chrono = NewChrono("Total draw time"); + wi->this_draw_chrono = NewChrono("Last draw time"); + wi->damaged_area_w = wi->damaged_area_h = 0; + wi->work_item_list = NULL; wi->work_pts = ZnListNew(8, sizeof(ZnPoint)); wi->work_xpts = ZnListNew(8, sizeof(XPoint)); @@ -559,11 +627,17 @@ ZincObjCmd(ClientData client_data, /* Main window associated with wi->damaged_area.corner.y = wi->height = wi->opt_height; /* - * Allocate double buffer pixmap. + * Allocate double buffer pixmap/image. */ - wi->draw_buffer = XCreatePixmap(wi->dpy, RootWindowOfScreen(wi->screen), - wi->width, wi->height, - DefaultDepthOfScreen(wi->screen)); + if (wi->local_render) { +#ifdef SHM + CreateSharedImageBuffer(wi); +#endif + } + if (!wi->local_render) { + wi->draw_buffer = XCreatePixmap(wi->dpy, RootWindowOfScreen(wi->screen), + wi->width, wi->height, Tk_Depth(wi->win)); + } #ifdef PTK Tcl_SetObjResult(interp, LangWidgetArg(interp, tkwin)); @@ -2409,7 +2483,7 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ int num = 0, i, j; char *end, *str; ZnTransfo *t = NULL; - Tcl_Obj *l, *lobjs[4]; + Tcl_Obj *l, *lobjs[10]; TagSearch *search_var = NULL; Tcl_HashEntry *entry; static char *sub_cmd_strings[] = { @@ -3371,7 +3445,7 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ */ case ZN_W_LOWER: { - Item mark = ZN_NO_ITEM; + Item group, mark = ZN_NO_ITEM; if (argc < 3) { Tcl_WrongNumArgs(interp, 1, args, "lower tagOrId ?belowThis?"); @@ -3401,7 +3475,11 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ if (mark == ZN_NO_ITEM) { mark = ((GroupItem) item->parent)->tail; } + group = mark->parent; for (; item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { + if (item->parent != group) { + continue; + } if (item != mark) { ITEM.UpdateItemPriority(item, mark, False); mark = item; @@ -3426,15 +3504,23 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ } wi->monitoring = on_off; if (on_off == True) { - wi->num_updates = 0; - wi->last_time = wi->total_time = 0; + ResetChronos(wi->total_draw_chrono); + ResetChronos(wi->this_draw_chrono); } } if ((argc == 2) || (on_off == False)) { - lobjs[0] = Tcl_NewIntObj(wi->num_updates); - lobjs[1] = Tcl_NewIntObj(wi->last_time); - lobjs[2] = Tcl_NewIntObj(wi->total_time); + long ttime, ltime; + int num_actions; + GetChrono(wi->total_draw_chrono, &ttime, &num_actions); + GetChrono(wi->this_draw_chrono, <ime, NULL); + lobjs[0] = Tcl_NewIntObj(num_actions); + lobjs[1] = Tcl_NewIntObj(ltime); + lobjs[2] = Tcl_NewIntObj(ttime); l = Tcl_NewListObj(3, lobjs); + /*lobjs[2] = Tcl_NewIntObj(wi->damaged_area_w); + lobjs[3] = Tcl_NewIntObj(wi->damaged_area_h); + lobjs[4] = Tcl_NewIntObj(ttime); + l = Tcl_NewListObj(5, lobjs);*/ Tcl_SetObjResult(interp, l); #ifdef PTK Tcl_DecrRefCount(l); @@ -3477,7 +3563,7 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ */ case ZN_W_RAISE: { - Item mark = ZN_NO_ITEM; + Item group, mark = ZN_NO_ITEM; if (argc < 3) { Tcl_WrongNumArgs(interp, 1, args, "raise tagOrId ?aboveThis?"); @@ -3507,7 +3593,11 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ if (mark == ZN_NO_ITEM) { mark = ((GroupItem) item->parent)->head; } + group = mark->parent; for (; item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) { + if (item->parent != group) { + continue; + } if (item != mark) { ITEM.UpdateItemPriority(item, mark, True); } @@ -4139,7 +4229,11 @@ Configure(Tcl_Interp *interp,/* Used for error reporting. */ #define CONFIG_PROBE(offset) (ISSET(config_specs[offset].specFlags, \ TK_CONFIG_OPTION_SPECIFIED)) ZnBBox bbox; - + Visual *visual; + int depth; + Bool local_render; + + local_render = wi->local_render; if (Tk_ConfigureWidget(interp, wi->win, config_specs, argc, #ifdef PTK (Tcl_Obj **) args, (char *) wi, flags) != TCL_OK) { @@ -4149,6 +4243,31 @@ Configure(Tcl_Interp *interp,/* Used for error reporting. */ return ZN_ERROR; } + if (flags & TK_CONFIG_ARGV_ONLY) { + /* + * Do not allow modification of the rendering scheme after + * the widget creation. + */ + wi->local_render = local_render; + } + else { + /* + * Turn off local rendering if shared memory is not supported. + * or if we cannot use the chosen visual, we cannot work with + * any visuals, only true color, 16, 24, 32 bits, and perhaps 15 bits + * and direct color (to be checked). + */ + wi->local_render = wi->local_render && wi->has_x_shm; + if (wi->local_render) { + visual = Tk_Visual(wi->win); + depth = Tk_Depth(wi->win); + if (((visual->class != TrueColor) && (visual->class != DirectColor)) || + ((depth != 16) && (depth != 24) && (depth != 32))) { + wi->local_render = False; + } + } + } + /* * Maintain the pick aperture within meaningful bounds. */ @@ -4402,8 +4521,8 @@ Event(ClientData client_data, /* Information about widget. */ height += bbox.orig.y; bbox.orig.y = 0; } - bbox.corner.x = bbox.orig.x + width; - bbox.corner.y = bbox.orig.y + height; + bbox.corner.x = MIN(wi->width, bbox.orig.x + width); + bbox.corner.y = MIN(wi->height, bbox.orig.y + height); /*printf("expose %d %d %d %d\n", ((XExposeEvent*) event)->x, ((XExposeEvent*) event)->y, @@ -4435,7 +4554,7 @@ Event(ClientData client_data, /* Information about widget. */ h = Tk_Height(wi->win)-2*wi->inset; if ((wi->width != w) || (wi->height != h)) { - /*printf("reallocating pixmap\n");*/ + /*printf("reallocating double buffer\n");*/ bbox.orig.x = bbox.orig.y = 0; bbox.corner.x = MAX(wi->width, w); bbox.corner.y = MAX(wi->height, h); @@ -4447,12 +4566,26 @@ Event(ClientData client_data, /* Information about widget. */ ITEM.Invalidate(wi->top_group, ZN_TRANSFO_FLAG); /* - * Reallocate the double buffer pixmap. + * Reallocate the double buffer pixmap/image. */ - XFreePixmap(wi->dpy, wi->draw_buffer); - wi->draw_buffer = XCreatePixmap(wi->dpy, RootWindowOfScreen(wi->screen), - wi->width, wi->height, - DefaultDepthOfScreen(wi->screen)); + if (wi->local_render) { +#ifdef SHM + /* Free the image and allocate a bigger one. */ + XShmDetach(wi->dpy, &wi->x_shm_info); + XDestroyImage(wi->draw_buffer_im); + wi->draw_buffer_im = NULL; + shmdt(wi->x_shm_info.shmaddr); + shmctl(wi->x_shm_info.shmid, IPC_RMID, 0); + ZnFree(wi->buf.buf); + CreateSharedImageBuffer(wi); +#endif + } + if (!wi->local_render) { + XFreePixmap(wi->dpy, wi->draw_buffer); + wi->draw_buffer = XCreatePixmap(wi->dpy, RootWindowOfScreen(wi->screen), + wi->width, wi->height, + DefaultDepthOfScreen(wi->screen)); + } } else { /* @@ -5214,11 +5347,20 @@ Destroy(char *mem_ptr) /* Info about the widget. */ wi->tile = ZnUnspecifiedImage; } - /* Free the double buffer pixmap */ + /* Free the double buffer pixmap/image */ if (wi->draw_buffer) { XFreePixmap(wi->dpy, wi->draw_buffer); } - + if (wi->draw_buffer_im) { +#ifdef SHM + XShmDetach(wi->dpy, &wi->x_shm_info); + XDestroyImage(wi->draw_buffer_im); + shmdt(wi->x_shm_info.shmaddr); + shmctl(wi->x_shm_info.shmid, IPC_RMID, 0); + ZnFree(wi->buf.buf); +#endif + } + Tcl_DeleteTimerHandler(wi->blink_handler); Tk_FreeOptions(config_specs, (char *) wi, wi->dpy, 0); @@ -5231,6 +5373,9 @@ Destroy(char *mem_ptr) /* Info about the widget. */ ZnListFree(wi->work_pts); ZnListFree(wi->work_xpts); + + FreeChrono(wi->total_draw_chrono); + FreeChrono(wi->this_draw_chrono); ZnFree(wi); /*printf("Destroy ending\n");*/ @@ -5262,32 +5407,16 @@ Redisplay(ClientData client_data) /* Information about the widget. */ ZnBBox merge; Tk_Window tkwin; XRectangle r; - struct timeval start, end; - struct timezone tz; wi->update_pending = 0; if (!wi->realized || !Tk_IsMapped(wi->win)) { return; } - /* - * Give the overlap manager a chance to do its work. - */ -#ifdef OM - if ((wi->om_group != ZN_NO_ITEM) && - ((GroupItem) wi->om_group)->call_om) { - ZnPoint scale={1.0,1.0}; - if (wi->om_group->transfo) { - ZnTransfoDecompose(wi->om_group->transfo, &scale, - NULL, NULL, NULL); - } - OmProcessOverlap((void *) wi, wi->width, wi->height, scale.x); - ((GroupItem) wi->om_group)->call_om = False; - } -#endif - if (wi->monitoring) { - gettimeofday(&start, &tz); + XStartChrono(wi->total_draw_chrono, wi->dpy, ZnWindowId(wi->win)); + ResetChronos(wi->this_draw_chrono); + XStartChrono(wi->this_draw_chrono, wi->dpy, ZnWindowId(wi->win)); } do { @@ -5329,13 +5458,22 @@ Redisplay(ClientData client_data) /* Information about the widget. */ ResetBBox(&merge); CopyBBox(&wi->damaged_area, &merge); + wi->damaged_area_w = wi->damaged_area.corner.x-wi->damaged_area.orig.x; + wi->damaged_area_h = wi->damaged_area.corner.y-wi->damaged_area.orig.y; AddBBoxToBBox(&merge, &wi->exposed_area); if (!IsEmptyBBox(&merge)) { BBox2XRect(&merge, &r); - /*printf("redisplay %d %d %d %d\n", r.x, r.y, r.width, r.height);*/ - XCopyArea(wi->dpy, - wi->draw_buffer, ZnWindowId(wi->win), wi->gc, - r.x, r.y, r.width, r.height, r.x+wi->inset, r.y+wi->inset); + if (wi->local_render) { +#ifdef SHM + XPutImage(wi->dpy, ZnWindowId(wi->win), wi->gc, wi->draw_buffer_im, + r.x, r.y, r.x+wi->inset, r.y+wi->inset, r.width, r.height); +#endif + } + else { + XCopyArea(wi->dpy, + wi->draw_buffer, ZnWindowId(wi->win), wi->gc, + r.x, r.y, r.width, r.height, r.x+wi->inset, r.y+wi->inset); + } } /* @@ -5368,11 +5506,8 @@ Redisplay(ClientData client_data) /* Information about the widget. */ } if (wi->monitoring) { - XSync(wi->dpy, 0); - gettimeofday(&end, &tz); - wi->num_updates++; - wi->last_time = (end.tv_sec-start.tv_sec)*1000 + (end.tv_usec-start.tv_usec)/1000; - wi->total_time += wi->last_time; + XStopChrono(wi->total_draw_chrono, wi->dpy, ZnWindowId(wi->win)); + XStopChrono(wi->this_draw_chrono, wi->dpy, ZnWindowId(wi->win)); } } -- cgit v1.1