From 34e9e2a7e4795e28f8189617f67adb32c0c91c2f Mon Sep 17 00:00:00 2001 From: lecoanet Date: Thu, 4 Mar 2004 08:39:00 +0000 Subject: * OpenGL contexts are allocated by display instead of by widget. * Colormaps are not allocated for each widget window but are cached by display (should be perhaps by screen) * Freed the visual info returned by each call to glXChooseVisual. This used to generate a memory leak for each widget instance. * Adapted for perl/Tk 804. * Some better init code to prevent valgrind from reporting use of unitialized memory (can be useful anyway). * Commented an OpenGL bug workaround dealing with bad partial redraw after moving the window. It seems to have disappeared (tested with NVIDIA 53.3). * Free the drawing GC as part of destroy cleanup. --- generic/tkZinc.c | 238 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 155 insertions(+), 83 deletions(-) (limited to 'generic/tkZinc.c') diff --git a/generic/tkZinc.c b/generic/tkZinc.c index c6d924c..5782f6a 100644 --- a/generic/tkZinc.c +++ b/generic/tkZinc.c @@ -129,6 +129,22 @@ static Tk_Uid neg_tag_val_uid; static Tk_Uid dot_uid; static Tk_Uid star_uid; +#ifdef GL +typedef struct _ZnGLContextEntry { + ZnGLContext context; +#ifdef WIN + HDC hdc; +#else + Display *dpy; + XVisualInfo *visual; /* Should these two be managed by screen ? */ + Colormap colormap; +#endif + struct _ZnGLContextEntry *next; +} ZnGLContextEntry; +static ZnGLContextEntry *gl_contexts = NULL; +#endif + + static void PickCurrentItem _ANSI_ARGS_((ZnWInfo *wi, XEvent *event)); static int ZnReliefParse _ANSI_ARGS_((ClientData client_data, Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *ovalue, @@ -676,10 +692,14 @@ ZincObjCmd(ClientData client_data, /* Main window associated with # ifdef _WIN32 Tcl_AppendResult(interp, " GL", NULL); # else - if (has_gl && glXChooseVisual(dpy, - XScreenNumberOfScreen(screen), - attribs)) { - Tcl_AppendResult(interp, " GL", NULL); + { + XVisualInfo *visual = glXChooseVisual(dpy, + XScreenNumberOfScreen(screen), + attribs); + if (has_gl && visual) { + Tcl_AppendResult(interp, " GL", NULL); + } + XFree(visual); } # endif #endif @@ -716,9 +736,12 @@ ZincObjCmd(ClientData client_data, /* Main window associated with #endif #ifdef PTK +#ifdef PTK_800 wi->cmd = Lang_CreateWidget(interp, tkwin, (Tcl_CmdProc *) WidgetObjCmd, (ClientData) wi, CmdDeleted); - +#else + wi->cmd = Lang_CreateWidget(interp, tkwin, WidgetObjCmd, (ClientData) wi, CmdDeleted); +#endif #else wi->cmd = Tcl_CreateObjCommand(interp, Tk_PathName(tkwin), WidgetObjCmd, (ClientData) wi, CmdDeleted); @@ -740,11 +763,7 @@ ZincObjCmd(ClientData client_data, /* Main window associated with #ifdef GL wi->font_tfi = NULL; wi->map_font_tfi = NULL; - wi->gl_context = NULL; wi->max_tex_size = 64; /* Minimum value is always valid */ -# ifndef _WIN32 - wi->gl_visual = NULL; -# endif #endif wi->map_distance_symbol = ZnUnspecifiedImage; wi->track_symbol = ZnUnspecifiedImage; @@ -781,6 +800,8 @@ ZincObjCmd(ClientData client_data, /* Main window associated with wi->gc = 0; wi->draw_buffer = 0; wi->pick_aperture = 0; + wi->state = 0; + memset(&wi->pick_event, 0, sizeof(XEvent)); wi->new_item = wi->current_item = ZN_NO_ITEM; wi->new_part = wi->current_part = ZN_NO_PART; wi->focus_item = ZN_NO_ITEM; @@ -822,6 +843,8 @@ ZincObjCmd(ClientData client_data, /* Main window associated with wi->highlight_width = 0; wi->highlight_color = NULL; wi->highlight_bg_color = NULL; + ZnResetBBox(&wi->exposed_area); + ZnResetBBox(&wi->damaged_area); ZnInitClipStack(wi); ZnInitTransformStack(wi); @@ -854,7 +877,6 @@ ZincObjCmd(ClientData client_data, /* Main window associated with return TCL_ERROR; } - ZnResetBBox(&wi->exposed_area); wi->damaged_area.orig.x = wi->damaged_area.orig.y = 0; wi->damaged_area.corner.x = wi->width = wi->opt_width; wi->damaged_area.corner.y = wi->height = wi->opt_height; @@ -864,7 +886,8 @@ ZincObjCmd(ClientData client_data, /* Main window associated with */ if (wi->render) { #ifdef GL - wi->gl_context = 0; + ZnGLContextEntry *context_entry; + ASSIGN(wi->flags, ZN_PRINT_CONFIG, (getenv("ZINC_GLX_INFO") != NULL)); if (ISSET(wi->flags, ZN_HAS_GL)) { @@ -895,74 +918,119 @@ ZincObjCmd(ClientData client_data, /* Main window associated with if (!wi->hdc) { OutputDebugString("Unable to get the hdc\n"); } - ipixel = ChoosePixelFormat(wi->hdc, &pfd); - /* sprintf(msg, "ipixel=%d dwFlags=0x%x req=0x%x iPixelType=%d\n", - ipixel, - pfd.dwFlags, - PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER, - pfd.iPixelType==PFD_TYPE_RGBA); - OutputDebugString(msg);*/ - if (!ipixel) { - OutputDebugString("ChoosePixelFormat failed\n"); - } - wi->render = (SetPixelFormat(wi->hdc, ipixel, &pfd) == TRUE); - if (wi->render) { - wi->gl_context = wglCreateContext(wi->hdc); - if (!wi->gl_context) { - OutputDebugString("wglCreateContext failed\n"); - } + /* + * Look for a matching context already available. + */ + for (context_entry = gl_contexts; + context_entry && context_entry->hdc != wi->hdc; + context_entry = context_entry->next); + if (context_entry) { + wi->gl_context = context_entry->context; + } + else { + ipixel = ChoosePixelFormat(wi->hdc, &pfd); + /* sprintf(msg, "ipixel=%d dwFlags=0x%x req=0x%x iPixelType=%d\n", + ipixel, + pfd.dwFlags, + PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER, + pfd.iPixelType==PFD_TYPE_RGBA); + OutputDebugString(msg);*/ + if (!ipixel) { + OutputDebugString("ChoosePixelFormat failed\n"); + } + wi->render = (SetPixelFormat(wi->hdc, ipixel, &pfd) == TRUE); + if (wi->render) { + wi->gl_context = wglCreateContext(wi->hdc); + if (!wi->gl_context) { + OutputDebugString("wglCreateContext failed\n"); + } + else { + context_entry = ZnMalloc(sizeof(ZnGLContextEntry)); + context_entry->context = wi->gl_context; + context_entry->hdc = wi->hdc; + context_entry->next = gl_contexts; + gl_contexts = context_entry; + } + } + ZnGLRelease(wi); } - ZnGLRelease(wi); # else /* _WIN32 */ - int val; + XVisualInfo *gl_visual = NULL; + Colormap colormap = 0; if (ISSET(wi->flags, ZN_PRINT_CONFIG)) { fprintf(stderr, "GLX version %d.%d\n", major_glx, minor_glx); } + + /* + * Look for a matching context already available. + */ + for (context_entry = gl_contexts; + context_entry && context_entry->dpy != wi->dpy; + context_entry = context_entry->next); - wi->gl_visual = glXChooseVisual(wi->dpy, - XScreenNumberOfScreen(wi->screen), - attribs); - if (!wi->gl_visual) { - fprintf(stderr, "No glx visual\n"); - wi->render = 0; + if (context_entry) { + wi->gl_context = context_entry->context; + gl_visual = context_entry->visual; + colormap = context_entry->colormap; } else { - wi->gl_context = glXCreateContext(wi->dpy, wi->gl_visual, - NULL, wi->render==1); - if (!wi->gl_context) { - fprintf(stderr, "No glx context\n"); + int val; + + gl_visual = glXChooseVisual(wi->dpy, + XScreenNumberOfScreen(wi->screen), + attribs); + if (!gl_visual) { + fprintf(stderr, "No glx visual\n"); wi->render = 0; } else { - if (ISSET(wi->flags, ZN_PRINT_CONFIG)) { - fprintf(stderr, " Visual : 0x%x, ", - (int) wi->gl_visual->visualid); - glXGetConfig(wi->dpy, wi->gl_visual, GLX_RGBA, &val); - fprintf(stderr, "RGBA : %d, ", val); - glXGetConfig(wi->dpy, wi->gl_visual, GLX_DOUBLEBUFFER, &val); - fprintf(stderr, "Double Buffer : %d, ", val); - glXGetConfig(wi->dpy, wi->gl_visual, GLX_STENCIL_SIZE, &val); - fprintf(stderr, "Stencil : %d, ", val); - glXGetConfig(wi->dpy, wi->gl_visual, GLX_BUFFER_SIZE, &val); - fprintf(stderr, "depth : %d, ", val); - glXGetConfig(wi->dpy, wi->gl_visual, GLX_RED_SIZE, &val); - fprintf(stderr, "red : %d, ", val); - glXGetConfig(wi->dpy, wi->gl_visual, GLX_GREEN_SIZE, &val); - fprintf(stderr, "green : %d, ", val); - glXGetConfig(wi->dpy, wi->gl_visual, GLX_BLUE_SIZE, &val); - fprintf(stderr, "blue : %d, ", val); - glXGetConfig(wi->dpy, wi->gl_visual, GLX_ALPHA_SIZE, &val); - fprintf(stderr, "alpha : %d\n", val); - fprintf(stderr, " Direct Rendering: %d\n", - glXIsDirect(wi->dpy, wi->gl_context)); + printf("creating context\n"); + wi->gl_context = glXCreateContext(wi->dpy, gl_visual, + NULL, wi->render==1); + if (!wi->gl_context) { + fprintf(stderr, "No glx context\n"); + wi->render = 0; + } + else { + colormap = XCreateColormap(wi->dpy, RootWindowOfScreen(wi->screen), + gl_visual->visual, AllocNone); + context_entry = ZnMalloc(sizeof(ZnGLContextEntry)); + context_entry->context = wi->gl_context; + context_entry->visual = gl_visual; + context_entry->colormap = colormap; + context_entry->dpy = wi->dpy; + context_entry->next = gl_contexts; + gl_contexts = context_entry; + + if (ISSET(wi->flags, ZN_PRINT_CONFIG)) { + fprintf(stderr, " Visual : 0x%x, ", + (int) gl_visual->visualid); + glXGetConfig(wi->dpy, gl_visual, GLX_RGBA, &val); + fprintf(stderr, "RGBA : %d, ", val); + glXGetConfig(wi->dpy, gl_visual, GLX_DOUBLEBUFFER, &val); + fprintf(stderr, "Double Buffer : %d, ", val); + glXGetConfig(wi->dpy, gl_visual, GLX_STENCIL_SIZE, &val); + fprintf(stderr, "Stencil : %d, ", val); + glXGetConfig(wi->dpy, gl_visual, GLX_BUFFER_SIZE, &val); + fprintf(stderr, "depth : %d, ", val); + glXGetConfig(wi->dpy, gl_visual, GLX_RED_SIZE, &val); + fprintf(stderr, "red : %d, ", val); + glXGetConfig(wi->dpy, gl_visual, GLX_GREEN_SIZE, &val); + fprintf(stderr, "green : %d, ", val); + glXGetConfig(wi->dpy, gl_visual, GLX_BLUE_SIZE, &val); + fprintf(stderr, "blue : %d, ", val); + glXGetConfig(wi->dpy, gl_visual, GLX_ALPHA_SIZE, &val); + fprintf(stderr, "alpha : %d\n", val); + fprintf(stderr, " Direct Rendering: %d\n", + glXIsDirect(wi->dpy, wi->gl_context)); + } } - Tk_SetWindowVisual(wi->win, wi->gl_visual->visual, - 24, - XCreateColormap(wi->dpy, RootWindowOfScreen(wi->screen), - wi->gl_visual->visual, AllocNone)); } } + if (gl_visual && colormap) { + Tk_SetWindowVisual(wi->win, gl_visual->visual, 24, colormap); + } # endif /* _WIN32 */ } else { @@ -2104,7 +2172,7 @@ LayoutItems(ZnWInfo *wi, { int index/*, result*/; /*ZnItem item;*/ -#ifdef PTK +#ifdef PTK_800 static char *layout_cmd_strings[] = #else static CONST char *layout_cmd_strings[] = @@ -2552,7 +2620,7 @@ FindItems(ZnWInfo *wi, ZnItem item; ZnPickStruct ps; char *str; -#ifdef PTK +#ifdef PTK_800 static char *search_cmd_strings[] = #else static CONST char *search_cmd_strings[] = @@ -3051,7 +3119,7 @@ Contour(ZnWInfo *wi, ZnContour *contours; /* Keep this array in sync with ZnContourCmd in Types.h */ -#ifdef PTK +#ifdef PTK_800 static char *op_strings[] = #else static CONST char *op_strings[] = @@ -3573,7 +3641,7 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ char c[] = "c"; double d; -#ifdef PTK +#ifdef PTK_800 static char *sub_cmd_strings[] = #else static CONST char *sub_cmd_strings[] = @@ -3604,7 +3672,7 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ ZN_W_TRESET, ZN_W_TRESTORE, ZN_W_TSAVE, ZN_W_TSET, ZN_W_TYPE, ZN_W_VERTEX_AT, ZN_W_XVIEW, ZN_W_YVIEW }; -#ifdef PTK +#ifdef PTK_800 static char *sel_cmd_strings[] = #else static CONST char *sel_cmd_strings[] = @@ -6036,11 +6104,18 @@ Configure(Tcl_Interp *interp,/* Used for error reporting. */ return TCL_ERROR; } #ifdef PTK +#ifdef PTK_800 if ((Tk_GetPixels(interp, wi->win, LangString(args2[0]), &wi->scroll_xo) != TCL_OK) || (Tk_GetPixels(interp, wi->win, LangString(args2[1]), &wi->scroll_yo) != TCL_OK) || (Tk_GetPixels(interp, wi->win, LangString(args2[2]), &wi->scroll_xc) != TCL_OK) || (Tk_GetPixels(interp, wi->win, LangString(args2[3]), &wi->scroll_yc) != TCL_OK)) #else + if ((Tk_GetPixelsFromObj(interp, wi->win, args2[0], &wi->scroll_xo) != TCL_OK) || + (Tk_GetPixelsFromObj(interp, wi->win, args2[1], &wi->scroll_yo) != TCL_OK) || + (Tk_GetPixelsFromObj(interp, wi->win, args2[2], &wi->scroll_xc) != TCL_OK) || + (Tk_GetPixelsFromObj(interp, wi->win, args2[3], &wi->scroll_yc) != TCL_OK)) +#endif +#else if ((Tk_GetPixels(interp, wi->win, args2[0], &wi->scroll_xo) != TCL_OK) || (Tk_GetPixels(interp, wi->win, args2[1], &wi->scroll_yo) != TCL_OK) || (Tk_GetPixels(interp, wi->win, args2[2], &wi->scroll_xc) != TCL_OK) || @@ -6152,7 +6227,7 @@ Focus(ZnWInfo *wi, } #ifdef GL_DAMAGE if (wi->render) { - ZnDamageAll(wi); + /* ZnDamageAll(wi);*/ } #endif } @@ -6879,7 +6954,7 @@ Bind(ClientData client_data, /* Information about widget. */ * enough to make the bug unnoticed. */ if (wi->render) { - ZnDamageAll(wi); + /* ZnDamageAll(wi);*/ } #endif @@ -7196,18 +7271,26 @@ Destroy(char *mem_ptr) /* Info about the widget. */ /* Free the double buffer pixmap/image */ if (wi->draw_buffer) { Tk_FreePixmap(wi->dpy, wi->draw_buffer); + wi->draw_buffer = 0; } if (wi->fore_color) { ZnFreeGradient(wi->fore_color); + wi->fore_color = NULL; } if (wi->back_color) { ZnFreeGradient(wi->back_color); + wi->back_color = NULL; } if (wi->relief_grad) { ZnFreeGradient(wi->relief_grad); + wi->relief_grad = NULL; } - + if (wi->gc) { + XFreeGC(wi->dpy, wi->gc); + wi->gc = 0; + } + Tcl_DeleteTimerHandler(wi->blink_handler); Tk_FreeOptions(config_specs, (char *) wi, wi->dpy, 0); @@ -7230,17 +7313,6 @@ Destroy(char *mem_ptr) /* Info about the widget. */ ZnFreeChrono(wi->this_draw_chrono); #endif -#ifdef GL - if (wi->gl_context) { - ZnGLDestroyContext(wi); - } -# ifndef _WIN32 - if (wi->gl_visual) { - XFree(wi->gl_visual); - } -# endif -#endif - if (wi->tess) { gluDeleteTess(wi->tess); } -- cgit v1.1