diff options
author | Donald Carr <donald.carr@nokia.com> | 2010-08-04 18:47:41 +0000 |
---|---|---|
committer | Donald Carr <donald.carr@nokia.com> | 2010-08-04 18:47:41 +0000 |
commit | 77704a984b6819230d98445e0117fd24633624f0 (patch) | |
tree | 4dd9bbc9b402ef378050e68542e88d01860daec8 /simpleglscreen.cpp |
Initial commit
Diffstat (limited to 'simpleglscreen.cpp')
-rw-r--r-- | simpleglscreen.cpp | 305 |
1 files changed, 305 insertions, 0 deletions
diff --git a/simpleglscreen.cpp b/simpleglscreen.cpp new file mode 100644 index 0000000..a10a619 --- /dev/null +++ b/simpleglscreen.cpp @@ -0,0 +1,305 @@ +/**************************************************************************** +** +** 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 "simpleglscreen.h" +#include "simpleglwindowsurface.h" +#include <QApplication> +#include <QRegExp> +#include <QDebug> +#include <QtGui/qwindowsystem_qws.h> +#include <QtGui/private/qeglcontext_p.h> +#ifdef OPENGL_USBHP_INIT +extern "C" { +#include <linuxusbhp.h> +}; +#endif + +QT_BEGIN_NAMESPACE + +static inline bool setIntOption(const QStringList &arguments, const QString &variable, int *value) +{ + Q_ASSERT(value); + QRegExp rx(QString::fromLatin1("%1=?(\\d+)").arg(variable)); + rx.setCaseSensitivity(Qt::CaseInsensitive); + if (arguments.indexOf(rx) != -1) { + *value = rx.cap(1).toInt(); + return true; + } + return false; +} + +SimpleGLScreen::SimpleGLScreen(int display_id) + : QGLScreen(display_id) +{ +#ifdef QT_QWS_CLIENTBLIT + setSupportsBlitInClients(false); +#endif + setOptions(NativeWindows); + setSurfaceFunctions(new SimpleGLScreenSurfaceFunctions(this)); + +#ifdef OPENGL_USBHP_INIT + // Initialize the USB connection to the OpenGL display device. + // Some Broadcom USB-based development devices need this. + initLibrary(); +#endif +} + +SimpleGLScreen::~SimpleGLScreen() +{ +} + +bool SimpleGLScreen::hasOpenGL() +{ + return true; +} + +bool SimpleGLScreen::initDevice() +{ + return true; +} + +// Edit this function to create a different default root window handle than 0. +EGLNativeWindowType SimpleGLScreen::defaultRootWindowHandle() +{ + return 0; +} + +static QImage::Format egl_config_to_image_format(QEglContext *context) +{ + EGLint red = context->configAttrib(EGL_RED_SIZE); + EGLint green = context->configAttrib(EGL_GREEN_SIZE); + EGLint blue = context->configAttrib(EGL_BLUE_SIZE); + EGLint alpha = context->configAttrib(EGL_ALPHA_SIZE); + + if (red == 8 && green == 8 && blue == 8 && alpha == 8) + return QImage::Format_ARGB32; + else if (red == 8 && green == 8 && blue == 8 && alpha == 0) + return QImage::Format_RGB32; + else if (red == 5 && green == 6 && blue == 5 && alpha == 0) + return QImage::Format_RGB16; + else if (red == 4 && green == 4 && blue == 4 && alpha == 4) + return QImage::Format_ARGB4444_Premultiplied; + else + return QImage::Format_ARGB32; +} + +bool SimpleGLScreen::connect(const QString &displaySpec) +{ + const QStringList displayArgs = displaySpec.split(QLatin1Char(':'), QString::SkipEmptyParts); + + // Initialize EGL and choose a default EGLConfig. + QEglContext *context = new QEglContext(); + context->setApi(QEgl::OpenGL); + + QEglProperties configProps; + if (displayArgs.contains(QLatin1String("argb32"))) { + configProps.setPixelFormat(QImage::Format_ARGB32); + } else if (displayArgs.contains(QLatin1String("rgb16"))) { + configProps.setPixelFormat(QImage::Format_RGB16); + } else { + qWarning("SimpleGLScreen: pixel format unspecified, trying argb32"); + configProps.setPixelFormat(QImage::Format_ARGB32); + } + +#if defined(QT_OPENGL_ES_2) + configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT); +#elif defined(QT_OPENGL_ES_1) + configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT); +#elif defined(QT_OPENGL_ES) + configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT); +#endif + + configProps.setRenderableType(QEgl::OpenGL); + if (!context->chooseConfig(configProps)) { + delete context; + return 0; + } + + // Create a full-screen window based on the native handle so that + // we can query its width and height. + QEglProperties props; + EGLSurface rootWindow = eglCreateWindowSurface + (context->display(), context->config(), + defaultRootWindowHandle(), props.properties()); + if (rootWindow == EGL_NO_SURFACE) { + qWarning("SimpleGLScreen: could not create the full-screen window"); + qWarning("SimpleGLScreen: may need to modify defaultRootWindowHandle()"); + delete context; + context = 0; + return false; + } + +#ifdef DONT_QUERY_EGL_DIMENSIONS + //Default to 720p, unless overridden + w = 1280; + h = 720; + setIntOption(displayArgs, QLatin1String("width"), &w); + setIntOption(displayArgs, QLatin1String("height"), &h); +#else + // Fetch the root window properties. + eglQuerySurface(context->display(), rootWindow, EGL_WIDTH, &w); + eglQuerySurface(context->display(), rootWindow, EGL_HEIGHT, &h); +#endif + + QImage::Format format = egl_config_to_image_format(context); + switch (format) { + case QImage::Format_ARGB32_Premultiplied: + case QImage::Format_ARGB32: + case QImage::Format_RGB32: + default: + d = 32; + lstep = w * 4; + break; + case QImage::Format_RGB16: + case QImage::Format_ARGB4444_Premultiplied: + d = 16; + lstep = w * 2; + break; + } + pixeltype = NormalPixel; + dw = w; + dh = h; + size = h * lstep; + mapsize = size; + setPixelFormat(format); + qDebug("screen size: %dx%dx%d", w, h, d); + + // We don't need the temporary surface or QEglContext any more. + eglDestroySurface(context->display(), rootWindow); + delete context; + + // Handle display physical size spec. From qscreenlinuxfb_qws.cpp. + 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); + } + + return true; +} + +void SimpleGLScreen::disconnect() +{ + // Nothing to do here. +} + +void SimpleGLScreen::shutdownDevice() +{ + QScreen::shutdownDevice(); +} + +void SimpleGLScreen::setMode(int,int,int) +{ + // Mode setting is not supported. +} + +void SimpleGLScreen::exposeRegion(QRegion, int) +{ + // We don't support raster composition of the screen. +} + +void SimpleGLScreen::blit + (const QImage &img, const QPoint &topLeft, const QRegion ®ion) +{ + // Not used in this implementation. + Q_UNUSED(img); + Q_UNUSED(topLeft); + Q_UNUSED(region); +} + +void SimpleGLScreen::solidFill(const QColor &color, const QRegion ®ion) +{ + // Not used in this implementation. + Q_UNUSED(color); + Q_UNUSED(region); +} + +// Create the client-side surface implementation. +QWSWindowSurface* SimpleGLScreen::createSurface(QWidget *widget) const +{ + if (QApplication::type() == QApplication::GuiServer) { + if (qobject_cast<QGLWidget*>(widget)) + return new SimpleGLWindowSurface(widget, const_cast<SimpleGLScreen *>(this)); + else + return QGLScreen::createSurface(widget); + } + +#ifndef QT_NO_QWS_MULTIPROCESS + qFatal("SimpleGLScreen: multiprocess is not supported by this screen driver"); +#endif + return 0; +} + +// Create the server-side surface implementation. +QWSWindowSurface* SimpleGLScreen::createSurface(const QString &key) const +{ + if (key == QLatin1String("simplegl")) + return new SimpleGLWindowSurface(); + else + return QGLScreen::createSurface(key); +} + +bool SimpleGLScreenSurfaceFunctions::createNativeWindow + (QWidget *widget, EGLNativeWindowType *native) +{ + // Every widget gets the root window handle. + Q_UNUSED(widget); + *native = screen->defaultRootWindowHandle(); + return true; +} + +QT_END_NAMESPACE |