summaryrefslogtreecommitdiffstats
path: root/simpleglscreen.cpp
diff options
context:
space:
mode:
authorDonald Carr <donald.carr@nokia.com>2010-08-04 18:47:41 +0000
committerDonald Carr <donald.carr@nokia.com>2010-08-04 18:47:41 +0000
commit77704a984b6819230d98445e0117fd24633624f0 (patch)
tree4dd9bbc9b402ef378050e68542e88d01860daec8 /simpleglscreen.cpp
Initial commit
Diffstat (limited to 'simpleglscreen.cpp')
-rw-r--r--simpleglscreen.cpp305
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 &region)
+{
+ // Not used in this implementation.
+ Q_UNUSED(img);
+ Q_UNUSED(topLeft);
+ Q_UNUSED(region);
+}
+
+void SimpleGLScreen::solidFill(const QColor &color, const QRegion &region)
+{
+ // 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