G4OpenGLXViewer.cc

Go to the documentation of this file.
00001 //
00002 // ********************************************************************
00003 // * License and Disclaimer                                           *
00004 // *                                                                  *
00005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
00006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
00007 // * conditions of the Geant4 Software License,  included in the file *
00008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
00009 // * include a list of copyright holders.                             *
00010 // *                                                                  *
00011 // * Neither the authors of this software system, nor their employing *
00012 // * institutes,nor the agencies providing financial support for this *
00013 // * work  make  any representation or  warranty, express or implied, *
00014 // * regarding  this  software system or assume any liability for its *
00015 // * use.  Please see the license in the file  LICENSE  and URL above *
00016 // * for the full disclaimer and the limitation of liability.         *
00017 // *                                                                  *
00018 // * This  code  implementation is the result of  the  scientific and *
00019 // * technical work of the GEANT4 collaboration.                      *
00020 // * By using,  copying,  modifying or  distributing the software (or *
00021 // * any work based  on the software)  you  agree  to acknowledge its *
00022 // * use  in  resulting  scientific  publications,  and indicate your *
00023 // * acceptance of all terms of the Geant4 Software license.          *
00024 // ********************************************************************
00025 //
00026 //
00027 // $Id$
00028 //
00029 // 
00030 // Andrew Walkden  7th February 1997
00031 // G4OpenGLXViewer : Class to provide XWindows specific
00032 //                 functionality for OpenGL in GEANT4
00033 
00034 #ifdef G4VIS_BUILD_OPENGLX_DRIVER
00035 
00036 #include "G4OpenGLXViewer.hh"
00037 #include "G4VViewer.hh"
00038 #include "G4OpenGLSceneHandler.hh"
00039 
00040 #include "G4OpenGLFontBaseStore.hh"
00041 
00042 #include <sstream>
00043 
00044 #include "G4VisExtent.hh"
00045 #include "G4LogicalVolume.hh"
00046 #include "G4VSolid.hh"
00047 #include "G4Point3D.hh"
00048 #include "G4Normal3D.hh"
00049 #include "G4StateManager.hh"
00050 #include "G4VisManager.hh"
00051 #include "G4Text.hh"
00052 
00053 #include <X11/Xatom.h>
00054 #include <X11/Xutil.h>
00055 #include <X11/Xmu/StdCmap.h>
00056 
00057 #include <assert.h>
00058 
00059 int G4OpenGLXViewer::snglBuf_RGBA[12] =
00060 { GLX_RGBA,
00061   GLX_RED_SIZE, 1,
00062   GLX_GREEN_SIZE, 1, 
00063   GLX_BLUE_SIZE, 1,
00064   GLX_DEPTH_SIZE, 1,
00065   GLX_STENCIL_SIZE, 1,
00066   None };
00067 
00068 int G4OpenGLXViewer::dblBuf_RGBA[13] =
00069 { GLX_RGBA,
00070   GLX_RED_SIZE, 1,
00071   GLX_GREEN_SIZE, 1,
00072   GLX_BLUE_SIZE, 1,
00073   GLX_DOUBLEBUFFER,
00074   GLX_DEPTH_SIZE, 1,
00075   GLX_STENCIL_SIZE, 1,
00076   None };
00077 
00078 #define NewString(str) \
00079   ((str) != 0 ? (strncpy((char*)malloc((unsigned)strlen(str) + 1), str, (unsigned)strlen(str) + 1)) : (char*)0)
00080 
00081 #define USE_DEFAULT_COLORMAP 1
00082 #define USE_STANDARD_COLORMAP 0
00083 
00084 XVisualInfo*  G4OpenGLXViewer::vi_single_buffer = 0;
00085 XVisualInfo*  G4OpenGLXViewer::vi_double_buffer = 0;
00086 
00087 extern "C" {
00088   static Bool G4OpenGLXViewerWaitForNotify (Display*, XEvent* e, char* arg) {
00089     return (e->type == MapNotify) && (e->xmap.window == (Window) arg);
00090   }
00091 }
00092 
00093 void G4OpenGLXViewer::SetView () {
00094   Bool success = glXMakeCurrent (dpy, win, cx);
00095   if (!success) {
00096     fViewId = -1;  // This flags an error.
00097     G4cerr << "G4OpenGLXViewer::G4OpenGLXViewer failed to attach a GLX context."
00098            << G4endl;
00099     GLint error = GL_NO_ERROR;
00100     while ((error = glGetError()) != GL_NO_ERROR) {
00101       G4cout << "GL Error: " << gluErrorString(error) << G4endl;
00102     }
00103     return;
00104   }
00105   G4OpenGLViewer::SetView ();  
00106 }
00107 
00108 void G4OpenGLXViewer::ShowView () {
00109   glXWaitGL (); //Wait for effects of all previous OpenGL commands to
00110                 //be propagated before progressing.
00111   glFlush ();
00112 
00113   if (fVP.IsPicking()) {
00114     G4cout <<
00115       "Window activated for picking (left-mouse), exit (middle-mouse)."
00116            << G4endl;
00117     while (true) {
00118       if (XPending(dpy)) {
00119         XNextEvent(dpy, &event);
00120         if (event.type == ButtonPress && event.xbutton.button == 1) {
00121           Pick(event.xbutton.x, event.xbutton.y);
00122         }
00123         else if (event.type == ButtonPress && event.xbutton.button == 2) break;
00124       }
00125     }
00126   }
00127 }
00128 
00129 void G4OpenGLXViewer::GetXConnection () {
00130 // get a connection.
00131   dpy = XOpenDisplay (0);
00132   if (!dpy) {
00133     fViewId = -1;  // This flags an error.
00134     G4cerr << "G4OpenGLXViewer::G4OpenGLXViewer couldn't open display." << G4endl;
00135     return;
00136   }
00137 
00138 // make sure OpenGL is supported and installed properly.
00139   if (!glXQueryExtension (dpy, &errorBase, &eventBase)) {
00140     fViewId = -1;  // This flags an error.
00141     G4cerr << "G4OpenGLXViewer::G4OpenGLXViewer X Server has no GLX extension." 
00142          << G4endl;
00143     return;
00144   }
00145 
00146 }
00147 
00148 void G4OpenGLXViewer::CreateGLXContext (XVisualInfo* v) {
00149 
00150   vi = v;
00151 // get window's attributes
00152   if (!XGetWindowAttributes(dpy, XRootWindow (dpy, vi -> screen), &xwa)) {
00153     fViewId = -1;  // This flags an error.
00154     G4cerr << "G4OpenGLXViewer::G4OpenGLXViewer couldn't return window attributes"
00155          << G4endl;
00156     return;
00157   }
00158   
00159 // create a GLX context
00160   cx = glXCreateContext (dpy, vi, 0, true);
00161   if (!cx) {
00162     fViewId = -1;  // This flags an error.
00163     G4cerr << "G4OpenGLXViewer::G4OpenGLXViewer couldn't create context."
00164          << G4endl;
00165     return;
00166   }
00167 
00168 // New stab at getting a colormap
00169 
00170   Status status;
00171   XStandardColormap *standardCmaps = XAllocStandardColormap ();
00172   int i, numCmaps;
00173 
00174   status = XmuLookupStandardColormap (dpy, 
00175                                       vi -> screen, 
00176                                       vi -> visualid, 
00177                                       vi -> depth, 
00178                                       XA_RGB_DEFAULT_MAP, 
00179                                       False, 
00180                                       True);
00181   
00182   if (status == 1) {
00183     cmap = 0;
00184     status = XGetRGBColormaps (dpy, 
00185                                XRootWindow (dpy, vi -> screen), 
00186                                &standardCmaps, 
00187                                &numCmaps, 
00188                                XA_RGB_DEFAULT_MAP);
00189     if (status == 1)
00190       for (i = 0; i < numCmaps; i++) {
00191         if (standardCmaps[i].visualid == vi -> visualid) {
00192           cmap = standardCmaps[i].colormap;
00193           XFree (standardCmaps);
00194           break;
00195         }
00196       }
00197     if (!cmap) {
00198       fViewId = -1;  // This flags an error.
00199       if (G4VisManager::GetVerbosity() >= G4VisManager::errors)
00200         G4cerr <<
00201   "G4OpenGLXViewer::G4OpenGLXViewer failed to allocate a standard colormap."
00202                << G4endl;
00203       return;
00204     }
00205     if (G4VisManager::GetVerbosity() >= G4VisManager::confirmations)
00206       G4cout << "Got standard cmap" << G4endl;
00207   } else {
00208     cmap = XCreateColormap (dpy, 
00209                             XRootWindow(dpy, vi -> screen), 
00210                             vi -> visual, 
00211                             AllocNone);
00212     if (G4VisManager::GetVerbosity() >= G4VisManager::confirmations)
00213       G4cout << "Created own cmap" << G4endl;
00214   }
00215 
00216   if (!cmap) {
00217     fViewId = -1;  // This flags an error.
00218     if (G4VisManager::GetVerbosity() >= G4VisManager::errors)
00219       G4cout << "G4OpenGLXViewer::G4OpenGLXViewer failed to allocate a Colormap."
00220              << G4endl;
00221     return;
00222   }
00223 
00224 }
00225   
00226 void G4OpenGLXViewer::CreateMainWindow () {
00227   
00228 // create a window
00229   swa.colormap = cmap;
00230   swa.border_pixel = 0;
00231   swa.event_mask = ExposureMask | ButtonPressMask | StructureNotifyMask;
00232   swa.backing_store = WhenMapped;
00233 
00234   // Window size and position...
00235   size_hints = XAllocSizeHints();
00236     
00237   ResizeWindow(fVP.GetWindowSizeHintX(),fVP.GetWindowSizeHintY());
00238 
00239   G4int x_origin = fVP.GetWindowAbsoluteLocationHintX(DisplayWidth(dpy, vi -> screen));
00240 
00241   // FIXME,  screen size != window size on MAC, but I don't know have to get the menuBar
00242   // size on MAC. L.Garnier 01/2009
00243   G4int y_origin = fVP.GetWindowAbsoluteLocationHintY(DisplayHeight(dpy, vi -> screen));
00244 
00245   size_hints->base_width = getWinWidth();
00246   size_hints->base_height = getWinHeight();
00247   size_hints->x = x_origin;
00248   size_hints->y = y_origin;
00249   if (fVP.IsWindowSizeHintX () && fVP.IsWindowLocationHintX () && fVP.IsWindowLocationHintY ()) {
00250     size_hints->flags |= PSize | PPosition;
00251   } else if (fVP.IsWindowSizeHintX () && !(fVP.IsWindowLocationHintX () || fVP.IsWindowLocationHintY ())) {
00252     size_hints->flags |= PSize;
00253   } else if ((!fVP.IsWindowSizeHintX ()) && fVP.IsWindowLocationHintX () && fVP.IsWindowLocationHintY ()) {
00254     size_hints->flags |= PPosition;
00255   }
00256   if (G4VisManager::GetVerbosity() >= G4VisManager::confirmations)
00257     G4cout << "Window name: " << fName << G4endl;
00258   strncpy (charViewName, fName, 99); charViewName[99] = '\0';
00259   char *window_name = charViewName;
00260   char *icon_name = charViewName;
00261   //char tmpatom[] = "XA_WM_NORMAL_HINTS"; 
00262   wm_hints = XAllocWMHints();
00263   class_hints = XAllocClassHint();
00264 
00265   XStringListToTextProperty (&window_name, 1, &windowName);
00266   XStringListToTextProperty (&icon_name, 1, &iconName);
00267 
00268   wm_hints -> initial_state = NormalState;
00269   wm_hints -> input = True;
00270   wm_hints -> icon_pixmap = icon_pixmap;
00271   wm_hints -> flags = StateHint | IconPixmapHint | InputHint;
00272 
00273   class_hints -> res_name  = NewString("G4OpenGL");
00274   class_hints -> res_class = NewString("G4OpenGL");
00275 
00276    win = XCreateWindow (dpy, XRootWindow (dpy, vi -> screen), x_origin, 
00277                         y_origin, getWinWidth(), getWinHeight(), 0, vi -> depth,
00278                         InputOutput, vi -> visual,  
00279                         CWBorderPixel | CWColormap | 
00280                         CWEventMask | CWBackingStore,
00281                         &swa);
00282   
00283    XSetWMProperties (dpy, win, &windowName, &iconName, 0, 0, 
00284                      size_hints, wm_hints, class_hints);
00285   
00286 // request X to Draw window on screen.
00287   XMapWindow (dpy, win);
00288 
00289 // Wait for window to appear (wait for an "expose" event).
00290   XIfEvent (dpy, &event, G4OpenGLXViewerWaitForNotify, (char*) win);
00291 
00292 // connect the context to a window
00293   Bool success = glXMakeCurrent (dpy, win, cx);
00294   if (!success) {
00295     fViewId = -1;  // This flags an error.
00296     G4cerr << "G4OpenGLXViewer::G4OpenGLXViewer failed to attach a GLX context."
00297          << G4endl;
00298     GLint error = GL_NO_ERROR;
00299     while ((error = glGetError()) != GL_NO_ERROR) {
00300       G4cout << "GL Error: " << gluErrorString(error) << G4endl;
00301     }
00302     return;
00303   }
00304 
00305 }
00306 
00307 void G4OpenGLXViewer::CreateFontLists()
00308 {
00309   std::map<G4double,G4String> fonts;  // G4VMarker screen size and font name.
00310   fonts[10.] = "-adobe-courier-bold-r-normal--10-100-75-75-m-60-iso8859-1";
00311   fonts[11.] = "-adobe-courier-bold-r-normal--11-80-100-100-m-60-iso8859-1";
00312   fonts[12.] = "-adobe-courier-bold-r-normal--12-120-75-75-m-70-iso8859-1";
00313   fonts[13.] = "fixed";
00314   fonts[14.] = "-adobe-courier-bold-r-normal--14-100-100-100-m-90-iso8859-1";
00315   fonts[17.] = "-adobe-courier-bold-r-normal--17-120-100-100-m-100-iso8859-1";
00316   fonts[18.] = "-adobe-courier-bold-r-normal--18-180-75-75-m-110-iso8859-1";
00317   fonts[20.] = "-adobe-courier-bold-r-normal--20-140-100-100-m-110-iso8859-1";
00318   fonts[24.] = "-adobe-courier-bold-r-normal--24-240-75-75-m-150-iso8859-1";
00319   fonts[25.] = "-adobe-courier-bold-r-normal--25-180-100-100-m-150-iso8859-1";
00320   fonts[34.] = "-adobe-courier-bold-r-normal--34-240-100-100-m-200-iso8859-1";
00321   std::map<G4double,G4String>::const_iterator i;
00322   for (i = fonts.begin(); i != fonts.end(); ++i) {
00323     XFontStruct* font_info = XLoadQueryFont(dpy, i->second);
00324     if (!font_info) {
00325       G4cerr <<
00326         "G4OpenGLXViewer::CreateFontLists XLoadQueryFont failed for font\n  "
00327              << i->second
00328              << G4endl;
00329       continue;
00330     }
00331     G4int font_base = glGenLists(256);
00332     if (!font_base) {
00333       G4cerr <<
00334         "G4OpenGLXViewer::CreateFontLists out of display lists for fonts." 
00335              << G4endl;
00336       continue;
00337     }
00338     G4int first = font_info->min_char_or_byte2;
00339     G4int last  = font_info->max_char_or_byte2;
00340     glXUseXFont(font_info->fid, first, last-first+1, font_base + first);
00341     G4int width = font_info->max_bounds.width;
00342     G4OpenGLFontBaseStore::AddFontBase
00343       (this, font_base, i->first, i->second, width);
00344   }
00345 }
00346 
00347 void G4OpenGLXViewer::DrawText(const G4Text& g4text)
00348 {
00349   if (isGl2psWriting()) {
00350 
00351     G4OpenGLViewer::DrawText(g4text);
00352 
00353   } else {
00354 
00355     G4VSceneHandler::MarkerSizeType sizeType;
00356     G4double size = fSceneHandler.GetMarkerSize(g4text,sizeType);
00357 
00358     const G4OpenGLFontBaseStore::FontInfo& fontInfo =
00359       G4OpenGLFontBaseStore::GetFontInfo(this,(int)size);
00360     if (fontInfo.fFontBase < 0) {
00361       static G4int callCount = 0;
00362       ++callCount;
00363       //if (callCount <= 10 || callCount%100 == 0) {
00364       if (callCount <= 1) {
00365         G4cout <<
00366           "G4OpenGLXViewer::DrawText: No fonts available for \""
00367                << fName <<
00368           "\"\n  Called with "
00369                << g4text
00370                << G4endl;
00371       }
00372       return;
00373     }
00374 
00375     const G4Colour& c = fSceneHandler.GetTextColour(g4text);
00376     glColor4d(c.GetRed(),c.GetGreen(),c.GetBlue(),c.GetAlpha());
00377 
00378     G4Point3D position = g4text.GetPosition();
00379 
00380     G4String textString = g4text.GetText();
00381     const char* textCString = textString.c_str();
00382   
00383     // Set position for raster-style drawers (X, Xm)
00384     glRasterPos3d(position.x(),position.y(),position.z());
00385 
00386     glPushAttrib(GL_LIST_BIT);
00387 
00388     // Calculate move for centre and right adjustment
00389     G4double span = textString.size() * fontInfo.fWidth;
00390     G4double xmove = 0., ymove = 0.;
00391     switch (g4text.GetLayout()) {
00392     case G4Text::left: break;
00393     case G4Text::centre: xmove -= span / 2.; break;
00394     case G4Text::right: xmove -= span;
00395     }
00396 
00397     //Add offsets
00398     xmove += g4text.GetXOffset();
00399     ymove += g4text.GetYOffset();
00400 
00401     // Do move
00402     glBitmap(0,0,0,0,xmove,ymove,0);
00403 
00404     // Write characters
00405     glListBase(fontInfo.fFontBase);
00406     glCallLists(strlen(textCString),GL_UNSIGNED_BYTE,(GLubyte*)textCString);
00407     glPopAttrib();
00408   }
00409 }
00410 
00411 
00412 G4OpenGLXViewer::G4OpenGLXViewer (G4OpenGLSceneHandler& scene):
00413 G4VViewer (scene, -1),
00414 G4OpenGLViewer (scene),
00415 vi_immediate (0),
00416 vi_stored (0),
00417 vi (0),
00418 cmap (0)
00419 {
00420   // To satisfy Coverity
00421   xwa.visual = 0;
00422   iconName.value = 0;
00423   xwa.screen = 0;
00424   windowName.value = 0;
00425 
00426   GetXConnection ();
00427   if (fViewId < 0) return;
00428   
00429   // Try for a visual suitable for OpenGLImmediate..
00430   // first try for a single buffered RGB window
00431   if (!vi_single_buffer) {
00432     vi_single_buffer =
00433       glXChooseVisual (dpy, XDefaultScreen (dpy), snglBuf_RGBA);
00434   }
00435   if (!vi_double_buffer) {
00436     vi_double_buffer =
00437       glXChooseVisual (dpy, XDefaultScreen (dpy), dblBuf_RGBA);
00438   }
00439 
00440   if (vi_single_buffer || vi_double_buffer) {
00441     if (!vi_double_buffer) {
00442       G4cout <<
00443         "G4OpenGLXViewer::G4OpenGLXViewer: unable to get a double buffer visual."
00444         "\n  Working with a single buffer."
00445              << G4endl;
00446     }
00447   } else {
00448     if (!vi_single_buffer) {
00449       G4cout <<
00450         "G4OpenGLXViewer::G4OpenGLXViewer: unable to get a single buffer visual."
00451              << G4endl;
00452     }
00453     if (!vi_double_buffer) {
00454       G4cout <<
00455         "G4OpenGLXViewer::G4OpenGLXViewer: unable to get a double buffer visual."
00456              << G4endl;
00457     }
00458   }
00459 
00460   if (vi_single_buffer) {
00461     vi_immediate = vi_single_buffer;
00462     attributeList = snglBuf_RGBA;
00463   }
00464   
00465   if (!vi_immediate){
00466     // next try for a double buffered RGB, but Draw to top buffer
00467     if (vi_double_buffer) {
00468       vi_immediate = vi_double_buffer;
00469       attributeList = dblBuf_RGBA;
00470     }
00471   }
00472 
00473   // Now try for a visual suitable for OpenGLStored...
00474   // Try for a double buffered RGB window
00475   if (vi_double_buffer) {
00476     vi_stored = vi_double_buffer;
00477     attributeList = dblBuf_RGBA;
00478   }
00479 
00480   if (!vi_immediate || !vi_stored) {
00481     G4cout <<
00482     "G4OpenGLXViewer::G4OpenGLXViewer: unable to get required visuals."
00483            << G4endl;
00484     fViewId = -1;  // This flags an error.
00485   }
00486 
00487   //  glClearColor (0., 0., 0., 0.);
00488   //  glClearDepth (1.);
00489 }
00490 
00491 G4OpenGLXViewer::~G4OpenGLXViewer () {
00492   if (fViewId >= 0) {
00493     //Close a window from here
00494     glXMakeCurrent (dpy, None, NULL);
00495     glXDestroyContext (dpy, cx);
00496     if (win) XDestroyWindow (dpy, win); // ...if already deleted in
00497     // sub-class G4OpenGLXmViewer.
00498     XFlush (dpy);
00499   }
00500 }
00501         
00502 
00503 #endif

Generated on Mon May 27 17:49:12 2013 for Geant4 by  doxygen 1.4.7