HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
RE_Visual.h
Go to the documentation of this file.
1 #ifndef __RE_Visual_h__
2 #define __RE_Visual_h__
3 
4 #include "RE_API.h"
5 #include "RE_Types.h"
6 
7 #include <UT/UT_Lock.h>
9 
10 #if defined(USE_QT5)
11 // Include this before including any QOpenGL files.
12 // This ensures that our OpenGL core profile API is included
13 // instead of the one shipped with Qt.
14 // TODO: We should look into moving over to Qt's OpenGL API
15 // (i.e. include QtGui/qopengl.h or maybe QtGui/QOpenGLFunctions.h
16 // instead of glcorearb.h)
17 #include "RE_OGL.h"
18 
19 #include <QtGui/QOpenGLContext>
20 #include <QtGui/QWindow>
21 #include <QtWidgets/QWidget>
22 #endif
23 
24 // Object names for QWidget and QWindow (drawable surface) objects used
25 // for OpenGL rendering. Note that the drawable surface name must be exactly
26 // equal to the drawable name plus "Window" as the suffix. This is a
27 // restriction of the QWidgetWindow class.
28 #define RE_GL_DRAWABLE_OBJ_NAME "RE_GLDrawable"
29 #define RE_GL_DRAWABLE_SURFACE_OBJ_NAME RE_GL_DRAWABLE_OBJ_NAME "Window"
30 
31 #define RE_GL_DRAWABLE_WRAPPER_OBJ_NAME RE_GL_DRAWABLE_OBJ_NAME "Wrapper"
32 
33 class RE_Server;
34 class RE_Window;
35 
36 #if defined(USE_QT5)
37 class RE_GLDrawable;
38 #endif
39 class QGLFormat;
40 #if defined(USE_QT5)
41 class QSurfaceFormat;
42 #else
43 class QGLWidget;
44 class QWidget;
45 #endif
46 
47 #if defined(USE_QT5)
48 class RE_GLContext : public QOpenGLContext
49 {
50 public:
51  RE_GLContext() :
52  myDrawable(NULL)
53  {}
54 
55  ~RE_GLContext() {}
56 
57  RE_GLDrawable *drawable() const { return myDrawable; }
58  void setDrawable(RE_GLDrawable *drawable) { myDrawable = drawable; }
59 
60 private:
61  RE_GLDrawable *myDrawable;
62 };
63 
64 /// GL drawable for Qt5.
65 /// It's basically a plain Qt widget that manages a GL context.
66 class RE_GLDrawable : public QWidget
67 {
68 public:
69  RE_GLDrawable(const QSurfaceFormat &format)
70  : QWidget()
71  {
72  myContext.setDrawable(this);
73  myContext.setFormat(format);
74 
75  init_();
76  }
77 
78  RE_GLDrawable(
79  const QSurfaceFormat &format, QWidget *parent,
80  QOpenGLContext *sharedContext)
81  : QWidget(parent)
82  {
83  myContext.setDrawable(this);
84  myContext.setFormat(format);
85  if (sharedContext)
86  myContext.setShareContext(sharedContext);
87 
88  init_();
89  }
90 
91  virtual ~RE_GLDrawable() {}
92 
93  RE_GLContext *context() { return &myContext; }
94 
95  virtual QPaintEngine *paintEngine() const { return nullptr; };
96  static const char *widgetTag() { return RE_GL_DRAWABLE_OBJ_NAME; }
97 
98  /// Return the string tag used to identify whether a QWindow
99  /// is used a drawable surface for Houdini.
100  static const char * drawableSurfaceTag()
102 
103  /// Return the string tag used to identify whether a QWidget
104  /// is the wrapper widget of a GL drawable in Houdini.
105  static const char *widgetWrapperTag()
107 
108 protected:
109  virtual void paintEvent(QPaintEvent *event) {}
110  virtual void resizeEvent(QResizeEvent *event) {}
111  virtual void mousePressEvent(QMouseEvent *event)
112  {
113  setFocus();
114  QWidget::mousePressEvent(event);
115  }
116 
117 private:
118  void init_()
119  {
120  // Neat little trick to force Qt to create the platform drawable without
121  // showing it. We need the platform drawable to exist before doing
122  // any OpenGL rendering.
123  //
124  // Note that we have to resize the window handle (surface) to keep its
125  // geometry in sync with the GL widget. This must be done *before* the
126  // call to winId() or else the underlying platform window (surface)
127  // will be initialized with a default size assigned by Qt.
128  (void)winId();
129  UT_ASSERT(windowHandle());
130  windowHandle()->resize(size());
131  (void)windowHandle()->winId();
132 
133  // Tag the drawable surface.
134  windowHandle()->setObjectName(RE_GLDrawable::drawableSurfaceTag());
135 
136  // Set these attributes to prevent Qt from trying to fill in the
137  // background with either black or white (system-dependent).
138  setAttribute(Qt::WA_PaintOnScreen);
139  setAttribute(Qt::WA_NoSystemBackground);
140 
141  UT_IF_ASSERT(bool created =) myContext.create();
142  UT_ASSERT(created && myContext.isValid());
143 
144  // Tag ourself so that we can be identified in the event loop.
145  setObjectName(widgetTag());
146  setAcceptDrops(true);
147  }
148 
149  RE_GLContext myContext;
150 };
151 #endif
152 
154 {
155 public:
156  RE_Visual(RE_DisplayMode newmode);
157  ~RE_Visual();
158 
159  RE_OGLContext createContext(RE_Window *win) const;
160  void deleteContext(RE_OGLContext) const;
161 
162  RE_OGLContext grabContext(RE_Window *win, bool attach = true);
163  void returnContext(RE_Window *win, RE_OGLContext ctx);
164 
165  // isMode() returns true on an exact match. isCompatibleWithMode() returns
166  // true if this visual is equal to or a superset of the features in 'match'
167  bool isMode(RE_DisplayMode match) const;
168  bool isCompatibleWithMode(RE_DisplayMode match) const;
169 
170  bool isRGB() const;
171 
172  /// Returns the display mode used for the request to create this visual.
173  RE_DisplayMode getMode() const { return myVisualMode; }
174 
175 #if defined(USE_QT5)
176  const QSurfaceFormat * getPixelFormat() const;
177  static QOpenGLContext * getSharedGLContext();
178  static void initDefaultGLFormat();
179 #else
180  const QGLFormat * getPixelFormat() const;
181  static const QGLWidget * getSharedGLWidget();
182 #endif
183 
184  static bool isDetachedContext(RE_OGLContext);
185 
186  /// Return the tag we use to identify our GL widgets.
187  /// This is useful when handling events in the event loop.
188  static const char * glWidgetTag();
189 
190  /// Return the tag we use to identify our GL widget wrappers.
191  /// This is useful when handling events in the event loop.
192  static const char * glWidgetWrapperTag();
193 
194  /// Return the window widget that is bound to the specified GL widget.
195  static QWidget * ownerWindowWidget(QWidget *gl_widget);
196 
197  bool canSupportQuadBufferStereo(OGLDrawable drawable);
198 
199 private:
200  void initPixelFormat_(RE_DisplayMode mode);
201  void createSharedGLWidget_();
202  void testGLVersions_();
203  bool canCreateGLContext_(
204  int gl_major, int gl_minor,
205  bool use_core_profile);
206 
207  RE_DisplayMode myVisualMode;
208 
209  UT_Lock myContextLock;
210  UT_Array<RE_OGLContext> myVisibleContexts;
211 
212 #if defined(USE_QT5)
213  // This widget is for stashing away returned GL widgets by containing them
214  // as children. This causes the GL widgets to be parented at all times so
215  // that their window flags do not change.
216  QWidget *myStashWidget;
217 #endif
218 
219 #if defined(USE_QT5)
220  QSurfaceFormat * myPixelFormat;
221 #else
222  QGLFormat * myPixelFormat;
223 #endif
224 
225 #if !defined(USE_QT5)
226  /// The widget bound to the OpenGL context that shares display lists and
227  /// textures with all other contexts.
228  static QGLWidget * theSharedGLWidget;
229 #endif
230 
231 };
232 
233 #endif
#define RE_API
Definition: RE_API.h:10
#define RE_GL_DRAWABLE_WRAPPER_OBJ_NAME
Definition: RE_Visual.h:31
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
GLsizeiptr size
Definition: glcorearb.h:663
void * RE_OGLContext
Definition: RE_Types.h:865
struct _cl_event * event
Definition: glcorearb.h:2960
#define RE_GL_DRAWABLE_SURFACE_OBJ_NAME
Definition: RE_Visual.h:29
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:102
RE_DisplayMode
Definition: RE_Types.h:533
RE_DisplayMode getMode() const
Returns the display mode used for the request to create this visual.
Definition: RE_Visual.h:173
GLenum mode
Definition: glcorearb.h:98
GLint GLint GLsizei GLint GLenum format
Definition: glcorearb.h:107
QGLWidget * OGLDrawable
Definition: RE_Types.h:872
#define RE_GL_DRAWABLE_OBJ_NAME
Definition: RE_Visual.h:28
#define UT_IF_ASSERT(ZZ)
Definition: UT_Assert.h:120