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

Last change on this file since 616 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
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 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 }