/**************************************************************************** ** ** 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 #include #include #include #include #ifdef OPENGL_USBHP_INIT extern "C" { #include }; #endif #ifdef RASP_PI #include "interface/vchiq_arm/vchiq_if.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) { #ifdef RASP_PI VCHI_INSTANCE_T vchiq_instance; VCHI_CONNECTION_T *vchi_connection; vcos_init(); if (vchi_initialise(&vchiq_instance) != VCHIQ_SUCCESS) { printf("* failed to open vchiq instance\n"); return -1; } //create a vchi connection if ( vchi_connect( NULL, 0, vchiq_instance ) != 0) { printf( "VCHI connection failed\n" ); return -1; } vc_vchi_dispmanx_init( vchiq_instance, &vchi_connection, 1 ); #endif 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(widget)) return new SimpleGLWindowSurface(widget, const_cast(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