ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
OpenGLArea.c
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file OpenGLArea.c
1 /*
2 #define DEBUG
3 */
4 
5 /*this*/
6 #include "OpenGLAreaP.h"
7 
8 #include <X11/StringDefs.h>
9 
10 #include <GL/glx.h>
11 
12 #include <stdio.h>
13 #include <stdlib.h>
14 
15 #ifdef __cplusplus
16 extern "C"{
17 #endif
18 static void InitializeClass(void);
19 static void InitializeWidget(Widget, Widget,ArgList,Cardinal*);
20 static void RealizeWidget(Widget, XtValueMask*, XSetWindowAttributes*);
21 static void DestroyWidget(Widget);
22 static void ChangeWidgetSize(Widget);
23 static void DrawWidget(Widget, XEvent*, Region);
24 static Boolean SetValues(Widget,Widget,Widget,ArgList,Cardinal *);
25 
26 static void EventHandler(Widget,XtPointer,XEvent*,Boolean*);
27 static int MakeCurrent(Widget);
28 static void XWidgetInstallColormap(Widget);
29 static void XWidgetUninstallColormap(Widget);
30 static Widget XWidgetGetShell(Widget);
31 #ifdef __cplusplus
32 }
33 #endif
34 
35 #define athis ((OpenGLAreaWidget)This)->openGLArea
36 #define acur ((OpenGLAreaWidget)a_current)->openGLArea
37 #define CWarn printf
38 #define CWarnF printf
39 
40 static XtResource resources [] = {
41  {XoNdoubleBufferOn,"DoubleBufferOn",XtRBoolean,sizeof(Boolean),
42  XtOffset(OpenGLAreaWidget,openGLArea.doubleBufferOn),XtRImmediate,(XtPointer)True},
43  {XoNpaintCallback,XtCCallback,XtRCallback,sizeof(XtCallbackList),
44  XtOffset(OpenGLAreaWidget,openGLArea.paintCallback),XtRImmediate,(XtPointer)NULL},
45  {XoNeventCallback,XtCCallback,XtRCallback,sizeof(XtCallbackList),
46  XtOffset(OpenGLAreaWidget,openGLArea.eventCallback),XtRImmediate,(XtPointer)NULL}
47 };
48 
50 /* Core Class Part */
51 {
52  (WidgetClass) &compositeClassRec, /* pointer to superclass ClassRec */
53  "OpenGLArea", /* widget resource class name */
54  sizeof(OpenGLAreaRec), /* size in bytes of widget record */
55  InitializeClass, /* class_initialize */
56  NULL, /* dynamic initialization */
57  FALSE, /* has class been initialized? */
58  InitializeWidget, /* initialize */
59  NULL, /* notify that initialize called */
60  RealizeWidget, /* XCreateWindow for widget */
61  NULL, /* widget semantics name to proc mapWidget*/
62  0, /* number of entries in actions */
63  resources, /* resources for subclass fields */
64  XtNumber(resources), /* number of entries in resources */
65  NULLQUARK, /* resource class quarkified */
66  TRUE, /* compress MotionNotify for widget */
67  TRUE, /* compress Expose events for widget*/
68  TRUE, /* compress enter and leave events */
69  TRUE, /* select for VisibilityNotify */
70  DestroyWidget, /* free data for subclass pointers */
71  ChangeWidgetSize, /* geom manager changed widget size */
72  DrawWidget, /* rediplay window */
73  SetValues, /* set subclass resource values */
74  NULL, /* notify that SetValues called */
75  XtInheritSetValuesAlmost, /* SetValues got "Almost" geo reply*/
76  NULL, /* notify that get_values called */
77  XtInheritAcceptFocus, /* assign input focus to widget */
78  XtVersion, /* version of intrinsics used */
79  NULL, /* list of callback offsets */
80  XtInheritTranslations, /* translations */
81  XtInheritQueryGeometry, /* return preferred geometry */
82  XtInheritDisplayAccelerator, /* display your accelerator */
83  NULL /* pointer to extension record */
84 },
85 /* Composite Class Part */
86 {
87  XtInheritGeometryManager, /* geometry manager for children */
88  XtInheritChangeManaged, /* change managed state of child */
89  XtInheritInsertChild, /* physically add child to parent */
90  XtInheritDeleteChild, /* physically remove child */
91  NULL /* pointer to extension record */
92 },
93 /* OpenGLArea */
94 {
95  NULL
96 }
97 
98 };
99 
100 WidgetClass openGLAreaWidgetClass = (WidgetClass) &openGLAreaClassRec;
101 
102 static void InitializeClass(void) {}
103 
104 static void InitializeWidget(Widget a_request,Widget This,ArgList a_args,Cardinal* a_argn) {
105  if(a_request->core.width<=0) This->core.width = 100;
106  if(a_request->core.height<=0) This->core.height = 100;
107 
108 #ifdef DEBUG
109  printf ("debug : OpenGLArea : InitializeWidget : %s\n",XtName(This));
110 #endif
111 
112  athis.visual = CopyFromParent;
113  athis.installColormap = False;
114  athis.glContext = NULL;
115 
116  {Display* display;
117  Screen* screen;
118  int iscreen;
119  XVisualInfo* vinfo;
120  display = XtDisplay(This);
121  screen = XtScreen(This);
122  iscreen = XScreenNumberOfScreen(screen);
123 
124  {int error,event;
125  if(glXQueryExtension(display,&error,&event)==0) {
126  CWarn ("X server does not have OpenGL extensions.\n");
127  }}
128 
129  if(athis.doubleBufferOn==True) {
130  int atbs[] = {
131  GLX_RGBA,
132  GLX_RED_SIZE, 1,
133  GLX_GREEN_SIZE, 1,
134  GLX_BLUE_SIZE, 1,
135  GLX_ALPHA_SIZE, 1,
136  GLX_DEPTH_SIZE, 1,
137  GLX_DOUBLEBUFFER,
138  None
139  };
140  vinfo = glXChooseVisual (display,iscreen,atbs);
141  if(vinfo==NULL) { /*GLX_ALPHA_SIZE : problem with Xming. Try without it.*/
142  int atbs[] = {
143  GLX_RGBA,
144  GLX_RED_SIZE, 1,
145  GLX_GREEN_SIZE, 1,
146  GLX_BLUE_SIZE, 1,
147  GLX_DEPTH_SIZE, 1,
148  GLX_DOUBLEBUFFER,
149  None
150  };
151  vinfo = glXChooseVisual (display,iscreen,atbs);
152  }
153  } else {
154  int atbs[] = {
155  GLX_RGBA,
156  GLX_RED_SIZE, 1,
157  GLX_GREEN_SIZE, 1,
158  GLX_BLUE_SIZE, 1,
159  GLX_ALPHA_SIZE, 1,
160  GLX_DEPTH_SIZE, 1,
161  None
162  };
163  vinfo = glXChooseVisual (display,iscreen,atbs);
164  if(vinfo==NULL) { /*GLX_ALPHA_SIZE : problem with Xming. Try without it.*/
165  int atbs[] = {
166  GLX_RGBA,
167  GLX_RED_SIZE, 1,
168  GLX_GREEN_SIZE, 1,
169  GLX_BLUE_SIZE, 1,
170  GLX_DEPTH_SIZE, 1,
171  None
172  };
173  vinfo = glXChooseVisual (display,iscreen,atbs);
174  }
175  }
176 
177  if(vinfo==NULL) {
178  CWarn ("Can't choose a visual.\n");
179  } else {
180  This->core.depth = vinfo->depth;
181  athis.visual = vinfo->visual;
182  if( (vinfo->depth ==DefaultDepth (display,iscreen)) &&
183  (vinfo->visual==DefaultVisual(display,iscreen)) ) {
184  This->core.colormap = XDefaultColormap (display,iscreen);
185  athis.installColormap = False;
186  } else {
187  This->core.colormap =
188  XCreateColormap (display,XRootWindow(display,iscreen),vinfo->visual, AllocNone);
189  athis.installColormap = True;
190  }
191  if(This->core.colormap==0L) {
192  CWarn ("Can't get/create a X colormap.\n");
193  }
194  athis.glContext = glXCreateContext (display,vinfo,NULL,GL_FALSE);
195  if(athis.glContext==NULL) {
196  CWarn ("Can't create a GLX context.\n");
197  }
198  XFree(vinfo);
199  }}
200 
201  XtAddEventHandler(This,ButtonPressMask|ButtonReleaseMask|ButtonMotionMask,0,EventHandler,NULL);
202 
203 #ifdef DEBUG
204  printf("debug : OpenGLArea : InitializeWidget : end\n");
205 #endif
206 
207  /*avoid C++ warnings*/
208  a_request = NULL;
209  a_args = NULL;
210  a_argn = 0;
211 }
212 
213 static void RealizeWidget(Widget This,XtValueMask* a_mask,XSetWindowAttributes* a_watbs) {
214 #ifdef DEBUG
215  printf("debug : OpenGLArea : RealizeWidget : %s\n",XtName(This));
216 #endif
217 
218  /*Have to create window ourselves due to OpenGL that compells it's visual.*/
219  /*In principle colormap is correctly set in a_watbs.*/
220 
221  XtCreateWindow(This,(unsigned int)InputOutput,athis.visual,*a_mask,a_watbs);
222 
223  /* Call the Realize procedure (XtInheritRealize) */
224  if(openGLAreaWidgetClass->core_class.superclass->core_class.realize!=NULL)
225  (openGLAreaWidgetClass->core_class.superclass->core_class.realize)(This, a_mask, a_watbs);
226 
227  /*If window is delete, all seems ok.*/
228  if(athis.installColormap==True) XWidgetInstallColormap(This);
229 
230  /*MakeCurrent(This);*/
231 
232 #ifdef DEBUG
233  printf("debug : OpenGLArea : RealizeWidget : end\n");
234 #endif
235 }
236 
237 static void DestroyWidget(Widget This) {
238  if(athis.installColormap==True) {
240  athis.installColormap = False;
241  XFreeColormap(XtDisplay(This),This->core.colormap);
242  }
243  if(athis.glContext!=NULL) {
244  glXMakeCurrent(XtDisplay(This),None,NULL);
245  glXDestroyContext(XtDisplay(This),athis.glContext);
246  athis.glContext = NULL;
247  }
248 }
249 
250 #define IFMOD(a_field) if(athis.a_field != acur.a_field)
251 static Boolean SetValues(Widget a_current,Widget a_request,Widget This,ArgList a_args,Cardinal* a_argn) {
252  IFMOD(doubleBufferOn) {
253  /* Can't change buffering here if X window is created.
254  With OpenGL, buffering fix parameter of the X window.
255  Buffering must be choosen before the execution of the
256  Realize method that create the window. */
257  if(XtIsRealized(This) && (athis.installColormap==True)) {
258  CWarn("Can't change buffering after \"realization\" of the widget.\n");
259  athis.doubleBufferOn = acur.doubleBufferOn;
260  }
261  }
262  /*avoid C++ warnings*/
263  a_request = NULL;
264  a_args = NULL;
265  a_argn = 0;
266  return False;
267 }
268 
269 static void ChangeWidgetSize(Widget This) {
270 #ifdef DEBUG
271  printf("debug : OpenGLArea : ChangeWidgetSize : %s\n",XtName(This));
272 #endif
273 
274  /* Call the Resize procedure (XtInheritResize) */
275  if(openGLAreaWidgetClass->core_class.superclass->core_class.resize!=NULL)
276  (openGLAreaWidgetClass->core_class.superclass->core_class.resize)(This);
277 
278 #ifdef DEBUG
279  printf("debug : OpenGLArea : ChangeWidgetSize : end\n");
280 #endif
281 }
282 
283 static void DrawWidget(Widget This,XEvent* a_event,Region a_region) {
284 #ifdef DEBUG
285  printf("debug : OpenGLArea : DrawWidget : %s\n",XtName(This));
286 #endif
287 
288  if(openGLAreaWidgetClass->core_class.superclass->core_class.expose!=NULL)
289  (openGLAreaWidgetClass->core_class.superclass->core_class.expose)(This,a_event,a_region);
290 
291  if(MakeCurrent(This)==1) {
292 #ifdef DEBUG
293  printf("debug : OpenGLArea : DrawWidget : %s : MakeCurrent ok : call paintCallback...\n",XtName(This));
294 #endif
296  value.reason = XoCR_PAINT;
297  value.event = a_event;
298  XtCallCallbacks(This,XoNpaintCallback,(XtPointer)&value);
299  glXSwapBuffers(XtDisplay(This),XtWindow(This));
300  glXMakeCurrent(XtDisplay(This),None,NULL);
301  }
302 
303 #ifdef DEBUG
304  printf("debug : OpenGLArea : DrawWidget : end\n");
305 #endif
306 
307  /*avoid C++ warnings*/
308  a_event = NULL;
309  a_region = NULL;
310 }
311 
312 
313 /*------------------------------------------------------------------------*/
314 /*------------------------------------------------------------------------*/
315 /*------------------------------------------------------------------------*/
316 
317 void OpenGLAreaPaint(Widget This) {
318  if(!XtIsRealized(This)) return;
319  if(MakeCurrent(This)==1) {
321  value.reason = XoCR_PAINT;
322  value.event = 0;
323  XtCallCallbacks(This,XoNpaintCallback,(XtPointer)&value);
324  glXSwapBuffers(XtDisplay(This),XtWindow(This));
325  glXMakeCurrent(XtDisplay(This),None,NULL);
326  }
327 }
328 
329 #ifdef TOOLS_XT_OPENGLAREA_HAS_GL2PS
330 
331 #include <tools/c_gl2ps.h>
332 
333 int OpenGLAreaWrite_gl2ps(Widget This,const char* aFileName,const char* opts) {
334  FILE* file;
335  int options;
336  int sort;
337  inlib_GLint vp[4];
338  int bufsize = 0;
339  static inlib_gl2ps_gl_funcs_t s_OpenGL_funcs = {
340  glIsEnabled,
341  glBegin,
342  glEnd,
343  glGetFloatv,
344  glVertex3f,
345  glGetBooleanv,
346  glGetIntegerv,
347  glRenderMode,
348  glFeedbackBuffer,
349  glPassThrough
350  };
351 
352  file = fopen(aFileName,"w");
353  if(!file) return 1;
354 
355  inlib_c_gl2ps_set_gl_funcs(&s_OpenGL_funcs);
356 
357  options = TOOLS_GL2PS_OCCLUSION_CULL
361  sort = TOOLS_GL2PS_BSP_SORT;
362  //sort = TOOLS_GL2PS_SIMPLE_SORT;
363 
364  vp[0] = 0;
365  vp[1] = 0;
366  vp[2] = This->core.width;
367  vp[3] = This->core.height;
368 
369  inlib_c_gl2psBeginPage("title","exlib_Xt_OpenGLArea",
370  vp,TOOLS_GL2PS_EPS,sort,options,
371  TOOLS_GL_RGBA,0, NULL,0,0,0,bufsize,
372  file,aFileName);
373 
375  value.reason = XoCR_PAINT;
376  value.event = 0;
377  XtCallCallbacks(This,XoNpaintCallback,(XtPointer)&value);}
378 
379  inlib_c_gl2psEndPage();
380 
381  inlib_c_gl2ps_reset_gl_funcs();
382 
383  fclose(file);
384 
385  return 0;
386 }
387 
388 #else
389 #ifdef __cplusplus
390 int OpenGLAreaWrite_gl2ps(Widget,const char*,const char*) {return 1;}
391 #else
392 int OpenGLAreaWrite_gl2ps(Widget w,const char* f,const char* o) {return 1;}
393 #endif
394 #endif
395 
396 /*------------------------------------------------------------------------*/
397 /*------------------------------------------------------------------------*/
398 /*------------------------------------------------------------------------*/
399 /*------------------------------------------------------------------------*/
400 static int MakeCurrent(Widget This) {
401  if(This==NULL) return 0;
402  if(!XtIsRealized(This)) return 0;
403  if(athis.glContext==NULL) return 0;
404  return (int)glXMakeCurrent(XtDisplay(This),XtWindow(This),athis.glContext);
405 }
406 
407 static void EventHandler(Widget This,XtPointer a_tag,XEvent* a_event ,Boolean* a_continue) {
409  value.reason = XoCR_EVENT;
410  value.event = a_event;
411  XtCallCallbacks(This,XoNeventCallback,(XtPointer)&value);
412  a_tag = NULL;
413  a_continue = NULL;
414 }
415 
416 /*------------------------------------------------------------------------*/
417 /*------------------------------------------------------------------------*/
418 /*------------------------------------------------------------------------*/
419 static void XWidgetInstallColormap(Widget This) {
420 /*
421  From Mesa/widgets/GLwDrawingArea.c/post_colormap routine.
422  Could use also XtSetWMColormapWindows.
423 */
424  Display* display;
425  XWindowAttributes watbs;
426  Widget shell;
427  Window* ws = NULL;
428  int wn = 0,found,count;
429  Window wshell,wthis;
430  Colormap cmapthis;
431 /*.........................................................................*/
432  if(This==NULL) return;
433  if( !XtIsWidget(This) || !XtIsRealized(This) ) return;
434  shell = XWidgetGetShell (This);
435  if(shell==NULL) return;
436  display = XtDisplay (This);
437  wthis = XtWindow (This);
438  wshell = XtWindow (shell);
439  XGetWMColormapWindows (display,wshell, &ws, &wn);
440 /* Check if colormap of this is a colormap of a Window in list.*/
441  XGetWindowAttributes (display,wthis,&watbs);
442  cmapthis = watbs.colormap;
443  found = -1;
444  for(count=0;count<wn;count++) {
445  Colormap cmap;
446  XGetWindowAttributes (display,ws[count],&watbs);
447  cmap = watbs.colormap;
448  if(cmap==cmapthis) {
449  XFree (ws);
450  return; /*done*/
451  }
452  if(ws[count]==wshell) {
453  found = count;
454  }
455  }
456  /*Have to add window of this in list.*/
457  if(wn==0) {
458  if(ws!=NULL) XFree(ws);
459  ws = (Window*)malloc ( 2 * sizeof(Window));
460  } else {
461  ws = (Window*)realloc (ws,(wn + 2) * sizeof(Window));
462  }
463  if(ws==NULL) return;
464  if(found==-1) {
465  /*Window of shell not in list.*/
466  ws[wn] = wthis; wn++;
467  ws[wn] = wshell;wn++;
468  } else {
469  ws[found] = wthis;
470  ws[wn] = wshell; wn++; /*Shell must be last.*/
471  }
472  if (XSetWMColormapWindows(display,wshell, ws, wn)==0) {
473  CWarnF ("XWidgetInstallColormap: can't install colormap of %s in %s.\n",XtName(This),XtName(shell));
474  }
475  XFree (ws);
476 }
477 
478 static void XWidgetUninstallColormap(Widget This) {
479  int count;
480  Widget shell;
481  Display* display;
482  Window wthis,wshell;
483  Window* ws = NULL;
484  int wn = 0;
485  Window* nws = NULL;
486  int nwn = 0;
487 /*.........................................................................*/
488  if(This==NULL) return;
489  if( !XtIsWidget(This) || !XtIsRealized(This) ) return;
490  shell = XWidgetGetShell (This);
491  if(shell==NULL) return;
492  display = XtDisplay (This);
493  wthis = XtWindow (This);
494  wshell = XtWindow (shell);
495  XGetWMColormapWindows (display,wshell, &ws, &wn);
496  if( (wn==0) || (ws==NULL) ) return;
497  nws = (Window*)malloc ( wn * sizeof(Window));
498  if(nws==NULL) {
499  XFree (ws);
500  return;
501  }
502  nwn = 0;
503  for(count=0;count<wn;count++) {
504  if(ws[count]!=wthis) {
505  nws[nwn] = ws[count];
506  nwn++;
507  }
508  }
509  if(wn!=nwn) {
510  if (XSetWMColormapWindows(display,wshell, nws, nwn)==0) {
511  CWarnF("XWidgetUninstallColormap: can't install colormap of %s in %s.\n",XtName(This),XtName(shell));
512  }
513  }
514  XFree (ws);
515  XFree (nws);
516 }
517 
518 Widget XWidgetGetShell(Widget This) {
519  Widget widget;
520  if(This==NULL) return NULL;
521  widget = This;
522  while(1) {
523  if(widget==NULL) return NULL;
524  if(XtIsShell(widget)) return widget;
525  widget = XtParent(widget);
526  }
527 }
528 
529 /*
530 exlib_build_use Xt inlib
531 */