diff -r 000000000000 -r 1918ee327afb src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.cpp Mon Jan 11 14:00:40 2010 +0000 @@ -0,0 +1,351 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "pvreglscreen.h" +#include "pvreglwindowsurface.h" +#include "pvrqwsdrawable_p.h" +#include +#include +#ifndef QT_NO_QWS_TRANSFORMED +#include +#endif +#include +#include +#include +#include +#include + +//![0] +PvrEglScreen::PvrEglScreen(int displayId) + : QGLScreen(displayId) +{ + setOptions(NativeWindows); + setSupportsBlitInClients(true); + setSurfaceFunctions(new PvrEglScreenSurfaceFunctions(this, displayId)); +//![0] + fd = -1; + ttyfd = -1; + doGraphicsMode = true; + oldKdMode = KD_TEXT; + parent = 0; + + // Make sure that the EGL layer is initialized and the drivers loaded. + EGLDisplay dpy = eglGetDisplay((EGLNativeDisplayType)EGL_DEFAULT_DISPLAY); + if (!eglInitialize(dpy, 0, 0)) + qWarning("Could not initialize EGL display - are the drivers loaded?"); + + // Make sure that screen 0 is initialized. + pvrQwsScreenWindow(0); +} + +PvrEglScreen::~PvrEglScreen() +{ + if (fd >= 0) + ::close(fd); +} + +bool PvrEglScreen::initDevice() +{ + openTty(); + return true; +} + +bool PvrEglScreen::connect(const QString &displaySpec) +{ + if (!pvrQwsDisplayOpen()) + return false; + + // Initialize the QScreen properties. + data = (uchar *)(pvrQwsDisplay.screens[0].mapped); + w = pvrQwsDisplay.screens[0].screenRect.width; + h = pvrQwsDisplay.screens[0].screenRect.height; + lstep = pvrQwsDisplay.screens[0].screenStride; + dw = w; + dh = h; + size = h * lstep; + mapsize = size; + switch (pvrQwsDisplay.screens[0].pixelFormat) { + case PVR2D_RGB565: + d = 16; + setPixelFormat(QImage::Format_RGB16); + break; + case PVR2D_ARGB4444: + d = 16; + setPixelFormat(QImage::Format_ARGB4444_Premultiplied); + break; + case PVR2D_ARGB8888: + d = 32; + setPixelFormat(QImage::Format_ARGB32_Premultiplied); + break; + default: + pvrQwsDisplayClose(); + qWarning("PvrEglScreen::connect: unsupported pixel format %d", (int)(pvrQwsDisplay.screens[0].pixelFormat)); + return false; + } + + // Handle display physical size spec. + QStringList displayArgs = displaySpec.split(QLatin1Char(':')); + QRegExp mmWidthRx(QLatin1String("mmWidth=?(\\d+)")); + int dimIdxW = displayArgs.indexOf(mmWidthRx); + QRegExp mmHeightRx(QLatin1String("mmHeight=?(\\d+)")); + int dimIdxH = displayArgs.indexOf(mmHeightRx); + if (dimIdxW >= 0) { + mmWidthRx.exactMatch(displayArgs.at(dimIdxW)); + physWidth = mmWidthRx.cap(1).toInt(); + if (dimIdxH < 0) + physHeight = dh*physWidth/dw; + } + if (dimIdxH >= 0) { + mmHeightRx.exactMatch(displayArgs.at(dimIdxH)); + physHeight = mmHeightRx.cap(1).toInt(); + if (dimIdxW < 0) + physWidth = dw*physHeight/dh; + } + if (dimIdxW < 0 && dimIdxH < 0) { + const int dpi = 72; + physWidth = qRound(dw * 25.4 / dpi); + physHeight = qRound(dh * 25.4 / dpi); + } + + // Find the name of the tty device to use. + QRegExp ttyRegExp(QLatin1String("tty=(.*)")); + if (displayArgs.indexOf(ttyRegExp) != -1) + ttyDevice = ttyRegExp.cap(1); + if (displayArgs.contains(QLatin1String("nographicsmodeswitch"))) + doGraphicsMode = false; + + // The screen is ready. + return true; +} + +void PvrEglScreen::disconnect() +{ + pvrQwsDisplayClose(); +} + +void PvrEglScreen::shutdownDevice() +{ + closeTty(); +} + +void PvrEglScreen::blit(const QImage &img, const QPoint &topLeft, const QRegion ®ion) +{ + QGLScreen::blit(img, topLeft, region); + sync(); +} + +void PvrEglScreen::solidFill(const QColor &color, const QRegion ®ion) +{ + QGLScreen::solidFill(color, region); + sync(); +} + +bool PvrEglScreen::chooseContext + (QGLContext *context, const QGLContext *shareContext) +{ + // We use PvrEglScreenSurfaceFunctions instead. + Q_UNUSED(context); + Q_UNUSED(shareContext); + return false; +} + +bool PvrEglScreen::hasOpenGL() +{ + return true; +} + +//![1] +QWSWindowSurface* PvrEglScreen::createSurface(QWidget *widget) const +{ + if (qobject_cast(widget)) + return new PvrEglWindowSurface(widget, (PvrEglScreen *)this, displayId); + + return QScreen::createSurface(widget); +} + +QWSWindowSurface* PvrEglScreen::createSurface(const QString &key) const +{ + if (key == QLatin1String("PvrEgl")) + return new PvrEglWindowSurface(); + + return QScreen::createSurface(key); +} +//![1] + +#ifndef QT_NO_QWS_TRANSFORMED + +static const QScreen *parentScreen + (const QScreen *current, const QScreen *lookingFor) +{ + if (!current) + return 0; + switch (current->classId()) { + case QScreen::ProxyClass: + case QScreen::TransformedClass: { + const QScreen *child = + static_cast(current)->screen(); + if (child == lookingFor) + return current; + else + return parentScreen(child, lookingFor); + } + // Not reached. + + case QScreen::MultiClass: { + QList screens = current->subScreens(); + foreach (QScreen *screen, screens) { + if (screen == lookingFor) + return current; + const QScreen *parent = parentScreen(screen, lookingFor); + if (parent) + return parent; + } + } + break; + + default: break; + } + return 0; +} + +int PvrEglScreen::transformation() const +{ + // We need to search for our parent screen, which is assumed to be + // "Transformed". If it isn't, then there is no transformation. + // There is no direct method to get the parent screen so we need + // to search every screen until we find ourselves. + if (!parent && qt_screen != this) + parent = parentScreen(qt_screen, this); + if (!parent) + return 0; + if (parent->classId() != QScreen::TransformedClass) + return 0; + return 90 * static_cast(parent) + ->transformation(); +} + +#else + +int PvrEglScreen::transformation() const +{ + return 0; +} + +#endif + +void PvrEglScreen::sync() +{ + // Put code here to synchronize 2D and 3D operations if necessary. +} + +void PvrEglScreen::openTty() +{ + const char *const devs[] = {"/dev/tty0", "/dev/tty", "/dev/console", 0}; + + if (ttyDevice.isEmpty()) { + for (const char * const *dev = devs; *dev; ++dev) { + ttyfd = ::open(*dev, O_RDWR); + if (ttyfd != -1) + break; + } + } else { + ttyfd = ::open(ttyDevice.toAscii().constData(), O_RDWR); + } + + if (ttyfd == -1) + return; + + ::fcntl(ttyfd, F_SETFD, FD_CLOEXEC); + + if (doGraphicsMode) { + ioctl(ttyfd, KDGETMODE, &oldKdMode); + if (oldKdMode != KD_GRAPHICS) { + int ret = ioctl(ttyfd, KDSETMODE, KD_GRAPHICS); + if (ret == -1) + doGraphicsMode = false; + } + } + + // No blankin' screen, no blinkin' cursor!, no cursor! + const char termctl[] = "\033[9;0]\033[?33l\033[?25l\033[?1c"; + ::write(ttyfd, termctl, sizeof(termctl)); +} + +void PvrEglScreen::closeTty() +{ + if (ttyfd == -1) + return; + + if (doGraphicsMode) + ioctl(ttyfd, KDSETMODE, oldKdMode); + + // Blankin' screen, blinkin' cursor! + const char termctl[] = "\033[9;15]\033[?33h\033[?25h\033[?0c"; + ::write(ttyfd, termctl, sizeof(termctl)); + + ::close(ttyfd); + ttyfd = -1; +} + +//![2] +bool PvrEglScreenSurfaceFunctions::createNativeWindow(QWidget *widget, EGLNativeWindowType *native) +{ +//![2] + QWSWindowSurface *surface = + static_cast(widget->windowSurface()); + if (!surface) { + // The widget does not have a surface yet, so give it one. + surface = new PvrEglWindowSurface(widget, screen, displayId); + widget->setWindowSurface(surface); + } else if (surface->key() != QLatin1String("PvrEgl")) { + // The application has attached a QGLContext to an ordinary QWidget. + // Replace the widget's window surface with a new one that can do GL. + QRect geometry = widget->frameGeometry(); + geometry.moveTo(widget->mapToGlobal(QPoint(0, 0))); + surface = new PvrEglWindowSurface(widget, screen, displayId); + surface->setGeometry(geometry); + widget->setWindowSurface(surface); + widget->setAttribute(Qt::WA_NoSystemBackground, true); + } + PvrEglWindowSurface *nsurface = static_cast(surface); + *native = (EGLNativeWindowType)(nsurface->nativeDrawable()); + return true; +}