aboutsummaryrefslogtreecommitdiff
path: root/generic
diff options
context:
space:
mode:
authorlecoanet2000-11-13 10:17:36 +0000
committerlecoanet2000-11-13 10:17:36 +0000
commitc914a00fb8b2257cc827d1d0b41ce5ee496b9289 (patch)
tree931d8fbd3311dd5650f4f9c3ae703c577f108a60 /generic
parent43907650b84fe72741678e0c992555d762f50777 (diff)
downloadtkzinc-c914a00fb8b2257cc827d1d0b41ce5ee496b9289.zip
tkzinc-c914a00fb8b2257cc827d1d0b41ce5ee496b9289.tar.gz
tkzinc-c914a00fb8b2257cc827d1d0b41ce5ee496b9289.tar.bz2
tkzinc-c914a00fb8b2257cc827d1d0b41ce5ee496b9289.tar.xz
* (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).
Diffstat (limited to 'generic')
-rw-r--r--generic/tkZinc.c287
1 files changed, 211 insertions, 76 deletions
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 <stdio.h>
#include <string.h>
#include <math.h>
-#include <sys/time.h>
-#include <unistd.h>
#include <X11/Xatom.h>
#ifdef SHM
#include <sys/shm.h>
@@ -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, &ltime, 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));
}
}