From 1761ee2e8ad9f23ef9231ec9952c25ab2ac88439 Mon Sep 17 00:00:00 2001 From: lecoanet Date: Fri, 7 May 2004 09:50:32 +0000 Subject: Slightly rearranged the init sequence for openGL. This will ensure that render will be reset has soon has possible if GL is not there. It will _stay_ set if we discover later that GL is not available. This will fix a rather bewildering situation when using images: The image is created for GL, then all of a sudden accessed in an X11 context. Fixed the event emitting code so that enter/leaves are not emitted (or omitted) out of sequence. --- generic/tkZinc.c | 362 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 184 insertions(+), 178 deletions(-) (limited to 'generic') diff --git a/generic/tkZinc.c b/generic/tkZinc.c index 135ddb2..706c399 100644 --- a/generic/tkZinc.c +++ b/generic/tkZinc.c @@ -927,7 +927,7 @@ ZnGLMakeCurrent(Display *dpy, ce->hdc = GetDC(ce->hwnd); SetPixelFormat(ce->hdc, ce->ipixel, &ce->pfd); - sprintf(msg, "hdc used: %d\n", ce->hdc); + /*sprintf(msg, "hdc used: %d\n", ce->hdc); OutputDebugString(msg); if (wglMakeCurrent(ce->hdc, ce->context)) { OutputDebugString("make current ok\n"); @@ -935,8 +935,8 @@ ZnGLMakeCurrent(Display *dpy, else { sprintf(msg, "erreur %d\n", GetLastError()); OutputDebugString(msg); - } - + }*/ + wglMakeCurrent(ce->hdc, ce->context); #else glXMakeCurrent(dpy, win?Tk_WindowId(win):DefaultRootWindow(dpy), ce->context); @@ -948,8 +948,6 @@ ZnGLMakeCurrent(Display *dpy, void ZnGLReleaseContext(ZnGLContextEntry *ce) { - sprintf(msg, "Relasing hdc: %d\n", ce->hdc); - OutputDebugString(msg); wglMakeCurrent(NULL, NULL); ReleaseDC(ce->hwnd, ce->hdc); } @@ -960,8 +958,6 @@ ZnGLSwapBuffers(ZnGLContextEntry *ce, Tk_Window win) { #ifdef _WIN32 - sprintf(msg, "Swapping hdc: %d\n", ce->hdc); - OutputDebugString(msg); SwapBuffers(ce->hdc); #else glXSwapBuffers(ce->dpy, Tk_WindowId(win)); @@ -974,172 +970,154 @@ static void InitRendering(ZnWInfo *wi) { ZnGLContextEntry *ce; - /* - * Allocate double buffer pixmap/image. - */ - if (wi->render) { -#ifdef GL - ASSIGN(wi->flags, ZN_PRINT_CONFIG, (getenv("ZINC_GLX_INFO") != NULL)); + ZnGLContext gl_context; + GLfloat r[2]; /* Min, Max */ + GLint i[1]; - if (ISSET(wi->flags, ZN_HAS_GL)) { - ZnGLContext gl_context; +#ifdef GL + if (wi->render) { # ifdef _WIN32 - /* - * 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); - SetPixelFormat(ce->hdc, ce->ipixel, &ce->pfd); + /* + * 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); + 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); + + memset(&ce->pfd, 0, sizeof(PIXELFORMATDESCRIPTOR)); + ce->pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); + ce->pfd.nVersion = 1; + ce->pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; + ce->pfd.iPixelType = PFD_TYPE_RGBA; + ce->pfd.cRedBits = 8; + ce->pfd.cGreenBits = 8; + ce->pfd.cBlueBits = 8; + ce->pfd.cAlphaBits = 8; + 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", + ce->ipixel, + ce->pfd.dwFlags, + PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER, + ce->pfd.iPixelType==PFD_TYPE_RGBA, + ce->hdc); + OutputDebugString(msg);*/ + if (!ce->ipixel) { + fprintf(stderr, "ChoosePixelFormat failed\n"); + OutputDebugString("ChoosePixelFormat failed\n"); } - else { - ce = ZnMalloc(sizeof(ZnGLContextEntry)); - ce->hwnd = Tk_GetHWND(Tk_WindowId(wi->win)); - ce->hdc = GetDC(ce->hwnd); - - memset(&ce->pfd, 0, sizeof(PIXELFORMATDESCRIPTOR)); - ce->pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); - ce->pfd.nVersion = 1; - ce->pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; - ce->pfd.iPixelType = PFD_TYPE_RGBA; - ce->pfd.cRedBits = 8; - ce->pfd.cGreenBits = 8; - ce->pfd.cBlueBits = 8; - ce->pfd.cAlphaBits = 8; - 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", - ce->ipixel, - ce->pfd.dwFlags, - PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER, - ce->pfd.iPixelType==PFD_TYPE_RGBA, - ce->hdc); - OutputDebugString(msg); - if (!ce->ipixel) { - OutputDebugString("ChoosePixelFormat failed\n"); - } - wi->render = (SetPixelFormat(ce->hdc, ce->ipixel, &ce->pfd) == TRUE); - if (wi->render) { - gl_context = wglCreateContext(ce->hdc); - if (gl_context) { - ce->context = gl_context; - ce->dpy = wi->dpy; - ce->max_tex_size = 64; /* Minimum value is always valid */ - ce->max_line_width = 1; - ce->max_point_width = 1; - ce->next = gl_contexts; - gl_contexts = ce; - } - else { - OutputDebugString("wglCreateContext failed\n"); - ZnFree(ce); - } + + if (SetPixelFormat(ce->hdc, ce->ipixel, &ce->pfd) == TRUE) { + gl_context = wglCreateContext(ce->hdc); + if (gl_context) { + ce->context = gl_context; + ce->dpy = wi->dpy; + ce->max_tex_size = 64; /* Minimum value is always valid */ + ce->max_line_width = 1; + ce->max_point_width = 1; + ce->next = gl_contexts; + gl_contexts = ce; } else { + fprintf(stderr, "wglCreateContext failed\n"); + OutputDebugString("wglCreateContext failed\n"); ZnFree(ce); } } - ReleaseDC(ce->hwnd, ce->hdc); - sprintf(msg, "render after: %d\n", wi->render); - OutputDebugString(msg); + else { + ZnFree(ce); + } + } + ReleaseDC(ce->hwnd, ce->hdc); + # else /* _WIN32 */ - XVisualInfo *gl_visual = NULL; - Colormap colormap = 0; - if (ISSET(wi->flags, ZN_PRINT_CONFIG)) { - fprintf(stderr, "GLX version %d.%d\n", ZnMajorGlx, ZnMinorGlx); - } + XVisualInfo *gl_visual = NULL; + Colormap colormap = 0; + + ASSIGN(wi->flags, ZN_PRINT_CONFIG, (getenv("ZINC_GLX_INFO") != NULL)); + + if (ISSET(wi->flags, ZN_PRINT_CONFIG)) { + fprintf(stderr, "GLX version %d.%d\n", ZnMajorGlx, ZnMinorGlx); + } + + /* + * Look for a matching context already available. + */ + ce = ZnGetGLContext(wi->dpy); + if (ce) { + gl_context = ce->context; + gl_visual = ce->visual; + colormap = ce->colormap; + } + else { + int val; - /* - * Look for a matching context already available. - */ - ce = ZnGetGLContext(wi->dpy); - if (ce) { - gl_context = ce->context; - gl_visual = ce->visual; - colormap = ce->colormap; + gl_visual = glXChooseVisual(wi->dpy, + XScreenNumberOfScreen(wi->screen), + ZnGLAttribs); + if (!gl_visual) { + fprintf(stderr, "No glx visual\n"); } else { - int val; - - gl_visual = glXChooseVisual(wi->dpy, - XScreenNumberOfScreen(wi->screen), - ZnGLAttribs); - if (!gl_visual) { - fprintf(stderr, "No glx visual\n"); - wi->render = 0; + gl_context = glXCreateContext(wi->dpy, gl_visual, + NULL, wi->render==1); + if (!gl_context) { + fprintf(stderr, "No glx context\n"); } else { - gl_context = glXCreateContext(wi->dpy, gl_visual, - NULL, wi->render==1); - if (!gl_context) { - fprintf(stderr, "No glx context\n"); - wi->render = 0; - } - else { - colormap = XCreateColormap(wi->dpy, RootWindowOfScreen(wi->screen), - gl_visual->visual, AllocNone); - ce = ZnMalloc(sizeof(ZnGLContextEntry)); - ce->context = gl_context; - ce->visual = gl_visual; - ce->colormap = colormap; - ce->dpy = wi->dpy; - ce->max_tex_size = 64; /* Minimum value is always valid */ - ce->max_line_width = 1; - ce->max_point_width = 1; - ce->next = gl_contexts; - gl_contexts = ce; - - 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, gl_context)); - } + colormap = XCreateColormap(wi->dpy, RootWindowOfScreen(wi->screen), + gl_visual->visual, AllocNone); + ce = ZnMalloc(sizeof(ZnGLContextEntry)); + ce->context = gl_context; + ce->visual = gl_visual; + ce->colormap = colormap; + ce->dpy = wi->dpy; + ce->max_tex_size = 64; /* Minimum value is always valid */ + ce->max_line_width = 1; + ce->max_point_width = 1; + ce->next = gl_contexts; + gl_contexts = ce; + + 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, gl_context)); } } } - if (gl_visual && colormap) { - Tk_SetWindowVisual(wi->win, gl_visual->visual, 24, colormap); - } -# endif /* _WIN32 */ } - else { - fprintf(stderr, "GL not available\n"); - wi->render = 0; + if (gl_visual && colormap) { + Tk_SetWindowVisual(wi->win, gl_visual->visual, 24, colormap); } -#else /* GL */ - wi->render = 0; -#endif /* GL */ - } - - if (!wi->render) { - wi->draw_buffer = Tk_GetPixmap(wi->dpy, RootWindowOfScreen(wi->screen), - wi->width, wi->height, Tk_Depth(wi->win)); - } - else { - GLfloat r[2]; /* Min, Max */ - GLint i[1]; +# endif /* _WIN32 */ ce = ZnGLMakeCurrent(wi->dpy, wi->win); glGetFloatv(ZN_GL_LINE_WIDTH_RANGE, r); @@ -1165,7 +1143,7 @@ InitRendering(ZnWInfo *wi) fprintf(stderr, "Max texture size: %d\n", ce->max_tex_size); } - + if (!wi->font_tfi) { wi->font_tfi = ZnGetTexFont(wi, wi->font); } @@ -1175,6 +1153,7 @@ InitRendering(ZnWInfo *wi) ZnGLReleaseContext(ce); } +#endif /* GL */ } @@ -1246,6 +1225,9 @@ ZincObjCmd(ClientData client_data, /* Main window associated with Tcl_AppendResult(interp, " GL", NULL); XFree(visual); } + else { + has_gl = False; + } } # endif #endif @@ -1437,6 +1419,22 @@ ZincObjCmd(ClientData client_data, /* Main window associated with wi->damaged_area.corner.x = wi->width = wi->opt_width; wi->damaged_area.corner.y = wi->height = wi->opt_height; + if (!has_gl) { + /* Do not allow GL rendering if not available. This should + * _not_ be changed later as images may have been created + * in the belief that GL will be available. + */ + wi->render = 0; + } + + if (!wi->render) { + /* + * Allocate double buffer pixmap/image. + */ + wi->draw_buffer = Tk_GetPixmap(wi->dpy, RootWindowOfScreen(wi->screen), + wi->width, wi->height, Tk_Depth(wi->win)); + } + #ifdef PTK Tcl_SetObjResult(interp, LangWidgetObj(interp, tkwin)); #else @@ -7402,8 +7400,7 @@ PickCurrentItem(ZnWInfo *wi, XEvent *event) { int button_down; - ZnItem item; - ZnBool back_inside = False; + ZnBool enter_item; ZnBool grab_release = False; /*printf("PickCurrent current=%d, new=%d\n", @@ -7418,6 +7415,7 @@ PickCurrentItem(ZnWInfo *wi, button_down = wi->state & (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask); if (!button_down) { + grab_release = ISSET(wi->flags, ZN_GRABBED_ITEM); CLEAR(wi->flags, ZN_GRABBED_ITEM); CLEAR(wi->flags, ZN_GRABBED_PART); } @@ -7473,7 +7471,6 @@ PickCurrentItem(ZnWInfo *wi, * A LeaveNotify event automatically means that there's no current * object, so the check for closest item can be skipped. */ - item = wi->new_item; if (wi->pick_event.type != LeaveNotify) { ZnPickStruct ps; ZnReal dist; @@ -7505,7 +7502,7 @@ PickCurrentItem(ZnWInfo *wi, * This state is needed to do a valid detection * of Enter during a grab. */ - back_inside = (wi->new_item != item); + enter_item = ((wi->new_item != wi->current_item) || ISSET(wi->flags, ZN_GRABBED_ITEM)); /*printf("------ PickCurrentItem current: %d %d, new %d %d\n", wi->current_item==ZN_NO_ITEM?0:wi->current_item->id, wi->current_part, @@ -7526,27 +7523,34 @@ PickCurrentItem(ZnWInfo *wi, * Remove the "current" tag from the previous current item. */ if ((wi->current_item != ZN_NO_ITEM) && - (((wi->new_item != wi->current_item) && ISCLEAR(wi->flags, ZN_GRABBED_ITEM)) || - ((wi->new_part != wi->current_part) && ISCLEAR(wi->flags, ZN_GRABBED_PART)))) { - XEvent event; - - item = wi->current_item; - event = wi->pick_event; - event.type = LeaveNotify; - - /*printf("== LEAVE %d %d ==\n", wi->current_item->id, wi->current_part);*/ + (((wi->new_item != wi->current_item) || (wi->new_part != wi->current_part)) && + ISCLEAR(wi->flags, ZN_GRABBED_ITEM))) { + ZnItem item = wi->current_item; /* - * If the event's detail happens to be NotifyInferior the - * binding mechanism will discard the event. To be consistent, - * always use NotifyAncestor. + * Actually emit the event only if not releasing a grab + * on button up. */ - event.xcrossing.detail = NotifyAncestor; - SET(wi->flags, ZN_REPICK_IN_PROGRESS); - DoEvent(wi, &event, - wi->new_item != wi->current_item, ISCLEAR(wi->flags, ZN_GRABBED_PART)); - CLEAR(wi->flags, ZN_REPICK_IN_PROGRESS); + if (!grab_release) { + XEvent event; + event = wi->pick_event; + event.type = LeaveNotify; + + /*printf("== LEAVE %d %d ==\n", wi->current_item->id, wi->current_part);*/ + /* + * If the event's detail happens to be NotifyInferior the + * binding mechanism will discard the event. To be consistent, + * always use NotifyAncestor. + */ + event.xcrossing.detail = NotifyAncestor; + SET(wi->flags, ZN_REPICK_IN_PROGRESS); + DoEvent(wi, &event, + wi->new_item != wi->current_item, ISCLEAR(wi->flags, ZN_GRABBED_PART)); + CLEAR(wi->flags, ZN_REPICK_IN_PROGRESS); + } /* + * In all cases, if a grab is not current, remove the current tag. + * * The check on item below is needed because there could be an * event handler for that deletes the current item. */ @@ -7570,7 +7574,9 @@ PickCurrentItem(ZnWInfo *wi, SET(wi->flags, ZN_GRABBED_ITEM); } else { - grab_release = ISSET(wi->flags, ZN_GRABBED_ITEM); + if (button_down) { + grab_release = ISSET(wi->flags, ZN_GRABBED_ITEM); + } CLEAR(wi->flags, ZN_GRABBED_ITEM); wi->current_item = wi->new_item; } @@ -7602,7 +7608,7 @@ PickCurrentItem(ZnWInfo *wi, event.type = EnterNotify; event.xcrossing.detail = NotifyAncestor; DoEvent(wi, &event, - back_inside, !(grab_release && ISSET(wi->flags, ZN_GRABBED_PART))); + enter_item, !(grab_release && ISSET(wi->flags, ZN_GRABBED_PART))); } } @@ -7678,7 +7684,7 @@ Bind(ClientData client_data, /* Information about widget. */ if (event->type == ButtonPress) { /* * On a button press, first repick the current item using - * the button state before the event, the process the event. + * the button state before the event, then process the event. */ wi->state = event->xbutton.state; PickCurrentItem(wi, event); -- cgit v1.1