Qt 4.8
shivavgwindowsurface.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #define GL_GLEXT_PROTOTYPES
43 #include "shivavgwindowsurface.h"
44 #include <QtOpenVG/private/qpaintengine_vg_p.h>
45 #if defined(Q_WS_X11)
46 #include "private/qt_x11_p.h"
47 #include "qx11info_x11.h"
48 #include <GL/glx.h>
49 
50 extern QX11Info *qt_x11Info(const QPaintDevice *pd);
51 #endif
52 
53 // Define this to use framebuffer objects.
54 //#define QVG_USE_FBO 1
55 
56 #include <vg/openvg.h>
57 
59 
61 {
62 public:
63  QShivaContext();
65 
67  void doneCurrent();
68 
72 };
73 
74 Q_GLOBAL_STATIC(QShivaContext, shivaContext);
75 
77 {
78 public:
80  : isCurrent(false)
81  , needsResize(true)
82  , engine(0)
83 #if defined(QVG_USE_FBO)
84  , fbo(0)
85  , texture(0)
86 #endif
87 #if defined(Q_WS_X11)
88  , drawable(0)
89  , context(0)
90 #endif
91  {
92  }
94 
95  void ensureContext(QWidget *widget);
96 
98  bool isCurrent;
101 #if defined(QVG_USE_FBO)
102  GLuint fbo;
103  GLuint texture;
104 #endif
105 #if defined(Q_WS_X11)
106  GLXDrawable drawable;
107  GLXContext context;
108 #endif
109 };
110 
112  : initialized(false)
113  , currentSurface(0)
114 {
115 }
116 
118 {
119  if (initialized)
120  vgDestroyContextSH();
121 }
122 
124 {
125  if (currentSurface)
126  currentSurface->isCurrent = false;
127  surface->isCurrent = true;
128  currentSurface = surface;
129  currentSize = surface->size;
130 #if defined(Q_WS_X11)
131  glXMakeCurrent(X11->display, surface->drawable, surface->context);
132 #endif
133  if (!initialized) {
134  if (!vgCreateContextSH(currentSize.width(), currentSize.height())) {
135  qWarning("vgCreateContextSH(%d, %d): could not create context", currentSize.width(), currentSize.height());
136  return false;
137  }
138  initialized = true;
139  } else {
140  vgResizeSurfaceSH(currentSize.width(), currentSize.height());
141  }
142 #if defined(QVG_USE_FBO)
143  if (surface->fbo)
144  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, surface->fbo);
145  else
146  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
147 #endif
148  return true;
149 }
150 
152 {
153  if (currentSurface) {
154  currentSurface->isCurrent = false;
155  currentSurface = 0;
156  }
157 #if defined(Q_WS_X11)
158  glXMakeCurrent(X11->display, 0, 0);
159 #endif
160 }
161 
163 {
164 #if defined(QVG_USE_FBO)
165  if (fbo) {
166  glDeleteTextures(1, &texture);
167  glDeleteFramebuffersEXT(1, &fbo);
168  }
169 #endif
170 }
171 
173 {
174 #if defined(Q_WS_X11)
175  Window win = widget->winId();
176  if (win != drawable) {
177  if (context)
178  glXDestroyContext(X11->display, context);
179  drawable = win;
180  }
181  if (context == 0) {
182  const QX11Info *xinfo = qt_x11Info(widget);
183  int spec[64];
184  int i = 0;
185  spec[i++] = GLX_DOUBLEBUFFER;
186  spec[i++] = GLX_DEPTH_SIZE;
187  spec[i++] = 1;
188  spec[i++] = GLX_STENCIL_SIZE;
189  spec[i++] = 1;
190  spec[i++] = GLX_RGBA;
191  spec[i++] = GLX_RED_SIZE;
192  spec[i++] = 1;
193  spec[i++] = GLX_GREEN_SIZE;
194  spec[i++] = 1;
195  spec[i++] = GLX_BLUE_SIZE;
196  spec[i++] = 1;
197  spec[i++] = GLX_SAMPLE_BUFFERS_ARB;
198  spec[i++] = 1;
199  spec[i++] = GLX_SAMPLES_ARB;
200  spec[i++] = 4;
201  spec[i] = XNone;
202  XVisualInfo *visual = glXChooseVisual
203  (xinfo->display(), xinfo->screen(), spec);
204  context = glXCreateContext(X11->display, visual, 0, True);
205  if (!context)
206  qWarning("glXCreateContext: could not create GL context for VG rendering");
207  }
208 #else
209  Q_UNUSED(widget);
210 #endif
211 #if defined(QVG_USE_FBO)
212  if (needsResize && fbo) {
213 #if defined(Q_WS_X11)
214  glXMakeCurrent(X11->display, drawable, context);
215 #endif
216  glDeleteTextures(1, &texture);
217  glDeleteFramebuffersEXT(1, &fbo);
218 #if defined(Q_WS_X11)
219  glXMakeCurrent(X11->display, 0, 0);
220 #endif
221  fbo = 0;
222  texture = 0;
223  }
224  if (!fbo) {
225 #if defined(Q_WS_X11)
226  glXMakeCurrent(X11->display, drawable, context);
227 #endif
228  glGenFramebuffersEXT(1, &fbo);
229  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
230 
231  glGenTextures(1, &texture);
232  glBindTexture(GL_TEXTURE_2D, texture);
233  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, size.width(), size.height(), 0,
234  GL_RGBA, GL_UNSIGNED_BYTE, NULL);
239  glFramebufferTexture2DEXT
241  texture, 0);
242 
243  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
244 #if defined(Q_WS_X11)
245  glXMakeCurrent(X11->display, 0, 0);
246 #endif
247  }
248 #endif
249  needsResize = false;
250 }
251 
253  : QWindowSurface(window), d_ptr(new ShivaVGWindowSurfacePrivate)
254 {
255 }
256 
258 {
259  if (d_ptr->isCurrent) {
260  shivaContext()->doneCurrent();
261  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
262  }
263 #if defined(Q_WS_X11)
264  if (d_ptr->context)
265  glXDestroyContext(X11->display, d_ptr->context);
266 #endif
267  delete d_ptr;
268 }
269 
271 {
273  shivaContext()->makeCurrent(d_ptr);
274  glClearDepth(0.0f);
276  return this;
277 }
278 
280 {
281  Q_UNUSED(region);
282  Q_UNUSED(offset);
283  QWidget *parent = widget->internalWinId() ? widget : widget->nativeParentWidget();
284  d_ptr->ensureContext(parent);
285  QShivaContext *context = shivaContext();
286  if (!d_ptr->isCurrent)
287  context->makeCurrent(d_ptr);
288 #if defined(QVG_USE_FBO)
289  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
290  if (d_ptr->fbo) {
291  static GLfloat const vertices[][2] = {
292  {-1, -1}, {1, -1}, {1, 1}, {-1, 1}
293  };
294  static GLfloat const texCoords[][2] = {
295  {0, 0}, {1, 0}, {1, 1}, {0, 1}
296  };
297  glMatrixMode(GL_PROJECTION);
298  glLoadIdentity();
299  glMatrixMode(GL_MODELVIEW);
300  glLoadIdentity();
301  glVertexPointer(2, GL_FLOAT, 0, vertices);
302  glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
303  glBindTexture(GL_TEXTURE_2D, d_ptr->texture);
304  glEnable(GL_TEXTURE_2D);
305  glEnableClientState(GL_VERTEX_ARRAY);
306  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
307  glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
308  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
309  glDisableClientState(GL_VERTEX_ARRAY);
310  glDisable(GL_TEXTURE_2D);
311  glBindTexture(GL_TEXTURE_2D, 0);
312  }
313 #endif
314 #if defined(Q_WS_X11)
315  glXSwapBuffers(X11->display, d_ptr->drawable);
316 #endif
317  context->doneCurrent();
318 }
319 
321 {
323  d_ptr->needsResize = true;
324  d_ptr->size = rect.size();
325 }
326 
327 bool ShivaVGWindowSurface::scroll(const QRegion &area, int dx, int dy)
328 {
329  return QWindowSurface::scroll(area, dx, dy);
330 }
331 
333 {
334  // Nothing to do here.
335  Q_UNUSED(region);
336 }
337 
339 {
340  // Nothing to do here.
341  Q_UNUSED(region);
342 }
343 
344 Q_GLOBAL_STATIC(QVGPaintEngine, sharedPaintEngine);
345 
347 {
348  if (!d_ptr->engine)
349  d_ptr->engine = sharedPaintEngine();
350  return d_ptr->engine;
351 }
352 
354 {
355  return qt_paint_device_metric(window(), met);
356 }
357 
Q_GLOBAL_STATIC(QShivaContext, shivaContext)
#define GL_CLAMP_TO_EDGE
Definition: glfunctions.h:62
#define GL_TEXTURE_MIN_FILTER
QPaintEngine * paintEngine() const
void setGeometry(const QRect &rect)
Sets the currently allocated area to be the given rect.
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
QPointer< QWidget > widget
QRect rect(const QWidget *widget) const
Returns the rectangle for widget in the coordinates of this window surface.
#define GL_STENCIL_BUFFER_BIT
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
virtual void setGeometry(const QRect &rect)
Sets the currently allocated area to be the given rect.
virtual QPoint offset(const QWidget *widget) const
Returns the offset of widget in the coordinates of this window surface.
#define GL_TEXTURE_WRAP_S
#define GL_FRAMEBUFFER_EXT
void endPaint(const QRegion &region)
This function is called after painting onto the surface has ended, with the region in which the paint...
#define X11
Definition: qt_x11_p.h:724
void beginPaint(const QRegion &region)
This function is called before painting onto the surface begins, with the region in which the paintin...
#define GL_TEXTURE_2D
QPaintDevice * paintDevice()
Implement this function to return the appropriate paint device.
bool makeCurrent(ShivaVGWindowSurfacePrivate *surface)
#define GL_COLOR_ATTACHMENT0_EXT
#define GLX_SAMPLE_BUFFERS_ARB
Definition: qgl_x11.cpp:96
NSWindow * window
int width() const
Returns the width.
Definition: qsize.h:126
QX11Info * qt_x11Info(const QPaintDevice *pd)
const Q_GUI_EXPORT QX11Info * qt_x11Info(const QPaintDevice *pd)
Returns the QX11Info structure for the pd paint device.
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
QWidget * nativeParentWidget() const
Returns the native parent for this widget, i.
Definition: qwidget.cpp:4514
void flush(QWidget *widget, const QRegion &region, const QPoint &offset)
Flushes the given region from the specified widget onto the screen.
friend Q_GUI_EXPORT int qt_paint_device_metric(const QPaintDevice *device, PaintDeviceMetric metric)
ShivaVGWindowSurfacePrivate * currentSurface
QSize size() const
Returns the size of the rectangle.
Definition: qrect.h:309
Q_CORE_EXPORT void qWarning(const char *,...)
#define GL_TRIANGLE_FAN
#define GL_FLOAT
The QRegion class specifies a clip region for a painter.
Definition: qregion.h:68
The QPaintEngine class provides an abstract definition of how QPainter draws to a given device on a g...
Definition: qpaintengine.h:90
int metric(PaintDeviceMetric metric) const
The QWindowSurface class provides the drawing area for top-level windows.
#define GL_DEPTH_BUFFER_BIT
#define GLX_SAMPLES_ARB
Definition: qgl_x11.cpp:97
#define GL_TEXTURE_WRAP_T
The QX11Info class provides information about the X display configuration.
Definition: qx11info_x11.h:63
ShivaVGWindowSurface(QWidget *window)
#define GL_UNSIGNED_BYTE
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
int height() const
Returns the height.
Definition: qsize.h:129
if(void) toggleToolbarShown
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
bool scroll(const QRegion &area, int dx, int dy)
Scrolls the given area dx pixels to the right and dy downward; both dx and dy may be negative...
WId internalWinId() const
Returns the window system identifier of the widget, or 0 if the widget is not created yet...
Definition: qwidget.h:244
#define GL_RGBA
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
WId winId() const
Returns the window system identifier of the widget.
Definition: qwidget.cpp:2557
#define GL_TEXTURE_MAG_FILTER
void ensureContext(QWidget *widget)
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
virtual bool scroll(const QRegion &area, int dx, int dy)
Scrolls the given area dx pixels to the right and dy downward; both dx and dy may be negative...
QWidget * window() const
Returns a pointer to the top-level window associated with this surface.
static Display * display()
Returns the default display for the application.
int screen() const
Returns the number of the screen currently in use.
ShivaVGWindowSurfacePrivate * d_ptr
static int area(const QSize &s)
Definition: qicon.cpp:155
#define GL_NEAREST