source: trunk/src/plugins/graphicssystems/shivavg/shivavgwindowsurface.cpp@ 561

Last change on this file since 561 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

  • Property svn:eol-style set to native
File size: 10.0 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the plugins of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
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
50extern 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
58QT_BEGIN_NAMESPACE
59
60class QShivaContext
61{
62public:
63 QShivaContext();
64 ~QShivaContext();
65
66 bool makeCurrent(ShivaVGWindowSurfacePrivate *surface);
67 void doneCurrent();
68
69 bool initialized;
70 QSize currentSize;
71 ShivaVGWindowSurfacePrivate *currentSurface;
72};
73
74Q_GLOBAL_STATIC(QShivaContext, shivaContext);
75
76class ShivaVGWindowSurfacePrivate
77{
78public:
79 ShivaVGWindowSurfacePrivate()
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 }
93 ~ShivaVGWindowSurfacePrivate();
94
95 void ensureContext(QWidget *widget);
96
97 QSize size;
98 bool isCurrent;
99 bool needsResize;
100 QVGPaintEngine *engine;
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
111QShivaContext::QShivaContext()
112 : initialized(false)
113 , currentSurface(0)
114{
115}
116
117QShivaContext::~QShivaContext()
118{
119 if (initialized)
120 vgDestroyContextSH();
121}
122
123bool QShivaContext::makeCurrent(ShivaVGWindowSurfacePrivate *surface)
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
151void QShivaContext::doneCurrent()
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
162ShivaVGWindowSurfacePrivate::~ShivaVGWindowSurfacePrivate()
163{
164#if defined(QVG_USE_FBO)
165 if (fbo) {
166 glDeleteTextures(1, &texture);
167 glDeleteFramebuffersEXT(1, &fbo);
168 }
169#endif
170}
171
172void ShivaVGWindowSurfacePrivate::ensureContext(QWidget *widget)
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);
235 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
236 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
237 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
238 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
239 glFramebufferTexture2DEXT
240 (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D,
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
252ShivaVGWindowSurface::ShivaVGWindowSurface(QWidget *window)
253 : QWindowSurface(window), d_ptr(new ShivaVGWindowSurfacePrivate)
254{
255}
256
257ShivaVGWindowSurface::~ShivaVGWindowSurface()
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
270QPaintDevice *ShivaVGWindowSurface::paintDevice()
271{
272 d_ptr->ensureContext(window());
273 shivaContext()->makeCurrent(d_ptr);
274 glClearDepth(0.0f);
275 glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
276 return this;
277}
278
279void ShivaVGWindowSurface::flush(QWidget *widget, const QRegion &region, const QPoint &offset)
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
320void ShivaVGWindowSurface::setGeometry(const QRect &rect)
321{
322 QWindowSurface::setGeometry(rect);
323 d_ptr->needsResize = true;
324 d_ptr->size = rect.size();
325}
326
327bool ShivaVGWindowSurface::scroll(const QRegion &area, int dx, int dy)
328{
329 return QWindowSurface::scroll(area, dx, dy);
330}
331
332void ShivaVGWindowSurface::beginPaint(const QRegion &region)
333{
334 // Nothing to do here.
335 Q_UNUSED(region);
336}
337
338void ShivaVGWindowSurface::endPaint(const QRegion &region)
339{
340 // Nothing to do here.
341 Q_UNUSED(region);
342}
343
344Q_GLOBAL_STATIC(QVGPaintEngine, sharedPaintEngine);
345
346QPaintEngine *ShivaVGWindowSurface::paintEngine() const
347{
348 if (!d_ptr->engine)
349 d_ptr->engine = sharedPaintEngine();
350 return d_ptr->engine;
351}
352
353int ShivaVGWindowSurface::metric(PaintDeviceMetric met) const
354{
355 return qt_paint_device_metric(window(), met);
356}
357
358QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.