1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the plugins of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
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.
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.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #include "pvreglscreen.h"
43 #include "pvreglwindowsurface.h"
44 #include "pvrqwsdrawable_p.h"
46 #include <qwindowsystem_qws.h>
47 #ifndef QT_NO_QWS_TRANSFORMED
48 #include <qscreentransformed_qws.h>
51 #include <sys/ioctl.h>
57 PvrEglScreen::PvrEglScreen(int displayId)
58 : QGLScreen(displayId)
60 setOptions(NativeWindows);
61 setSupportsBlitInClients(true);
62 setSurfaceFunctions(new PvrEglScreenSurfaceFunctions(this, displayId));
66 doGraphicsMode = true;
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?");
75 // Make sure that screen 0 is initialized.
76 pvrQwsScreenWindow(0);
79 PvrEglScreen::~PvrEglScreen()
85 bool PvrEglScreen::initDevice()
91 bool PvrEglScreen::connect(const QString &displaySpec)
93 if (!pvrQwsDisplayOpen())
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;
105 switch (pvrQwsDisplay.screens[0].pixelFormat) {
108 setPixelFormat(QImage::Format_RGB16);
112 setPixelFormat(QImage::Format_ARGB4444_Premultiplied);
116 setPixelFormat(QImage::Format_ARGB32_Premultiplied);
119 pvrQwsDisplayClose();
120 qWarning("PvrEglScreen::connect: unsupported pixel format %d", (int)(pvrQwsDisplay.screens[0].pixelFormat));
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);
131 mmWidthRx.exactMatch(displayArgs.at(dimIdxW));
132 physWidth = mmWidthRx.cap(1).toInt();
134 physHeight = dh*physWidth/dw;
137 mmHeightRx.exactMatch(displayArgs.at(dimIdxH));
138 physHeight = mmHeightRx.cap(1).toInt();
140 physWidth = dw*physHeight/dh;
142 if (dimIdxW < 0 && dimIdxH < 0) {
144 physWidth = qRound(dw * 25.4 / dpi);
145 physHeight = qRound(dh * 25.4 / dpi);
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;
155 // The screen is ready.
159 void PvrEglScreen::disconnect()
161 pvrQwsDisplayClose();
164 void PvrEglScreen::shutdownDevice()
169 void PvrEglScreen::blit(const QImage &img, const QPoint &topLeft, const QRegion ®ion)
171 QGLScreen::blit(img, topLeft, region);
175 void PvrEglScreen::solidFill(const QColor &color, const QRegion ®ion)
177 QGLScreen::solidFill(color, region);
181 bool PvrEglScreen::chooseContext
182 (QGLContext *context, const QGLContext *shareContext)
184 // We use PvrEglScreenSurfaceFunctions instead.
186 Q_UNUSED(shareContext);
190 bool PvrEglScreen::hasOpenGL()
196 QWSWindowSurface* PvrEglScreen::createSurface(QWidget *widget) const
198 if (qobject_cast<QGLWidget*>(widget))
199 return new PvrEglWindowSurface(widget, (PvrEglScreen *)this, displayId);
201 return QScreen::createSurface(widget);
204 QWSWindowSurface* PvrEglScreen::createSurface(const QString &key) const
206 if (key == QLatin1String("PvrEgl"))
207 return new PvrEglWindowSurface();
209 return QScreen::createSurface(key);
213 #ifndef QT_NO_QWS_TRANSFORMED
215 static const QScreen *parentScreen
216 (const QScreen *current, const QScreen *lookingFor)
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)
228 return parentScreen(child, lookingFor);
232 case QScreen::MultiClass: {
233 QList<QScreen *> screens = current->subScreens();
234 foreach (QScreen *screen, screens) {
235 if (screen == lookingFor)
237 const QScreen *parent = parentScreen(screen, lookingFor);
249 int PvrEglScreen::transformation() const
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);
259 if (parent->classId() != QScreen::TransformedClass)
261 return 90 * static_cast<const QTransformedScreen *>(parent)
262 ->transformOrientation();
267 int PvrEglScreen::transformation() const
274 void PvrEglScreen::sync()
276 // Put code here to synchronize 2D and 3D operations if necessary.
279 void PvrEglScreen::openTty()
281 const char *const devs[] = {"/dev/tty0", "/dev/tty", "/dev/console", 0};
283 if (ttyDevice.isEmpty()) {
284 for (const char * const *dev = devs; *dev; ++dev) {
285 ttyfd = ::open(*dev, O_RDWR);
290 ttyfd = ::open(ttyDevice.toAscii().constData(), O_RDWR);
296 ::fcntl(ttyfd, F_SETFD, FD_CLOEXEC);
298 if (doGraphicsMode) {
299 ioctl(ttyfd, KDGETMODE, &oldKdMode);
300 if (oldKdMode != KD_GRAPHICS) {
301 int ret = ioctl(ttyfd, KDSETMODE, KD_GRAPHICS);
303 doGraphicsMode = false;
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));
312 void PvrEglScreen::closeTty()
318 ioctl(ttyfd, KDSETMODE, oldKdMode);
320 // Blankin' screen, blinkin' cursor!
321 const char termctl[] = "\033[9;15]\033[?33h\033[?25h\033[?0c";
322 ::write(ttyfd, termctl, sizeof(termctl));
329 bool PvrEglScreenSurfaceFunctions::createNativeWindow(QWidget *widget, EGLNativeWindowType *native)
332 QWSWindowSurface *surface =
333 static_cast<QWSWindowSurface *>(widget->windowSurface());
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);
348 PvrEglWindowSurface *nsurface = static_cast<PvrEglWindowSurface*>(surface);
349 *native = (EGLNativeWindowType)(nsurface->nativeDrawable());