aboutsummaryrefslogtreecommitdiff
path: root/generic/tkZinc.c
diff options
context:
space:
mode:
authorlecoanet2004-05-10 15:49:16 +0000
committerlecoanet2004-05-10 15:49:16 +0000
commitfad230827c3293da9fb99540e88d50b990abc8c9 (patch)
tree0e22a7f422ad80a523661b11b54d123a7b30d910 /generic/tkZinc.c
parent4292d3c53a8d15c44d74912c73bcc1767d66fe91 (diff)
downloadtkzinc-fad230827c3293da9fb99540e88d50b990abc8c9.zip
tkzinc-fad230827c3293da9fb99540e88d50b990abc8c9.tar.gz
tkzinc-fad230827c3293da9fb99540e88d50b990abc8c9.tar.bz2
tkzinc-fad230827c3293da9fb99540e88d50b990abc8c9.tar.xz
Suppressed all OutputDebugString traces.
Fixed the GL redrawing problem occuring under Windows after a window move and under Linux when the window was clipped by the screen border. The graphic context is freed when no longer needed, (no more zinc windows on a given display). This code is suspended on Linux because of a problem (perhaps in nvidia driver) causing a random) crash of the server. Fixed under Windows the problem of activating a GL context for freeing resources after the destruction of a widget. Now a list of active widgets is kept and the code activate a remaining widget in the same context. Fixed default GL font loading.
Diffstat (limited to 'generic/tkZinc.c')
-rw-r--r--generic/tkZinc.c249
1 files changed, 157 insertions, 92 deletions
diff --git a/generic/tkZinc.c b/generic/tkZinc.c
index 706c399..ef92355 100644
--- a/generic/tkZinc.c
+++ b/generic/tkZinc.c
@@ -148,10 +148,6 @@ static int ZnGLAttribs[] = {
#endif
#endif
-#ifdef _WIN32
- char msg[256];
-#endif
-
/*
* Temporary object lists
*/
@@ -914,54 +910,63 @@ ZnGetGLContext(Display *dpy)
}
ZnGLContextEntry *
-ZnGLMakeCurrent(Display *dpy,
- Tk_Window win)
+ZnGLMakeCurrent(Display *dpy,
+ ZnWInfo *wi)
{
ZnGLContextEntry *ce;
ce = ZnGetGLContext(dpy);
#ifdef _WIN32
- if (win) {
- ce->hwnd = Tk_GetHWND(Tk_WindowId(win));
+ if (!wi) {
+ /* Get a zinc widget from the context struct
+ * for this display. If no more are left,
+ * returns, nothing can be done. This can
+ * happend only when freeing images or fonts
+ * after the last zinc on a given display has
+ * been deleted. In this case the context has
+ * been already deleted, freeing all resources
+ * including textures.
+ */
+ return NULL;
}
+ ce->hwnd = Tk_GetHWND(Tk_WindowId(wi->win));
ce->hdc = GetDC(ce->hwnd);
SetPixelFormat(ce->hdc, ce->ipixel, &ce->pfd);
- /*sprintf(msg, "hdc used: %d\n", ce->hdc);
- OutputDebugString(msg);
- if (wglMakeCurrent(ce->hdc, ce->context)) {
- OutputDebugString("make current ok\n");
+ if (!wglMakeCurrent(ce->hdc, ce->context)) {
+ fprintf(stderr, "Can't make the GL context current: %d\n", GetLastError());
}
- else {
- sprintf(msg, "erreur %d\n", GetLastError());
- OutputDebugString(msg);
- }*/
- wglMakeCurrent(ce->hdc, ce->context);
#else
- glXMakeCurrent(dpy, win?Tk_WindowId(win):DefaultRootWindow(dpy),
+ glXMakeCurrent(dpy, wi?Tk_WindowId(wi->win):DefaultRootWindow(dpy),
ce->context);
#endif
return ce;
}
-#ifdef _WIN32
void
ZnGLReleaseContext(ZnGLContextEntry *ce)
{
- wglMakeCurrent(NULL, NULL);
- ReleaseDC(ce->hwnd, ce->hdc);
-}
+ if (ce) {
+#ifdef _WIN32
+ wglMakeCurrent(NULL, NULL);
+ ReleaseDC(ce->hwnd, ce->hdc);
+#else
+ /*glXMakeCurrent(ce->dpy, None, NULL);*/
#endif
+ }
+}
static void
ZnGLSwapBuffers(ZnGLContextEntry *ce,
- Tk_Window win)
+ ZnWInfo *wi)
{
+ if (ce) {
#ifdef _WIN32
- SwapBuffers(ce->hdc);
+ SwapBuffers(ce->hdc);
#else
- glXSwapBuffers(ce->dpy, Tk_WindowId(win));
-#endif
+ glXSwapBuffers(ce->dpy, Tk_WindowId(wi->win));
+#endif
+ }
}
#endif
@@ -980,19 +985,21 @@ InitRendering(ZnWInfo *wi)
/*
* Look for a matching context already available.
*/
- Tk_MakeWindowExist(wi->win);
ce = ZnGetGLContext(wi->dpy);
if (ce) {
gl_context = ce->context;
ce->hwnd = Tk_GetHWND(Tk_WindowId(wi->win));
ce->hdc = GetDC(ce->hwnd);
+ ZnListAdd(ce->widgets, &wi, ZnListTail);
SetPixelFormat(ce->hdc, ce->ipixel, &ce->pfd);
}
else {
ce = ZnMalloc(sizeof(ZnGLContextEntry));
ce->hwnd = Tk_GetHWND(Tk_WindowId(wi->win));
ce->hdc = GetDC(ce->hwnd);
-
+ ce->widgets = ZnListNew(1, sizeof(ZnWInfo *));
+ ZnListAdd(ce->widgets, &wi, ZnListTail);
+
memset(&ce->pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
ce->pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
ce->pfd.nVersion = 1;
@@ -1005,16 +1012,14 @@ InitRendering(ZnWInfo *wi)
ce->pfd.cStencilBits = 8;
ce->pfd.iLayerType = PFD_MAIN_PLANE;
ce->ipixel = ChoosePixelFormat(ce->hdc, &ce->pfd);
- /*sprintf(msg, "ipixel=%d dwFlags=0x%x req=0x%x iPixelType=%d hdc=%d\n",
+ /*printf("ipixel=%d dwFlags=0x%x req=0x%x iPixelType=%d hdc=%d\n",
ce->ipixel,
ce->pfd.dwFlags,
PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER,
ce->pfd.iPixelType==PFD_TYPE_RGBA,
- ce->hdc);
- OutputDebugString(msg);*/
+ ce->hdc);*/
if (!ce->ipixel) {
fprintf(stderr, "ChoosePixelFormat failed\n");
- OutputDebugString("ChoosePixelFormat failed\n");
}
if (SetPixelFormat(ce->hdc, ce->ipixel, &ce->pfd) == TRUE) {
@@ -1030,7 +1035,6 @@ InitRendering(ZnWInfo *wi)
}
else {
fprintf(stderr, "wglCreateContext failed\n");
- OutputDebugString("wglCreateContext failed\n");
ZnFree(ce);
}
}
@@ -1059,6 +1063,7 @@ InitRendering(ZnWInfo *wi)
gl_context = ce->context;
gl_visual = ce->visual;
colormap = ce->colormap;
+ ZnListAdd(ce->widgets, &wi, ZnListTail);
}
else {
int val;
@@ -1088,6 +1093,8 @@ InitRendering(ZnWInfo *wi)
ce->max_point_width = 1;
ce->next = gl_contexts;
gl_contexts = ce;
+ ce->widgets = ZnListNew(1, sizeof(ZnWInfo *));
+ ZnListAdd(ce->widgets, &wi, ZnListTail);
if (ISSET(wi->flags, ZN_PRINT_CONFIG)) {
fprintf(stderr, " Visual : 0x%x, ",
@@ -1119,7 +1126,7 @@ InitRendering(ZnWInfo *wi)
}
# endif /* _WIN32 */
- ce = ZnGLMakeCurrent(wi->dpy, wi->win);
+ ce = ZnGLMakeCurrent(wi->dpy, wi);
glGetFloatv(ZN_GL_LINE_WIDTH_RANGE, r);
ce->max_line_width = r[1];
glGetFloatv(ZN_GL_POINT_SIZE_RANGE, r);
@@ -1144,13 +1151,6 @@ InitRendering(ZnWInfo *wi)
ce->max_tex_size);
}
- if (!wi->font_tfi) {
- wi->font_tfi = ZnGetTexFont(wi, wi->font);
- }
- if (!wi->map_font_tfi) {
- wi->map_font_tfi = ZnGetTexFont(wi, wi->map_text_font);
- }
-
ZnGLReleaseContext(ce);
}
#endif /* GL */
@@ -6493,14 +6493,14 @@ Configure(Tcl_Interp *interp,/* Used for error reporting. */
if (CONFIG_PROBE(FONT_SPEC) || !wi->font_tfi) {
if (wi->font_tfi) {
ZnFreeTexFont(wi->font_tfi);
- wi->font_tfi = NULL;
}
+ wi->font_tfi = ZnGetTexFont(wi, wi->font);
}
if (CONFIG_PROBE(MAP_TEXT_FONT_SPEC) || !wi->map_font_tfi) {
if (wi->map_font_tfi) {
ZnFreeTexFont(wi->map_font_tfi);
- wi->map_font_tfi = NULL;
}
+ wi->map_font_tfi = ZnGetTexFont(wi, wi->map_text_font);
}
#endif
@@ -6776,14 +6776,14 @@ Configure(Tcl_Interp *interp,/* Used for error reporting. */
if ((mask & CONFIG_FONT) || !wi->font_tfi) {
if (wi->font_tfi) {
ZnFreeTexFont(wi->font_tfi);
- wi->font_tfi = NULL;
}
+ wi->font_tfi = ZnGetTexFont(wi, wi->font);
}
if ((mask & CONFIG_MAP_FONT) || !wi->map_font_tfi) {
if (wi->map_font_tfi) {
ZnFreeTexFont(wi->map_font_tfi);
- wi->map_font_tfi = NULL;
}
+ wi->map_font_tfi = ZnGetTexFont(wi, wi->map_text_font);
}
#endif
@@ -7036,6 +7036,17 @@ Focus(ZnWInfo *wi,
*----------------------------------------------------------------------
*/
static void
+TopEvent(ClientData client_data, /* Information about widget. */
+ XEvent *event)
+{
+ ZnWInfo *wi = (ZnWInfo *) client_data;
+ if (event->type == ConfigureNotify) {
+ /*printf("Window moved\n");*/
+ SET(wi->flags, ZN_CONFIGURE_EVENT);
+ }
+}
+
+static void
Event(ClientData client_data, /* Information about widget. */
XEvent *event) /* Information about event. */
{
@@ -7047,13 +7058,13 @@ Event(ClientData client_data, /* Information about widget. */
event->type == MapNotify ? "MAP":
event->type == Expose? "EXPOSE" :
event->type == ConfigureNotify ? "CONFIGURE" :
+ event->type == VisibilityNotify ? "VISIBILITY" :
event->type == DestroyNotify ? "DESTROY" :
"??", event->type);*/
if (event->type == MapNotify) {
SET(wi->flags, ZN_CONFIGURE_EVENT);
if (!wi->gc) {
SET(wi->flags, ZN_REALIZED);
- /*OutputDebugString("MAP\n");*/
InitRendering(wi);
/*
@@ -7078,12 +7089,19 @@ Event(ClientData client_data, /* Information about widget. */
}
success = XQueryTree(wi->dpy, Tk_WindowId(top_level), &root, &parent,
&children, &num_children);
- if (root == parent) {
+ if (!success || (root == parent)) {
wi->real_top = Tk_WindowId(top_level);
}
else {
wi->real_top = parent;
}
+ /*
+ * Needed under glx to suspend update with scissors after
+ * a move to synchronise the two buffers. Fix a refresh
+ * bug when the window is partially clipped by the display
+ * border. Can be usefull under Windows too.
+ */
+ Tk_CreateEventHandler(top_level, StructureNotifyMask, TopEvent, (ClientData) wi);
if (children && success) {
XFree(children);
}
@@ -7120,10 +7138,6 @@ Event(ClientData client_data, /* Information about widget. */
* if we are done adding exposed parts.
*/
ZnAddBBoxToBBox(&wi->exposed_area, &bbox);
- /*sprintf(msg, "EXPOSE %g %g %g %g\n",
- wi->exposed_area.orig.x, wi->exposed_area.orig.y,
- wi->exposed_area.corner.x, wi->exposed_area.corner.y);
- OutputDebugString(msg);*/
if (/*(((XExposeEvent*) event)->count == 0) &&*/
!ZnIsEmptyBBox(&wi->exposed_area)) {
ZnNeedRedisplay(wi);
@@ -7224,6 +7238,7 @@ Event(ClientData client_data, /* Information about widget. */
event->type == MapNotify ? "MAP":
event->type == Expose? "EXPOSE" :
event->type == ConfigureNotify ? "CONFIGURE" :
+ event->type == VisibilityNotify ? "VISIBILITY" :
event->type == DestroyNotify ? "DESTROY" :
"??");*/
}
@@ -7710,19 +7725,6 @@ Bind(ClientData client_data, /* Information about widget. */
}
else if ((event->type == EnterNotify) || (event->type == LeaveNotify)) {
-#if defined(_WIN32) && defined(GL)
- /* Only needed on Windows to help get the display right
- * after a window move. It also helps with the first redraw
- * after window creation.
- */
- ZnBBox bbox;
-
- bbox.orig.x = bbox.orig.y = 0;
- bbox.corner.x = Tk_Width(wi->win);
- bbox.corner.y = Tk_Height(wi->win);
- ZnDamage(wi, &bbox);
-#endif
-
wi->state = event->xcrossing.state;
PickCurrentItem(wi, event);
goto done;
@@ -7937,12 +7939,15 @@ static void
Destroy(char *mem_ptr) /* Info about the widget. */
{
ZnWInfo *wi = (ZnWInfo *) mem_ptr;
- unsigned int num;
+ unsigned int num, i;
Tcl_HashSearch search;
Tcl_HashEntry *entry;
+#ifdef GL
+ ZnGLContextEntry *ce;
+ ZnWInfo **wip;
+#endif
/*printf("Destroy begining\n");*/
- /*OutputDebugString("Destroy begining\n");*/
/*
* This procedure could be invoked either because the window was
* destroyed and the command was then deleted (in which case win
@@ -7975,24 +7980,6 @@ Destroy(char *mem_ptr) /* Info about the widget. */
Tcl_CancelIdleCall(Redisplay, (ClientData) wi);
}
-#ifdef GL
- if (wi->font_tfi) {
- ZnFreeTexFont(wi->font_tfi);
- wi->font_tfi = NULL;
- }
- if (wi->map_font_tfi) {
- ZnFreeTexFont(wi->map_font_tfi);
- wi->map_font_tfi = NULL;
- }
-#endif
- /*
- if (wi->font) {
- Tk_FreeFont(wi->font);
- }
- if (wi->map_text_font) {
- Tk_FreeFont(wi->map_text_font);
- }*/
-
for (num = 0; num < ZN_NUM_ALPHA_STEPS; num++) {
if (wi->alpha_stipples[num] != None) {
Tk_FreeBitmap(wi->dpy, wi->alpha_stipples[num]);
@@ -8071,6 +8058,72 @@ Destroy(char *mem_ptr) /* Info about the widget. */
Tk_FreeConfigOptions((char *) wi, wi->opt_table, wi->win);
#endif
+#ifdef GL
+ if (wi->font_tfi) {
+ ZnFreeTexFont(wi->font_tfi);
+ wi->font_tfi = NULL;
+ }
+ if (wi->map_font_tfi) {
+ ZnFreeTexFont(wi->map_font_tfi);
+ wi->map_font_tfi = NULL;
+ }
+ /*
+ * Remove the widget from the context list and
+ * free the context if no more widgets are active.
+ */
+ ce = ZnGetGLContext(wi->dpy);
+ if (ce) {
+ wip = ZnListArray(ce->widgets);
+ num = ZnListSize(ce->widgets);
+ for (i = 0; i < num; i++, wip++) {
+ if (*wip == wi) {
+ ZnListDelete(ce->widgets, i);
+ }
+ }
+ /*
+ * This code cause spurious X11 server reboots
+ * with nvidia drivers (not tested with others
+ * though). Thus it has been limited to WIN for
+ * the time being.
+ */
+#ifdef _WIN32
+ if (ZnListSize(ce->widgets) == 0) {
+ ZnGLContextEntry *prev, *next;
+ /*printf("Freeing a GL context\n");*/
+ if (ce == gl_contexts) {
+ gl_contexts = ce->next;
+ }
+ else {
+ for (prev = gl_contexts, next = gl_contexts->next; next;
+ prev = next, next = next->next) {
+ if (next == ce) {
+ prev->next = next->next;
+ break;
+ }
+ }
+ }
+#ifdef _WIN32
+ ZnGLReleaseContext(ce);
+ wglDeleteContext(ce->context);
+#else
+ glXDestroyContext(ce->dpy, ce->context);
+ XFreeColormap(ce->dpy, ce->colormap);
+ XFree(ce->visual);
+#endif
+ ZnListFree(ce->widgets);
+ ZnFree(ce);
+ }
+#endif
+ }
+#endif
+ /*
+ if (wi->font) {
+ Tk_FreeFont(wi->font);
+ }
+ if (wi->map_text_font) {
+ Tk_FreeFont(wi->map_text_font);
+ }*/
+
/*
* Should be empty by now.
*/
@@ -8084,7 +8137,6 @@ Destroy(char *mem_ptr) /* Info about the widget. */
ZnFree(wi);
/*printf("Destroy ending\n");*/
- /*OutputDebugString("Destroy ending\n");*/
}
@@ -8193,12 +8245,10 @@ Update(ZnWInfo *wi)
ZnGroupSetCallOm(wi->om_group, False);
}
#endif
- /*OutputDebugString("Update Begin\n");*/
if (ISSET(wi->top_group->inv_flags, ZN_COORDS_FLAG) ||
ISSET(wi->top_group->inv_flags, ZN_TRANSFO_FLAG)) {
wi->top_group->class->ComputeCoordinates(wi->top_group, False);
}
- /*OutputDebugString("Update End\n");*/
}
@@ -8222,9 +8272,15 @@ Repair(ZnWInfo *wi)
int int_height = Tk_Height(wi->win);
ZnGLContextEntry *ce;
+ /*SET(wi->flags, ZN_CONFIGURE_EVENT);*/
if (wi->render) {
- ZnGLWaitX();
#ifdef GL
+ /* Load deferred font glyphs just before making the context
+ * current. Mandatory under Windows (probably due to hdc use conflict).
+ */
+ ZnGetDeferredGLGlyphs();
+
+ ZnGLWaitX();
#ifdef GL_DAMAGE
if (ISCLEAR(wi->flags, ZN_CONFIGURE_EVENT)) {
ClampDamageArea(wi);
@@ -8238,9 +8294,8 @@ Repair(ZnWInfo *wi)
}
#endif
- /*sprintf(msg, "Repair, scissors: %d\n", ISCLEAR(wi->flags, ZN_CONFIGURE_EVENT));
- OutputDebugString(msg);*/
- ce = ZnGLMakeCurrent(wi->dpy, wi->win);
+ /*printf("Repair, scissors: %d\n", ISCLEAR(wi->flags, ZN_CONFIGURE_EVENT));*/
+ ce = ZnGLMakeCurrent(wi->dpy, wi);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_LINE_SMOOTH);
#if 0
@@ -8286,6 +8341,7 @@ Repair(ZnWInfo *wi)
(int) (wi->damaged_area.corner.y - wi->damaged_area.orig.y));
}
else {
+ glDisable(GL_SCISSOR_TEST);
wi->damaged_area.orig.x = wi->damaged_area.orig.y = wi->inset;
wi->damaged_area.corner.x = int_width-wi->inset;
wi->damaged_area.corner.y = int_height-wi->inset;
@@ -8379,7 +8435,16 @@ Repair(ZnWInfo *wi)
}
/* Switch the GL buffers. */
- ZnGLSwapBuffers(ce, wi->win);
+ /* The scissor test might be needed under windows, should be tested.
+ * Symptom: when moving the window, the buffer switch results in a
+ * shifted display all around the damaged area.
+ */
+#ifdef GL_DAMAGE
+ if (ISCLEAR(wi->flags, ZN_CONFIGURE_EVENT)) {
+ glEnable(GL_SCISSOR_TEST);
+ }
+#endif
+ ZnGLSwapBuffers(ce, wi);
/*
* Wait the end of GL update if we need to synchronize