Geant4 Cross Reference |
1 // Copyright (C) 2010, Guy Barrand. All rights 2 // See the file tools.license for terms. 3 4 #ifndef toolx_Xt_OpenGLArea 5 #define toolx_Xt_OpenGLArea 6 7 #include <X11/IntrinsicP.h> 8 #include <X11/CoreP.h> 9 #include <X11/CompositeP.h> 10 #include <X11/StringDefs.h> 11 12 #include <GL/glx.h> 13 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <stdarg.h> 17 18 namespace toolx { 19 namespace Xt { 20 21 ////////////////////////////////////////////// 22 ////////////////////////////////////////////// 23 ////////////////////////////////////////////// 24 25 typedef struct _OpenGLAreaClassRec* OpenGLArea 26 typedef struct _OpenGLAreaRec* OpenGLAreaWidge 27 28 typedef struct { 29 int reason; 30 XEvent* event; 31 } XoAnyCallbackStruct; 32 33 #define XoCR_PAINT 1 34 #define XoCR_EVENT 2 35 36 #define XoNdoubleBufferOn toolx::Xt::OpenGLAre 37 #define XoNpaintCallback toolx::Xt::OpenGLAre 38 #define XoNeventCallback toolx::Xt::OpenGLAre 39 40 ////////////////////////////////////////////// 41 ////////////////////////////////////////////// 42 ////////////////////////////////////////////// 43 44 typedef struct { 45 void* extension; 46 } OpenGLAreaClassPart; 47 48 typedef struct _OpenGLAreaClassRec { 49 CoreClassPart core_class; 50 CompositeClassPart composite_class; 51 OpenGLAreaClassPart openGLArea_class; 52 } OpenGLAreaClassRec; 53 54 typedef struct { 55 Boolean doubleBufferOn; 56 XtCallbackList paintCallback; 57 XtCallbackList eventCallback; 58 Visual* visual; 59 Boolean installColormap; 60 GLXContext glContext; 61 } OpenGLAreaPart; 62 63 typedef struct _OpenGLAreaRec { 64 CorePart core; 65 CompositePart composite; 66 OpenGLAreaPart openGLArea; 67 } OpenGLAreaRec; 68 69 ////////////////////////////////////////////// 70 ////////////////////////////////////////////// 71 ////////////////////////////////////////////// 72 73 class OpenGLArea { 74 protected: 75 static const char* class_name() {sta 76 static const char* XoC_DoubleBufferOn() {sta 77 public: 78 static const char* XoN_doubleBufferOn() {sta 79 static const char* XoN_paintCallback() {sta 80 static const char* XoN_eventCallback() {sta 81 public: 82 static void paint(Widget a_this) { 83 if(!XtIsRealized(a_this)) return; 84 if(make_current(a_this)==1) { 85 XoAnyCallbackStruct value; 86 value.reason = XoCR_PAINT; 87 value.event = 0; 88 ::XtCallCallbacks(a_this,XoNpaintCallbac 89 ::glXSwapBuffers(XtDisplay(a_this),XtWin 90 ::glXMakeCurrent(XtDisplay(a_this),None, 91 } 92 } 93 protected: 94 static void initialize_class(void) {} 95 96 static void initialize_widget(Widget a_reque 97 if(a_request->core.width<=0) a_this->core 98 if(a_request->core.height<=0) a_this->core 99 100 #ifdef TOOLX_XT_OPENGLAREA_DEBUG 101 ::printf ("debug : OpenGLArea : Initialize 102 #endif 103 104 OpenGLAreaPart& athis = _athis(a_this); 105 athis.visual = CopyFromParent; 106 athis.installColormap = False; 107 athis.glContext = NULL; 108 109 Display* display; 110 Screen* screen; 111 int iscreen; 112 XVisualInfo* vinfo; 113 display = XtDisplay(a_this); 114 screen = XtScreen(a_this); 115 iscreen = XScreenNumberOfScreen(screen); 116 117 {int error,event; 118 if(::glXQueryExtension(display,&error,&eve 119 CWarn ("X server does not have OpenGL ex 120 }} 121 122 if(athis.doubleBufferOn==True) { 123 int atbs_1[] = { 124 GLX_RGBA, 125 GLX_RED_SIZE, 1, 126 GLX_GREEN_SIZE, 1, 127 GLX_BLUE_SIZE, 1, 128 GLX_ALPHA_SIZE, 1, 129 GLX_DEPTH_SIZE, 1, 130 GLX_DOUBLEBUFFER, 131 None 132 }; 133 vinfo = ::glXChooseVisual (display,iscr 134 if(vinfo==NULL) { //GLX_ALPHA_SIZE : pro 135 int atbs_2[] = { 136 GLX_RGBA, 137 GLX_RED_SIZE, 1, 138 GLX_GREEN_SIZE, 1, 139 GLX_BLUE_SIZE, 1, 140 GLX_DEPTH_SIZE, 1, 141 GLX_DOUBLEBUFFER, 142 None 143 }; 144 vinfo = ::glXChooseVisual (display,is 145 } 146 } else { 147 int atbs_1[] = { 148 GLX_RGBA, 149 GLX_RED_SIZE, 1, 150 GLX_GREEN_SIZE, 1, 151 GLX_BLUE_SIZE, 1, 152 GLX_ALPHA_SIZE, 1, 153 GLX_DEPTH_SIZE, 1, 154 None 155 }; 156 vinfo = ::glXChooseVisual (display,iscr 157 if(vinfo==NULL) { //GLX_ALPHA_SIZE : pro 158 int atbs_2[] = { 159 GLX_RGBA, 160 GLX_RED_SIZE, 1, 161 GLX_GREEN_SIZE, 1, 162 GLX_BLUE_SIZE, 1, 163 GLX_DEPTH_SIZE, 1, 164 None 165 }; 166 vinfo = ::glXChooseVisual (display,is 167 } 168 } 169 170 if(vinfo==NULL) { 171 CWarn ("Can't choose a visual.\n"); 172 } else { 173 a_this->core.depth = vinfo->depth; 174 athis.visual = vinfo->visual; 175 if( (vinfo->depth ==DefaultDepth (displa 176 (vinfo->visual==DefaultVisual(displa 177 a_this->core.colormap = XDefaultColorm 178 athis.installColormap = False; 179 } else { 180 a_this->core.colormap = 181 XCreateColormap (display,XRootWindow(displ 182 athis.installColormap = True; 183 } 184 if(a_this->core.colormap==0L) { 185 CWarn ("Can't get/create a X colormap. 186 } 187 athis.glContext = ::glXCreateContext (di 188 if(athis.glContext==NULL) { 189 athis.glContext = ::glXCreateContext ( 190 if(athis.glContext==NULL) { 191 CWarn ("Can't create a GLX context.\ 192 } 193 } 194 ::XFree(vinfo); 195 } 196 197 ::XtAddEventHandler 198 (a_this,ButtonPressMask|ButtonReleaseMa 199 200 #ifdef TOOLX_XT_OPENGLAREA_DEBUG 201 printf("debug : OpenGLArea : InitializeWid 202 #endif 203 } 204 205 static void realize_widget(Widget a_this,XtV 206 #ifdef TOOLX_XT_OPENGLAREA_DEBUG 207 printf("debug : OpenGLArea : realize_widge 208 #endif 209 210 // Have to create window ourselves due to 211 // In principle colormap is correctly set 212 213 OpenGLAreaPart& athis = _athis(a_this); 214 215 ::XtCreateWindow(a_this,(unsigned int)Inpu 216 217 // Call the Realize procedure (XtInheritRe 218 if(widget_class()->core_class.superclass-> 219 (widget_class()->core_class.superclass-> 220 221 // If window is delete, all seems ok : 222 if(athis.installColormap==True) install_co 223 224 //make_current(a_this); 225 226 #ifdef TOOLX_XT_OPENGLAREA_DEBUG 227 printf("debug : OpenGLArea : realize_widge 228 #endif 229 } 230 231 static void destroy_widget(Widget a_this) { 232 #ifdef TOOLX_XT_OPENGLAREA_DEBUG 233 printf("debug : OpenGLArea : destroy_widge 234 #endif 235 OpenGLAreaPart& athis = _athis(a_this); 236 if(athis.installColormap==True) { 237 uninstall_colormap (a_this); 238 athis.installColormap = False; 239 ::XFreeColormap(XtDisplay(a_this),a_this 240 } 241 if(athis.glContext!=NULL) { 242 ::glXMakeCurrent(XtDisplay(a_this),None, 243 ::glXDestroyContext(XtDisplay(a_this),at 244 athis.glContext = NULL; 245 } 246 #ifdef TOOLX_XT_OPENGLAREA_DEBUG 247 printf("debug : OpenGLArea : destroy_widge 248 #endif 249 } 250 251 static Boolean set_values(Widget a_current,W 252 OpenGLAreaPart& athis = _athis(a_this); 253 if(athis.doubleBufferOn != ((OpenGLAreaWid 254 // Can't change buffering here if X wind 255 // With OpenGL, buffering fix parameter 256 // Buffering must be choosen before the 257 // Realize method that create the window 258 if(XtIsRealized(a_this) && (athis.instal 259 CWarn("Can't change buffering after \" 260 athis.doubleBufferOn = ((OpenGLAreaWid 261 } 262 } 263 return False; 264 } 265 266 static void change_widget_size(Widget a_this 267 #ifdef TOOLX_XT_OPENGLAREA_DEBUG 268 printf("debug : OpenGLArea : change_widget 269 #endif 270 271 // Call the Resize procedure (XtInheritRes 272 if(widget_class()->core_class.superclass-> 273 (widget_class()->core_class.superclass-> 274 275 #ifdef TOOLX_XT_OPENGLAREA_DEBUG 276 printf("debug : OpenGLArea : change_widget 277 #endif 278 } 279 280 static void draw_widget(Widget a_this,XEven 281 #ifdef TOOLX_XT_OPENGLAREA_DEBUG 282 printf("debug : OpenGLArea : draw_widget : 283 #endif 284 285 if(widget_class()->core_class.superclass-> 286 (widget_class()->core_class.superclass-> 287 288 if(make_current(a_this)==1) { 289 #ifdef TOOLX_XT_OPENGLAREA_DEBUG 290 printf("debug : OpenGLArea : draw_widget 291 #endif 292 XoAnyCallbackStruct value; 293 value.reason = XoCR_PAINT; 294 value.event = a_event; 295 ::XtCallCallbacks(a_this,XoNpaintCallbac 296 ::glXSwapBuffers(XtDisplay(a_this),XtWin 297 ::glXMakeCurrent(XtDisplay(a_this),None, 298 } 299 300 #ifdef TOOLX_XT_OPENGLAREA_DEBUG 301 printf("debug : OpenGLArea : draw_widget : e 302 #endif 303 } 304 305 protected: 306 static OpenGLAreaPart& _athis(Widget a_this) 307 static void CWarn(const char* a_msg) { 308 ::printf("%s",a_msg); 309 } 310 static void CWarnF(const char* a_format,...) 311 va_list args; 312 va_start(args,a_format); 313 ::vprintf(a_format,args); 314 va_end(args); 315 } 316 static int make_current(Widget a_this) { 317 if(!XtIsRealized(a_this)) return 0; 318 OpenGLAreaPart& athis = _athis(a_this); 319 if(athis.glContext==NULL) return 0; 320 return (int)::glXMakeCurrent(XtDisplay(a_t 321 } 322 323 static void event_handler(Widget a_this,XtPo 324 XoAnyCallbackStruct value; 325 value.reason = XoCR_EVENT; 326 value.event = a_event; 327 ::XtCallCallbacks(a_this,XoNeventCallback, 328 } 329 330 static void install_colormap(Widget a_this) 331 // From Mesa/widgets/GLwDrawingArea.c/post 332 // Could use also XtSetWMColormapWindows. 333 if( !XtIsWidget(a_this) || !XtIsRealized(a 334 Widget shell = get_shell(a_this); 335 if(shell==NULL) return; 336 Display* display = XtDisplay (a_this); 337 Window wthis = XtWindow (a_this); 338 Window wshell = XtWindow (shell); 339 Window* ws = NULL; 340 int wn = 0; 341 ::XGetWMColormapWindows (display,wshell, & 342 // Check if colormap of this is a colormap 343 XWindowAttributes watbs; 344 XGetWindowAttributes (display,wthis,&watb 345 Colormap cmapthis = watbs.colormap; 346 int found = -1; 347 for(int count=0;count<wn;count++) { 348 Colormap cmap; 349 XGetWindowAttributes (display,ws[count], 350 cmap = watbs.colormap; 351 if(cmap==cmapthis) { 352 ::XFree (ws); 353 return; 354 } 355 if(ws[count]==wshell) { 356 found = count; 357 } 358 } 359 // Have to add window of this in list : 360 if(wn==0) { 361 if(ws!=NULL) ::XFree(ws); 362 ws = (Window*)::malloc( 2 * sizeof(Windo 363 } else { 364 ws = (Window*)::realloc(ws,(wn + 2) * si 365 } 366 if(ws==NULL) return; 367 if(found==-1) { 368 // Window of shell not in list : 369 ws[wn] = wthis; wn++; 370 ws[wn] = wshell;wn++; 371 } else { 372 ws[found] = wthis; 373 ws[wn] = wshell; wn++; // Shell must 374 } 375 if (::XSetWMColormapWindows(display,wshell 376 CWarnF ("install_colormap: can't install 377 } 378 ::free(ws); 379 } 380 381 static void uninstall_colormap(Widget a_this 382 if( !XtIsWidget(a_this) || !XtIsRealized(a 383 Widget shell = get_shell (a_this); 384 if(shell==NULL) return; 385 Display* display = XtDisplay (a_this); 386 Window wthis = XtWindow (a_this); 387 Window wshell = XtWindow (shell); 388 Window* ws = NULL; 389 int wn = 0; 390 ::XGetWMColormapWindows (display,wshell, & 391 if( (wn==0) || (ws==NULL) ) return; 392 Window* nws = (Window*)::malloc( wn * siz 393 if(nws==NULL) { 394 ::XFree (ws); 395 return; 396 } 397 int nwn = 0; 398 for(int count=0;count<wn;count++) { 399 if(ws[count]!=wthis) { 400 nws[nwn] = ws[count]; 401 nwn++; 402 } 403 } 404 if(wn!=nwn) { 405 if (::XSetWMColormapWindows(display,wshe 406 CWarnF("uninstall_colormap: can't inst 407 } 408 } 409 ::XFree (ws); 410 ::free (nws); 411 } 412 413 static Widget get_shell(Widget a_this) { 414 Widget widget = a_this; 415 while(1) { 416 if(widget==NULL) return NULL; 417 if(XtIsShell(widget)) return widget; 418 widget = XtParent(widget); 419 } 420 } 421 422 public: 423 static WidgetClass widget_class() { 424 static XtResource s_resources[] = { 425 {(String)XoN_doubleBufferOn(),(String)Xo 426 XtOffset(OpenGLAreaWidget,openGLArea.do 427 {(String)XoN_paintCallback(),XtCCallback 428 XtOffset(OpenGLAreaWidget,openGLArea.pa 429 {(String)XoN_eventCallback(),XtCCallback 430 XtOffset(OpenGLAreaWidget,openGLArea.ev 431 }; 432 433 static OpenGLAreaClassRec s_openGLAreaClas 434 // Core Class Part : 435 { 436 (WidgetClass) &compositeClassRec, // p 437 (String)class_name(), // w 438 sizeof(OpenGLAreaRec), // si 439 initialize_class, // cl 440 NULL, // dy 441 FALSE, // ha 442 initialize_widget, // in 443 NULL, // no 444 realize_widget, // XC 445 NULL, // wi 446 0, // nu 447 s_resources, // re 448 XtNumber(s_resources), // nu 449 NULLQUARK, // re 450 TRUE, // co 451 TRUE, // co 452 TRUE, // co 453 TRUE, // se 454 destroy_widget, // fr 455 change_widget_size, // ge 456 draw_widget, // re 457 set_values, // se 458 NULL, // no 459 XtInheritSetValuesAlmost, // Se 460 NULL, // no 461 XtInheritAcceptFocus, // as 462 XtVersion, // ve 463 NULL, // li 464 XtInheritTranslations, // tr 465 XtInheritQueryGeometry, // re 466 XtInheritDisplayAccelerator, // di 467 NULL // po 468 }, 469 // Composite Class Part : 470 { 471 XtInheritGeometryManager, // geometr 472 XtInheritChangeManaged, // change 473 XtInheritInsertChild, // physica 474 XtInheritDeleteChild, // physica 475 NULL // pointer 476 }, 477 // OpenGLArea : 478 { 479 NULL 480 } 481 }; 482 return (WidgetClass)&s_openGLAreaClassRec; 483 } 484 }; 485 486 }} 487 488 489 #endif