1 /*--------------------------------------------------------------------------*/
2 /* ALBERTA:  an Adaptive multi Level finite element toolbox using           */
3 /*           Bisectioning refinement and Error control by Residual          */
4 /*           Techniques for scientific Applications                         */
5 /*                                                                          */
6 /* file:     graphXO.c                                                      */
7 /*                                                                          */
8 /*                                                                          */
9 /* description:  simple graphical routines                                  */
10 /*                                                                          */
11 /*--------------------------------------------------------------------------*/
12 /*                                                                          */
13 /*  authors:   Alfred Schmidt                                               */
14 /*             Zentrum fuer Technomathematik                                */
15 /*             Fachbereich 3 Mathematik/Informatik                          */
16 /*             Universitaet Bremen                                          */
17 /*             Bibliothekstr. 2                                             */
18 /*             D-28359 Bremen, Germany                                      */
19 /*                                                                          */
20 /*             Kunibert G. Siebert                                          */
21 /*             Institut fuer Mathematik                                     */
22 /*             Universitaet Augsburg                                        */
23 /*             Universitaetsstr. 14                                         */
24 /*             D-86159 Augsburg, Germany                                    */
25 /*                                                                          */
26 /*  http://www.mathematik.uni-freiburg.de/IAM/ALBERTA                       */
27 /*                                                                          */
28 /*  (c) by A. Schmidt and K.G. Siebert (1996-2003)                          */
29 /*                                                                          */
30 /*--------------------------------------------------------------------------*/
31 
32 #ifdef HAVE_CONFIG_H
33 # include "config.h"
34 #endif
35 
36 #include "alberta.h"
37 
38 #include <GL/glx.h>
39 #include <GL/gl.h>
40 #include <unistd.h>
41 
42 /*---8<---------------------------------------------------------------------*/
43 /*---  standard colors                                                   ---*/
44 /*--------------------------------------------------------------------->8---*/
45 
46 const GRAPH_RGBCOLOR rgb_black   = {0.0,0.0,0.0};
47 const GRAPH_RGBCOLOR rgb_white   = {1.0,1.0,1.0};
48 const GRAPH_RGBCOLOR rgb_red     = {1.0,0.0,0.0};
49 const GRAPH_RGBCOLOR rgb_green   = {0.0,1.0,0.0};
50 const GRAPH_RGBCOLOR rgb_blue    = {0.0,0.0,1.0};
51 const GRAPH_RGBCOLOR rgb_yellow  = {1.0,1.0,0.0};
52 const GRAPH_RGBCOLOR rgb_magenta = {1.0,0.0,1.0};
53 const GRAPH_RGBCOLOR rgb_cyan    = {0.0,1.0,1.0};
54 const GRAPH_RGBCOLOR rgb_grey50  = {0.5,0.5,0.5};
55 
56 const GRAPH_RGBCOLOR rgb_albert  = {0.433,0.781,0.969};
57 const GRAPH_RGBCOLOR rgb_alberta = {0.000,0.391,0.605};
58 
59 
60 struct ogl_window
61 {
62   Display      *dpy;
63   Window       win;
64   GLXContext   context;
65   unsigned int width, height;
66   float        xmin[MAX(2,DIM_MAX)];
67   float        xmax[MAX(2,DIM_MAX)];
68   float        diam[MAX(2,DIM_MAX)];
69   Bool         doubleBuffered;
70 };
71 typedef struct ogl_window OGL_WINDOW;
72 
73 #if DIM_OF_WORLD < 3
74 static Bool opengl_available = True;
75 #endif
76 
77 /****************************************************************************/
78 
79 #if DIM_OF_WORLD < 3
WaitForNotify(Display * d,XEvent * e,char * arg)80 static Bool WaitForNotify(Display *d, XEvent *e, char *arg)
81 {
82   return (e->type == MapNotify) && (e->xmap.window == (Window)arg);
83 }
84 #endif
85 
86 /****************************************************************************/
87 
88 #if DIM_OF_WORLD < 3
OGL_set_std_window(OGL_WINDOW * ogl_win)89 static Bool OGL_set_std_window(OGL_WINDOW *ogl_win)
90 {
91   Bool res = false;
92 
93   if (ogl_win) {
94 
95     res = glXMakeCurrent(ogl_win->dpy, ogl_win->win, ogl_win->context);
96 
97     glViewport(0, 0, ogl_win->width, ogl_win->height);
98 
99     glMatrixMode(GL_PROJECTION);
100     glLoadIdentity();
101     glMatrixMode(GL_MODELVIEW);
102     glLoadIdentity();
103     glOrtho(ogl_win->xmin[0], ogl_win->xmax[0],
104 	    ogl_win->xmin[1], ogl_win->xmax[1],
105 	    -1.0, 1.0);
106   }
107   return res;
108 }
109 
110 #define OGL_FLUSH(ogl)\
111 if ((ogl)->doubleBuffered)glXSwapBuffers((ogl)->dpy, ogl->win);else glFlush()
112 
113 static int open_info = 0;
114 
findVisual(Display * dpy,int screen,Bool * doubleBuffered)115 static XVisualInfo *findVisual(Display *dpy, int screen, Bool *doubleBuffered)
116 {
117 	/*
118 	 * Find a GLX Visual to use.
119 	 *   Order of preference
120 	 *       24 bit mono double buffered
121 	 *       24 bit single buffered
122 	 *       any depth double buffered
123 	 *       any depth single buffered
124 	 */
125   int dblBuf24[] = { GLX_RGBA, GLX_DOUBLEBUFFER,
126 		     GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, None };
127   int snglBuf24[] = { GLX_RGBA,
128 		      GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, None };
129   int dblBuf[] = { GLX_RGBA, GLX_DOUBLEBUFFER, None };
130   int snglBuf[] = { GLX_RGBA, None };
131 
132   XVisualInfo *vi = NULL;
133 
134   if ((vi = glXChooseVisual(dpy, screen, dblBuf24)))
135   {
136     INFO(open_info,2,"Using dblBuf24\n");
137     *doubleBuffered = True;
138     return(vi);
139   }
140 
141   if ((vi = glXChooseVisual(dpy, screen, snglBuf24)))
142   {
143     *doubleBuffered = False;
144     INFO(open_info,2,"Using snglBuf24\n");
145     return(vi);
146   }
147 
148   if ((vi = glXChooseVisual(dpy, screen, dblBuf)))
149   {
150     *doubleBuffered = True;
151     INFO(open_info,2,"Using dblBuf\n");
152     return(vi);
153   }
154 
155   if ((vi = glXChooseVisual(dpy, screen, snglBuf)))
156   {
157     INFO(open_info,2,"Using snglBuf\n");
158     *doubleBuffered = False;
159     return(vi);
160   }
161 
162   WARNING("can't find visual\n");
163   return(NULL);
164 }
165 
createWindow(Display * dpy,int screen,XVisualInfo * vi,const char * name,const char * geom)166 static Window createWindow(Display *dpy, int screen, XVisualInfo *vi,
167 			   const char *name, const char *geom)
168 {
169   XSetWindowAttributes attributes;
170   unsigned long valuemask = 0;
171   Window        root = RootWindow(dpy, screen);
172   Atom	        delete_window_atom = XInternAtom(dpy, "WM_DELETE_WINDOW", 0);
173   Window        window;
174   XSizeHints    size_hints;
175   XEvent        event;
176   int           status;
177   const char    *default_geom = "300x300+0+0";
178 
179   attributes.colormap = XCreateColormap(dpy, root, vi->visual, AllocNone);
180   if (!attributes.colormap)
181   {
182     WARNING("no color map\n");
183     return(0);
184   }
185   valuemask = CWColormap;
186   valuemask = CWColormap|CWBorderPixel|CWBackPixel;
187 
188   size_hints.flags = PResizeInc | PMinSize ;
189   size_hints.width_inc  =  1;
190   size_hints.height_inc =  1;
191   size_hints.min_width  = 10;
192   size_hints.min_height = 10;
193 
194   if (!geom) geom = default_geom;
195 
196   status = XGeometry(dpy, vi->screen, (char *) geom, (char *) default_geom,
197 		     2, 1, 1, 0, 0, &(size_hints.x), &(size_hints.y),
198 		     &(size_hints.width), &(size_hints.height));
199   if (status & (XValue|YValue))
200   {
201     size_hints.flags |= USPosition;
202     size_hints.flags &= ~PPosition;
203   }
204   if (status & (WidthValue|HeightValue))
205   {
206     size_hints.flags |= USSize;
207     size_hints.flags &= ~PSize;
208   }
209 
210   if (size_hints.flags & USSize)
211   {
212     size_hints.flags |= PAspect;
213     size_hints.min_aspect.x = size_hints.width;
214     size_hints.min_aspect.y = size_hints.height;
215     size_hints.max_aspect.x = size_hints.width;
216     size_hints.max_aspect.y = size_hints.height;
217   }
218 
219   attributes.border_pixel = 0;
220   attributes.background_pixel = 0;
221   attributes.event_mask = StructureNotifyMask;
222   window = XCreateWindow(dpy, root, size_hints.x, size_hints.y,
223 			 size_hints.width, size_hints.height, 0, vi->depth,
224 			 InputOutput, vi->visual, valuemask, &attributes);
225 
226   if (!window)
227   {
228     WARNING("couldn't create a window\n");
229     return(0);
230   }
231 
232   XSetStandardProperties(dpy, window, name, name, None, NULL, 0, &size_hints);
233   XSelectInput(dpy, window, ExposureMask|StructureNotifyMask);
234 
235   XMapWindow(dpy, window);
236 
237   XSetWMProtocols(dpy, window, &delete_window_atom, 1);
238   XIfEvent(dpy, &event, WaitForNotify, (char*) window);
239   XStoreName(dpy, window, name);
240 
241   return(window);
242 }
243 
OGL_create_window(const char * name,const char * geometry)244 static OGL_WINDOW *OGL_create_window(const char *name, const char *geometry)
245 {
246   FUNCNAME("OGL_create_window");
247   Display      *dpy;
248   int          screen;
249   Window       window, root;
250   int          dummy;
251   Bool	       doubleBuffered;
252   XVisualInfo  *vi;
253   GLXContext   context;
254   unsigned int bwidth, depth;
255   int          x, y;
256   OGL_WINDOW * ogl_win;
257 
258   if (!(dpy = XOpenDisplay(NULL)))
259   {
260     WARNING("can't open X display\n");
261     return (NULL);
262   }
263   screen = DefaultScreen(dpy);
264 
265   if (!(opengl_available = glXQueryExtension(dpy, &dummy, &dummy)))
266   {
267     WARNING("server doesn't support GLX Extension\n");
268     return (NULL);
269   }
270 
271   if (!(vi = findVisual(dpy, screen, &doubleBuffered)))
272     return(NULL);
273 
274   if (!(window = createWindow(dpy, screen, vi, name, geometry)))
275     return(NULL);
276 
277   context = glXCreateContext(dpy, vi, NULL, GL_TRUE);
278 
279   XFree(vi);
280 
281   if (context == NULL)
282   {
283     WARNING("can't create context\n");
284     return(NULL);
285   }
286 
287   if (!glXMakeCurrent(dpy, window, context))
288   {
289     WARNING("glXMakeCurrent failed\n");
290     return (NULL);
291   }
292 
293   ogl_win = MEM_ALLOC(1, OGL_WINDOW);
294   ogl_win->dpy = dpy;
295   ogl_win->win = window;
296   ogl_win->context  = context;
297   ogl_win->doubleBuffered = doubleBuffered;
298 
299   XGetGeometry(dpy, window, &root, &x, &y,
300 	       &ogl_win->width, &ogl_win->height,
301 	       &bwidth, &depth);
302 
303   return(ogl_win);
304 }
305 
306 /****************************************************************************/
307 
OGL_destroy_window(OGL_WINDOW * ogl_win)308 static void OGL_destroy_window(OGL_WINDOW *ogl_win)
309 {
310   /* FUNCNAME("OGL_destroy_window"); re-enable when MSG() is used here ... */
311 
312   if (!ogl_win)  return;
313 
314   glXDestroyContext(ogl_win->dpy, ogl_win->context);
315 
316   XDestroyWindow(ogl_win->dpy, ogl_win->win);
317   XFlush(ogl_win->dpy);
318 
319   MEM_FREE(ogl_win, 1, OGL_WINDOW);
320 }
321 
322 /****************************************************************************/
323 
OGL_clear_window(OGL_WINDOW * ogl_win,const GRAPH_RGBCOLOR c)324 static void OGL_clear_window(OGL_WINDOW *ogl_win, const GRAPH_RGBCOLOR c)
325 {
326   FUNCNAME("OGL_clear_window");
327 
328   Window       root;
329   unsigned int w, h, depth, bwidth;
330   int          x, y;
331 
332   if (!ogl_win) {
333     MSG("no OGL_WINDOW\n");
334     return;
335   }
336 
337   OGL_set_std_window(ogl_win);
338 
339   /* Has the window size changed? */
340   XGetGeometry(ogl_win->dpy, ogl_win->win,
341 	       &root, &x, &y, &w, &h, &bwidth, &depth);
342 
343   if (w != ogl_win->width || h != ogl_win->height){
344     ogl_win->width  = w;
345     ogl_win->height = h;
346     XResizeWindow(ogl_win->dpy, ogl_win->win, w, h);
347   }
348 
349   glXMakeCurrent(ogl_win->dpy, ogl_win->win, ogl_win->context);
350 
351   glViewport(0, 0, w, h);
352 
353   glMatrixMode(GL_PROJECTION);
354   glLoadIdentity();
355   glMatrixMode(GL_MODELVIEW);
356   glLoadIdentity();
357   glOrtho(ogl_win->xmin[0], ogl_win->xmax[0],
358 	  ogl_win->xmin[1], ogl_win->xmax[1],
359 	  -1.0, 1.0);
360 
361   if (c)
362     glClearColor(c[0], c[1], c[2], 1.0);
363   else
364     glClearColor(1.0, 1.0, 1.0, 1.0);
365 
366   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
367   OGL_FLUSH(ogl_win);
368 }
369 #endif
370 
371 /****************************************************************************/
372 
373 /****************************************************************************/
374 /* Common graphic routines available to the user                            */
375 /****************************************************************************/
376 
377 #if DIM_OF_WORLD == 1
378 #include "graphXO_1d.c"
379 #endif
380 #if DIM_OF_WORLD == 2
381 #include "graphXO_2d.c"
382 #endif
383 
graph_open_window(const char * title,const char * geometry,REAL * world,MESH * mesh)384 GRAPH_WINDOW graph_open_window(const char *title, const char *geometry,
385 			       REAL *world, MESH *mesh)
386 {
387   FUNCNAME("graph_open_window");
388 
389   switch(mesh->dim) {
390 #if DIM_OF_WORLD == 1
391       case 1:
392 	return graph_open_window_1d(title, geometry, world, mesh);
393 #endif
394 #if DIM_OF_WORLD == 2
395       case 2:
396 	return graph_open_window_2d(title, geometry, world, mesh);
397 #endif
398       case 3:
399 	ERROR("Not implemented for dim == 3!\n");
400 	return 0;
401       default:
402 	ERROR_EXIT("Illegal mesh->dim: must equal DIM_OF_WORLD\n");
403   }
404 
405   return 0;
406 }
407 
408 
graph_close_window(GRAPH_WINDOW win)409 void graph_close_window(GRAPH_WINDOW win)
410 {
411 #if DIM_OF_WORLD==1
412   graph_close_window_1d(win);
413 #elif DIM_OF_WORLD==2
414   graph_close_window_2d(win);
415 #else
416   ERROR("Not implemented for dim == 3!\n");
417 #endif
418   return;
419 }
420 
421 
graph_clear_window(GRAPH_WINDOW win,const GRAPH_RGBCOLOR c)422 void graph_clear_window(GRAPH_WINDOW win, const GRAPH_RGBCOLOR c)
423 {
424 #if DIM_OF_WORLD==1
425   graph_clear_window_1d(win, c);
426 #elif DIM_OF_WORLD==2
427   graph_clear_window_2d(win, c);
428 #else
429   ERROR("Not implemented for dim == 3!\n");
430 #endif
431   return;
432 }
433 
434 
graph_mesh(GRAPH_WINDOW win,MESH * mesh,const GRAPH_RGBCOLOR c,FLAGS flag)435 void graph_mesh(GRAPH_WINDOW win, MESH *mesh, const GRAPH_RGBCOLOR c,
436 		FLAGS flag)
437 {
438   FUNCNAME("graph_mesh");
439 
440   switch(mesh->dim) {
441 #if DIM_OF_WORLD == 1
442       case 1:
443 	if(DIM_OF_WORLD != 1) {
444 	  ERROR("dim must equal DIM_OF_WORLD == %d!\n", DIM_OF_WORLD);
445 	  return;
446 	}
447 	graph_mesh_1d(win, mesh, c, flag);
448 	break;
449 #endif
450 #if DIM_OF_WORLD == 2
451       case 2:
452 	if(DIM_OF_WORLD != 2) {
453 	  ERROR("dim must equal DIM_OF_WORLD == %d!\n", DIM_OF_WORLD);
454 	  return;
455 	}
456 	graph_mesh_2d(win, mesh, c, flag);
457 	break;
458 #endif
459       case 3:
460 	ERROR("Not implemented for dim == 3!\n");
461 	return;
462       default:
463 	ERROR_EXIT("Illegal dim!\n");
464   }
465 }
466 
graph_drv(GRAPH_WINDOW win,const DOF_REAL_VEC * u,REAL min,REAL max,int refine)467 void graph_drv(GRAPH_WINDOW win, const DOF_REAL_VEC *u,
468 	       REAL min, REAL max, int refine)
469 {
470   FUNCNAME("graph_drv");
471 
472   TEST_EXIT(u && u->fe_space && u->fe_space->admin && u->fe_space->admin->mesh,
473     "no vec or fe_space or admin or mesh!\n");
474 
475   switch(u->fe_space->admin->mesh->dim) {
476 #if DIM_OF_WORLD == 1
477       case 1:
478 	if(DIM_OF_WORLD != 1) {
479 	  ERROR("dim must equal DIM_OF_WORLD == %d!\n", DIM_OF_WORLD);
480 	  return;
481 	}
482 	graph_drv_1d(win, u, min, max, refine, NULL);
483 	break;
484 #endif
485 #if DIM_OF_WORLD == 2
486       case 2:
487 	if(DIM_OF_WORLD != 2) {
488 	  ERROR("dim must equal DIM_OF_WORLD == %d!\n", DIM_OF_WORLD);
489 	  return;
490 	}
491 	graph_drv_2d(win, u, min, max, refine);
492 	break;
493 #endif
494       case 3:
495 	ERROR("Not implemented for dim == 3!\n");
496 	return;
497       default:
498 	ERROR_EXIT("Illegal dim!\n");
499   }
500 }
501 
graph_drv_d(GRAPH_WINDOW win,const DOF_REAL_D_VEC * ud,REAL min,REAL max,int refine)502 void graph_drv_d(GRAPH_WINDOW win, const DOF_REAL_D_VEC *ud,
503 		 REAL min, REAL max, int refine)
504 {
505   FUNCNAME("graph_drv_d");
506 
507   TEST_EXIT(ud && ud->fe_space && ud->fe_space->admin && ud->fe_space->admin->mesh,
508     "no vec or fe_space or admin or mesh!\n");
509 
510   switch(ud->fe_space->admin->mesh->dim) {
511 #if DIM_OF_WORLD == 1
512       case 1:
513 	if(DIM_OF_WORLD != 1) {
514 	  ERROR("dim must equal DIM_OF_WORLD == %d!\n", DIM_OF_WORLD);
515 	  return;
516 	}
517 	graph_drv_d_1d(win, ud, min, max, refine, NULL);
518 	break;
519 #endif
520 #if DIM_OF_WORLD ==2
521       case 2:
522 	if(DIM_OF_WORLD != 2) {
523 	  ERROR("dim must equal DIM_OF_WORLD == %d!\n", DIM_OF_WORLD);
524 	  return;
525 	}
526 	graph_drv_d_2d(win, ud, min, max, refine);
527 	break;
528 #endif
529       case 3:
530 	ERROR("Not implemented for dim == 3!\n");
531 	return;
532       default:
533 	ERROR_EXIT("Illegal dim!\n");
534   }
535 }
536 
graph_el_est(GRAPH_WINDOW win,MESH * mesh,REAL (* get_est)(EL *),REAL min,REAL max)537 void graph_el_est(GRAPH_WINDOW win, MESH *mesh, REAL (*get_est)(EL *),
538 		  REAL min, REAL max)
539 {
540   FUNCNAME("graph_drv_d");
541 
542   if(!mesh) {
543     ERROR("No mesh given!\n");
544     return;
545   }
546 
547   switch(mesh->dim) {
548 #if DIM_OF_WORLD == 1
549       case 1:
550 	if(DIM_OF_WORLD != 1) {
551 	  ERROR("dim must equal DIM_OF_WORLD == %d!\n", DIM_OF_WORLD);
552 	  return;
553 	}
554 	graph_el_est_1d(win, mesh, get_est, min, max, NULL);
555 	break;
556 #endif
557 #if DIM_OF_WORLD == 2
558       case 2:
559 	if(DIM_OF_WORLD != 2) {
560 	  ERROR("dim must equal DIM_OF_WORLD == %d!\n", DIM_OF_WORLD);
561 	  return;
562 	}
563 	graph_el_est_2d(win, mesh, get_est, min, max);
564 	break;
565 #endif
566       case 3:
567 	ERROR("Not implemented for dim == 3!\n");
568 	return;
569       default:
570 	ERROR_EXIT("Illegal dim!\n");
571   }
572 }
573 
574 /****************************************************************************/
575 
graph_point(GRAPH_WINDOW win,const REAL p0[2],const GRAPH_RGBCOLOR c,float ps)576 void graph_point(GRAPH_WINDOW win, const REAL p0[2], const GRAPH_RGBCOLOR c,
577 		 float ps)
578 {
579 #if DIM_OF_WORLD >= 3
580   FUNCNAME("graph_point");
581 
582   ERROR("Not implemented for dim == 3!\n");
583 #else
584   OGL_WINDOW *ogl_win = (OGL_WINDOW *)win;
585 
586   OGL_set_std_window(ogl_win);
587 
588   glColor3fv(c ? c : rgb_black);
589   glPointSize(ps > 0 ? ps : 1.0);
590 
591   glBegin(GL_POINTS);
592   glVertex2d(p0[0], p0[1]);
593   glEnd();
594 
595   OGL_FLUSH(ogl_win);
596 #endif
597   return;
598 }
599 
600 
graph_points(GRAPH_WINDOW win,int np,REAL (* p)[2],const GRAPH_RGBCOLOR c,float ps)601 void graph_points(GRAPH_WINDOW win, int np, REAL (*p)[2],
602 		  const GRAPH_RGBCOLOR c, float ps)
603 {
604 #if DIM_OF_WORLD >= 3
605   FUNCNAME("graph_points");
606 
607   ERROR("Not implemented for dim == 3!\n");
608 #else
609   int        i;
610   OGL_WINDOW *ogl_win = (OGL_WINDOW *)win;
611 
612   OGL_set_std_window(ogl_win);
613 
614   glColor3fv(c ? c : rgb_black);
615   glPointSize(ps > 0 ? ps : 1.0);
616 
617   glBegin(GL_POINTS);
618   for (i = 0; i < np; i++)
619     glVertex2d(p[i][0], p[i][1]);
620 
621   glEnd();
622 
623   OGL_FLUSH(ogl_win);
624 #endif
625 
626   return;
627 }
628 
629 /****************************************************************************/
630 
graph_line(GRAPH_WINDOW win,const REAL p0[2],const REAL p1[2],const GRAPH_RGBCOLOR c,float lw)631 void graph_line(GRAPH_WINDOW win, const REAL p0[2], const REAL p1[2],
632 		const GRAPH_RGBCOLOR c, float lw)
633 {
634 #if DIM_OF_WORLD >= 3
635   FUNCNAME("graph_line");
636 
637   ERROR("Not implemented for dim == 3!\n");
638 #else
639   float xy[2];
640   int   j;
641   OGL_WINDOW *ogl_win = (OGL_WINDOW *)win;
642 
643   OGL_set_std_window(ogl_win);
644 
645   glColor3fv(c ? c : rgb_black);
646   glLineWidth(lw > 0 ? lw : 1.0);
647 
648   glBegin(GL_LINE_STRIP);
649   for (j=0; j<2; j++) xy[j] = p0[j];
650   glVertex2fv(xy);
651   for (j=0; j<2; j++) xy[j] = p1[j];
652   glVertex2fv(xy);
653   glEnd();
654 
655   OGL_FLUSH(ogl_win);
656 #endif
657 
658   return;
659 }
660