source: trunk/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.cpp@ 769

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

trunk: Merged in qt 4.6.3 sources from branches/vendor/nokia/qt.

  • Property svn:eol-style set to native
File size: 10.3 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 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#include "pvreglscreen.h"
43#include "pvreglwindowsurface.h"
44#include "pvrqwsdrawable_p.h"
45#include <QRegExp>
46#include <qwindowsystem_qws.h>
47#ifndef QT_NO_QWS_TRANSFORMED
48#include <qscreentransformed_qws.h>
49#endif
50#include <sys/stat.h>
51#include <sys/ioctl.h>
52#include <sys/kd.h>
53#include <fcntl.h>
54#include <unistd.h>
55
56//![0]
57PvrEglScreen::PvrEglScreen(int displayId)
58 : QGLScreen(displayId)
59{
60 setOptions(NativeWindows);
61 setSupportsBlitInClients(true);
62 setSurfaceFunctions(new PvrEglScreenSurfaceFunctions(this, displayId));
63//![0]
64 fd = -1;
65 ttyfd = -1;
66 doGraphicsMode = true;
67 oldKdMode = KD_TEXT;
68 parent = 0;
69
70 // Make sure that the EGL layer is initialized and the drivers loaded.
71 EGLDisplay dpy = eglGetDisplay((EGLNativeDisplayType)EGL_DEFAULT_DISPLAY);
72 if (!eglInitialize(dpy, 0, 0))
73 qWarning("Could not initialize EGL display - are the drivers loaded?");
74
75 // Make sure that screen 0 is initialized.
76 pvrQwsScreenWindow(0);
77}
78
79PvrEglScreen::~PvrEglScreen()
80{
81 if (fd >= 0)
82 ::close(fd);
83}
84
85bool PvrEglScreen::initDevice()
86{
87 openTty();
88 return true;
89}
90
91bool PvrEglScreen::connect(const QString &displaySpec)
92{
93 if (!pvrQwsDisplayOpen())
94 return false;
95
96 // Initialize the QScreen properties.
97 data = (uchar *)(pvrQwsDisplay.screens[0].mapped);
98 w = pvrQwsDisplay.screens[0].screenRect.width;
99 h = pvrQwsDisplay.screens[0].screenRect.height;
100 lstep = pvrQwsDisplay.screens[0].screenStride;
101 dw = w;
102 dh = h;
103 size = h * lstep;
104 mapsize = size;
105 switch (pvrQwsDisplay.screens[0].pixelFormat) {
106 case PVR2D_RGB565:
107 d = 16;
108 setPixelFormat(QImage::Format_RGB16);
109 break;
110 case PVR2D_ARGB4444:
111 d = 16;
112 setPixelFormat(QImage::Format_ARGB4444_Premultiplied);
113 break;
114 case PVR2D_ARGB8888:
115 d = 32;
116 setPixelFormat(QImage::Format_ARGB32_Premultiplied);
117 break;
118 default:
119 pvrQwsDisplayClose();
120 qWarning("PvrEglScreen::connect: unsupported pixel format %d", (int)(pvrQwsDisplay.screens[0].pixelFormat));
121 return false;
122 }
123
124 // Handle display physical size spec.
125 QStringList displayArgs = displaySpec.split(QLatin1Char(':'));
126 QRegExp mmWidthRx(QLatin1String("mmWidth=?(\\d+)"));
127 int dimIdxW = displayArgs.indexOf(mmWidthRx);
128 QRegExp mmHeightRx(QLatin1String("mmHeight=?(\\d+)"));
129 int dimIdxH = displayArgs.indexOf(mmHeightRx);
130 if (dimIdxW >= 0) {
131 mmWidthRx.exactMatch(displayArgs.at(dimIdxW));
132 physWidth = mmWidthRx.cap(1).toInt();
133 if (dimIdxH < 0)
134 physHeight = dh*physWidth/dw;
135 }
136 if (dimIdxH >= 0) {
137 mmHeightRx.exactMatch(displayArgs.at(dimIdxH));
138 physHeight = mmHeightRx.cap(1).toInt();
139 if (dimIdxW < 0)
140 physWidth = dw*physHeight/dh;
141 }
142 if (dimIdxW < 0 && dimIdxH < 0) {
143 const int dpi = 72;
144 physWidth = qRound(dw * 25.4 / dpi);
145 physHeight = qRound(dh * 25.4 / dpi);
146 }
147
148 // Find the name of the tty device to use.
149 QRegExp ttyRegExp(QLatin1String("tty=(.*)"));
150 if (displayArgs.indexOf(ttyRegExp) != -1)
151 ttyDevice = ttyRegExp.cap(1);
152 if (displayArgs.contains(QLatin1String("nographicsmodeswitch")))
153 doGraphicsMode = false;
154
155 // The screen is ready.
156 return true;
157}
158
159void PvrEglScreen::disconnect()
160{
161 pvrQwsDisplayClose();
162}
163
164void PvrEglScreen::shutdownDevice()
165{
166 closeTty();
167}
168
169void PvrEglScreen::blit(const QImage &img, const QPoint &topLeft, const QRegion &region)
170{
171 QGLScreen::blit(img, topLeft, region);
172 sync();
173}
174
175void PvrEglScreen::solidFill(const QColor &color, const QRegion &region)
176{
177 QGLScreen::solidFill(color, region);
178 sync();
179}
180
181bool PvrEglScreen::chooseContext
182 (QGLContext *context, const QGLContext *shareContext)
183{
184 // We use PvrEglScreenSurfaceFunctions instead.
185 Q_UNUSED(context);
186 Q_UNUSED(shareContext);
187 return false;
188}
189
190bool PvrEglScreen::hasOpenGL()
191{
192 return true;
193}
194
195//![1]
196QWSWindowSurface* PvrEglScreen::createSurface(QWidget *widget) const
197{
198 if (qobject_cast<QGLWidget*>(widget))
199 return new PvrEglWindowSurface(widget, (PvrEglScreen *)this, displayId);
200
201 return QScreen::createSurface(widget);
202}
203
204QWSWindowSurface* PvrEglScreen::createSurface(const QString &key) const
205{
206 if (key == QLatin1String("PvrEgl"))
207 return new PvrEglWindowSurface();
208
209 return QScreen::createSurface(key);
210}
211//![1]
212
213#ifndef QT_NO_QWS_TRANSFORMED
214
215static const QScreen *parentScreen
216 (const QScreen *current, const QScreen *lookingFor)
217{
218 if (!current)
219 return 0;
220 switch (current->classId()) {
221 case QScreen::ProxyClass:
222 case QScreen::TransformedClass: {
223 const QScreen *child =
224 static_cast<const QProxyScreen *>(current)->screen();
225 if (child == lookingFor)
226 return current;
227 else
228 return parentScreen(child, lookingFor);
229 }
230 // Not reached.
231
232 case QScreen::MultiClass: {
233 QList<QScreen *> screens = current->subScreens();
234 foreach (QScreen *screen, screens) {
235 if (screen == lookingFor)
236 return current;
237 const QScreen *parent = parentScreen(screen, lookingFor);
238 if (parent)
239 return parent;
240 }
241 }
242 break;
243
244 default: break;
245 }
246 return 0;
247}
248
249int PvrEglScreen::transformation() const
250{
251 // We need to search for our parent screen, which is assumed to be
252 // "Transformed". If it isn't, then there is no transformation.
253 // There is no direct method to get the parent screen so we need
254 // to search every screen until we find ourselves.
255 if (!parent && qt_screen != this)
256 parent = parentScreen(qt_screen, this);
257 if (!parent)
258 return 0;
259 if (parent->classId() != QScreen::TransformedClass)
260 return 0;
261 return 90 * static_cast<const QTransformedScreen *>(parent)
262 ->transformOrientation();
263}
264
265#else
266
267int PvrEglScreen::transformation() const
268{
269 return 0;
270}
271
272#endif
273
274void PvrEglScreen::sync()
275{
276 // Put code here to synchronize 2D and 3D operations if necessary.
277}
278
279void PvrEglScreen::openTty()
280{
281 const char *const devs[] = {"/dev/tty0", "/dev/tty", "/dev/console", 0};
282
283 if (ttyDevice.isEmpty()) {
284 for (const char * const *dev = devs; *dev; ++dev) {
285 ttyfd = ::open(*dev, O_RDWR);
286 if (ttyfd != -1)
287 break;
288 }
289 } else {
290 ttyfd = ::open(ttyDevice.toAscii().constData(), O_RDWR);
291 }
292
293 if (ttyfd == -1)
294 return;
295
296 ::fcntl(ttyfd, F_SETFD, FD_CLOEXEC);
297
298 if (doGraphicsMode) {
299 ioctl(ttyfd, KDGETMODE, &oldKdMode);
300 if (oldKdMode != KD_GRAPHICS) {
301 int ret = ioctl(ttyfd, KDSETMODE, KD_GRAPHICS);
302 if (ret == -1)
303 doGraphicsMode = false;
304 }
305 }
306
307 // No blankin' screen, no blinkin' cursor!, no cursor!
308 const char termctl[] = "\033[9;0]\033[?33l\033[?25l\033[?1c";
309 ::write(ttyfd, termctl, sizeof(termctl));
310}
311
312void PvrEglScreen::closeTty()
313{
314 if (ttyfd == -1)
315 return;
316
317 if (doGraphicsMode)
318 ioctl(ttyfd, KDSETMODE, oldKdMode);
319
320 // Blankin' screen, blinkin' cursor!
321 const char termctl[] = "\033[9;15]\033[?33h\033[?25h\033[?0c";
322 ::write(ttyfd, termctl, sizeof(termctl));
323
324 ::close(ttyfd);
325 ttyfd = -1;
326}
327
328//![2]
329bool PvrEglScreenSurfaceFunctions::createNativeWindow(QWidget *widget, EGLNativeWindowType *native)
330{
331//![2]
332 QWSWindowSurface *surface =
333 static_cast<QWSWindowSurface *>(widget->windowSurface());
334 if (!surface) {
335 // The widget does not have a surface yet, so give it one.
336 surface = new PvrEglWindowSurface(widget, screen, displayId);
337 widget->setWindowSurface(surface);
338 } else if (surface->key() != QLatin1String("PvrEgl")) {
339 // The application has attached a QGLContext to an ordinary QWidget.
340 // Replace the widget's window surface with a new one that can do GL.
341 QRect geometry = widget->frameGeometry();
342 geometry.moveTo(widget->mapToGlobal(QPoint(0, 0)));
343 surface = new PvrEglWindowSurface(widget, screen, displayId);
344 surface->setGeometry(geometry);
345 widget->setWindowSurface(surface);
346 widget->setAttribute(Qt::WA_NoSystemBackground, true);
347 }
348 PvrEglWindowSurface *nsurface = static_cast<PvrEglWindowSurface*>(surface);
349 *native = (EGLNativeWindowType)(nsurface->nativeDrawable());
350 return true;
351}
Note: See TracBrowser for help on using the repository browser.