Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
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$
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"
39
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
59int 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
68int 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
84XVisualInfo* G4OpenGLXViewer::vi_single_buffer = 0;
85XVisualInfo* G4OpenGLXViewer::vi_double_buffer = 0;
86
87extern "C" {
88 static Bool G4OpenGLXViewerWaitForNotify (Display*, XEvent* e, char* arg) {
89 return (e->type == MapNotify) && (e->xmap.window == (Window) arg);
90 }
91}
92
93void 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
108void 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
129void 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
148void 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
226void 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
307void 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
347void 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 =
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
412G4OpenGLXViewer::G4OpenGLXViewer (G4OpenGLSceneHandler& scene):
413G4VViewer (scene, -1),
414G4OpenGLViewer (scene),
415vi_immediate (0),
416vi_stored (0),
417vi (0),
418cmap (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
491G4OpenGLXViewer::~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
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
#define NewString(str)
#define G4endl
Definition: G4ios.hh:52
G4DLLIMPORT std::ostream G4cerr
G4DLLIMPORT std::ostream G4cout
G4double GetBlue() const
Definition: G4Colour.hh:140
G4double GetAlpha() const
Definition: G4Colour.hh:141
G4double GetRed() const
Definition: G4Colour.hh:138
G4double GetGreen() const
Definition: G4Colour.hh:139
static void AddFontBase(G4VViewer *, G4int fontBase, G4double size, const G4String &fontName, G4int width)
static const FontInfo & GetFontInfo(G4VViewer *, G4double size)
Definition: G4Text.hh:73
Layout GetLayout() const
G4double GetYOffset() const
G4double GetXOffset() const
G4String GetText() const
@ centre
Definition: G4Text.hh:77
@ right
Definition: G4Text.hh:77
@ left
Definition: G4Text.hh:77
G4Point3D GetPosition() const
static Verbosity GetVerbosity()