1// @configure_input@
2
3/**************************************************************************\
4 * Copyright (c) Kongsberg Oil & Gas Technologies AS
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 *
14 * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * Neither the name of the copyright holder nor the names of its
19 * contributors may be used to endorse or promote products derived from
20 * this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33\**************************************************************************/
34
35#define PRIVATE(obj) ((SoGuiGLWidgetP *)(obj->pimpl))
36
37// *************************************************************************
38
39/*!
40  \class So@Gui@GLWidget So@Gui@GLWidget.h Inventor/@Gui@/So@Gui@GLWidget.h
41  \brief The So@Gui@GLWidget class manages OpenGL contexts.
42
43  \ingroup components
44
45  This is the basic, abstract component class which sets up an OpenGL
46  canvas for its subclasses.
47
48  Application programmers will normally not use this class directly,
49  but rather through the interface of either its direct descendent;
50  So@Gui@RenderArea, or through one of the "rapid application
51  development"-style viewer subclasses.
52
53  \if SOQT_DOC
54
55  An important thing to know about embedding So@Gui@GLWidget derived
56  components into other @Gui@ widgets is that you need to set up
57  "focus proxying" to have events still be sent to the OpenGL canvas
58  widget. This is true for both the So@Gui@RenderArea aswell as all
59  the viewer components (like So@Gui@ExaminerViewer,
60  So@Gui@PlaneViewer etc).
61
62  As an example, if you embed an So@Gui@ExaminerViewer inside a QFrame
63  like this:
64
65  \code
66  QMainWindow * toplevel = new QMainWindow;
67  QFrame * frame = new QFrame(toplevel);
68  So@Gui@ExaminerViewer * viewer = new So@Gui@ExaminerViewer(toplevel);
69  \endcode
70
71  ...events from the keyboard will not always automatically be
72  forwarded to the viewer OpenGL canvas. This is the code you need to
73  add in this case:
74
75  \code
76  toplevel->setFocusProxy(viewer->getWidget());
77  \endcode
78
79  \endif
80
81  \if SOWIN_DOC
82
83  For debugging purposes, SoWinGLWidget provides the
84  OIV_FORCE_PIXEL_FORMAT environment variable to make it possible to
85  override the pixel format chosen by the internal attribute match
86  algorithm.
87
88  \endif
89*/
90
91// *************************************************************************
92
93#ifdef HAVE_CONFIG_H
94#include <config.h>
95#endif // HAVE_CONFIG_H
96
97#include <Inventor/@Gui@/common/gl.h>
98#include <Inventor/@Gui@/So@Gui@GLWidget.h>
99#include <Inventor/@Gui@/So@Gui@GLWidgetP.h>
100
101// *************************************************************************
102
103// All shared documentation for functions with specific
104// implementations in the individual toolkits.
105
106/*!
107  \fn So@Gui@GLWidget::So@Gui@GLWidget(@WIDGET@ const parent, const char * const name, const SbBool embed, const int glmodes, const SbBool build)
108
109  The constructor is protected, as this is an abstract class to only
110  be used by it's subclasses.
111*/
112
113/*!
114  \fn So@Gui@GLWidget::~So@Gui@GLWidget()
115
116  Clean up all use of internal resources.
117
118  The destructor is protected, as this is an abstract class to only be
119  used by it's subclasses.
120*/
121
122/*!
123  \fn void So@Gui@GLWidget::setBorder(const SbBool enable)
124
125  Specify whether or not there should be a border framing the OpenGL
126  canvas. The border will be 2 pixels wide.
127
128  The default is to display the OpenGL canvas with no border.
129
130  \sa isBorder()
131*/
132
133/*!
134  \fn SbBool So@Gui@GLWidget::isBorder(void) const
135
136  Returns whether or not there's a border framing the OpenGL canvas.
137
138  \sa setBorder()
139*/
140
141/*!
142  \fn void So@Gui@GLWidget::setOverlayRender(const SbBool onoff)
143
144  Turn on or off the use of overlay planes.
145
146  \sa isOverlayRender()
147*/
148
149/*!
150  \fn SbBool So@Gui@GLWidget::isOverlayRender(void) const
151
152  Returns a flag indicating whether or not overplay planes are
153  currently used.
154
155  \sa setOverlayRender()
156*/
157
158/*!
159  \fn void So@Gui@GLWidget::setDoubleBuffer(const SbBool enable)
160
161  Switch between single and double buffer mode for the OpenGL canvas.
162  The default is to use a single buffer canvas.
163
164  \sa isDoubleBuffer()
165*/
166
167/*!
168  \fn SbBool So@Gui@GLWidget::isDoubleBuffer(void) const
169
170  Returns the status of the buffer mode.
171
172  \sa setDoubleBuffer()
173*/
174
175/*!
176  \fn void So@Gui@GLWidget::setQuadBufferStereo(const SbBool enable)
177
178  Enables or disables OpenGL quad buffer stereo.
179*/
180
181/*!
182  \fn SbBool So@Gui@GLWidget::isQuadBufferStereo(void) const
183
184  Returns \c TRUE if quad buffer stereo is enabled for this widget.
185*/
186
187/*!
188  \fn void So@Gui@GLWidget::setAccumulationBuffer(const SbBool enable)
189
190  Enables/disables the OpenGL accumulation buffer.
191
192  For general information about accumulation buffers, confer with your
193  OpenGL reference documentation.
194
195  By default, the accumulation buffer will be attempted disabled.
196  Whether or not it will \e actually be disabled depends on what
197  OpenGL contexts are available on the system. It is perfectly
198  possible that the only usable contexts with regard to the other
199  settings (like double buffering and RGBA mode versus color index
200  mode) causes the context selection to choose an OpenGL format that
201  contains an accumulation buffer, even though it was not
202  requested.
203
204  Vice versa, one is not guaranteed to get accumulation buffers even
205  when requested through this function, either because they are not
206  available, or because they are only available in combination with
207  other OpenGL context settings that are not wanted (like single
208  buffers, non-accellerated rendering, etc).
209
210  If you try to enable accumulation buffers by using this function,
211  you should therefore in succession use the
212  So@Gui@GLWidget::getAccumulationBuffer() to query whether or not an
213  accumulation buffer could actually be set up.
214
215  \sa So@Gui@RenderArea::setAntiAliasing()
216*/
217
218/*!
219  \fn SbBool So@Gui@GLWidget::getAccumulationBuffer(void) const
220
221  Returns whether the OpenGL accumulation buffer is enabled.
222
223  The returned flag will indicate whether or not accumulation buffers
224  are \e actually present, and not just parrot the input value to
225  So@Gui@GLWidget::setAccumulationBuffer(). See documentation of that
226  function for more information.
227*/
228
229/*!
230  \fn void So@Gui@GLWidget::setStencilBuffer(const SbBool enable)
231
232  Enables/disables the OpenGL stencil buffer.
233
234  For general information about stencil buffers, confer with your
235  OpenGL reference documentation.
236
237  By default, the stencil buffer will be attempted disabled, but the
238  same notes apply for stencil buffers as for accumulation
239  buffers. For an explanation on the issue of stencil and accumulation
240  buffer availability, see the function documentation of
241  So@Gui@GLWidget::setAccumulationBuffer().
242*/
243
244/*!
245  \fn SbBool So@Gui@GLWidget::getStencilBuffer(void) const
246
247  Returns whether the OpenGL stencil buffer is enabled.
248
249  The returned flag will indicate whether or not stencil buffers are
250  \e actually present, in the same manner as for
251  So@Gui@GLWidget::getAccumulationBuffer(). See documentation of
252  So@Gui@GLWidget::setStencilBuffer().
253*/
254
255/*!
256  \fn void So@Gui@GLWidget::setAlphaChannel(const SbBool enable)
257
258  Enables/disables the alpha channel for the OpenGL context.
259*/
260
261/*!
262  \fn SbBool So@Gui@GLWidget::getAlphaChannel(void) const
263
264  Returns whether the alpha channel is enabled for the OpenGL context.
265*/
266
267/*!
268  \fn void So@Gui@GLWidget::setDrawToFrontBufferEnable(const SbBool enable)
269
270  If this is set to \c TRUE, rendering will happen in the front buffer
271  even if the current rendering mode is double buffered.
272*/
273
274/*!
275  \fn SbBool So@Gui@GLWidget::isDrawToFrontBufferEnable(void) const
276  \sa setDrawToFrontBufferEnable()
277*/
278
279/*!
280  \fn @WIDGET@ So@Gui@GLWidget::buildWidget(@WIDGET@ parent)
281
282  This method builds the component contents in the given \a parent
283  widget. For subclasses adding new user interface items, this method
284  is typically overridden in the following manner:
285
286  \code
287  @WIDGET@ MyOwnViewer::buildWidget(@WIDGET@ parent)
288  {
289     @WIDGET@ superw = <superclass>::buildWidget(parent);
290     // [then move superw within MyOwnViewer framework and add own
291     // user interface components]
292  }
293  \endcode
294*/
295
296/*!
297  \fn virtual void So@Gui@GLWidget::redraw(void)
298
299  This method is invoked when the GL buffer needs to be redrawn.
300 */
301
302/*!
303  \var SbBool So@Gui@GLWidget::waitForExpose
304
305  If this is \c TRUE, rendering should not be done yet. Upon the first
306  expose event of a newly created OpenGL widget, this variable will
307  be set to \c FALSE.
308*/
309
310/*!
311  \var SbBool So@Gui@GLWidget::drawToFrontBuffer
312
313  If this is \c TRUE, rendering will happen in the front buffer even
314  if the current rendering mode is double buffered.
315*/
316
317/*!
318  \fn @WIDGET@ So@Gui@GLWidget::getNormalWidget(void) const
319
320  \if SOQT_DOC
321  For SoQt, this returns the same widget pointer as that of
322  SoQtGLWidget::getGLWidget().
323  \endif
324*/
325
326/*!
327  \fn @WIDGET@ So@Gui@GLWidget::getOverlayWidget(void) const
328
329  Returns widget associated with overlay planes, or \c NULL if no
330  overlay planes are available.
331
332  \if SOQT_DOC
333  For the Qt toolkit, overlay planes is a feature of the QGLWidget,
334  and not seen at a separate widget entity. So this call will just
335  return the same widget reference as the SoQt::getGLWidget() call (if
336  overlay planes are supported).
337  \endif
338*/
339
340/*!
341  \fn void So@Gui@GLWidget::setGLSize(const SbVec2s size)
342  Sets the size of the GL canvas.
343*/
344
345/*!
346  \fn SbVec2s So@Gui@GLWidget::getGLSize(void) const
347
348  Return the dimensions of the OpenGL canvas.
349*/
350
351/*!
352  \fn float So@Gui@GLWidget::getGLAspectRatio(void) const
353
354  Return the aspect ratio of the OpenGL canvas.
355*/
356
357/*!
358  \fn void So@Gui@GLWidget::setGlxSize(const SbVec2s size)
359  This function has been renamed to the more appropriate setGLSize.
360  \sa setGLSize
361*/
362
363/*!
364  \fn SbVec2s So@Gui@GLWidget::getGlxSize(void) const
365  This function has been renamed to the more appropriate getGLSize.
366  \sa getGLSize
367*/
368
369/*!
370  \fn float So@Gui@GLWidget::getGlxAspectRatio(void) const
371  This function has been renamed to the more appropriate getGLAspectRatio.
372  \sa getGLAspectRatio
373*/
374
375/*!
376  \fn @WIDGET@ So@Gui@GLWidget::getGLWidget(void) const
377
378  Returns a pointer to the toolkit-native GL widget.
379*/
380
381/*!
382  \fn void So@Gui@GLWidget::widgetChanged(@WIDGET@ w)
383
384  This is the method which gets called whenever we change which OpenGL
385  widget is used.
386
387  Should be overridden in subclasses which directly or indirectly
388  store the return value from the So@Gui@GLWidget::getGLWidget()
389  method.
390
391  \sa sizeChanged()
392*/
393
394/*!
395  \fn void So@Gui@GLWidget::processEvent(@EVENT@ anyevent)
396
397  Any events from the native window system that goes to the OpenGL
398  canvas gets piped through this method.
399
400  It is overridden in the subclasses to catch user interaction with
401  the render canvas in the viewers, aswell as forwarding relevant
402  events to the scenegraph.
403*/
404
405/*!
406  \fn void So@Gui@GLWidget::glLockNormal(void)
407
408  This method calls make-current on the correct context and ups the
409  lock level.
410*/
411
412/*!
413  \fn void So@Gui@GLWidget::glUnlockNormal(void)
414
415  This method drops the lock level.
416*/
417
418/*!
419  \fn void So@Gui@GLWidget::glSwapBuffers(void)
420  Swap back buffer to front and vice versa.
421*/
422
423/*!
424  \fn void So@Gui@GLWidget::glFlushBuffer(void)
425
426  Flush the current GL buffer. Simply calls glFlush().
427*/
428
429/*!
430  \fn void So@Gui@GLWidget::glLockOverlay(void)
431
432  This method calls make-current on the correct context and ups the
433  lock level.
434*/
435
436/*!
437  \fn void So@Gui@GLWidget::glUnlockOverlay(void)
438
439  This method drops the lock level.
440*/
441
442/*!
443  \fn unsigned long So@Gui@GLWidget::getOverlayTransparentPixel(void)
444  Returns the overlay transparent pixel.
445*/
446
447/*!
448  \fn SbBool So@Gui@GLWidget::isRGBMode(void)
449
450  Returns \c TRUE if the normal GL context is in RGBA mode.
451  Return \c FALSE if color index mode is used.
452*/
453
454/*!
455  \fn void So@Gui@GLWidget::redrawOverlay(void)
456
457  Renders the overlay scene graph. Default method is empty. Subclasses
458  should override this method.
459*/
460
461/*!
462  \fn SbBool So@Gui@GLWidget::hasNormalGLArea(void) const
463
464  Will return \c TRUE if a normal GL drawing area exists.
465*/
466
467/*!
468  \fn SbBool So@Gui@GLWidget::hasOverlayGLArea(void) const
469
470  Will return \c TRUE if an overlay GL drawing area exists.
471*/
472
473/*!
474  \fn void So@Gui@GLWidget::initGraphic(void)
475
476  Will be called when GL widget should initialize graphic, after
477  the widget has been created. Default method enabled GL_DEPTH_TEST.
478*/
479
480/*!
481  \fn void So@Gui@GLWidget::initOverlayGraphic(void)
482
483  Will be called after the overlay widget has been created, and subclasses
484  should override this to initialize overlay stuff.
485
486  Default method does nothing.
487*/
488
489/*!
490  \fn SbBool So@Gui@GLWidget::glScheduleRedraw(void)
491
492  Will be called whenever scene graph needs to be redrawn.  If this
493  method return \c FALSE, redraw() will be called immediately.
494
495  Default method simply returns \c FALSE. Override this method to
496  schedule a redraw and return \c TRUE if you're trying to do The
497  Right Thing.
498*/
499
500/*!
501  \fn void So@Gui@GLWidget::setStealFocus(SbBool enable)
502
503  Sets whether the GL widget should steal keyboard focus when the
504  mouse is over the GL view.
505
506  Default is \c TRUE.
507
508  \sa isStealFocus
509  \since So@Gui@ 1.3.0
510*/
511
512/*!
513  \fn SbBool So@Gui@GLWidget::isStealFocus(void) const
514
515  Returns whether focus stealing policy is on (\c TRUE) or off (\c
516  FALSE).
517
518  Default is \c TRUE.
519
520  \sa setStealFocus
521  \since So@Gui@ 1.3.0
522*/
523
524
525/*!
526  \fn void So@Gui@GLWidget::setSampleBuffers(const int numsamples)
527
528  Set the number of samples use when enabling multisample buffer contexts.
529  Multisampling will be enabled when numsamples > 1.
530
531*/
532
533/*!
534  \fn int So@Gui@GLWidget::getSampleBuffers(void) const
535
536  Returns the number of samples used for multisampling. Returns 1 if
537  multisampling is disabled.
538*/
539
540// Documented in common/SoGuiGLWidgetCommon.cpp.in.
541void
542So@Gui@GLWidget::setStealFocus(SbBool enable)
543{
544  PRIVATE(this)->stealFocus = enable;
545}
546
547// Documented in common/SoGuiGLWidgetCommon.cpp.in.
548SbBool
549So@Gui@GLWidget::isStealFocus(void) const
550{
551  return PRIVATE(this)->stealFocus;
552}
553
554// *************************************************************************
555
556/*!
557  This function is provided as a convenience for the application
558  programmer to help with acquiring the OpenGL implementation limits
559  for rendering points.
560
561  For robust application code, one needs to consider the range limits
562  when setting the SoDrawStyle::pointSize field.
563*/
564void
565So@Gui@GLWidget::getPointSizeLimits(SbVec2f & range, float & granularity)
566{
567  this->glLockNormal();
568
569  GLfloat vals[2];
570  glGetFloatv(GL_POINT_SIZE_RANGE, vals);
571
572  // Matthias Koenig reported on coin-discuss that the OpenGL
573  // implementation on SGI Onyx 2 InfiniteReality returns 0 for the
574  // lowest pointsize, but it will still set the return value of
575  // glGetError() to GL_INVALID_VALUE if this size is attempted
576  // used. So the boundary range fix in the next line of code is a
577  // workaround for that OpenGL implementation bug.
578  //
579  // 0.0f and lower values are explicitly disallowed, according to
580  // the OpenGL 1.3 specification, Chapter 3.3.
581
582  if (vals[0] <= 0.0f) { vals[0] = So@Gui@Min(1.0f, vals[1]); }
583
584  range.setValue(vals[0], vals[1]);
585
586  GLfloat gran[1];
587  glGetFloatv(GL_POINT_SIZE_GRANULARITY, gran);
588  granularity = gran[0];
589
590  this->glUnlockNormal();
591}
592
593/*!
594  This function is provided as a convenience for the application
595  programmer to help with acquiring the OpenGL implementation limits
596  for rendering lines.
597
598  For robust application code, one needs to consider the range limits
599  when setting the SoDrawStyle::lineWidth field.
600*/
601void
602So@Gui@GLWidget::getLineWidthLimits(SbVec2f & range, float & granularity)
603{
604  this->glLockNormal();
605
606  GLfloat vals[2];
607  glGetFloatv(GL_LINE_WIDTH_RANGE, vals);
608
609  // Matthias Koenig reported on coin-discuss that the OpenGL
610  // implementation on SGI Onyx 2 InfiniteReality returns 0 for the
611  // lowest linewidth, but it will still set the return value of
612  // glGetError() to GL_INVALID_VALUE if this size is attempted
613  // used. This is a workaround for what looks like an OpenGL bug.
614
615  if (vals[0] <= 0.0f) { vals[0] = So@Gui@Min(1.0f, vals[1]); }
616
617  range.setValue(vals[0], vals[1]);
618
619  GLfloat gran[1];
620  glGetFloatv(GL_LINE_WIDTH_GRANULARITY, gran);
621  granularity = gran[0];
622
623  this->glUnlockNormal();
624}
625
626// FIXME: other implementation specifics to check are
627//
628//  * maximum stack depths (attribute, modelview matrix, name,
629//    projection matrix, texture matrix)
630//
631//  * max display list nesting
632//
633//  * max nr of clipplanes
634//
635//  * max nr of light sources
636//
637//  * max 3D texture size (needs specific extension?)
638//
639// 20020802 mortene.
640
641/*!
642  Sets whether OpenGL stereo buffers (quad buffer stereo) should be
643  used.
644*/
645void
646So@Gui@GLWidget::setStereoBuffer(SbBool flag)
647{
648  // FIXME: is this really correct? 20011012 mortene.
649  this->setQuadBufferStereo(flag);
650}
651
652/*!
653  Returns whether OpenGL stereo buffers are being used.
654*/
655SbBool
656So@Gui@GLWidget::isStereoBuffer(void) const
657{
658  // FIXME: is this really correct? 20011012 mortene.
659  return this->isQuadBufferStereo();
660}
661
662// *************************************************************************
663
664#ifndef DOXYGEN_SKIP_THIS
665
666// Remaining code is for the SoGuiGLWidgetP "private implementation"
667// class.
668
669
670SoGuiGLWidgetP::SoGuiGLWidgetP(So@Gui@GLWidget * publ)
671{
672  this->pub = publ;
673  this->stealFocus = TRUE;
674}
675
676SoGuiGLWidgetP::~SoGuiGLWidgetP()
677{
678}
679
680// Just forward from a static function, so we can find out from
681// anywhere within the library -- without exposing the API for the app
682// programmer.
683SbBool
684SoGuiGLWidgetP::isDirectRendering(So@Gui@GLWidget * w)
685{
686  return ((SoGuiGLWidgetP *)(w->pimpl))->isDirectRendering();
687}
688
689#undef PRIVATE
690#endif // DOXYGEN_SKIP_THIS
691
692// *************************************************************************
693