Geant4_10
G4OpenGLXViewer.cc
Go to the documentation of this file.
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 //
27 // $Id: G4OpenGLXViewer.cc 66870 2013-01-14 23:38:59Z adotti $
28 //
29 //
30 // Andrew Walkden 7th February 1997
31 // G4OpenGLXViewer : Class to provide XWindows specific
32 // functionality for OpenGL in GEANT4
33 
34 #ifdef G4VIS_BUILD_OPENGLX_DRIVER
35 
36 #include "G4OpenGLXViewer.hh"
37 #include "G4VViewer.hh"
38 #include "G4OpenGLSceneHandler.hh"
39 
40 #include "G4OpenGLFontBaseStore.hh"
41 
42 #include <sstream>
43 
44 #include "G4VisExtent.hh"
45 #include "G4LogicalVolume.hh"
46 #include "G4VSolid.hh"
47 #include "G4Point3D.hh"
48 #include "G4Normal3D.hh"
49 #include "G4StateManager.hh"
50 #include "G4VisManager.hh"
51 #include "G4Text.hh"
52 
53 #include <X11/Xatom.h>
54 #include <X11/Xutil.h>
55 #include <X11/Xmu/StdCmap.h>
56 
57 #include <assert.h>
58 
59 int G4OpenGLXViewer::snglBuf_RGBA[12] =
60 { GLX_RGBA,
61  GLX_RED_SIZE, 1,
62  GLX_GREEN_SIZE, 1,
63  GLX_BLUE_SIZE, 1,
64  GLX_DEPTH_SIZE, 1,
65  GLX_STENCIL_SIZE, 1,
66  None };
67 
68 int G4OpenGLXViewer::dblBuf_RGBA[13] =
69 { GLX_RGBA,
70  GLX_RED_SIZE, 1,
71  GLX_GREEN_SIZE, 1,
72  GLX_BLUE_SIZE, 1,
73  GLX_DOUBLEBUFFER,
74  GLX_DEPTH_SIZE, 1,
75  GLX_STENCIL_SIZE, 1,
76  None };
77 
78 #define NewString(str) \
79  ((str) != 0 ? (strncpy((char*)malloc((unsigned)strlen(str) + 1), str, (unsigned)strlen(str) + 1)) : (char*)0)
80 
81 #define USE_DEFAULT_COLORMAP 1
82 #define USE_STANDARD_COLORMAP 0
83 
84 XVisualInfo* G4OpenGLXViewer::vi_single_buffer = 0;
85 XVisualInfo* G4OpenGLXViewer::vi_double_buffer = 0;
86 
87 extern "C" {
88  static Bool G4OpenGLXViewerWaitForNotify (Display*, XEvent* e, char* arg) {
89  return (e->type == MapNotify) && (e->xmap.window == (Window) arg);
90  }
91 }
92 
93 void G4OpenGLXViewer::SetView () {
94  Bool success = glXMakeCurrent (dpy, win, cx);
95  if (!success) {
96  fViewId = -1; // This flags an error.
97  G4cerr << "G4OpenGLXViewer::G4OpenGLXViewer failed to attach a GLX context."
98  << G4endl;
99  GLint error = GL_NO_ERROR;
100  while ((error = glGetError()) != GL_NO_ERROR) {
101  G4cout << "GL Error: " << gluErrorString(error) << G4endl;
102  }
103  return;
104  }
105  G4OpenGLViewer::SetView ();
106 }
107 
108 void G4OpenGLXViewer::ShowView () {
109  glXWaitGL (); //Wait for effects of all previous OpenGL commands to
110  //be propagated before progressing.
111  glFlush ();
112 
113  if (fVP.IsPicking()) {
114  G4cout <<
115  "Window activated for picking (left-mouse), exit (middle-mouse)."
116  << G4endl;
117  while (true) {
118  if (XPending(dpy)) {
119  XNextEvent(dpy, &event);
120  if (event.type == ButtonPress && event.xbutton.button == 1) {
121  Pick(event.xbutton.x, event.xbutton.y);
122  }
123  else if (event.type == ButtonPress && event.xbutton.button == 2) break;
124  }
125  }
126  }
127 }
128 
129 void G4OpenGLXViewer::GetXConnection () {
130 // get a connection.
131  dpy = XOpenDisplay (0);
132  if (!dpy) {
133  fViewId = -1; // This flags an error.
134  G4cerr << "G4OpenGLXViewer::G4OpenGLXViewer couldn't open display." << G4endl;
135  return;
136  }
137 
138 // make sure OpenGL is supported and installed properly.
139  if (!glXQueryExtension (dpy, &errorBase, &eventBase)) {
140  fViewId = -1; // This flags an error.
141  G4cerr << "G4OpenGLXViewer::G4OpenGLXViewer X Server has no GLX extension."
142  << G4endl;
143  return;
144  }
145 
146 }
147 
148 void G4OpenGLXViewer::CreateGLXContext (XVisualInfo* v) {
149 
150  vi = v;
151 // get window's attributes
152  if (!XGetWindowAttributes(dpy, XRootWindow (dpy, vi -> screen), &xwa)) {
153  fViewId = -1; // This flags an error.
154  G4cerr << "G4OpenGLXViewer::G4OpenGLXViewer couldn't return window attributes"
155  << G4endl;
156  return;
157  }
158 
159 // create a GLX context
160  cx = glXCreateContext (dpy, vi, 0, true);
161  if (!cx) {
162  fViewId = -1; // This flags an error.
163  G4cerr << "G4OpenGLXViewer::G4OpenGLXViewer couldn't create context."
164  << G4endl;
165  return;
166  }
167 
168 // New stab at getting a colormap
169 
170  Status status;
171  XStandardColormap *standardCmaps = XAllocStandardColormap ();
172  int i, numCmaps;
173 
174  status = XmuLookupStandardColormap (dpy,
175  vi -> screen,
176  vi -> visualid,
177  vi -> depth,
178  XA_RGB_DEFAULT_MAP,
179  False,
180  True);
181 
182  if (status == 1) {
183  cmap = 0;
184  status = XGetRGBColormaps (dpy,
185  XRootWindow (dpy, vi -> screen),
186  &standardCmaps,
187  &numCmaps,
188  XA_RGB_DEFAULT_MAP);
189  if (status == 1)
190  for (i = 0; i < numCmaps; i++) {
191  if (standardCmaps[i].visualid == vi -> visualid) {
192  cmap = standardCmaps[i].colormap;
193  XFree (standardCmaps);
194  break;
195  }
196  }
197  if (!cmap) {
198  fViewId = -1; // This flags an error.
200  G4cerr <<
201  "G4OpenGLXViewer::G4OpenGLXViewer failed to allocate a standard colormap."
202  << G4endl;
203  return;
204  }
206  G4cout << "Got standard cmap" << G4endl;
207  } else {
208  cmap = XCreateColormap (dpy,
209  XRootWindow(dpy, vi -> screen),
210  vi -> visual,
211  AllocNone);
213  G4cout << "Created own cmap" << G4endl;
214  }
215 
216  if (!cmap) {
217  fViewId = -1; // This flags an error.
219  G4cout << "G4OpenGLXViewer::G4OpenGLXViewer failed to allocate a Colormap."
220  << G4endl;
221  return;
222  }
223 
224 }
225 
226 void G4OpenGLXViewer::CreateMainWindow () {
227 
228 // create a window
229  swa.colormap = cmap;
230  swa.border_pixel = 0;
231  swa.event_mask = ExposureMask | ButtonPressMask | StructureNotifyMask;
232  swa.backing_store = WhenMapped;
233 
234  // Window size and position...
235  size_hints = XAllocSizeHints();
236 
237  ResizeWindow(fVP.GetWindowSizeHintX(),fVP.GetWindowSizeHintY());
238 
239  G4int x_origin = fVP.GetWindowAbsoluteLocationHintX(DisplayWidth(dpy, vi -> screen));
240 
241  // FIXME, screen size != window size on MAC, but I don't know have to get the menuBar
242  // size on MAC. L.Garnier 01/2009
243  G4int y_origin = fVP.GetWindowAbsoluteLocationHintY(DisplayHeight(dpy, vi -> screen));
244 
245  size_hints->base_width = getWinWidth();
246  size_hints->base_height = getWinHeight();
247  size_hints->x = x_origin;
248  size_hints->y = y_origin;
249  if (fVP.IsWindowSizeHintX () && fVP.IsWindowLocationHintX () && fVP.IsWindowLocationHintY ()) {
250  size_hints->flags |= PSize | PPosition;
251  } else if (fVP.IsWindowSizeHintX () && !(fVP.IsWindowLocationHintX () || fVP.IsWindowLocationHintY ())) {
252  size_hints->flags |= PSize;
253  } else if ((!fVP.IsWindowSizeHintX ()) && fVP.IsWindowLocationHintX () && fVP.IsWindowLocationHintY ()) {
254  size_hints->flags |= PPosition;
255  }
257  G4cout << "Window name: " << fName << G4endl;
258  strncpy (charViewName, fName, 99); charViewName[99] = '\0';
259  char *window_name = charViewName;
260  char *icon_name = charViewName;
261  //char tmpatom[] = "XA_WM_NORMAL_HINTS";
262  wm_hints = XAllocWMHints();
263  class_hints = XAllocClassHint();
264 
265  XStringListToTextProperty (&window_name, 1, &windowName);
266  XStringListToTextProperty (&icon_name, 1, &iconName);
267 
268  wm_hints -> initial_state = NormalState;
269  wm_hints -> input = True;
270  wm_hints -> icon_pixmap = icon_pixmap;
271  wm_hints -> flags = StateHint | IconPixmapHint | InputHint;
272 
273  class_hints -> res_name = NewString("G4OpenGL");
274  class_hints -> res_class = NewString("G4OpenGL");
275 
276  win = XCreateWindow (dpy, XRootWindow (dpy, vi -> screen), x_origin,
277  y_origin, getWinWidth(), getWinHeight(), 0, vi -> depth,
278  InputOutput, vi -> visual,
279  CWBorderPixel | CWColormap |
280  CWEventMask | CWBackingStore,
281  &swa);
282 
283  XSetWMProperties (dpy, win, &windowName, &iconName, 0, 0,
284  size_hints, wm_hints, class_hints);
285 
286 // request X to Draw window on screen.
287  XMapWindow (dpy, win);
288 
289 // Wait for window to appear (wait for an "expose" event).
290  XIfEvent (dpy, &event, G4OpenGLXViewerWaitForNotify, (char*) win);
291 
292 // connect the context to a window
293  Bool success = glXMakeCurrent (dpy, win, cx);
294  if (!success) {
295  fViewId = -1; // This flags an error.
296  G4cerr << "G4OpenGLXViewer::G4OpenGLXViewer failed to attach a GLX context."
297  << G4endl;
298  GLint error = GL_NO_ERROR;
299  while ((error = glGetError()) != GL_NO_ERROR) {
300  G4cout << "GL Error: " << gluErrorString(error) << G4endl;
301  }
302  return;
303  }
304 
305 }
306 
307 void G4OpenGLXViewer::CreateFontLists()
308 {
309  std::map<G4double,G4String> fonts; // G4VMarker screen size and font name.
310  fonts[10.] = "-adobe-courier-bold-r-normal--10-100-75-75-m-60-iso8859-1";
311  fonts[11.] = "-adobe-courier-bold-r-normal--11-80-100-100-m-60-iso8859-1";
312  fonts[12.] = "-adobe-courier-bold-r-normal--12-120-75-75-m-70-iso8859-1";
313  fonts[13.] = "fixed";
314  fonts[14.] = "-adobe-courier-bold-r-normal--14-100-100-100-m-90-iso8859-1";
315  fonts[17.] = "-adobe-courier-bold-r-normal--17-120-100-100-m-100-iso8859-1";
316  fonts[18.] = "-adobe-courier-bold-r-normal--18-180-75-75-m-110-iso8859-1";
317  fonts[20.] = "-adobe-courier-bold-r-normal--20-140-100-100-m-110-iso8859-1";
318  fonts[24.] = "-adobe-courier-bold-r-normal--24-240-75-75-m-150-iso8859-1";
319  fonts[25.] = "-adobe-courier-bold-r-normal--25-180-100-100-m-150-iso8859-1";
320  fonts[34.] = "-adobe-courier-bold-r-normal--34-240-100-100-m-200-iso8859-1";
321  std::map<G4double,G4String>::const_iterator i;
322  for (i = fonts.begin(); i != fonts.end(); ++i) {
323  XFontStruct* font_info = XLoadQueryFont(dpy, i->second);
324  if (!font_info) {
325  G4cerr <<
326  "G4OpenGLXViewer::CreateFontLists XLoadQueryFont failed for font\n "
327  << i->second
328  << G4endl;
329  continue;
330  }
331  G4int font_base = glGenLists(256);
332  if (!font_base) {
333  G4cerr <<
334  "G4OpenGLXViewer::CreateFontLists out of display lists for fonts."
335  << G4endl;
336  continue;
337  }
338  G4int first = font_info->min_char_or_byte2;
339  G4int last = font_info->max_char_or_byte2;
340  glXUseXFont(font_info->fid, first, last-first+1, font_base + first);
341  G4int width = font_info->max_bounds.width;
343  (this, font_base, i->first, i->second, width);
344  }
345 }
346 
347 void G4OpenGLXViewer::DrawText(const G4Text& g4text)
348 {
349  if (isGl2psWriting()) {
350 
351  G4OpenGLViewer::DrawText(g4text);
352 
353  } else {
354 
356  G4double size = fSceneHandler.GetMarkerSize(g4text,sizeType);
357 
358  const G4OpenGLFontBaseStore::FontInfo& fontInfo =
359  G4OpenGLFontBaseStore::GetFontInfo(this,(int)size);
360  if (fontInfo.fFontBase < 0) {
361  static G4int callCount = 0;
362  ++callCount;
363  //if (callCount <= 10 || callCount%100 == 0) {
364  if (callCount <= 1) {
365  G4cout <<
366  "G4OpenGLXViewer::DrawText: No fonts available for \""
367  << fName <<
368  "\"\n Called with "
369  << g4text
370  << G4endl;
371  }
372  return;
373  }
374 
375  const G4Colour& c = fSceneHandler.GetTextColour(g4text);
376  glColor4d(c.GetRed(),c.GetGreen(),c.GetBlue(),c.GetAlpha());
377 
378  G4Point3D position = g4text.GetPosition();
379 
380  G4String textString = g4text.GetText();
381  const char* textCString = textString.c_str();
382 
383  // Set position for raster-style drawers (X, Xm)
384  glRasterPos3d(position.x(),position.y(),position.z());
385 
386  glPushAttrib(GL_LIST_BIT);
387 
388  // Calculate move for centre and right adjustment
389  G4double span = textString.size() * fontInfo.fWidth;
390  G4double xmove = 0., ymove = 0.;
391  switch (g4text.GetLayout()) {
392  case G4Text::left: break;
393  case G4Text::centre: xmove -= span / 2.; break;
394  case G4Text::right: xmove -= span;
395  }
396 
397  //Add offsets
398  xmove += g4text.GetXOffset();
399  ymove += g4text.GetYOffset();
400 
401  // Do move
402  glBitmap(0,0,0,0,xmove,ymove,0);
403 
404  // Write characters
405  glListBase(fontInfo.fFontBase);
406  glCallLists(strlen(textCString),GL_UNSIGNED_BYTE,(GLubyte*)textCString);
407  glPopAttrib();
408  }
409 }
410 
411 
412 G4OpenGLXViewer::G4OpenGLXViewer (G4OpenGLSceneHandler& scene):
413 G4VViewer (scene, -1),
414 G4OpenGLViewer (scene),
415 vi_immediate (0),
416 vi_stored (0),
417 vi (0),
418 cmap (0)
419 {
420  // To satisfy Coverity
421  xwa.visual = 0;
422  iconName.value = 0;
423  xwa.screen = 0;
424  windowName.value = 0;
425 
426  GetXConnection ();
427  if (fViewId < 0) return;
428 
429  // Try for a visual suitable for OpenGLImmediate..
430  // first try for a single buffered RGB window
431  if (!vi_single_buffer) {
432  vi_single_buffer =
433  glXChooseVisual (dpy, XDefaultScreen (dpy), snglBuf_RGBA);
434  }
435  if (!vi_double_buffer) {
436  vi_double_buffer =
437  glXChooseVisual (dpy, XDefaultScreen (dpy), dblBuf_RGBA);
438  }
439 
440  if (vi_single_buffer || vi_double_buffer) {
441  if (!vi_double_buffer) {
442  G4cout <<
443  "G4OpenGLXViewer::G4OpenGLXViewer: unable to get a double buffer visual."
444  "\n Working with a single buffer."
445  << G4endl;
446  }
447  } else {
448  if (!vi_single_buffer) {
449  G4cout <<
450  "G4OpenGLXViewer::G4OpenGLXViewer: unable to get a single buffer visual."
451  << G4endl;
452  }
453  if (!vi_double_buffer) {
454  G4cout <<
455  "G4OpenGLXViewer::G4OpenGLXViewer: unable to get a double buffer visual."
456  << G4endl;
457  }
458  }
459 
460  if (vi_single_buffer) {
461  vi_immediate = vi_single_buffer;
462  attributeList = snglBuf_RGBA;
463  }
464 
465  if (!vi_immediate){
466  // next try for a double buffered RGB, but Draw to top buffer
467  if (vi_double_buffer) {
468  vi_immediate = vi_double_buffer;
469  attributeList = dblBuf_RGBA;
470  }
471  }
472 
473  // Now try for a visual suitable for OpenGLStored...
474  // Try for a double buffered RGB window
475  if (vi_double_buffer) {
476  vi_stored = vi_double_buffer;
477  attributeList = dblBuf_RGBA;
478  }
479 
480  if (!vi_immediate || !vi_stored) {
481  G4cout <<
482  "G4OpenGLXViewer::G4OpenGLXViewer: unable to get required visuals."
483  << G4endl;
484  fViewId = -1; // This flags an error.
485  }
486 
487  // glClearColor (0., 0., 0., 0.);
488  // glClearDepth (1.);
489 }
490 
491 G4OpenGLXViewer::~G4OpenGLXViewer () {
492  if (fViewId >= 0) {
493  //Close a window from here
494  glXMakeCurrent (dpy, None, NULL);
495  glXDestroyContext (dpy, cx);
496  if (win) XDestroyWindow (dpy, win); // ...if already deleted in
497  // sub-class G4OpenGLXmViewer.
498  XFlush (dpy);
499  }
500 }
501 
502 
503 #endif
Definition: G4Text.hh:73
G4double GetAlpha() const
Definition: G4Colour.hh:142
G4String fName
Definition: G4AttUtils.hh:55
#define width
G4double GetBlue() const
Definition: G4Colour.hh:141
G4Point3D GetPosition() const
int G4int
Definition: G4Types.hh:78
#define NewString(str)
G4double GetYOffset() const
G4GLOB_DLL std::ostream G4cout
G4double GetRed() const
Definition: G4Colour.hh:139
static const FontInfo & GetFontInfo(G4VViewer *, G4double size)
Layout GetLayout() const
G4double GetGreen() const
Definition: G4Colour.hh:140
static void AddFontBase(G4VViewer *, G4int fontBase, G4double size, const G4String &fontName, G4int width)
tuple v
Definition: test.py:18
int status
Definition: tracer.cxx:24
G4double GetXOffset() const
G4String GetText() const
G4int first
static Verbosity GetVerbosity()
#define G4endl
Definition: G4ios.hh:61
double G4double
Definition: G4Types.hh:76
tuple c
Definition: test.py:13
G4GLOB_DLL std::ostream G4cerr