source: trunk/src/opengl/qgl_qws.cpp@ 595

Last change on this file since 595 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.4 KB
RevLine 
[556]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 QtOpenGL module 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#include "qgl.h"
43#include "qgl_egl_p.h"
44#include "qglpixelbuffer.h"
45
46#include <qglscreen_qws.h>
47#include <qscreenproxy_qws.h>
48#include <private/qglwindowsurface_qws_p.h>
49
50#include <private/qbackingstore_p.h>
51#include <private/qfont_p.h>
52#include <private/qfontengine_p.h>
53#include <private/qgl_p.h>
54#include <private/qpaintengine_opengl_p.h>
55#include <qpixmap.h>
56#include <qtimer.h>
57#include <qapplication.h>
58#include <qstack.h>
59#include <qdesktopwidget.h>
60#include <qdebug.h>
61#include <qvarlengtharray.h>
62
63QT_BEGIN_NAMESPACE
64
65static QGLScreen *glScreenForDevice(QPaintDevice *device)
66{
67 QScreen *screen = qt_screen;
68 if (screen->classId() == QScreen::MultiClass) {
69 int screenNumber;
70 if (device && device->devType() == QInternal::Widget)
71 screenNumber = qApp->desktop()->screenNumber(static_cast<QWidget *>(device));
72 else
73 screenNumber = 0;
74 screen = screen->subScreens()[screenNumber];
75 }
76 while (screen->classId() == QScreen::ProxyClass ||
77 screen->classId() == QScreen::TransformedClass) {
78 screen = static_cast<QProxyScreen *>(screen)->screen();
79 }
80 if (screen->classId() == QScreen::GLClass)
81 return static_cast<QGLScreen *>(screen);
82 else
83 return 0;
84}
85
86/*****************************************************************************
87 QOpenGL debug facilities
88 *****************************************************************************/
89//#define DEBUG_OPENGL_REGION_UPDATE
90
91bool QGLFormat::hasOpenGLOverlays()
92{
93 QGLScreen *glScreen = glScreenForDevice(0);
94 if (glScreen)
95 return (glScreen->options() & QGLScreen::Overlays);
96 else
97 return false;
98}
99
100void qt_egl_add_platform_config(QEglProperties& props, QPaintDevice *device)
101{
102 // Find the QGLScreen for this paint device.
103 QGLScreen *glScreen = glScreenForDevice(device);
104 if (!glScreen) {
105 qWarning("QGLContext::chooseContext(): The screen is not a QGLScreen");
106 return;
107 }
108 int devType = device->devType();
109 if (devType == QInternal::Image)
110 props.setPixelFormat(static_cast<QImage *>(device)->format());
111 else
112 props.setPixelFormat(glScreen->pixelFormat());
113}
114
115static EGLSurface qt_egl_create_surface
116 (QEglContext *context, QPaintDevice *device,
117 const QEglProperties *properties = 0)
118{
119 // Get the screen surface functions, which are used to create native ids.
120 QGLScreen *glScreen = glScreenForDevice(device);
121 if (!glScreen)
122 return EGL_NO_SURFACE;
123 QGLScreenSurfaceFunctions *funcs = glScreen->surfaceFunctions();
124 if (!funcs)
125 return EGL_NO_SURFACE;
126
127 // Create the native drawable for the paint device.
128 int devType = device->devType();
129 EGLNativePixmapType pixmapDrawable = 0;
130 EGLNativeWindowType windowDrawable = 0;
131 bool ok;
132 if (devType == QInternal::Pixmap) {
133 ok = funcs->createNativePixmap(static_cast<QPixmap *>(device), &pixmapDrawable);
134 } else if (devType == QInternal::Image) {
135 ok = funcs->createNativeImage(static_cast<QImage *>(device), &pixmapDrawable);
136 } else {
137 ok = funcs->createNativeWindow(static_cast<QWidget *>(device), &windowDrawable);
138 }
139 if (!ok) {
140 qWarning("QEglContext::createSurface(): Cannot create the native EGL drawable");
141 return EGL_NO_SURFACE;
142 }
143
144 // Create the EGL surface to draw into, based on the native drawable.
145 const int *props;
146 if (properties)
147 props = properties->properties();
148 else
149 props = 0;
150 EGLSurface surf;
151 if (devType == QInternal::Widget) {
152 surf = eglCreateWindowSurface
153 (context->display(), context->config(), windowDrawable, props);
154 } else {
155 surf = eglCreatePixmapSurface
156 (context->display(), context->config(), pixmapDrawable, props);
157 }
158 if (surf == EGL_NO_SURFACE)
159 qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError());
160 return surf;
161}
162
163bool QGLContext::chooseContext(const QGLContext* shareContext)
164{
165 Q_D(QGLContext);
166
167 // Validate the device.
168 if (!device())
169 return false;
170 int devType = device()->devType();
171 if (devType != QInternal::Pixmap && devType != QInternal::Image && devType != QInternal::Widget) {
172 qWarning("QGLContext::chooseContext(): Cannot create QGLContext's for paint device type %d", devType);
173 return false;
174 }
175
176 // Get the display and initialize it.
177 d->eglContext = new QEglContext();
178 d->eglContext->setApi(QEgl::OpenGL);
179 if (!d->eglContext->openDisplay(device())) {
180 delete d->eglContext;
181 d->eglContext = 0;
182 return false;
183 }
184
185 // Construct the configuration we need for this surface.
186 QEglProperties configProps;
187 qt_egl_add_platform_config(configProps, device());
188 qt_egl_set_format(configProps, devType, d->glFormat);
189 configProps.setRenderableType(QEgl::OpenGL);
190
191 // Search for a matching configuration, reducing the complexity
192 // each time until we get something that matches.
193 if (!d->eglContext->chooseConfig(configProps)) {
194 delete d->eglContext;
195 d->eglContext = 0;
196 return false;
197 }
198
199 // Inform the higher layers about the actual format properties.
200 qt_egl_update_format(*(d->eglContext), d->glFormat);
201
202 // Create a new context for the configuration.
203 if (!d->eglContext->createContext
204 (shareContext ? shareContext->d_func()->eglContext : 0)) {
205 delete d->eglContext;
206 d->eglContext = 0;
207 return false;
208 }
209 d->sharing = d->eglContext->isSharing();
210 if (d->sharing && shareContext)
211 const_cast<QGLContext *>(shareContext)->d_func()->sharing = true;
212
213#if defined(EGL_VERSION_1_1)
214 if (d->glFormat.swapInterval() != -1 && devType == QInternal::Widget)
215 eglSwapInterval(d->eglContext->display(), d->glFormat.swapInterval());
216#endif
217
218 // Create the EGL surface to draw into. We cannot use
219 // QEglContext::createSurface() because it does not have
220 // access to the QGLScreen.
221 d->eglSurface = qt_egl_create_surface(d->eglContext, device());
222 if (d->eglSurface == EGL_NO_SURFACE) {
223 delete d->eglContext;
224 d->eglContext = 0;
225 return false;
226 }
227
228 return true;
229}
230
231
232bool QGLWidget::event(QEvent *e)
233{
234 return QWidget::event(e);
235}
236
237
238void QGLWidget::resizeEvent(QResizeEvent *)
239{
240 Q_D(QGLWidget);
241 if (!isValid())
242 return;
243 makeCurrent();
244 if (!d->glcx->initialized())
245 glInit();
246 resizeGL(width(), height());
247 //handle overlay
248}
249
250const QGLContext* QGLWidget::overlayContext() const
251{
252 return 0;
253}
254
255void QGLWidget::makeOverlayCurrent()
256{
257 //handle overlay
258}
259
260void QGLWidget::updateOverlayGL()
261{
262 //handle overlay
263}
264
265void QGLWidget::setContext(QGLContext *context, const QGLContext* shareContext, bool deleteOldContext)
266{
267 Q_D(QGLWidget);
268 if(context == 0) {
269 qWarning("QGLWidget::setContext: Cannot set null context");
270 return;
271 }
272
273 if(d->glcx)
274 d->glcx->doneCurrent();
275 QGLContext* oldcx = d->glcx;
276 d->glcx = context;
277 if(!d->glcx->isValid())
278 d->glcx->create(shareContext ? shareContext : oldcx);
279 if(deleteOldContext)
280 delete oldcx;
281}
282
283void QGLWidgetPrivate::init(QGLContext *context, const QGLWidget* shareWidget)
284{
285 Q_Q(QGLWidget);
286
287 QGLScreen *glScreen = glScreenForDevice(q);
288 if (glScreen) {
289 wsurf = static_cast<QWSGLWindowSurface*>(glScreen->createSurface(q));
290 q->setWindowSurface(wsurf);
291 }
292
293 initContext(context, shareWidget);
294
295 if(q->isValid() && glcx->format().hasOverlay()) {
296 //no overlay
297 qWarning("QtOpenGL ES doesn't currently support overlays");
298 }
299}
300
301void QGLWidgetPrivate::cleanupColormaps()
302{
303}
304
305const QGLColormap & QGLWidget::colormap() const
306{
307 return d_func()->cmap;
308}
309
310void QGLWidget::setColormap(const QGLColormap &)
311{
312}
313
314void QGLExtensions::init()
315{
316 static bool init_done = false;
317
318 if (init_done)
319 return;
320 init_done = true;
321
322 // We need a context current to initialize the extensions,
323 // but getting a valid EGLNativeWindowType this early can be
324 // problematic under QWS. So use a pbuffer instead.
325 //
326 // Unfortunately OpenGL/ES 2.0 systems don't normally
327 // support pbuffers, so we have no choice but to try
328 // our luck with a window on those systems.
329#if defined(QT_OPENGL_ES_2)
330 QGLWidget tmpWidget;
331 tmpWidget.makeCurrent();
332
333 init_extensions();
334
335 tmpWidget.doneCurrent();
336#else
337 QGLPixelBuffer pbuffer(16, 16);
338 pbuffer.makeCurrent();
339
340 init_extensions();
341
342 pbuffer.doneCurrent();
343#endif
344}
345
346QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.