diff options
Diffstat (limited to 'src/plugins/platforms')
119 files changed, 5160 insertions, 1151 deletions
diff --git a/src/plugins/platforms/directfb/qdirectfbglcontext.cpp b/src/plugins/platforms/directfb/qdirectfbglcontext.cpp index ee46691..85effc9 100644 --- a/src/plugins/platforms/directfb/qdirectfbglcontext.cpp +++ b/src/plugins/platforms/directfb/qdirectfbglcontext.cpp @@ -70,11 +70,13 @@ QDirectFbGLContext::QDirectFbGLContext(IDirectFBGL *glContext) void QDirectFbGLContext::makeCurrent() { + QPlatformGLContext::makeCurrent(); m_dfbGlContext->Lock(m_dfbGlContext); } void QDirectFbGLContext::doneCurrent() { + QPlatformGLContext::doneCurrent(); m_dfbGlContext->Unlock(m_dfbGlContext); } diff --git a/src/plugins/platforms/eglconvenience/eglconvenience.pri b/src/plugins/platforms/eglconvenience/eglconvenience.pri new file mode 100644 index 0000000..322d4e4 --- /dev/null +++ b/src/plugins/platforms/eglconvenience/eglconvenience.pri @@ -0,0 +1,7 @@ +INCLUDEPATH += $$PWD + +SOURCES += \ + $$PWD/qeglconvenience.cpp + +HEADERS += \ + $$PWD/qeglconvenience.h diff --git a/src/plugins/platforms/eglconvenience/qeglconvenience.cpp b/src/plugins/platforms/eglconvenience/qeglconvenience.cpp index ec4577a..df7abc1 100644 --- a/src/plugins/platforms/eglconvenience/qeglconvenience.cpp +++ b/src/plugins/platforms/eglconvenience/qeglconvenience.cpp @@ -206,12 +206,12 @@ bool q_reduceConfigAttributes(QVector<EGLint> *configAttributes) return false; } -EGLConfig q_configFromQPlatformWindowFormat(EGLDisplay display, const QPlatformWindowFormat &format, bool highestPixelFormat) +EGLConfig q_configFromQPlatformWindowFormat(EGLDisplay display, const QPlatformWindowFormat &format, bool highestPixelFormat, int surfaceType) { EGLConfig cfg = 0; QVector<EGLint> configureAttributes = q_createConfigAttributesFromFormat(format); configureAttributes.append(EGL_SURFACE_TYPE); //we only support eglconfigs for windows for now - configureAttributes.append(EGL_WINDOW_BIT); + configureAttributes.append(surfaceType); configureAttributes.append(EGL_RENDERABLE_TYPE); if (format.windowApi() == QPlatformWindowFormat::OpenVG) { diff --git a/src/plugins/platforms/eglconvenience/qeglconvenience.h b/src/plugins/platforms/eglconvenience/qeglconvenience.h index 8668095..c7d3d61 100644 --- a/src/plugins/platforms/eglconvenience/qeglconvenience.h +++ b/src/plugins/platforms/eglconvenience/qeglconvenience.h @@ -46,16 +46,12 @@ #include <QtGui/QPlatformWindowFormat> #include <QtCore/QVector> -#ifdef Q_PLATFORM_WAYLAND -#include "qwaylandinclude.h" -#else #include <EGL/egl.h> -#endif QT_BEGIN_NAMESPACE QVector<EGLint> q_createConfigAttributesFromFormat(const QPlatformWindowFormat &format); bool q_reduceConfigAttributes(QVector<EGLint> *configAttributes); -EGLConfig q_configFromQPlatformWindowFormat(EGLDisplay display, const QPlatformWindowFormat &format, bool highestPixelFormat = false); +EGLConfig q_configFromQPlatformWindowFormat(EGLDisplay display, const QPlatformWindowFormat &format, bool highestPixelFormat = false, int surfaceType = EGL_WINDOW_BIT); QPlatformWindowFormat qt_qPlatformWindowFormatFromConfig(EGLDisplay display, const EGLConfig config); bool q_hasEglExtension(EGLDisplay display,const char* extensionName); diff --git a/src/plugins/platforms/eglconvenience/qeglplatformcontext.cpp b/src/plugins/platforms/eglconvenience/qeglplatformcontext.cpp index 9a2bc61..ae5215f 100644 --- a/src/plugins/platforms/eglconvenience/qeglplatformcontext.cpp +++ b/src/plugins/platforms/eglconvenience/qeglplatformcontext.cpp @@ -146,11 +146,6 @@ void* QEGLPlatformContext::getProcAddress(const QString& procName) return (void *)eglGetProcAddress(qPrintable(procName)); } -void QEGLPlatformContext::makeDefaultSharedContext() -{ - setDefaultSharedContext(this); -} - QPlatformWindowFormat QEGLPlatformContext::platformWindowFormat() const { return m_windowFormat; diff --git a/src/plugins/platforms/eglconvenience/qeglplatformcontext.h b/src/plugins/platforms/eglconvenience/qeglplatformcontext.h index d688660..69835d7 100644 --- a/src/plugins/platforms/eglconvenience/qeglplatformcontext.h +++ b/src/plugins/platforms/eglconvenience/qeglplatformcontext.h @@ -56,8 +56,6 @@ public: void swapBuffers(); void* getProcAddress(const QString& procName); - void makeDefaultSharedContext(); - QPlatformWindowFormat platformWindowFormat() const; EGLContext eglContext() const; diff --git a/src/plugins/platforms/eglconvenience/qxlibeglintegration.cpp b/src/plugins/platforms/eglconvenience/qxlibeglintegration.cpp index 7f296c5..45746e9 100644 --- a/src/plugins/platforms/eglconvenience/qxlibeglintegration.cpp +++ b/src/plugins/platforms/eglconvenience/qxlibeglintegration.cpp @@ -52,13 +52,11 @@ static int countBits(unsigned long mask) return count; } -VisualID QXlibEglIntegration::getCompatibleVisualId(Display *display, EGLConfig config) +VisualID QXlibEglIntegration::getCompatibleVisualId(Display *display, EGLDisplay eglDisplay, EGLConfig config) { VisualID visualId = 0; EGLint eglValue = 0; - EGLDisplay eglDisplay = eglGetDisplay(display); - EGLint configRedSize = 0; eglGetConfigAttrib(eglDisplay, config, EGL_RED_SIZE, &configRedSize); diff --git a/src/plugins/platforms/eglconvenience/qxlibeglintegration.h b/src/plugins/platforms/eglconvenience/qxlibeglintegration.h index 51996da..6c2e266 100644 --- a/src/plugins/platforms/eglconvenience/qxlibeglintegration.h +++ b/src/plugins/platforms/eglconvenience/qxlibeglintegration.h @@ -47,7 +47,7 @@ class QXlibEglIntegration { public: - static VisualID getCompatibleVisualId(Display *display, EGLConfig config); + static VisualID getCompatibleVisualId(Display *display, EGLDisplay eglDisplay, EGLConfig config); }; #endif // QTESTLITEEGLINTEGRATION_H diff --git a/src/plugins/platforms/eglconvenience/xlibeglintegration.pri b/src/plugins/platforms/eglconvenience/xlibeglintegration.pri new file mode 100644 index 0000000..9404a70 --- /dev/null +++ b/src/plugins/platforms/eglconvenience/xlibeglintegration.pri @@ -0,0 +1,7 @@ +INCLUDEPATH += $$PWD + +HEADERS += \ + $$PWD/qxlibeglintegration.h + +SOURCES += \ + $$PWD/qxlibeglintegration.cpp diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp index 78981f9..1bc0806 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp @@ -44,12 +44,12 @@ #include "qeglfswindow.h" #include "qeglfswindowsurface.h" +#include "qgenericunixfontdatabase.h" + #include <QtGui/QPlatformWindow> #include <QtGui/QPlatformWindowFormat> #include <QtOpenGL/private/qpixmapdata_gl_p.h> -#include "qgenericunixfontdatabase.h" - #include <EGL/egl.h> QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.cpp b/src/plugins/platforms/eglfs/qeglfsscreen.cpp index 2200d1d..b6f2805 100644 --- a/src/plugins/platforms/eglfs/qeglfsscreen.cpp +++ b/src/plugins/platforms/eglfs/qeglfsscreen.cpp @@ -203,7 +203,6 @@ void QEglFSScreen::createAndSetPlatformContext() attribList[temp++] = EGL_NONE; QEGLPlatformContext *platformContext = new QEGLPlatformContext(m_dpy,config,attribList,m_surface,EGL_OPENGL_ES_API); - platformContext->makeDefaultSharedContext(); m_platformContext = platformContext; EGLint w,h; // screen size detection diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.h b/src/plugins/platforms/eglfs/qeglfsscreen.h index 6a2a504..f300842 100644 --- a/src/plugins/platforms/eglfs/qeglfsscreen.h +++ b/src/plugins/platforms/eglfs/qeglfsscreen.h @@ -44,6 +44,7 @@ #include <QPlatformScreen> +#include <QtCore/QTextStream> #include <EGL/egl.h> diff --git a/src/plugins/platforms/eglfs/qeglfswindow.h b/src/plugins/platforms/eglfs/qeglfswindow.h index ad51114..f125eab 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.h +++ b/src/plugins/platforms/eglfs/qeglfswindow.h @@ -45,12 +45,9 @@ #include "qeglfsintegration.h" #include "qeglfsscreen.h" - #include <QPlatformWindow> #include <QtGui/QWidget> -#include <EGL/egl.h> - QT_BEGIN_NAMESPACE class QEglFSWindow : public QPlatformWindow diff --git a/src/plugins/platforms/fontdatabases/genericunix/genericunix.pri b/src/plugins/platforms/fontdatabases/genericunix/genericunix.pri index dbcfbce..1153ab3 100644 --- a/src/plugins/platforms/fontdatabases/genericunix/genericunix.pri +++ b/src/plugins/platforms/fontdatabases/genericunix/genericunix.pri @@ -5,6 +5,6 @@ contains(QT_CONFIG, fontconfig) { include(../basicunix/basicunix.pri) } -INCLUDEPATH += $$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/genericunix +INCLUDEPATH += $$PWD HEADERS += \ - $$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/genericunix/qgenericunixfontdatabase.h + $$PWD/qgenericunixfontdatabase.h diff --git a/src/plugins/platforms/glxconvenience/glxconvenience.pri b/src/plugins/platforms/glxconvenience/glxconvenience.pri new file mode 100644 index 0000000..d6c9922 --- /dev/null +++ b/src/plugins/platforms/glxconvenience/glxconvenience.pri @@ -0,0 +1,7 @@ +INCLUDEPATH += $$PWD + +HEADERS += \ + $$PWD/qglxconvenience.h + +SOURCES += \ + $$PWD/qglxconvenience.cpp diff --git a/src/plugins/platforms/glxconvenience/qglxconvenience.cpp b/src/plugins/platforms/glxconvenience/qglxconvenience.cpp new file mode 100644 index 0000000..7cee3e2 --- /dev/null +++ b/src/plugins/platforms/glxconvenience/qglxconvenience.cpp @@ -0,0 +1,243 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 "qglxconvenience.h" + +#include <QtCore/QVector> + +enum { + XFocusOut = FocusOut, + XFocusIn = FocusIn, + XKeyPress = KeyPress, + XKeyRelease = KeyRelease, + XNone = None, + XRevertToParent = RevertToParent, + XGrayScale = GrayScale, + XCursorShape = CursorShape +}; +#undef FocusOut +#undef FocusIn +#undef KeyPress +#undef KeyRelease +#undef None +#undef RevertToParent +#undef GrayScale +#undef CursorShape + +#ifdef FontChange +#undef FontChange +#endif + +QVector<int> qglx_buildSpec(const QPlatformWindowFormat &format, int drawableBit) +{ + QVector<int> spec(48); + int i = 0; + + spec[i++] = GLX_LEVEL; + spec[i++] = 0; + spec[i++] = GLX_DRAWABLE_TYPE; spec[i++] = drawableBit; + + if (format.rgba()) { + spec[i++] = GLX_RENDER_TYPE; spec[i++] = GLX_RGBA_BIT; + spec[i++] = GLX_RED_SIZE; spec[i++] = (format.redBufferSize() == -1) ? 1 : format.redBufferSize(); + spec[i++] = GLX_GREEN_SIZE; spec[i++] = (format.greenBufferSize() == -1) ? 1 : format.greenBufferSize(); + spec[i++] = GLX_BLUE_SIZE; spec[i++] = (format.blueBufferSize() == -1) ? 1 : format.blueBufferSize(); + if (format.alpha()) { + spec[i++] = GLX_ALPHA_SIZE; spec[i++] = (format.alphaBufferSize() == -1) ? 1 : format.alphaBufferSize(); + } + + spec[i++] = GLX_ACCUM_RED_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize(); + spec[i++] = GLX_ACCUM_GREEN_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize(); + spec[i++] = GLX_ACCUM_BLUE_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize(); + + if (format.alpha()) { + spec[i++] = GLX_ACCUM_ALPHA_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize(); + } + + } else { + spec[i++] = GLX_RENDER_TYPE; spec[i++] = GLX_COLOR_INDEX_BIT; //I'm really not sure if this works.... + spec[i++] = GLX_BUFFER_SIZE; spec[i++] = 8; + } + + spec[i++] = GLX_DOUBLEBUFFER; spec[i++] = format.doubleBuffer() ? True : False; + spec[i++] = GLX_STEREO; spec[i++] = format.stereo() ? True : False; + + if (format.depth()) { + spec[i++] = GLX_DEPTH_SIZE; spec[i++] = (format.depthBufferSize() == -1) ? 1 : format.depthBufferSize(); + } + + if (format.stencil()) { + spec[i++] = GLX_STENCIL_SIZE; spec[i++] = (format.stencilBufferSize() == -1) ? 1 : format.stencilBufferSize(); + } + if (format.sampleBuffers()) { + spec[i++] = GLX_SAMPLE_BUFFERS_ARB; + spec[i++] = 1; + spec[i++] = GLX_SAMPLES_ARB; + spec[i++] = format.samples() == -1 ? 4 : format.samples(); + } + + spec[i++] = XNone; + return spec; +} + +GLXFBConfig qglx_findConfig(Display *display, int screen , const QPlatformWindowFormat &format, int drawableBit) +{ + bool reduced = true; + GLXFBConfig chosenConfig = 0; + QPlatformWindowFormat reducedFormat = format; + while (!chosenConfig && reduced) { + QVector<int> spec = qglx_buildSpec(reducedFormat, drawableBit); + int confcount = 0; + GLXFBConfig *configs; + configs = glXChooseFBConfig(display, screen,spec.constData(),&confcount); + if (confcount) + { + for (int i = 0; i < confcount; i++) { + chosenConfig = configs[i]; + // Make sure we try to get an ARGB visual if the format asked for an alpha: + if (reducedFormat.alpha()) { + int alphaSize; + glXGetFBConfigAttrib(display,configs[i],GLX_ALPHA_SIZE,&alphaSize); + if (alphaSize > 0) + break; + } else { + break; // Just choose the first in the list if there's no alpha requested + } + } + + XFree(configs); + } + reducedFormat = qglx_reducePlatformWindowFormat(reducedFormat,&reduced); + } + + if (!chosenConfig) + qWarning("Warning: no suitable glx confiuration found"); + + return chosenConfig; +} + +XVisualInfo *qglx_findVisualInfo(Display *display, int screen, const QPlatformWindowFormat &format) +{ + GLXFBConfig config = qglx_findConfig(display,screen,format); + XVisualInfo *visualInfo = glXGetVisualFromFBConfig(display,config); + return visualInfo; +} + +QPlatformWindowFormat qglx_platformWindowFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext ctx) +{ + QPlatformWindowFormat format; + int redSize = 0; + int greenSize = 0; + int blueSize = 0; + int alphaSize = 0; + int depthSize = 0; + int stencilSize = 0; + int sampleBuffers = 0; + int sampleCount = 0; + int level = 0; + int rgba = 0; + int stereo = 0; + int accumSizeA = 0; + int accumSizeR = 0; + int accumSizeG = 0; + int accumSizeB = 0; + + XVisualInfo *vi = glXGetVisualFromFBConfig(display,config); + glXGetConfig(display,vi,GLX_RGBA,&rgba); + XFree(vi); + glXGetFBConfigAttrib(display, config, GLX_RED_SIZE, &redSize); + glXGetFBConfigAttrib(display, config, GLX_GREEN_SIZE, &greenSize); + glXGetFBConfigAttrib(display, config, GLX_BLUE_SIZE, &blueSize); + glXGetFBConfigAttrib(display, config, GLX_ALPHA_SIZE, &alphaSize); + glXGetFBConfigAttrib(display, config, GLX_DEPTH_SIZE, &depthSize); + glXGetFBConfigAttrib(display, config, GLX_STENCIL_SIZE, &stencilSize); + glXGetFBConfigAttrib(display, config, GLX_SAMPLES, &sampleBuffers); + glXGetFBConfigAttrib(display, config, GLX_LEVEL, &level); + glXGetFBConfigAttrib(display, config, GLX_STEREO, &stereo); + glXGetFBConfigAttrib(display, config, GLX_ACCUM_ALPHA_SIZE, &accumSizeA); + glXGetFBConfigAttrib(display, config, GLX_ACCUM_RED_SIZE, &accumSizeR); + glXGetFBConfigAttrib(display, config, GLX_ACCUM_GREEN_SIZE, &accumSizeG); + glXGetFBConfigAttrib(display, config, GLX_ACCUM_BLUE_SIZE, &accumSizeB); + + format.setRedBufferSize(redSize); + format.setGreenBufferSize(greenSize); + format.setBlueBufferSize(blueSize); + format.setAlphaBufferSize(alphaSize); + format.setDepthBufferSize(depthSize); + format.setStencilBufferSize(stencilSize); + format.setSampleBuffers(sampleBuffers); + if (format.sampleBuffers()) { + glXGetFBConfigAttrib(display, config, GLX_SAMPLES_ARB, &sampleCount); + format.setSamples(sampleCount); + } + + format.setDirectRendering(glXIsDirect(display, ctx)); + format.setRgba(rgba); + format.setStereo(stereo); + format.setAccumBufferSize(accumSizeB); + + return format; +} + +QPlatformWindowFormat qglx_reducePlatformWindowFormat(const QPlatformWindowFormat &format, bool *reduced) +{ + QPlatformWindowFormat retFormat = format; + *reduced = true; + + if (retFormat.sampleBuffers()) { + retFormat.setSampleBuffers(false); + } else if (retFormat.stereo()) { + retFormat.setStereo(false); + } else if (retFormat.accum()) { + retFormat.setAccum(false); + }else if (retFormat.stencil()) { + retFormat.setStencil(false); + }else if (retFormat.alpha()) { + retFormat.setAlpha(false); + }else if (retFormat.depth()) { + retFormat.setDepth(false); + }else if (retFormat.doubleBuffer()) { + retFormat.setDoubleBuffer(false); + }else{ + *reduced = false; + } + return retFormat; +} diff --git a/src/plugins/platforms/glxconvenience/qglxconvenience.h b/src/plugins/platforms/glxconvenience/qglxconvenience.h new file mode 100644 index 0000000..2c59dbb --- /dev/null +++ b/src/plugins/platforms/glxconvenience/qglxconvenience.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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$ +** +****************************************************************************/ + +#ifndef QGLXCONVENIENCE_H +#define QGLXCONVENIENCE_H + +#include <QPlatformWindowFormat> + +#include <X11/Xlib.h> +#include <GL/glx.h> + +XVisualInfo *qglx_findVisualInfo(Display *display, int screen, const QPlatformWindowFormat &format); +GLXFBConfig qglx_findConfig(Display *display, int screen, const QPlatformWindowFormat &format, int drawableBit = GLX_WINDOW_BIT); +QPlatformWindowFormat qglx_platformWindowFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext context); +QVector<int> qglx_buildSpec(const QPlatformWindowFormat &format, int drawableBit = GLX_WINDOW_BIT); +QPlatformWindowFormat qglx_reducePlatformWindowFormat(const QPlatformWindowFormat &format, bool *reduced); + +#endif // QGLXCONVENIENCE_H diff --git a/src/plugins/platforms/openkode/qopenkodeintegration.cpp b/src/plugins/platforms/openkode/qopenkodeintegration.cpp index 35e744be..703b1a9 100644 --- a/src/plugins/platforms/openkode/qopenkodeintegration.cpp +++ b/src/plugins/platforms/openkode/qopenkodeintegration.cpp @@ -122,7 +122,9 @@ QOpenKODEScreen::QOpenKODEScreen(KDDisplayNV *kdDisplay, KDDesktopNV *kdDesktop } QOpenKODEIntegration::QOpenKODEIntegration() - : mEventLoopIntegration(0), mFontDb(new QGenericUnixFontDatabase()) + : mEventLoopIntegration(0) + , mFontDb(new QGenericUnixFontDatabase()) + , mMainGlContext(0) { if (kdInitializeNV() == KD_ENOTINITIALIZED) { qFatal("Did not manage to initialize openkode"); @@ -190,6 +192,7 @@ bool QOpenKODEIntegration::hasCapability(QPlatformIntegration::Capability cap) c { switch (cap) { case ThreadedPixmaps: return true; + case OpenGL: return true; default: return QPlatformIntegration::hasCapability(cap); } } @@ -226,11 +229,6 @@ QWindowSurface *QOpenKODEIntegration::createWindowSurface(QWidget *widget, WId) return returnSurface; } -bool QOpenKODEIntegration::hasOpenGL() const -{ - return true; -} - QPlatformEventLoopIntegration *QOpenKODEIntegration::createEventLoopIntegration() const { if (!mEventLoopIntegration) { diff --git a/src/plugins/platforms/openkode/qopenkodeintegration.h b/src/plugins/platforms/openkode/qopenkodeintegration.h index 7582e60..d5aac98 100644 --- a/src/plugins/platforms/openkode/qopenkodeintegration.h +++ b/src/plugins/platforms/openkode/qopenkodeintegration.h @@ -96,8 +96,6 @@ public: QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId = 0) const; QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; - bool hasOpenGL() const; - QPlatformEventLoopIntegration *createEventLoopIntegration() const; QPlatformFontDatabase *fontDatabase() const; @@ -106,10 +104,14 @@ public: static GLuint blitterProgram(); + void setMainGLContext(QEGLPlatformContext *ctx) { mMainGlContext = ctx; } + void mainGLContext() const { return mMainGlContext; } + private: QList<QPlatformScreen *> mScreens; QOpenKODEEventLoopIntegration *mEventLoopIntegration; QPlatformFontDatabase *mFontDb; + QEGLPlatformContext *mMainGlContext; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/openkode/qopenkodewindow.cpp b/src/plugins/platforms/openkode/qopenkodewindow.cpp index 66530a5..d34dff8 100644 --- a/src/plugins/platforms/openkode/qopenkodewindow.cpp +++ b/src/plugins/platforms/openkode/qopenkodewindow.cpp @@ -147,9 +147,9 @@ QOpenKODEWindow::QOpenKODEWindow(QWidget *tlw) } + QOpenKODEIntegration *integration = static_cast<QOpenKODEIntegration *>(QApplicationPrivate::platformIntegration()); - - if (!isFullScreen || (isFullScreen && !QPlatformGLContext::defaultSharedContext())) { + if (!isFullScreen || (isFullScreen && !integration->mainGLContext())) { if (kdRealizeWindow(m_kdWindow, &m_eglWindow)) { qErrnoWarning(kdGetError(), "Could not realize native window"); return; @@ -158,9 +158,9 @@ QOpenKODEWindow::QOpenKODEWindow(QWidget *tlw) EGLSurface surface = eglCreateWindowSurface(screen->eglDisplay(),m_eglConfig,m_eglWindow,m_eglWindowAttrs.constData()); m_platformGlContext = new QEGLPlatformContext(screen->eglDisplay(), m_eglConfig, m_eglContextAttrs.data(), surface, m_eglApi); - m_platformGlContext->makeDefaultSharedContext(); + integration->setMainGLContext(m_platformGLContext); } else { - m_platformGlContext = const_cast<QEGLPlatformContext *>(static_cast<const QEGLPlatformContext *>(QPlatformGLContext::defaultSharedContext())); + m_platformGlContext = integration->mainGLContext(); kdDestroyWindow(m_kdWindow); m_kdWindow = 0; } @@ -169,7 +169,7 @@ QOpenKODEWindow::QOpenKODEWindow(QWidget *tlw) QOpenKODEWindow::~QOpenKODEWindow() { - if (m_platformGlContext != QPlatformGLContext::defaultSharedContext()) { + if (m_platformGlContext != static_cast<QOpenKODEIntegration *>(QApplicationPrivate::platformIntegration())) { delete m_platformGlContext; } if (m_kdWindow) diff --git a/src/plugins/platforms/uikit/README b/src/plugins/platforms/uikit/README index b2984fc..a101a3a 100644 --- a/src/plugins/platforms/uikit/README +++ b/src/plugins/platforms/uikit/README @@ -18,11 +18,11 @@ After configuring and building Qt you need to also build src/plugins/platforms/u Simulator: ---------- -configure -qpa -xplatform qws/macx-iphonesimulator-g++ -arch i386 -developer-build -no-accessibility -no-qt3support -no-multimedia -no-phonon -no-phonon-backend -no-svg -no-webkit -no-scripttools -no-openssl -no-sql-mysql -no-sql-odbc -no-cups -no-iconv -no-dbus -no-opengl -static -nomake tools -nomake demos -nomake docs -nomake examples -nomake translations +configure -qpa -xplatform qws/macx-iphonesimulator-g++ -arch i386 -developer-build -opengl es1 -no-accessibility -no-qt3support -no-multimedia -no-phonon -no-phonon-backend -no-svg -no-webkit -no-scripttools -no-openssl -no-sql-mysql -no-sql-odbc -no-cups -no-iconv -no-dbus -static -nomake tools -nomake demos -nomake docs -nomake examples -nomake translations Device: ------- -configure -qpa -xplatform qws/macx-iphonedevice-g++ -arch armv7 -developer-build -release -no-accessibility -no-qt3support -no-multimedia -no-phonon -no-phonon-backend -no-svg -no-webkit -no-scripttools -no-openssl -no-sql-mysql -no-sql-odbc -no-cups -no-iconv -no-dbus -no-opengl -static -nomake tools -nomake demos -nomake docs -nomake examples -nomake translations +configure -qpa -xplatform qws/macx-iphonedevice-g++ -arch armv7 -developer-build -release -opengl es1 -no-accessibility -no-qt3support -no-multimedia -no-phonon -no-phonon-backend -no-svg -no-webkit -no-scripttools -no-openssl -no-sql-mysql -no-sql-odbc -no-cups -no-iconv -no-dbus -static -nomake tools -nomake demos -nomake docs -nomake examples -nomake translations 2) XCode setup: - there are examples in the examples subdirectory of the platform plugin diff --git a/src/plugins/platforms/uikit/examples/qmltest/main.mm b/src/plugins/platforms/uikit/examples/qmltest/main.mm index 6fd5629..ea4e90c 100644 --- a/src/plugins/platforms/uikit/examples/qmltest/main.mm +++ b/src/plugins/platforms/uikit/examples/qmltest/main.mm @@ -39,36 +39,40 @@ ** ****************************************************************************/ -// -// main.m -// qmltest -// -// Created by Eike Troll on 18.02.11. -// Copyright 2011 __MyCompanyName__. All rights reserved. -// - #import <UIKit/UIKit.h> #include "qmlapplicationviewer/qmlapplicationviewer.h" #include <QtGui/QApplication> #include <QtCore/QtPlugin> +#include <QtDeclarative/QDeclarativeEngine> Q_IMPORT_PLUGIN(UIKit) +static QString qStringFromNSString(NSString *nsstring) +{ + return QString::fromUtf8([nsstring UTF8String]); +} + +static QString documentsDirectory() +{ + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDirectory = [paths objectAtIndex:0]; + return qStringFromNSString(documentsDirectory); +} + int main(int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; - setenv("QT_QPA_PLATFORM","uikit",1); - - QApplication app(argc, argv); + QApplication app(argc, argv); QmlApplicationViewer viewer; viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto); - NSString *resourcePath = [[NSBundle mainBundle] resourcePath]; - viewer.setMainQmlFile(QString::fromUtf8([[resourcePath stringByAppendingPathComponent:@"qml/main.qml"] UTF8String])); + viewer.engine()->setOfflineStoragePath(documentsDirectory()); + NSString *resourcePath = [[NSBundle mainBundle] resourcePath]; + viewer.setMainQmlFile(qStringFromNSString([resourcePath stringByAppendingPathComponent:@"qml/main.qml"])); viewer.showMaximized(); - int retVal = app.exec(); + int retVal = app.exec(); [pool release]; return retVal; } diff --git a/src/plugins/platforms/uikit/examples/qmltest/qmltest.xcodeproj/project.pbxproj b/src/plugins/platforms/uikit/examples/qmltest/qmltest.xcodeproj/project.pbxproj index fc4f1df..10bb20f 100755 --- a/src/plugins/platforms/uikit/examples/qmltest/qmltest.xcodeproj/project.pbxproj +++ b/src/plugins/platforms/uikit/examples/qmltest/qmltest.xcodeproj/project.pbxproj @@ -10,6 +10,14 @@ 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765A40DF7441C002DB57D /* CoreGraphics.framework */; }; + D316594E1338B29E00760B02 /* libQtXml_debug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D31659431338B21000760B02 /* libQtXml_debug.a */; }; + D316594F1338B29E00760B02 /* libQtXmlPatterns_debug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D31659441338B21000760B02 /* libQtXmlPatterns_debug.a */; }; + D35784241345D8C90046D202 /* libQtOpenGL_debug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D35784231345D8C90046D202 /* libQtOpenGL_debug.a */; }; + D35784261345D9940046D202 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D35784251345D9940046D202 /* OpenGLES.framework */; }; + D35784281345D9E00046D202 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D35784271345D9E00046D202 /* QuartzCore.framework */; }; + D3578436134A09990046D202 /* libQtOpenGL.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3578435134A09990046D202 /* libQtOpenGL.a */; }; + D3578439134A0AAE0046D202 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D35784251345D9940046D202 /* OpenGLES.framework */; }; + D357843A134A0AB10046D202 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D35784271345D9E00046D202 /* QuartzCore.framework */; }; D3CAA7C813264AAD008BB877 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = D3CAA7C713264AAD008BB877 /* main.mm */; }; D3CAA7E613264EA6008BB877 /* moc_qmlapplicationviewer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D3CAA7E313264EA6008BB877 /* moc_qmlapplicationviewer.cpp */; }; D3CAA7E713264EA6008BB877 /* qmlapplicationviewer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D3CAA7E413264EA6008BB877 /* qmlapplicationviewer.cpp */; }; @@ -50,6 +58,12 @@ 288765A40DF7441C002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 32CA4F630368D1EE00C91783 /* qmltest_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = qmltest_Prefix.pch; sourceTree = "<group>"; }; 8D1107310486CEB800E47090 /* qmltest-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "qmltest-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = "<group>"; }; + D31659431338B21000760B02 /* libQtXml_debug.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtXml_debug.a; path = "../../../../../../../qt-lighthouse-ios-simulator/lib/libQtXml_debug.a"; sourceTree = SOURCE_ROOT; }; + D31659441338B21000760B02 /* libQtXmlPatterns_debug.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtXmlPatterns_debug.a; path = "../../../../../../../qt-lighthouse-ios-simulator/lib/libQtXmlPatterns_debug.a"; sourceTree = SOURCE_ROOT; }; + D35784231345D8C90046D202 /* libQtOpenGL_debug.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtOpenGL_debug.a; path = "../../../../../../../qt-lighthouse-ios-simulator/lib/libQtOpenGL_debug.a"; sourceTree = "<group>"; }; + D35784251345D9940046D202 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; + D35784271345D9E00046D202 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; + D3578435134A09990046D202 /* libQtOpenGL.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtOpenGL.a; path = "../../../../../../../qt-lighthouse-ios-device/lib/libQtOpenGL.a"; sourceTree = "<group>"; }; D3CAA7C713264AAD008BB877 /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = "<group>"; }; D3CAA7E313264EA6008BB877 /* moc_qmlapplicationviewer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = moc_qmlapplicationviewer.cpp; path = qmlapplicationviewer/moc_qmlapplicationviewer.cpp; sourceTree = "<group>"; }; D3CAA7E413264EA6008BB877 /* qmlapplicationviewer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = qmlapplicationviewer.cpp; path = qmlapplicationviewer/qmlapplicationviewer.cpp; sourceTree = "<group>"; }; @@ -81,9 +95,11 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + D35784281345D9E00046D202 /* QuartzCore.framework in Frameworks */, 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */, + D35784261345D9940046D202 /* OpenGLES.framework in Frameworks */, D3CAA7FA13264F8A008BB877 /* libz.1.2.3.dylib in Frameworks */, D3CAA81B13265056008BB877 /* libQtCore_debug.a in Frameworks */, D3CAA81C13265056008BB877 /* libQtDeclarative_debug.a in Frameworks */, @@ -92,6 +108,9 @@ D3CAA81F13265056008BB877 /* libQtSql_debug.a in Frameworks */, D3CAA8211326507D008BB877 /* libquikit_debug.a in Frameworks */, D3CAA82813265220008BB877 /* libQtNetwork_debug.a in Frameworks */, + D316594E1338B29E00760B02 /* libQtXml_debug.a in Frameworks */, + D316594F1338B29E00760B02 /* libQtXmlPatterns_debug.a in Frameworks */, + D35784241345D8C90046D202 /* libQtOpenGL_debug.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -99,6 +118,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + D357843A134A0AB10046D202 /* QuartzCore.framework in Frameworks */, + D3578439134A0AAE0046D202 /* OpenGLES.framework in Frameworks */, D3CAA7F013264F52008BB877 /* Foundation.framework in Frameworks */, D3CAA7F113264F52008BB877 /* UIKit.framework in Frameworks */, D3CAA7F213264F52008BB877 /* CoreGraphics.framework in Frameworks */, @@ -112,6 +133,7 @@ D3D817B8132A2CFD00CDE422 /* libQtXml.a in Frameworks */, D3D817B9132A2CFD00CDE422 /* libQtXmlPatterns.a in Frameworks */, D3D817BB132A2D0E00CDE422 /* libquikit.a in Frameworks */, + D3578436134A09990046D202 /* libQtOpenGL.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -166,6 +188,8 @@ 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, 1D30AB110D05D00D00671497 /* Foundation.framework */, 288765A40DF7441C002DB57D /* CoreGraphics.framework */, + D35784251345D9940046D202 /* OpenGLES.framework */, + D35784271345D9E00046D202 /* QuartzCore.framework */, D3CAA7F913264F8A008BB877 /* libz.1.2.3.dylib */, ); name = Frameworks; @@ -189,6 +213,7 @@ D3D817AB132A2CFD00CDE422 /* libQtDeclarative.a */, D3D817AC132A2CFD00CDE422 /* libQtGui.a */, D3D817AD132A2CFD00CDE422 /* libQtNetwork.a */, + D3578435134A09990046D202 /* libQtOpenGL.a */, D3D817AE132A2CFD00CDE422 /* libQtScript.a */, D3D817AF132A2CFD00CDE422 /* libQtSql.a */, D3D817B0132A2CFD00CDE422 /* libQtXml.a */, @@ -205,8 +230,11 @@ D3CAA81713265056008BB877 /* libQtDeclarative_debug.a */, D3CAA81813265056008BB877 /* libQtGui_debug.a */, D3CAA82713265220008BB877 /* libQtNetwork_debug.a */, + D35784231345D8C90046D202 /* libQtOpenGL_debug.a */, D3CAA81913265056008BB877 /* libQtScript_debug.a */, D3CAA81A13265056008BB877 /* libQtSql_debug.a */, + D31659431338B21000760B02 /* libQtXml_debug.a */, + D31659441338B21000760B02 /* libQtXmlPatterns_debug.a */, ); name = Simulator; sourceTree = "<group>"; diff --git a/src/plugins/platforms/uikit/quikiteventloop.h b/src/plugins/platforms/uikit/quikiteventloop.h index cf5c682..b81e0fd 100644 --- a/src/plugins/platforms/uikit/quikiteventloop.h +++ b/src/plugins/platforms/uikit/quikiteventloop.h @@ -42,6 +42,9 @@ #ifndef QUIKITEVENTLOOP_H #define QUIKITEVENTLOOP_H +#include "quikitsoftwareinputhandler.h" + +#include <QtCore/QEvent> #include <QtGui/QPlatformEventLoopIntegration> @class EventLoopHelper; @@ -61,6 +64,7 @@ public: EventLoopHelper *mHelper; NSTimer *mTimer; + QUIKitSoftwareInputHandler *mInputHandler; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/uikit/quikiteventloop.mm b/src/plugins/platforms/uikit/quikiteventloop.mm index 70757b1..8d2603c 100644 --- a/src/plugins/platforms/uikit/quikiteventloop.mm +++ b/src/plugins/platforms/uikit/quikiteventloop.mm @@ -78,10 +78,6 @@ } QUIKitWindow *platformWindow = static_cast<QUIKitWindow *>(widget->platformWindow()); platformWindow->ensureNativeWindow(); - QUIKitWindowSurface *surface = static_cast<QUIKitWindowSurface*>(widget->windowSurface()); - UIView *view = surface->nativeView(); - [platformWindow->nativeWindow() addSubview:view]; - [platformWindow->nativeWindow() makeKeyAndVisible]; } return YES; } @@ -128,6 +124,7 @@ QT_BEGIN_NAMESPACE QUIKitEventLoop::QUIKitEventLoop() { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + mInputHandler = new QUIKitSoftwareInputHandler; mHelper = [[EventLoopHelper alloc] initWithEventLoopIntegration:this]; mTimer = [[NSTimer timerWithTimeInterval:0.030 target:mHelper selector:@selector(processEventsAndSchedule) userInfo:nil repeats:YES] retain]; [pool release]; @@ -137,10 +134,12 @@ QUIKitEventLoop::~QUIKitEventLoop() { [mTimer release]; [mHelper release]; + delete mInputHandler; } void QUIKitEventLoop::startEventLoop() { + qApp->installEventFilter(mInputHandler); NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; [[NSRunLoop currentRunLoop] addTimer:[mTimer autorelease] forMode:NSDefaultRunLoopMode]; UIApplicationMain(qApp->argc(), qApp->argv(), nil, @"QUIKitAppDelegate"); @@ -157,4 +156,24 @@ void QUIKitEventLoop::qtNeedsToProcessEvents() [mHelper performSelectorOnMainThread:@selector(processEvents) withObject:nil waitUntilDone:NO]; } +bool QUIKitSoftwareInputHandler::eventFilter(QObject *obj, QEvent *event) +{ + if (event->type() == QEvent::RequestSoftwareInputPanel) { + QWidget *widget = qobject_cast<QWidget *>(obj); + if (widget) { + QUIKitWindow *platformWindow = static_cast<QUIKitWindow *>(widget->platformWindow()); + [platformWindow->nativeView() becomeFirstResponder]; + return true; + } + } else if (event->type() == QEvent::CloseSoftwareInputPanel) { + QWidget *widget = qobject_cast<QWidget *>(obj); + if (widget) { + QUIKitWindow *platformWindow = static_cast<QUIKitWindow *>(widget->platformWindow()); + [platformWindow->nativeView() resignFirstResponder]; + return true; + } + } + return false; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/uikit/quikitscreen.mm b/src/plugins/platforms/uikit/quikitscreen.mm index ec94e3a..21494c9 100644 --- a/src/plugins/platforms/uikit/quikitscreen.mm +++ b/src/plugins/platforms/uikit/quikitscreen.mm @@ -41,6 +41,8 @@ #include "quikitscreen.h" +#include <QtGui/QApplication> + #include <QtDebug> QT_BEGIN_NAMESPACE @@ -51,21 +53,22 @@ QUIKitScreen::QUIKitScreen(int screenIndex) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; UIScreen *screen = [[UIScreen screens] objectAtIndex:screenIndex]; - UIScreenMode *mode = [screen currentMode]; - CGSize size = [mode size]; - m_geometry = QRect(0, 0, size.width, size.height); - CGRect bounds = [screen bounds]; // in 'points', 1p == 1/160in - -// qreal xDpi = size.width * 160. / bounds.size.width; -// qreal yDpi = size.height * 160. / bounds.size.height; -// qDebug() << xDpi << yDpi; + CGRect bounds = [screen bounds]; + m_geometry = QRect(0, 0, bounds.size.width, bounds.size.height); m_format = QImage::Format_ARGB32; m_depth = 24; const qreal inch = 25.4; - m_physicalSize = QSize(qRound(bounds.size.width * inch / 160.), qRound(bounds.size.height * inch / 160.)); + qreal dpi = 160.; + int dragDistance = 14; + if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { + dpi = 132.; + dragDistance = 10; + } + m_physicalSize = QSize(qRound(bounds.size.width * inch / dpi), qRound(bounds.size.height * inch / dpi)); + qApp->setStartDragDistance(dragDistance); [pool release]; } diff --git a/src/plugins/platforms/uikit/quikitsoftwareinputhandler.h b/src/plugins/platforms/uikit/quikitsoftwareinputhandler.h new file mode 100644 index 0000000..629fd13 --- /dev/null +++ b/src/plugins/platforms/uikit/quikitsoftwareinputhandler.h @@ -0,0 +1,61 @@ + + +/**************************************************************************** +** +** Copyright (C) 2011 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$ +** +****************************************************************************/ + +#ifndef QUIKITSOFTWAREINPUTHANDLER_H +#define QUIKITSOFTWAREINPUTHANDLER_H + +#include <QtCore/QObject> + +QT_BEGIN_NAMESPACE + +class QUIKitSoftwareInputHandler : public QObject +{ + Q_OBJECT + +public: + bool eventFilter(QObject *obj, QEvent *event); +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/uikit/quikitwindow.h b/src/plugins/platforms/uikit/quikitwindow.h index d5a6690..9e73754 100644 --- a/src/plugins/platforms/uikit/quikitwindow.h +++ b/src/plugins/platforms/uikit/quikitwindow.h @@ -43,7 +43,54 @@ #define QUIKITWINDOW_H #include <QPlatformWindow> -#include <UIKit/UIKit.h> + +#import <UIKit/UIKit.h> +#import <OpenGLES/ES1/gl.h> +#import <OpenGLES/ES1/glext.h> +#import <OpenGLES/EAGL.h> + +@interface EAGLView : UIView <UIKeyInput> +{ + QPlatformWindow *mWindow; + EAGLContext *mContext; + + GLint mFramebufferWidth; + GLint mFramebufferHeight; + + GLuint mFramebuffer, mColorRenderbuffer, mDepthRenderbuffer; + + // ------- Text Input ---------- + UITextAutocapitalizationType autocapitalizationType; + UITextAutocorrectionType autocorrectionType; + BOOL enablesReturnKeyAutomatically; + UIKeyboardAppearance keyboardAppearance; + UIKeyboardType keyboardType; + UIReturnKeyType returnKeyType; + BOOL secureTextEntry; +} + +- (void)setContext:(EAGLContext *)newContext; +- (void)presentFramebuffer; +- (void)deleteFramebuffer; +- (void)createFramebuffer; +- (void)makeCurrent; +- (void)setWindow:(QPlatformWindow *)window; +- (void)sendMouseEventForTouches:(NSSet *)touches withEvent:(UIEvent *)event fakeButtons:(Qt::MouseButtons)buttons; + + +// ------- Text Input ---------- + +@property(nonatomic) UITextAutocapitalizationType autocapitalizationType; +@property(nonatomic) UITextAutocorrectionType autocorrectionType; +@property(nonatomic) BOOL enablesReturnKeyAutomatically; +@property(nonatomic) UIKeyboardAppearance keyboardAppearance; +@property(nonatomic) UIKeyboardType keyboardType; +@property(nonatomic) UIReturnKeyType returnKeyType; +@property(nonatomic, getter=isSecureTextEntry) BOOL secureTextEntry; + +@end + +class EAGLPlatformContext; QT_BEGIN_NAMESPACE @@ -56,13 +103,18 @@ public: ~QUIKitWindow(); UIWindow *nativeWindow() const { return mWindow; } + UIView *nativeView() const { return mView; } void setGeometry(const QRect &rect); UIWindow *ensureNativeWindow(); + QPlatformGLContext *glContext() const; + private: QUIKitScreen *mScreen; UIWindow *mWindow; + EAGLView *mView; + mutable EAGLPlatformContext *mContext; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/uikit/quikitwindow.mm b/src/plugins/platforms/uikit/quikitwindow.mm index ebdee06..52d1846 100644 --- a/src/plugins/platforms/uikit/quikitwindow.mm +++ b/src/plugins/platforms/uikit/quikitwindow.mm @@ -39,17 +39,284 @@ ** ****************************************************************************/ +#import <QuartzCore/CAEAGLLayer.h> + #include "quikitwindow.h" #include "quikitscreen.h" #include <QtDebug> +#include <QtGui/QApplication> +#include <QtGui/QKeyEvent> +#include <QtGui/QPlatformGLContext> +#include <QtGui/QWindowSystemInterface> + +#include <QtDebug> + +class EAGLPlatformContext : public QPlatformGLContext +{ +public: + EAGLPlatformContext(EAGLView *view) + : mView(view) + { + mFormat.setWindowApi(QPlatformWindowFormat::OpenGL); + mFormat.setDepthBufferSize(24); + mFormat.setAccumBufferSize(0); + mFormat.setRedBufferSize(8); + mFormat.setGreenBufferSize(8); + mFormat.setBlueBufferSize(8); + mFormat.setAlphaBufferSize(8); + mFormat.setStencilBufferSize(8); + mFormat.setSampleBuffers(false); + mFormat.setSamples(1); +// mFormat.setSwapInterval(?) + mFormat.setDoubleBuffer(true); + mFormat.setDepth(true); + mFormat.setRgba(true); + mFormat.setAlpha(true); + mFormat.setAccum(false); + mFormat.setStencil(true); + mFormat.setStereo(false); + mFormat.setDirectRendering(false); + + EAGLContext *aContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1]; + [mView setContext:aContext]; + } + + ~EAGLPlatformContext() { } + + void makeCurrent() + { + QPlatformGLContext::makeCurrent(); + [mView makeCurrent]; + } + + void doneCurrent() + { + QPlatformGLContext::doneCurrent(); + } + + void swapBuffers() + { + [mView presentFramebuffer]; + } + + void* getProcAddress(const QString& ) { return 0; } + + QPlatformWindowFormat platformWindowFormat() const + { + return mFormat; + } + +private: + EAGLView *mView; + + QPlatformWindowFormat mFormat; +}; + +@implementation EAGLView + ++ (Class)layerClass +{ + return [CAEAGLLayer class]; +} + +- (id)initWithFrame:(CGRect)frame +{ + if ((self = [super initWithFrame:frame])) { + CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer; + eaglLayer.opaque = TRUE; + eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithBool:YES], kEAGLDrawablePropertyRetainedBacking, + kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, + nil]; + autocapitalizationType = UITextAutocapitalizationTypeNone; + autocorrectionType = UITextAutocorrectionTypeNo; + enablesReturnKeyAutomatically = NO; + keyboardAppearance = UIKeyboardAppearanceDefault; + keyboardType = UIKeyboardTypeDefault; + returnKeyType = UIReturnKeyDone; + secureTextEntry = NO; + } + return self; +} + +- (void)setContext:(EAGLContext *)newContext +{ + if (mContext != newContext) + { + [self deleteFramebuffer]; + [mContext release]; + mContext = [newContext retain]; + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)presentFramebuffer +{ + if (mContext) { + [EAGLContext setCurrentContext:mContext]; + glBindRenderbufferOES(GL_RENDERBUFFER_OES, mColorRenderbuffer); + [mContext presentRenderbuffer:GL_RENDERBUFFER_OES]; + } +} + +- (void)deleteFramebuffer +{ + if (mContext) + { + [EAGLContext setCurrentContext:mContext]; + if (mFramebuffer) { + glDeleteFramebuffersOES(1, &mFramebuffer); + mFramebuffer = 0; + } + if (mColorRenderbuffer) { + glDeleteRenderbuffersOES(1, &mColorRenderbuffer); + mColorRenderbuffer = 0; + } + if (mDepthRenderbuffer) { + glDeleteRenderbuffersOES(1, &mDepthRenderbuffer); + mDepthRenderbuffer = 0; + } + } +} + +- (void)createFramebuffer +{ + if (mContext && !mFramebuffer) + { + [EAGLContext setCurrentContext:mContext]; + glGenFramebuffersOES(1, &mFramebuffer); + glBindFramebufferOES(GL_FRAMEBUFFER_OES, mFramebuffer); + + glGenRenderbuffersOES(1, &mColorRenderbuffer); + glBindRenderbufferOES(GL_RENDERBUFFER_OES, mColorRenderbuffer); + [mContext renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer *)self.layer]; + glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &mFramebufferWidth); + glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &mFramebufferHeight); + glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, mColorRenderbuffer); + + glGenRenderbuffersOES(1, &mDepthRenderbuffer); + glBindRenderbufferOES(GL_RENDERBUFFER_OES, mDepthRenderbuffer); + glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH24_STENCIL8_OES, mFramebufferWidth, mFramebufferHeight); + glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, mDepthRenderbuffer); + glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, mDepthRenderbuffer); + + if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) + NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES)); + } +} + +- (void)makeCurrent +{ + if (mContext) + { + [EAGLContext setCurrentContext:mContext]; + if (!mFramebuffer) + [self createFramebuffer]; + glBindFramebufferOES(GL_FRAMEBUFFER_OES, mFramebuffer); + glViewport(0, 0, mFramebufferWidth, mFramebufferHeight); + } +} + +- (void)setWindow:(QPlatformWindow *)window +{ + mWindow = window; +} + +- (void)sendMouseEventForTouches:(NSSet *)touches withEvent:(UIEvent *)event fakeButtons:(Qt::MouseButtons)buttons +{ + UITouch *touch = [touches anyObject]; + CGPoint locationInView = [touch locationInView:self]; + QPoint p(locationInView.x, locationInView.y); + // TODO handle global touch point? for status bar? + QWindowSystemInterface::handleMouseEvent(mWindow->widget(), (ulong)(event.timestamp*1000), + p, p, buttons); +} + +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event +{ + [self sendMouseEventForTouches:touches withEvent:event fakeButtons:Qt::LeftButton]; +} + +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event +{ + [self sendMouseEventForTouches:touches withEvent:event fakeButtons:Qt::LeftButton]; +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event +{ + [self sendMouseEventForTouches:touches withEvent:event fakeButtons:Qt::NoButton]; +} + +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event +{ + [self sendMouseEventForTouches:touches withEvent:event fakeButtons:Qt::NoButton]; +} + +// ------- Text Input ---------- + +@synthesize autocapitalizationType; +@synthesize autocorrectionType; +@synthesize enablesReturnKeyAutomatically; +@synthesize keyboardAppearance; +@synthesize keyboardType; +@synthesize returnKeyType; +@synthesize secureTextEntry; + +- (BOOL)canBecomeFirstResponder +{ + return YES; +} + +- (BOOL)hasText +{ + return YES; +} + +- (void)insertText:(NSString *)text +{ + QKeyEvent *ev; + int key = 0; + if ([text isEqualToString:@"\n"]) + key = (int)Qt::Key_Return; + ev = new QKeyEvent(QEvent::KeyPress, + key, + Qt::NoModifier, + QString::fromUtf8([text UTF8String]) + ); + qApp->postEvent(qApp->focusWidget(), ev); + ev = new QKeyEvent(QEvent::KeyRelease, + key, + Qt::NoModifier, + QString::fromUtf8([text UTF8String]) + ); + qApp->postEvent(qApp->focusWidget(), ev); +} + +- (void)deleteBackward +{ + QKeyEvent *ev; + ev = new QKeyEvent(QEvent::KeyPress, + (int)Qt::Key_Backspace, + Qt::NoModifier + ); + qApp->postEvent(qApp->focusWidget(), ev); + ev = new QKeyEvent(QEvent::KeyRelease, + (int)Qt::Key_Backspace, + Qt::NoModifier + ); + qApp->postEvent(qApp->focusWidget(), ev); +} + +@end QT_BEGIN_NAMESPACE QUIKitWindow::QUIKitWindow(QWidget *tlw) : QPlatformWindow(tlw), - mWindow(nil) + mWindow(nil), + mContext(0) { mScreen = static_cast<QUIKitScreen *>(QPlatformScreen::platformScreenForWidget(tlw)); CGRect screenBounds = [mScreen->uiScreen() bounds]; @@ -60,6 +327,8 @@ QUIKitWindow::QUIKitWindow(QWidget *tlw) : QUIKitWindow::~QUIKitWindow() { + delete mContext; mContext = 0; + [mView release]; [mWindow release]; } @@ -67,6 +336,8 @@ void QUIKitWindow::setGeometry(const QRect &rect) { if (mWindow) { mWindow.frame = CGRectMake(rect.x(), rect.y(), rect.width(), rect.height()); + mView.frame = CGRectMake(0, 0, rect.width(), rect.height()); + [mView deleteFramebuffer]; [mWindow setNeedsDisplay]; } QPlatformWindow::setGeometry(rect); @@ -75,15 +346,30 @@ void QUIKitWindow::setGeometry(const QRect &rect) UIWindow *QUIKitWindow::ensureNativeWindow() { if (!mWindow) { - CGRect screenBounds = [mScreen->uiScreen() bounds]; + // window QRect geom = geometry(); CGRect frame = CGRectMake(geom.x(), geom.y(), geom.width(), geom.height()); mWindow = [[UIWindow alloc] initWithFrame:frame]; mWindow.screen = mScreen->uiScreen(); mWindow.frame = frame; // for some reason setting the screen resets frame.origin + + // view + mView = [[EAGLView alloc] initWithFrame:CGRectMake(0, 0, geom.width(), geom.height())]; + [mView setMultipleTouchEnabled:YES]; + [mView setWindow:this]; + [mWindow addSubview:mView]; [mWindow setNeedsDisplay]; + [mWindow makeKeyAndVisible]; } return mWindow; } +QPlatformGLContext *QUIKitWindow::glContext() const +{ + if (!mContext) { + mContext = new EAGLPlatformContext(mView); + } + return mContext; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/uikit/quikitwindowsurface.h b/src/plugins/platforms/uikit/quikitwindowsurface.h index 50d02b4..ca10a71 100644 --- a/src/plugins/platforms/uikit/quikitwindowsurface.h +++ b/src/plugins/platforms/uikit/quikitwindowsurface.h @@ -43,23 +43,6 @@ #define QUIKITWINDOWSURFACE_H #include <QtGui/QPlatformIntegration> -#include <QtGui/QImage> -#include <QtGui/QWindowSystemInterface> - -#include <UIKit/UIKit.h> - -@interface QImageView : UIView -{ - CGImageRef m_cgImage; - QWidget *m_widget; -} - -- (void)setImage:(QImage *)image; -- (void)setWidget:(QWidget *)widget; - -//- (QList<struct QWindowSystemInterface::TouchPoint>)touchPointsForTouches:(NSSet *)touches; -- (void)sendMouseEventForTouches:(NSSet *)touches withEvent:(UIEvent *)event fakeButtons:(Qt::MouseButtons)buttons; -@end QT_BEGIN_NAMESPACE @@ -70,12 +53,10 @@ public: QPaintDevice *paintDevice(); void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); - void resize (const QSize &size); + WindowSurfaceFeatures features() const; - QImageView *nativeView() const { return mView; } private: - QImage *mImage; - QImageView *mView; + QPaintDevice *mPaintDevice; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/uikit/quikitwindowsurface.mm b/src/plugins/platforms/uikit/quikitwindowsurface.mm index 1274fca..bb7dcd7 100644 --- a/src/plugins/platforms/uikit/quikitwindowsurface.mm +++ b/src/plugins/platforms/uikit/quikitwindowsurface.mm @@ -42,201 +42,55 @@ #include "quikitwindowsurface.h" #include "quikitwindow.h" -#include <QtDebug> - -@implementation QImageView - -- (void)dealloc -{ - CGImageRelease(m_cgImage); - [super dealloc]; -} - -- (void)setImage:(QImage *)image -{ - CGImageRelease(m_cgImage); - - const uchar *imageData = image->bits(); - int bitDepth = image->depth(); - int colorBufferSize = 8; - int bytesPrLine = image->bytesPerLine(); - int width = image->width(); - int height = image->height(); - - CGColorSpaceRef cgColourSpaceRef = CGColorSpaceCreateDeviceRGB(); - - CGDataProviderRef cgDataProviderRef = CGDataProviderCreateWithData( - NULL, - imageData, - image->byteCount(), - NULL); - - m_cgImage = CGImageCreate(width, - height, - colorBufferSize, - bitDepth, - bytesPrLine, - cgColourSpaceRef, - kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little, - cgDataProviderRef, - NULL, - false, - kCGRenderingIntentDefault); - - CGDataProviderRelease(cgDataProviderRef); - CGColorSpaceRelease(cgColourSpaceRef); -} - -- (void)setWidget:(QWidget *)widget -{ - m_widget = widget; -} - -- (void)drawRect:(CGRect)rect -{ - - if (!m_cgImage) - return; - - CGContextRef cgContext = UIGraphicsGetCurrentContext(); - CGContextSaveGState( cgContext ); +#include <QtOpenGL/private/qgl_p.h> +#include <QtOpenGL/private/qglpaintdevice_p.h> - int dy = rect.origin.y + CGRectGetMaxY(rect); - CGContextTranslateCTM(cgContext, 0, dy); - CGContextScaleCTM(cgContext, 1, -1); - CGImageRef subImage = CGImageCreateWithImageInRect(m_cgImage, rect); - CGContextDrawImage(cgContext,rect,subImage); - CGImageRelease(subImage); - - CGContextRestoreGState(cgContext); -} - -//- (QList<struct QWindowSystemInterface::TouchPoint>)touchPointsForTouches:(NSSet *)touches -//{ -// NSEnumerator *enumerator = [touches objectEnumerator]; -// id touch; -// int count = 0; -// QList<struct QWindowSystemInterface::TouchPoint> result; -// while ((touch = [enumerator nextObject])) { -// CGPoint locationInView = [touch locationInView:self]; -// CGRect bounds = [self bounds]; -// struct QWindowSystemInterface::TouchPoint p; -// p.id = count; -// p.isPrimary = true; -// p.normalPosition = QPointF(locationInView.x / bounds.size.width, -// locationInView.y / bounds.size.height); -// p.area = QRectF(locationInView.x, locationInView.y, 1, 1); -// p.pressure = 1.; -// switch ([touch phase]) { -// case UITouchPhaseBegan: -// p.state = Qt::TouchPointPressed; -// break; -// case UITouchPhaseMoved: -// p.state = Qt::TouchPointMoved; -// break; -// case UITouchPhaseStationary: -// p.state = Qt::TouchPointStationary; -// break; -// case UITouchPhaseEnded: -// case UITouchPhaseCancelled: -// p.state = Qt::TouchPointReleased; -// break; -// } -// result << p; -// qDebug() << p.id << ":" << p.normalPosition << p.area << p.state; -// ++count; -// } -// qDebug() << result.size(); -// return result; -//} - -- (void)sendMouseEventForTouches:(NSSet *)touches withEvent:(UIEvent *)event fakeButtons:(Qt::MouseButtons)buttons -{ - UITouch *touch = [touches anyObject]; - CGPoint locationInView = [touch locationInView:self]; - QPoint p(locationInView.x, locationInView.y); - // TODO handle global touch point? for status bar? - QWindowSystemInterface::handleMouseEvent(m_widget, (ulong)(event.timestamp*1000), - p, p, buttons); -} - -- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event -{ - //QWindowSystemInterface::handleTouchEvent(m_widget, (ulong)(event.timestamp*1000), - // QEvent::TouchBegin, QTouchEvent::TouchScreen, - // [self touchPointsForTouches:touches]); - [self sendMouseEventForTouches:touches withEvent:event fakeButtons:Qt::LeftButton]; -} +#include <QtDebug> -- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event +class EAGLPaintDevice : public QGLPaintDevice { - //QWindowSystemInterface::handleTouchEvent(m_widget, (ulong)(event.timestamp*1000), - // QEvent::TouchUpdate, QTouchEvent::TouchScreen, - // [self touchPointsForTouches:touches]); - [self sendMouseEventForTouches:touches withEvent:event fakeButtons:Qt::LeftButton]; -} +public: + EAGLPaintDevice(QPlatformWindow *window) + :QGLPaintDevice(), mWindow(window) + { + } -- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event -{ - //QWindowSystemInterface::handleTouchEvent(m_widget, (ulong)(event.timestamp*1000), - // QEvent::TouchEnd, QTouchEvent::TouchScreen, - // [self touchPointsForTouches:touches]); - [self sendMouseEventForTouches:touches withEvent:event fakeButtons:Qt::NoButton]; -} + int devType() const { return QInternal::OpenGL; } + QSize size() const { return mWindow->geometry().size(); } + QGLContext* context() const { return QGLContext::fromPlatformGLContext(mWindow->glContext()); } -- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event -{ - //QWindowSystemInterface::handleTouchEvent(m_widget, (ulong)(event.timestamp*1000), - // QEvent::TouchEnd, QTouchEvent::TouchScreen, - // [self touchPointsForTouches:touches]); - [self sendMouseEventForTouches:touches withEvent:event fakeButtons:Qt::NoButton]; -} + QPaintEngine *paintEngine() const { return qt_qgl_paint_engine(); } -@end + void beginPaint(){ + QGLPaintDevice::beginPaint(); + } +private: + QPlatformWindow *mWindow; +}; QT_BEGIN_NAMESPACE QUIKitWindowSurface::QUIKitWindowSurface(QWidget *window) - : QWindowSurface(window) + : QWindowSurface(window), mPaintDevice(new EAGLPaintDevice(window->platformWindow())) { - QUIKitWindow *platformWindow = static_cast<QUIKitWindow *>(window->platformWindow()); - Q_ASSERT(platformWindow); - const QRect geo = window->geometry(); - mView = [[QImageView alloc] initWithFrame:CGRectMake(geo.x(),geo.y(),geo.width(),geo.height())]; - [mView setMultipleTouchEnabled:YES]; - [mView setWidget:window]; - mImage = new QImage(window->size(),QImage::Format_ARGB32_Premultiplied); - [mView setImage:mImage]; - if (platformWindow->nativeWindow()) { - [platformWindow->nativeWindow() addSubview:mView]; - [mView setNeedsDisplay]; - } } QPaintDevice *QUIKitWindowSurface::paintDevice() { - return mImage; + return mPaintDevice; } void QUIKitWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) { Q_UNUSED(widget); + Q_UNUSED(region); Q_UNUSED(offset); - - QRect geo = region.boundingRect(); - [mView setNeedsDisplayInRect:CGRectMake(geo.x(),geo.y(),geo.width(),geo.height())]; + widget->platformWindow()->glContext()->swapBuffers(); } -void QUIKitWindowSurface::resize (const QSize &size) +QWindowSurface::WindowSurfaceFeatures QUIKitWindowSurface::features() const { - QWindowSurface::resize(size); - - delete mImage; - mImage = new QImage(size,QImage::Format_ARGB32_Premultiplied); - [mView setImage:mImage]; - const QRect geo = geometry(); - [mView setFrame:CGRectMake(geo.x(), geo.y(), size.width(), size.height())]; - [mView setNeedsDisplay]; + return PartialUpdates; } QT_END_NAMESPACE diff --git a/src/plugins/platforms/uikit/uikit.pro b/src/plugins/platforms/uikit/uikit.pro index b73c334..6f5947f 100644 --- a/src/plugins/platforms/uikit/uikit.pro +++ b/src/plugins/platforms/uikit/uikit.pro @@ -2,6 +2,8 @@ TARGET = quikit include(../../qpluginbase.pri) QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms +QT += opengl + OBJECTIVE_SOURCES = main.mm \ quikitintegration.mm \ quikitwindow.mm \ @@ -15,6 +17,8 @@ OBJECTIVE_HEADERS = quikitintegration.h \ quikiteventloop.h \ quikitwindowsurface.h +HEADERS = quikitsoftwareinputhandler.h + #add libz for freetype. LIBS += -lz diff --git a/src/plugins/platforms/wayland/gl_integration/gl_integration.pri b/src/plugins/platforms/wayland/gl_integration/gl_integration.pri new file mode 100644 index 0000000..d9b5fa9 --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/gl_integration.pri @@ -0,0 +1,57 @@ +contains(QT_CONFIG, opengl) { + DEFINES += QT_WAYLAND_GL_SUPPORT + QT += opengl + +HEADERS += \ + $$PWD/qwaylandglintegration.h \ + $$PWD/qwaylandglwindowsurface.h + +SOURCES += \ + $$PWD/qwaylandglintegration.cpp \ + $$PWD/qwaylandglwindowsurface.cpp + + QT_WAYLAND_GL_CONFIG = $$(QT_WAYLAND_GL_CONFIG) + contains(QT_CONFIG, opengles2) { + isEqual(QT_WAYLAND_GL_CONFIG, wayland_egl) { + QT_WAYLAND_GL_INTEGRATION = $$QT_WAYLAND_GL_CONFIG + CONFIG += wayland_egl + } else:isEqual(QT_WAYLAND_GL_CONFIG,readback) { + QT_WAYLAND_GL_INTEGRATION = readback_egl + CONFIG += readback_egl + } else { + QT_WAYLAND_GL_INTEGRATION = xcomposite_egl + CONFIG += xcomposite_egl + } + } else { + isEqual(QT_WAYLAND_GL_CONFIG, readback) { + QT_WAYLAND_GL_INTEGRATION = readback_glx + CONFIG += readback_glx + } else { + QT_WAYLAND_GL_INTEGRATION = xcomposite_glx + CONFIG += xcomposite_glx + } + } + + message("Wayland GL Integration: $$QT_WAYLAND_GL_INTEGRATION") +} + + +wayland_egl { + include ($$PWD/wayland_egl/wayland_egl.pri) +} + +readback_egl { + include ($$PWD/readback_egl/readback_egl.pri) +} + +readback_glx { + include ($$PWD/readback_glx/readback_glx.pri) +} + +xcomposite_glx { + include ($$PWD/xcomposite_glx/xcomposite_glx.pri) +} + +xcomposite_egl { + include ($$PWD/xcomposite_egl/xcomposite_egl.pri) +} diff --git a/src/plugins/platforms/wayland/gl_integration/qwaylandglintegration.cpp b/src/plugins/platforms/wayland/gl_integration/qwaylandglintegration.cpp new file mode 100644 index 0000000..9c8ef4e --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/qwaylandglintegration.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 "qwaylandglintegration.h" + +QWaylandGLIntegration::QWaylandGLIntegration() +{ + +} + +QWaylandGLIntegration::~QWaylandGLIntegration() +{ + +} diff --git a/src/plugins/platforms/wayland/gl_integration/qwaylandglintegration.h b/src/plugins/platforms/wayland/gl_integration/qwaylandglintegration.h new file mode 100644 index 0000000..ac16039 --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/qwaylandglintegration.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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$ +** +****************************************************************************/ + +#ifndef QWAYLANDGLINTEGRATION_H +#define QWAYLANDGLINTEGRATION_H + +class QWaylandWindow; +class QWaylandDisplay; +class QWidget; + +class QWaylandGLIntegration +{ +public: + QWaylandGLIntegration(); + virtual ~QWaylandGLIntegration(); + + virtual void initialize() = 0; + + virtual QWaylandWindow *createEglWindow(QWidget *widget) = 0; + + static QWaylandGLIntegration *createGLIntegration(QWaylandDisplay *waylandDisplay); +}; + +#endif // QWAYLANDGLINTEGRATION_H diff --git a/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp b/src/plugins/platforms/wayland/gl_integration/qwaylandglwindowsurface.cpp index a8bc352..ebe4c7b 100644 --- a/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp +++ b/src/plugins/platforms/wayland/gl_integration/qwaylandglwindowsurface.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#include "qwaylanddrmsurface.h" +#include "qwaylandglwindowsurface.h" #include "qwaylanddisplay.h" #include "qwaylandwindow.h" @@ -52,10 +52,11 @@ QT_BEGIN_NAMESPACE - - static void drawTexture(const QRectF &rect, GLuint tex_id, const QSize &texSize, const QRectF &br) { +#if !defined(QT_OPENGL_ES_2) + QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext()); +#endif const GLenum target = GL_TEXTURE_2D; QRectF src = br.isEmpty() ? QRectF(QPointF(), texSize) @@ -132,7 +133,7 @@ static void blitTexture(QGLContext *ctx, GLuint texture, const QSize &viewport, drawTexture(r, texture, texSize, sourceRect); } -QWaylandDrmWindowSurface::QWaylandDrmWindowSurface(QWidget *window) +QWaylandGLWindowSurface::QWaylandGLWindowSurface(QWidget *window) : QWindowSurface(window) , mDisplay(QWaylandScreen::waylandScreenFromWidget(window)->display()) , mPaintDevice(0) @@ -140,24 +141,24 @@ QWaylandDrmWindowSurface::QWaylandDrmWindowSurface(QWidget *window) } -QWaylandDrmWindowSurface::~QWaylandDrmWindowSurface() +QWaylandGLWindowSurface::~QWaylandGLWindowSurface() { delete mPaintDevice; } -QPaintDevice *QWaylandDrmWindowSurface::paintDevice() +QPaintDevice *QWaylandGLWindowSurface::paintDevice() { return mPaintDevice; } -void QWaylandDrmWindowSurface::beginPaint(const QRegion &) +void QWaylandGLWindowSurface::beginPaint(const QRegion &) { window()->platformWindow()->glContext()->makeCurrent(); glClearColor(0,0,0,0xff); glClear(GL_COLOR_BUFFER_BIT); } -void QWaylandDrmWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +void QWaylandGLWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) { Q_UNUSED(offset); Q_UNUSED(region); @@ -172,12 +173,12 @@ void QWaylandDrmWindowSurface::flush(QWidget *widget, const QRegion ®ion, con ww->glContext()->swapBuffers(); } -void QWaylandDrmWindowSurface::resize(const QSize &size) +void QWaylandGLWindowSurface::resize(const QSize &size) { QWindowSurface::resize(size); window()->platformWindow()->glContext()->makeCurrent(); delete mPaintDevice; - mPaintDevice = new QGLFramebufferObject(size,QGLFramebufferObject::CombinedDepthStencil,GL_TEXTURE_2D,GL_RGBA); + mPaintDevice = new QGLFramebufferObject(size); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylanddrmsurface.h b/src/plugins/platforms/wayland/gl_integration/qwaylandglwindowsurface.h index 78418ee..8d53b42 100644 --- a/src/plugins/platforms/wayland/qwaylanddrmsurface.h +++ b/src/plugins/platforms/wayland/gl_integration/qwaylandglwindowsurface.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the config.tests of the Qt Toolkit. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -48,11 +48,11 @@ class QGLFramebufferObject; -class QWaylandDrmWindowSurface : public QWindowSurface +class QWaylandGLWindowSurface : public QWindowSurface { public: - QWaylandDrmWindowSurface(QWidget *window); - ~QWaylandDrmWindowSurface(); + QWaylandGLWindowSurface(QWidget *window); + ~QWaylandGLWindowSurface(); void beginPaint(const QRegion &); @@ -62,7 +62,6 @@ public: void resize(const QSize &size); private: - QWaylandDisplay *mDisplay; QGLFramebufferObject *mPaintDevice; }; diff --git a/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglcontext.cpp b/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglcontext.cpp new file mode 100644 index 0000000..d63087d --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglcontext.cpp @@ -0,0 +1,174 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 "qwaylandreadbackeglcontext.h" + +#include "../../../eglconvenience/qeglconvenience.h" + +#include <QtOpenGL/QGLContext> +#include <QtOpenGL/private/qglextensions_p.h> + +#include "qwaylandshmsurface.h" + +#include <QtCore/QDebug> + +static inline void qgl_byteSwapImage(QImage &img, GLenum pixel_type) +{ + const int width = img.width(); + const int height = img.height(); + + if (pixel_type == GL_UNSIGNED_INT_8_8_8_8_REV + || (pixel_type == GL_UNSIGNED_BYTE && QSysInfo::ByteOrder == QSysInfo::LittleEndian)) + { + for (int i = 0; i < height; ++i) { + uint *p = (uint *) img.scanLine(i); + for (int x = 0; x < width; ++x) + p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00); + } + } else { + for (int i = 0; i < height; ++i) { + uint *p = (uint *) img.scanLine(i); + for (int x = 0; x < width; ++x) + p[x] = (p[x] << 8) | ((p[x] >> 24) & 0xff); + } + } +} + +QWaylandReadbackEglContext::QWaylandReadbackEglContext(QWaylandReadbackEglIntegration *eglIntegration, QWaylandReadbackEglWindow *window) + : mEglIntegration(eglIntegration) + , mWindow(window) + , mBuffer(0) + , mPixmap(0) + , mConfig(q_configFromQPlatformWindowFormat(eglIntegration->eglDisplay(),window->widget()->platformWindowFormat(),true,EGL_PIXMAP_BIT)) + , mPixmapSurface(EGL_NO_SURFACE) +{ + QVector<EGLint> eglContextAttrs; + eglContextAttrs.append(EGL_CONTEXT_CLIENT_VERSION); + eglContextAttrs.append(2); + eglContextAttrs.append(EGL_NONE); + + mContext = eglCreateContext(eglIntegration->eglDisplay(),mConfig,0,eglContextAttrs.constData()); + + geometryChanged(); +} + +QWaylandReadbackEglContext::~QWaylandReadbackEglContext() +{ + eglDestroyContext(mEglIntegration->eglDisplay(),mContext); +} + +void QWaylandReadbackEglContext::makeCurrent() +{ + QPlatformGLContext::makeCurrent(); + + mWindow->waitForFrameSync(); + + eglMakeCurrent(mEglIntegration->eglDisplay(),mPixmapSurface,mPixmapSurface,mContext); +} + +void QWaylandReadbackEglContext::doneCurrent() +{ + QPlatformGLContext::doneCurrent(); + eglMakeCurrent(mEglIntegration->eglDisplay(),EGL_NO_SURFACE,EGL_NO_SURFACE,EGL_NO_CONTEXT); +} + +void QWaylandReadbackEglContext::swapBuffers() +{ + eglSwapBuffers(mEglIntegration->eglDisplay(),mPixmapSurface); + + if (QPlatformGLContext::currentContext() != this) { + makeCurrent(); + } + + QSize size = mWindow->geometry().size(); + + QImage img(size,QImage::Format_ARGB32); + const uchar *constBits = img.bits(); + void *pixels = const_cast<uchar *>(constBits); + + glReadPixels(0,0, size.width(), size.height(), GL_RGBA,GL_UNSIGNED_BYTE, pixels); + + img = img.mirrored(); + qgl_byteSwapImage(img,GL_UNSIGNED_INT_8_8_8_8_REV); + constBits = img.bits(); + + const uchar *constDstBits = mBuffer->image()->bits(); + uchar *dstBits = const_cast<uchar *>(constDstBits); + memcpy(dstBits,constBits,(img.width()*4) * img.height()); + + + mWindow->damage(QRegion(QRect(QPoint(0,0),size))); +} + +void * QWaylandReadbackEglContext::getProcAddress(const QString &procName) +{ + return (void *) eglGetProcAddress(procName.toLatin1().data()); +} + +QPlatformWindowFormat QWaylandReadbackEglContext::platformWindowFormat() const +{ + return qt_qPlatformWindowFormatFromConfig(mEglIntegration->eglDisplay(),mConfig); +} + +void QWaylandReadbackEglContext::geometryChanged() +{ + QSize size(mWindow->geometry().size()); + if (size.isEmpty()) { + //QGLWidget wants a context for a window without geometry + size = QSize(1,1); + } + + mWindow->waitForFrameSync(); + + delete mBuffer; + if (mPixmap) + XFreePixmap(mEglIntegration->xDisplay(),mPixmap); + + mBuffer = new QWaylandShmBuffer(mEglIntegration->waylandDisplay(),size,QImage::Format_ARGB32); + mWindow->attach(mBuffer); + mPixmap = XCreatePixmap(mEglIntegration->xDisplay(),mEglIntegration->rootWindow(),size.width(),size.height(),mEglIntegration->depth()); + XSync(mEglIntegration->xDisplay(),False); + + mPixmapSurface = eglCreatePixmapSurface(mEglIntegration->eglDisplay(),mConfig,mPixmap,0); + if (mPixmapSurface == EGL_NO_SURFACE) { + qDebug() << "Could not make egl surface out of pixmap :("; + } +} diff --git a/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglcontext.h b/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglcontext.h new file mode 100644 index 0000000..ac68275 --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglcontext.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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$ +** +****************************************************************************/ + +#ifndef QWAYLANDREADBACKEGLGLCONTEXT_H +#define QWAYLANDREADBACKEGLGLCONTEXT_H + +#include <QPlatformGLContext> +#include <QtGui/QWidget> + +#include "qwaylandreadbackeglintegration.h" +#include "qwaylandreadbackeglwindow.h" + +class QWaylandShmBuffer; + +class QWaylandReadbackEglContext : public QPlatformGLContext +{ +public: + QWaylandReadbackEglContext(QWaylandReadbackEglIntegration *eglIntegration, QWaylandReadbackEglWindow *window); + ~QWaylandReadbackEglContext(); + + void makeCurrent(); + void doneCurrent(); + void swapBuffers(); + void* getProcAddress(const QString& procName); + + virtual QPlatformWindowFormat platformWindowFormat() const; + + void geometryChanged(); + +private: + QWaylandReadbackEglIntegration *mEglIntegration; + QWaylandReadbackEglWindow *mWindow; + QWaylandShmBuffer *mBuffer; + + Pixmap mPixmap; + + EGLConfig mConfig; + EGLContext mContext; + EGLSurface mPixmapSurface; +}; + +#endif // QWAYLANDREADBACKEGLGLCONTEXT_H diff --git a/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglintegration.cpp b/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglintegration.cpp new file mode 100644 index 0000000..20f7ffb --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglintegration.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 "qwaylandreadbackeglintegration.h" + +#include <QDebug> + +#include "qwaylandreadbackeglwindow.h" + +QWaylandReadbackEglIntegration::QWaylandReadbackEglIntegration(QWaylandDisplay *display) + : QWaylandGLIntegration() + , mWaylandDisplay(display) +{ + qDebug() << "Using Readback-EGL"; + char *display_name = getenv("DISPLAY"); + mDisplay = XOpenDisplay(display_name); + mScreen = XDefaultScreen(mDisplay); + mRootWindow = XDefaultRootWindow(mDisplay); + XSync(mDisplay, False); +} + +QWaylandReadbackEglIntegration::~QWaylandReadbackEglIntegration() +{ + XCloseDisplay(mDisplay); +} + + +QWaylandGLIntegration *QWaylandGLIntegration::createGLIntegration(QWaylandDisplay *waylandDisplay) +{ + return new QWaylandReadbackEglIntegration(waylandDisplay); +} + +void QWaylandReadbackEglIntegration::initialize() +{ + eglBindAPI(EGL_OPENGL_ES_API); + mEglDisplay = eglGetDisplay(mDisplay); + EGLint major, minor; + EGLBoolean initialized = eglInitialize(mEglDisplay,&major,&minor); + if (initialized) { + qDebug() << "EGL initialized successfully" << major << "," << minor; + } else { + qDebug() << "EGL could not initialized. All EGL and GL operations will fail"; + } +} + +QWaylandWindow * QWaylandReadbackEglIntegration::createEglWindow(QWidget *widget) +{ + return new QWaylandReadbackEglWindow(widget,this); +} + +EGLDisplay QWaylandReadbackEglIntegration::eglDisplay() +{ + return mEglDisplay; +} + +Window QWaylandReadbackEglIntegration::rootWindow() const +{ + return mRootWindow; +} + +int QWaylandReadbackEglIntegration::depth() const +{ + return XDefaultDepth(mDisplay,mScreen); +} + +Display * QWaylandReadbackEglIntegration::xDisplay() const +{ + return mDisplay; +} + +QWaylandDisplay * QWaylandReadbackEglIntegration::waylandDisplay() const +{ + return mWaylandDisplay; +} diff --git a/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglintegration.h b/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglintegration.h new file mode 100644 index 0000000..84fa64f --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglintegration.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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$ +** +****************************************************************************/ + +#ifndef QWAYLANDREADBACKEGLINTEGRATION_H +#define QWAYLANDREADBACKEGLINTEGRATION_H + +#include "gl_integration/qwaylandglintegration.h" + +#include <QtCore/QTextStream> +#include <QtCore/QDataStream> +#include <QtCore/QMetaType> +#include <QtCore/QVariant> +#include <QtGui/QWidget> + +#include <X11/Xlib.h> + +#include <EGL/egl.h> + +class QWaylandReadbackEglIntegration : public QWaylandGLIntegration +{ +public: + QWaylandReadbackEglIntegration(QWaylandDisplay *display); + ~QWaylandReadbackEglIntegration(); + + void initialize(); + QWaylandWindow *createEglWindow(QWidget *widget); + + QWaylandDisplay *waylandDisplay() const; + Display *xDisplay() const; + Window rootWindow() const; + int depth() const; + + EGLDisplay eglDisplay(); + +private: + QWaylandDisplay *mWaylandDisplay; + Display *mDisplay; + int mScreen; + Window mRootWindow; + EGLDisplay mEglDisplay; + +}; + +#endif // QWAYLANDREADBACKEGLINTEGRATION_H diff --git a/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglwindow.cpp b/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglwindow.cpp new file mode 100644 index 0000000..2ae212b --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglwindow.cpp @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 "qwaylandreadbackeglwindow.h" + +#include "qwaylandreadbackeglcontext.h" + +QWaylandReadbackEglWindow::QWaylandReadbackEglWindow(QWidget *window, QWaylandReadbackEglIntegration *eglIntegration) + : QWaylandShmWindow(window) + , mEglIntegration(eglIntegration) + , mContext(0) +{ +} + +QWaylandWindow::WindowType QWaylandReadbackEglWindow::windowType() const +{ + //We'r lying, maybe we should add a type, but for now it will do + //since this is primarly used by the windowsurface. + return QWaylandWindow::Egl; +} + +QPlatformGLContext *QWaylandReadbackEglWindow::glContext() const +{ + if (!mContext) { + QWaylandReadbackEglWindow *that = const_cast<QWaylandReadbackEglWindow *>(this); + that->mContext = new QWaylandReadbackEglContext(mEglIntegration,that); + } + return mContext; +} + +void QWaylandReadbackEglWindow::setGeometry(const QRect &rect) +{ + QPlatformWindow::setGeometry(rect); + + if (mContext) + mContext->geometryChanged(); +} + diff --git a/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglwindow.h b/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglwindow.h new file mode 100644 index 0000000..453ad27 --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglwindow.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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$ +** +****************************************************************************/ + +#ifndef QWAYLANDREADBACKEGLWINDOW_H +#define QWAYLANDREADBACKEGLWINDOW_H + +#include "qwaylandshmwindow.h" +#include "qwaylandreadbackeglintegration.h" + +class QWaylandReadbackEglContext; + +class QWaylandReadbackEglWindow : public QWaylandShmWindow +{ +public: + QWaylandReadbackEglWindow(QWidget *window, QWaylandReadbackEglIntegration *eglIntegration); + + WindowType windowType() const; + + QPlatformGLContext *glContext() const; + + void setGeometry(const QRect &rect); + +private: + QWaylandReadbackEglIntegration *mEglIntegration; + QWaylandReadbackEglContext *mContext; +}; + +#endif // QWAYLANDREADBACKEGLWINDOW_H diff --git a/src/plugins/platforms/wayland/gl_integration/readback_egl/readback_egl.pri b/src/plugins/platforms/wayland/gl_integration/readback_egl/readback_egl.pri new file mode 100644 index 0000000..0d8e01b --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/readback_egl/readback_egl.pri @@ -0,0 +1,14 @@ + +LIBS += -lX11 -lXext -lEGL + +HEADERS += \ + $$PWD/qwaylandreadbackeglintegration.h \ + $$PWD/qwaylandreadbackeglcontext.h \ + $$PWD/qwaylandreadbackeglwindow.h \ + $$PWD/../../../eglconvenience/qeglconvenience.h + +SOURCES += \ + $$PWD/qwaylandreadbackeglintegration.cpp \ + $$PWD/qwaylandreadbackeglwindow.cpp \ + $$PWD/qwaylandreadbackeglcontext.cpp \ + $$PWD/../../../eglconvenience/qeglconvenience.cpp diff --git a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxcontext.cpp b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxcontext.cpp new file mode 100644 index 0000000..08c5cf6c --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxcontext.cpp @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 "qwaylandreadbackglxcontext.h" + +#include "qwaylandshmsurface.h" +#include "qwaylandreadbackglxwindow.h" + +#include <QtCore/QDebug> + +static inline void qgl_byteSwapImage(QImage &img, GLenum pixel_type) +{ + const int width = img.width(); + const int height = img.height(); + + if (pixel_type == GL_UNSIGNED_INT_8_8_8_8_REV + || (pixel_type == GL_UNSIGNED_BYTE && QSysInfo::ByteOrder == QSysInfo::LittleEndian)) + { + for (int i = 0; i < height; ++i) { + uint *p = (uint *) img.scanLine(i); + for (int x = 0; x < width; ++x) + p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00); + } + } else { + for (int i = 0; i < height; ++i) { + uint *p = (uint *) img.scanLine(i); + for (int x = 0; x < width; ++x) + p[x] = (p[x] << 8) | ((p[x] >> 24) & 0xff); + } + } +} + +QWaylandReadbackGlxContext::QWaylandReadbackGlxContext(QWaylandReadbackGlxIntegration *glxIntegration, QWaylandReadbackGlxWindow *window) + : QPlatformGLContext() + , mGlxIntegration(glxIntegration) + , mWindow(window) + , mBuffer(0) + , mPixmap(0) + , mConfig(qglx_findConfig(glxIntegration->xDisplay(),glxIntegration->screen(),window->widget()->platformWindowFormat(),GLX_PIXMAP_BIT)) + , mGlxPixmap(0) +{ + XVisualInfo *visualInfo = glXGetVisualFromFBConfig(glxIntegration->xDisplay(),mConfig); + mContext = glXCreateContext(glxIntegration->xDisplay(),visualInfo,0,TRUE); + + geometryChanged(); +} + +void QWaylandReadbackGlxContext::makeCurrent() +{ + QPlatformGLContext::makeCurrent(); + + glXMakeCurrent(mGlxIntegration->xDisplay(),mGlxPixmap,mContext); +} + +void QWaylandReadbackGlxContext::doneCurrent() +{ + QPlatformGLContext::doneCurrent(); +} + +void QWaylandReadbackGlxContext::swapBuffers() +{ + if (QPlatformGLContext::currentContext() != this) { + makeCurrent(); + } + + QSize size = mWindow->geometry().size(); + + QImage img(size,QImage::Format_ARGB32); + const uchar *constBits = img.bits(); + void *pixels = const_cast<uchar *>(constBits); + + glReadPixels(0,0, size.width(), size.height(), GL_RGBA,GL_UNSIGNED_BYTE, pixels); + + img = img.mirrored(); + qgl_byteSwapImage(img,GL_UNSIGNED_INT_8_8_8_8_REV); + constBits = img.bits(); + + const uchar *constDstBits = mBuffer->image()->bits(); + uchar *dstBits = const_cast<uchar *>(constDstBits); + memcpy(dstBits,constBits,(img.width()*4) * img.height()); + + + mWindow->damage(QRegion(QRect(QPoint(0,0),size))); + mWindow->waitForFrameSync(); + +} + +void * QWaylandReadbackGlxContext::getProcAddress(const QString &procName) +{ + return (void *) glXGetProcAddress(reinterpret_cast<GLubyte *>(procName.toLatin1().data())); +} + +QPlatformWindowFormat QWaylandReadbackGlxContext::platformWindowFormat() const +{ + return qglx_platformWindowFromGLXFBConfig(mGlxIntegration->xDisplay(),mConfig,mContext); +} + +void QWaylandReadbackGlxContext::geometryChanged() +{ + QSize size(mWindow->geometry().size()); + if (size.isEmpty()) { + //QGLWidget wants a context for a window without geometry + size = QSize(1,1); + } + + mWindow->waitForFrameSync(); + + delete mBuffer; + //XFreePixmap deletes the glxPixmap as well + if (mPixmap) { + XFreePixmap(mGlxIntegration->xDisplay(),mPixmap); + } + + mBuffer = new QWaylandShmBuffer(mGlxIntegration->waylandDisplay(),size,QImage::Format_ARGB32); + mWindow->attach(mBuffer); + int depth = XDefaultDepth(mGlxIntegration->xDisplay(),mGlxIntegration->screen()); + mPixmap = XCreatePixmap(mGlxIntegration->xDisplay(),mGlxIntegration->rootWindow(),size.width(),size.height(),depth); + XSync(mGlxIntegration->xDisplay(),False); + + mGlxPixmap = glXCreatePixmap(mGlxIntegration->xDisplay(),mConfig,mPixmap,0); + + if (!mGlxPixmap) { + qDebug() << "Could not make egl surface out of pixmap :("; + } +} diff --git a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxcontext.h b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxcontext.h new file mode 100644 index 0000000..5fafcf0 --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxcontext.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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$ +** +****************************************************************************/ + +#ifndef QWAYLANDREADBACKGLXCONTEXT_H +#define QWAYLANDREADBACKGLXCONTEXT_H + +#include <QPlatformGLContext> + +#include "qwaylandreadbackglxintegration.h" + +#include "qglxconvenience.h" + +class QWaylandReadbackGlxWindow; +class QWaylandShmBuffer; + +class QWaylandReadbackGlxContext : public QPlatformGLContext +{ +public: + QWaylandReadbackGlxContext(QWaylandReadbackGlxIntegration *glxIntegration, QWaylandReadbackGlxWindow *window); + + void makeCurrent(); + void doneCurrent(); + void swapBuffers(); + void* getProcAddress(const QString& procName); + + QPlatformWindowFormat platformWindowFormat() const; + + void geometryChanged(); + +private: + QWaylandReadbackGlxIntegration *mGlxIntegration; + QWaylandReadbackGlxWindow *mWindow; + QWaylandShmBuffer *mBuffer; + + Pixmap mPixmap; + GLXFBConfig mConfig; + GLXContext mContext; + GLXPixmap mGlxPixmap; +}; + +#endif // QWAYLANDREADBACKGLXCONTEXT_H diff --git a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxintegration.cpp b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxintegration.cpp new file mode 100644 index 0000000..4651f0c --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxintegration.cpp @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 "qwaylandreadbackglxintegration.h" + +#include "qwaylandreadbackglxwindow.h" + +#include <QtCore/QDebug> + +QWaylandReadbackGlxIntegration::QWaylandReadbackGlxIntegration(QWaylandDisplay * waylandDispaly) + : QWaylandGLIntegration() + , mWaylandDisplay(waylandDispaly) +{ + qDebug() << "Using Readback-GLX"; + char *display_name = getenv("DISPLAY"); + mDisplay = XOpenDisplay(display_name); + mScreen = XDefaultScreen(mDisplay); + mRootWindow = XDefaultRootWindow(mDisplay); + XSync(mDisplay, False); +} + +QWaylandReadbackGlxIntegration::~QWaylandReadbackGlxIntegration() +{ + XCloseDisplay(mDisplay); +} + +void QWaylandReadbackGlxIntegration::initialize() +{ +} + +QWaylandWindow * QWaylandReadbackGlxIntegration::createEglWindow(QWidget *widget) +{ + return new QWaylandReadbackGlxWindow(widget,this); +} + +QWaylandGLIntegration * QWaylandGLIntegration::createGLIntegration(QWaylandDisplay *waylandDisplay) +{ + return new QWaylandReadbackGlxIntegration(waylandDisplay); +} + +Display * QWaylandReadbackGlxIntegration::xDisplay() const +{ + return mDisplay; +} + +int QWaylandReadbackGlxIntegration::screen() const +{ + return mScreen; +} + +Window QWaylandReadbackGlxIntegration::rootWindow() const +{ + return mRootWindow; +} + +QWaylandDisplay * QWaylandReadbackGlxIntegration::waylandDisplay() const +{ + return mWaylandDisplay; +} diff --git a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxintegration.h b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxintegration.h new file mode 100644 index 0000000..9056393 --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxintegration.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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$ +** +****************************************************************************/ + +#ifndef QWAYLANDREADBACKGLXINTEGRATION_H +#define QWAYLANDREADBACKGLXINTEGRATION_H + +#include "gl_integration/qwaylandglintegration.h" + +#include <QtCore/QTextStream> +#include <QtCore/QDataStream> +#include <QtCore/QMetaType> +#include <QtCore/QVariant> +#include <QtGui/QWidget> + +#include <X11/Xlib.h> + +class QWaylandReadbackGlxIntegration : public QWaylandGLIntegration +{ +public: + QWaylandReadbackGlxIntegration(QWaylandDisplay * waylandDispaly); + ~QWaylandReadbackGlxIntegration(); + + void initialize(); + + QWaylandWindow *createEglWindow(QWidget *widget); + + QWaylandDisplay *waylandDisplay() const; + + Display *xDisplay() const; + int screen() const; + Window rootWindow() const; + +private: + QWaylandDisplay *mWaylandDisplay; + + Display *mDisplay; + int mScreen; + Window mRootWindow; + +}; + +#endif // QWAYLANDREADBACKGLXINTEGRATION_H diff --git a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxwindow.cpp b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxwindow.cpp new file mode 100644 index 0000000..ca1603c --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxwindow.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 "qwaylandreadbackglxwindow.h" + +QWaylandReadbackGlxWindow::QWaylandReadbackGlxWindow(QWidget *window, QWaylandReadbackGlxIntegration *glxIntegration) + : QWaylandShmWindow(window) + , mGlxIntegration(glxIntegration) + , mContext(0) +{ +} + +QWaylandWindow::WindowType QWaylandReadbackGlxWindow::windowType() const +{ + //yeah. this type needs a new name + return QWaylandWindow::Egl; +} + +QPlatformGLContext * QWaylandReadbackGlxWindow::glContext() const +{ + if (!mContext) { + QWaylandReadbackGlxWindow *that = const_cast<QWaylandReadbackGlxWindow *>(this); + that->mContext = new QWaylandReadbackGlxContext(mGlxIntegration,that); + } + return mContext; +} + +void QWaylandReadbackGlxWindow::setGeometry(const QRect &rect) +{ + QWaylandShmWindow::setGeometry(rect); + + if (mContext) { + mContext->geometryChanged(); + } +} diff --git a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxwindow.h b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxwindow.h new file mode 100644 index 0000000..4d7bb3e --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxwindow.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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$ +** +****************************************************************************/ + +#ifndef QWAYLANDREADBACKGLXWINDOW_H +#define QWAYLANDREADBACKGLXWINDOW_H + +#include "qwaylandshmwindow.h" +#include "qwaylandreadbackglxintegration.h" +#include "qwaylandreadbackglxcontext.h" + +class QWaylandReadbackGlxWindow : public QWaylandShmWindow +{ +public: + QWaylandReadbackGlxWindow(QWidget *window, QWaylandReadbackGlxIntegration *glxIntegration); + WindowType windowType() const; + + QPlatformGLContext *glContext() const; + + void setGeometry(const QRect &rect); + +private: + QWaylandReadbackGlxIntegration *mGlxIntegration; + QWaylandReadbackGlxContext *mContext; + +}; + +#endif // QWAYLANDREADBACKGLXWINDOW_H diff --git a/src/plugins/platforms/wayland/gl_integration/readback_glx/readback_glx.pri b/src/plugins/platforms/wayland/gl_integration/readback_glx/readback_glx.pri new file mode 100644 index 0000000..f8ea005 --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/readback_glx/readback_glx.pri @@ -0,0 +1,12 @@ +include (../../../glxconvenience/glxconvenience.pri) +HEADERS += \ + $$PWD/qwaylandreadbackglxintegration.h \ + $$PWD/qwaylandreadbackglxwindow.h \ + $$PWD/qwaylandreadbackglxcontext.h + +SOURCES += \ + $$PWD/qwaylandreadbackglxintegration.cpp \ + $$PWD/qwaylandreadbackglxwindow.cpp \ + $$PWD/qwaylandreadbackglxcontext.cpp + +LIBS += -lX11 diff --git a/src/plugins/platforms/wayland/qwaylandinclude.h b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglinclude.h index 0135251..5dc2add 100644 --- a/src/plugins/platforms/wayland/qwaylandinclude.h +++ b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglinclude.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the config.tests of the Qt Toolkit. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -39,12 +39,11 @@ ** ****************************************************************************/ -#ifndef QWAYLANDINCLUDE_H -#define QWAYLANDINCLUDE_H +#ifndef QWAYLANDEGLINCLUDE_H +#define QWAYLANDEGLINCLUDE_H #include <wayland-client.h> -#ifdef QT_WAYLAND_GL_SUPPORT #include <wayland-egl.h> #define GL_GLEXT_PROTOTYPES @@ -52,12 +51,7 @@ #include <GLES2/gl2ext.h> #define EGL_EGLEXT_PROTOTYPES - #include <EGL/egl.h> - #include <EGL/eglext.h> +#include <EGL/egl.h> +#include <EGL/eglext.h> -#else -typedef void* EGLDisplay; -typedef void* EGLConfig; -#endif - -#endif // QWAYLANDINCLUDE_H +#endif // QWAYLANDEGLINCLUDE_H diff --git a/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglintegration.cpp b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglintegration.cpp new file mode 100644 index 0000000..39e7be5 --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglintegration.cpp @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 "qwaylandeglintegration.h" + +#include "gl_integration/qwaylandglintegration.h" + +#include "qwaylandeglwindow.h" + +#include <QtCore/QDebug> + +QWaylandEglIntegration::QWaylandEglIntegration(struct wl_display *waylandDisplay) + : mWaylandDisplay(waylandDisplay) + , mNativeEglDisplay(wl_egl_display_create(mWaylandDisplay)) +{ + qDebug() << "Using Wayland-EGL"; +} + + +QWaylandEglIntegration::~QWaylandEglIntegration() +{ + eglTerminate(mEglDisplay); +} + +void QWaylandEglIntegration::initialize() +{ + EGLint major,minor; + mEglDisplay = eglGetDisplay((EGLNativeDisplayType)mNativeEglDisplay); + if (mEglDisplay == NULL) { + qWarning("EGL not available"); + } else { + if (!eglInitialize(mEglDisplay, &major, &minor)) { + qWarning("failed to initialize EGL display"); + return; + } + } +} + +QWaylandWindow *QWaylandEglIntegration::createEglWindow(QWidget *window) +{ + return new QWaylandEglWindow(window); +} + +EGLDisplay QWaylandEglIntegration::eglDisplay() const +{ + return mEglDisplay; +} + +wl_egl_display * QWaylandEglIntegration::nativeDisplay() const +{ + return mNativeEglDisplay; +} + +QWaylandGLIntegration *QWaylandGLIntegration::createGLIntegration(QWaylandDisplay *waylandDisplay) +{ + return new QWaylandEglIntegration(waylandDisplay->wl_display()); +} diff --git a/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglintegration.h b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglintegration.h new file mode 100644 index 0000000..bf4c3fe --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglintegration.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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$ +** +****************************************************************************/ + +#ifndef QWAYLANDEGLINTEGRATION_H +#define QWAYLANDEGLINTEGRATION_H + +#include "gl_integration/qwaylandglintegration.h" + +#include "qwaylandeglinclude.h" + +class QWaylandWindow; +class QWidget; + +class QWaylandEglIntegration : public QWaylandGLIntegration +{ +public: + QWaylandEglIntegration(struct wl_display *waylandDisplay); + ~QWaylandEglIntegration(); + + void initialize(); + + QWaylandWindow *createEglWindow(QWidget *window); + + EGLDisplay eglDisplay() const; + struct wl_egl_display *nativeDisplay() const; +private: + struct wl_display *mWaylandDisplay; + + EGLDisplay mEglDisplay; + struct wl_egl_display *mNativeEglDisplay; + + +}; + +#endif // QWAYLANDEGLINTEGRATION_H diff --git a/src/plugins/platforms/wayland/qwaylandeglwindow.cpp b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglwindow.cpp index ed54bb9..d7cf0a5 100644 --- a/src/plugins/platforms/wayland/qwaylandeglwindow.cpp +++ b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglwindow.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the config.tests of the Qt Toolkit. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -43,21 +43,20 @@ #include "qwaylandscreen.h" #include "qwaylandglcontext.h" -#include "qwaylandinclude.h" QWaylandEglWindow::QWaylandEglWindow(QWidget *window) : QWaylandWindow(window) , mGLContext(0) , mWaylandEglWindow(0) { + mEglIntegration = static_cast<QWaylandEglIntegration *>(mDisplay->eglIntegration()); //super creates a new surface newSurfaceCreated(); } QWaylandEglWindow::~QWaylandEglWindow() { - if (mGLContext) - delete mGLContext; + delete mGLContext; } QWaylandWindow::WindowType QWaylandEglWindow::windowType() const @@ -84,10 +83,10 @@ QPlatformGLContext * QWaylandEglWindow::glContext() const { if (!mGLContext) { QWaylandEglWindow *that = const_cast<QWaylandEglWindow *>(this); - that->mGLContext = new QWaylandGLContext(that->mDisplay,widget()->platformWindowFormat()); + that->mGLContext = new QWaylandGLContext(mEglIntegration->eglDisplay(),widget()->platformWindowFormat()); EGLNativeWindowType window(reinterpret_cast<EGLNativeWindowType>(mWaylandEglWindow)); - EGLSurface surface = eglCreateWindowSurface(mDisplay->eglDisplay(),mGLContext->eglConfig(),window,NULL); + EGLSurface surface = eglCreateWindowSurface(mEglIntegration->eglDisplay(),mGLContext->eglConfig(),window,NULL); that->mGLContext->setEglSurface(surface); } @@ -104,10 +103,10 @@ void QWaylandEglWindow::newSurfaceCreated() if (!size.isValid()) size = QSize(0,0); - mWaylandEglWindow = wl_egl_window_create(mDisplay->nativeDisplay(),mSurface,size.width(),size.height(),visual); + mWaylandEglWindow = wl_egl_window_create(mEglIntegration->nativeDisplay(),mSurface,size.width(),size.height(),visual); if (mGLContext) { EGLNativeWindowType window(reinterpret_cast<EGLNativeWindowType>(mWaylandEglWindow)); - EGLSurface surface = eglCreateWindowSurface(mDisplay->eglDisplay(),mGLContext->eglConfig(),window,NULL); + EGLSurface surface = eglCreateWindowSurface(mEglIntegration->eglDisplay(),mGLContext->eglConfig(),window,NULL); mGLContext->setEglSurface(surface); } } diff --git a/src/plugins/platforms/wayland/qwaylandeglwindow.h b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglwindow.h index 4b3bb5b..549d039 100644 --- a/src/plugins/platforms/wayland/qwaylandeglwindow.h +++ b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglwindow.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the config.tests of the Qt Toolkit. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -43,6 +43,8 @@ #define QWAYLANDEGLWINDOW_H #include "qwaylandwindow.h" +#include "qwaylandeglinclude.h" +#include "qwaylandeglintegration.h" class QWaylandGLContext; @@ -58,6 +60,7 @@ public: protected: void newSurfaceCreated(); private: + QWaylandEglIntegration *mEglIntegration; QWaylandGLContext *mGLContext; struct wl_egl_window *mWaylandEglWindow; EGLConfig mConfig; diff --git a/src/plugins/platforms/wayland/qwaylandglcontext.cpp b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandglcontext.cpp index 3720567..d293019 100644 --- a/src/plugins/platforms/wayland/qwaylandglcontext.cpp +++ b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandglcontext.cpp @@ -43,37 +43,22 @@ #include "qwaylanddisplay.h" #include "qwaylandwindow.h" -#include "qwaylanddrmsurface.h" -#include "../eglconvenience/qeglconvenience.h" +#include "../../../eglconvenience/qeglconvenience.h" #include <QtGui/QPlatformGLContext> #include <QtGui/QPlatformWindowFormat> +#include <QtCore/QMutex> -Q_GLOBAL_STATIC(QMutex,qt_defaultSharedContextMutex) - -QWaylandGLContext::QWaylandGLContext(QWaylandDisplay *wd, const QPlatformWindowFormat &format) +QWaylandGLContext::QWaylandGLContext(EGLDisplay eglDisplay, const QPlatformWindowFormat &format) : QPlatformGLContext() - , mDisplay(wd) + , mEglDisplay(eglDisplay) , mSurface(EGL_NO_SURFACE) - , mConfig(q_configFromQPlatformWindowFormat(mDisplay->eglDisplay(),format,true)) - , mFormat(qt_qPlatformWindowFormatFromConfig(mDisplay->eglDisplay(),mConfig)) + , mConfig(q_configFromQPlatformWindowFormat(mEglDisplay,format,true)) + , mFormat(qt_qPlatformWindowFormatFromConfig(mEglDisplay,mConfig)) { QPlatformGLContext *sharePlatformContext = 0; - if (format.useDefaultSharedContext()) { - if (!QPlatformGLContext::defaultSharedContext()) { - if (qt_defaultSharedContextMutex()->tryLock()){ - createDefaultSharedContex(wd); - qt_defaultSharedContextMutex()->unlock(); - } else { - qt_defaultSharedContextMutex()->lock(); //wait to the the shared context is created - qt_defaultSharedContextMutex()->unlock(); - } - } - sharePlatformContext = QPlatformGLContext::defaultSharedContext(); - } else { - sharePlatformContext = format.sharedGLContext(); - } + sharePlatformContext = format.sharedGLContext(); mFormat.setSharedContext(sharePlatformContext); EGLContext shareEGLContext = EGL_NO_CONTEXT; if (sharePlatformContext) @@ -86,13 +71,13 @@ QWaylandGLContext::QWaylandGLContext(QWaylandDisplay *wd, const QPlatformWindowF eglContextAttrs.append(2); eglContextAttrs.append(EGL_NONE); - mContext = eglCreateContext(mDisplay->eglDisplay(), mConfig, + mContext = eglCreateContext(mEglDisplay, mConfig, shareEGLContext, eglContextAttrs.constData()); } QWaylandGLContext::QWaylandGLContext() : QPlatformGLContext() - , mDisplay(0) + , mEglDisplay(0) , mContext(EGL_NO_CONTEXT) , mSurface(EGL_NO_SURFACE) , mConfig(0) @@ -100,7 +85,7 @@ QWaylandGLContext::QWaylandGLContext() QWaylandGLContext::~QWaylandGLContext() { - eglDestroyContext(mDisplay->eglDisplay(),mContext); + eglDestroyContext(mEglDisplay,mContext); } void QWaylandGLContext::makeCurrent() @@ -109,18 +94,18 @@ void QWaylandGLContext::makeCurrent() if (mSurface == EGL_NO_SURFACE) { qWarning("makeCurrent with EGL_NO_SURFACE"); } - eglMakeCurrent(mDisplay->eglDisplay(), mSurface, mSurface, mContext); + eglMakeCurrent(mEglDisplay, mSurface, mSurface, mContext); } void QWaylandGLContext::doneCurrent() { QPlatformGLContext::doneCurrent(); - eglMakeCurrent(mDisplay->eglDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); } void QWaylandGLContext::swapBuffers() { - eglSwapBuffers(mDisplay->eglDisplay(),mSurface); + eglSwapBuffers(mEglDisplay,mSurface); } void *QWaylandGLContext::getProcAddress(const QString &string) @@ -128,20 +113,6 @@ void *QWaylandGLContext::getProcAddress(const QString &string) return (void *) eglGetProcAddress(string.toLatin1().data()); } -void QWaylandGLContext::createDefaultSharedContex(QWaylandDisplay *display) -{ - QVector<EGLint> eglContextAttrs; - eglContextAttrs.append(EGL_CONTEXT_CLIENT_VERSION); - eglContextAttrs.append(2); - eglContextAttrs.append(EGL_NONE); - - QWaylandGLContext *defaultSharedContext = new QWaylandGLContext; - defaultSharedContext->mDisplay = display; - defaultSharedContext->mContext = eglCreateContext(mDisplay->eglDisplay(),mConfig, - EGL_NO_CONTEXT, eglContextAttrs.constData()); - QPlatformGLContext::setDefaultSharedContext(defaultSharedContext); -} - void QWaylandGLContext::setEglSurface(EGLSurface surface) { doneCurrent(); diff --git a/src/plugins/platforms/wayland/qwaylandglcontext.h b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandglcontext.h index dd319fd..76caffa 100644 --- a/src/plugins/platforms/wayland/qwaylandglcontext.h +++ b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandglcontext.h @@ -46,14 +46,14 @@ #include <QtGui/QPlatformGLContext> -class QWaylandWindow; -class QWaylandDrmWindowSurface; +#include "qwaylandeglinclude.h" -#include "qwaylandinclude.h" +class QWaylandWindow; +class QWaylandGLWindowSurface; class QWaylandGLContext : public QPlatformGLContext { public: - QWaylandGLContext(QWaylandDisplay *wd, const QPlatformWindowFormat &format); + QWaylandGLContext(EGLDisplay eglDisplay, const QPlatformWindowFormat &format); ~QWaylandGLContext(); void makeCurrent(); void doneCurrent(); @@ -65,14 +65,13 @@ public: void setEglSurface(EGLSurface surface); EGLConfig eglConfig() const; private: - QWaylandDisplay *mDisplay; + EGLDisplay mEglDisplay; EGLContext mContext; EGLSurface mSurface; EGLConfig mConfig; QPlatformWindowFormat mFormat; - void createDefaultSharedContex(QWaylandDisplay *display); QWaylandGLContext(); }; diff --git a/src/plugins/platforms/wayland/gl_integration/wayland_egl/wayland_egl.pri b/src/plugins/platforms/wayland/gl_integration/wayland_egl/wayland_egl.pri new file mode 100644 index 0000000..bc97864 --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/wayland_egl/wayland_egl.pri @@ -0,0 +1,12 @@ +LIBS += -lwayland-egl -lEGL +INCLUDEPATH += $$PWD +SOURCES += $$PWD/qwaylandeglintegration.cpp \ + $$PWD/qwaylandglcontext.cpp \ + $$PWD/qwaylandeglwindow.cpp \ + $$PWD/../../../eglconvenience/qeglconvenience.cpp + +HEADERS += $$PWD/qwaylandeglintegration.h \ + $$PWD/qwaylandglcontext.h \ + $$PWD/qwaylandeglwindow.h \ + $$PWD/../../../eglconvenience/qeglconvenience.h \ + gl_integration/wayland_egl/qwaylandeglinclude.h diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglcontext.cpp b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglcontext.cpp new file mode 100644 index 0000000..92acf75 --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglcontext.cpp @@ -0,0 +1,169 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 "qwaylandxcompositeeglcontext.h" + +#include "qwaylandxcompositeeglwindow.h" +#include "qwaylandxcompositebuffer.h" + +#include "wayland-xcomposite-client-protocol.h" +#include <QtCore/QDebug> + +#include "qeglconvenience.h" +#include "qxlibeglintegration.h" + +#include <X11/extensions/Xcomposite.h> + +QWaylandXCompositeEGLContext::QWaylandXCompositeEGLContext(QWaylandXCompositeEGLIntegration *glxIntegration, QWaylandXCompositeEGLWindow *window) + : QPlatformGLContext() + , mEglIntegration(glxIntegration) + , mWindow(window) + , mBuffer(0) + , mXWindow(0) + , mConfig(q_configFromQPlatformWindowFormat(glxIntegration->eglDisplay(),window->widget()->platformWindowFormat(),true,EGL_WINDOW_BIT)) + , mWaitingForSync(false) +{ + QVector<EGLint> eglContextAttrs; + eglContextAttrs.append(EGL_CONTEXT_CLIENT_VERSION); eglContextAttrs.append(2); + eglContextAttrs.append(EGL_NONE); + + mContext = eglCreateContext(glxIntegration->eglDisplay(),mConfig,EGL_NO_CONTEXT,eglContextAttrs.constData()); + if (mContext == EGL_NO_CONTEXT) { + qFatal("failed to find context"); + } + + geometryChanged(); +} + +void QWaylandXCompositeEGLContext::makeCurrent() +{ + QPlatformGLContext::makeCurrent(); + + eglMakeCurrent(mEglIntegration->eglDisplay(),mEglWindowSurface,mEglWindowSurface,mContext); +} + +void QWaylandXCompositeEGLContext::doneCurrent() +{ + QPlatformGLContext::doneCurrent(); + eglMakeCurrent(mEglIntegration->eglDisplay(),EGL_NO_SURFACE,EGL_NO_SURFACE,EGL_NO_CONTEXT); +} + +void QWaylandXCompositeEGLContext::swapBuffers() +{ + QSize size = mWindow->geometry().size(); + + eglSwapBuffers(mEglIntegration->eglDisplay(),mEglWindowSurface); + mWindow->damage(QRegion(QRect(QPoint(0,0),size))); + mWindow->waitForFrameSync(); +} + +void * QWaylandXCompositeEGLContext::getProcAddress(const QString &procName) +{ + return (void *)eglGetProcAddress(qPrintable(procName)); +} + +QPlatformWindowFormat QWaylandXCompositeEGLContext::platformWindowFormat() const +{ + return qt_qPlatformWindowFormatFromConfig(mEglIntegration->eglDisplay(),mConfig); +} + +void QWaylandXCompositeEGLContext::sync_function(void *data) +{ + QWaylandXCompositeEGLContext *that = static_cast<QWaylandXCompositeEGLContext *>(data); + that->mWaitingForSync = false; +} + +void QWaylandXCompositeEGLContext::geometryChanged() +{ + QSize size(mWindow->geometry().size()); + if (size.isEmpty()) { + //QGLWidget wants a context for a window without geometry + size = QSize(1,1); + } + + delete mBuffer; + //XFreePixmap deletes the glxPixmap as well + if (mXWindow) { + XDestroyWindow(mEglIntegration->xDisplay(),mXWindow); + } + + VisualID visualId = QXlibEglIntegration::getCompatibleVisualId(mEglIntegration->xDisplay(),mEglIntegration->eglDisplay(),mConfig); + + XVisualInfo visualInfoTemplate; + memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); + visualInfoTemplate.visualid = visualId; + + int matchingCount = 0; + XVisualInfo *visualInfo = XGetVisualInfo(mEglIntegration->xDisplay(), VisualIDMask, &visualInfoTemplate, &matchingCount); + + Colormap cmap = XCreateColormap(mEglIntegration->xDisplay(),mEglIntegration->rootWindow(),visualInfo->visual,AllocNone); + + XSetWindowAttributes a; + a.colormap = cmap; + mXWindow = XCreateWindow(mEglIntegration->xDisplay(), mEglIntegration->rootWindow(),0, 0, size.width(), size.height(), + 0, visualInfo->depth, InputOutput, visualInfo->visual, + CWColormap, &a); + + XCompositeRedirectWindow(mEglIntegration->xDisplay(), mXWindow, CompositeRedirectManual); + XMapWindow(mEglIntegration->xDisplay(), mXWindow); + + mEglWindowSurface = eglCreateWindowSurface(mEglIntegration->eglDisplay(),mConfig,mXWindow,0); + if (mEglWindowSurface == EGL_NO_SURFACE) { + qFatal("Could not make eglsurface"); + } + + XSync(mEglIntegration->xDisplay(),False); + mBuffer = new QWaylandXCompositeBuffer(mEglIntegration->waylandXComposite(), + (uint32_t)mXWindow, + size, + mEglIntegration->waylandDisplay()->argbVisual()); + mWindow->attach(mBuffer); + wl_display_sync_callback(mEglIntegration->waylandDisplay()->wl_display(), + QWaylandXCompositeEGLContext::sync_function, + this); + + mWaitingForSync = true; + wl_display_sync(mEglIntegration->waylandDisplay()->wl_display(),0); + mEglIntegration->waylandDisplay()->flushRequests(); + while (mWaitingForSync) { + mEglIntegration->waylandDisplay()->readEvents(); + } +} diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglcontext.h b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglcontext.h new file mode 100644 index 0000000..f0693d4 --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglcontext.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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$ +** +****************************************************************************/ + +#ifndef QWAYLANDXCOMPOSITEEGLCONTEXT_H +#define QWAYLANDXCOMPOSITEEGLCONTEXT_H + +#include <QtGui/QPlatformGLContext> + +#include <QtCore/QWaitCondition> + +#include "qwaylandbuffer.h" +#include "qwaylandxcompositeeglintegration.h" + +class QWaylandXCompositeEGLWindow; + +class QWaylandXCompositeEGLContext : public QPlatformGLContext +{ +public: + QWaylandXCompositeEGLContext(QWaylandXCompositeEGLIntegration *glxIntegration, QWaylandXCompositeEGLWindow *window); + + void makeCurrent(); + void doneCurrent(); + void swapBuffers(); + void* getProcAddress(const QString& procName); + + QPlatformWindowFormat platformWindowFormat() const; + + void geometryChanged(); + +private: + QWaylandXCompositeEGLIntegration *mEglIntegration; + QWaylandXCompositeEGLWindow *mWindow; + QWaylandBuffer *mBuffer; + + Window mXWindow; + EGLConfig mConfig; + EGLContext mContext; + EGLSurface mEglWindowSurface; + + static void sync_function(void *data); + bool mWaitingForSync; +}; + +#endif // QWAYLANDXCOMPOSITEEGLCONTEXT_H diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglintegration.cpp b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglintegration.cpp new file mode 100644 index 0000000..95b4112 --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglintegration.cpp @@ -0,0 +1,139 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 "qwaylandxcompositeeglintegration.h" + +#include "qwaylandxcompositeeglwindow.h" + +#include <QtCore/QDebug> + +#include "wayland-xcomposite-client-protocol.h" + +QWaylandGLIntegration * QWaylandGLIntegration::createGLIntegration(QWaylandDisplay *waylandDisplay) +{ + return new QWaylandXCompositeEGLIntegration(waylandDisplay); +} + +QWaylandXCompositeEGLIntegration::QWaylandXCompositeEGLIntegration(QWaylandDisplay * waylandDispaly) + : QWaylandGLIntegration() + , mWaylandDisplay(waylandDispaly) +{ + qDebug() << "Using XComposite-EGL"; + wl_display_add_global_listener(mWaylandDisplay->wl_display(), QWaylandXCompositeEGLIntegration::wlDisplayHandleGlobal, + this); +} + +QWaylandXCompositeEGLIntegration::~QWaylandXCompositeEGLIntegration() +{ + XCloseDisplay(mDisplay); +} + +void QWaylandXCompositeEGLIntegration::initialize() +{ +} + +QWaylandWindow * QWaylandXCompositeEGLIntegration::createEglWindow(QWidget *widget) +{ + return new QWaylandXCompositeEGLWindow(widget,this); +} + +Display * QWaylandXCompositeEGLIntegration::xDisplay() const +{ + return mDisplay; +} + +EGLDisplay QWaylandXCompositeEGLIntegration::eglDisplay() const +{ + return mEglDisplay; +} + +int QWaylandXCompositeEGLIntegration::screen() const +{ + return mScreen; +} + +Window QWaylandXCompositeEGLIntegration::rootWindow() const +{ + return mRootWindow; +} + +QWaylandDisplay * QWaylandXCompositeEGLIntegration::waylandDisplay() const +{ + return mWaylandDisplay; +} +wl_xcomposite * QWaylandXCompositeEGLIntegration::waylandXComposite() const +{ + return mWaylandComposite; +} + +const struct wl_xcomposite_listener QWaylandXCompositeEGLIntegration::xcomposite_listener = { + QWaylandXCompositeEGLIntegration::rootInformation +}; + +void QWaylandXCompositeEGLIntegration::wlDisplayHandleGlobal(wl_display *display, uint32_t id, const char *interface, uint32_t version, void *data) +{ + Q_UNUSED(version); + if (strcmp(interface, "xcomposite") == 0) { + QWaylandXCompositeEGLIntegration *integration = static_cast<QWaylandXCompositeEGLIntegration *>(data); + integration->mWaylandComposite = wl_xcomposite_create(display,id); + wl_xcomposite_add_listener(integration->mWaylandComposite,&xcomposite_listener,integration); + } + +} + +void QWaylandXCompositeEGLIntegration::rootInformation(void *data, wl_xcomposite *xcomposite, const char *display_name, uint32_t root_window) +{ + Q_UNUSED(xcomposite); + QWaylandXCompositeEGLIntegration *integration = static_cast<QWaylandXCompositeEGLIntegration *>(data); + + integration->mDisplay = XOpenDisplay(display_name); + integration->mRootWindow = (Window) root_window; + integration->mScreen = XDefaultScreen(integration->mDisplay); + integration->mEglDisplay = eglGetDisplay(integration->mDisplay); + eglBindAPI(EGL_OPENGL_ES_API); + EGLint minor,major; + if (!eglInitialize(integration->mEglDisplay,&major,&minor)) { + qFatal("Failed to initialize EGL"); + } + eglSwapInterval(integration->eglDisplay(),0); + qDebug() << "ROOT INFORMATION" << integration->mDisplay << integration->mRootWindow << integration->mScreen; +} + diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglintegration.h b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglintegration.h new file mode 100644 index 0000000..590ae37 --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglintegration.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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$ +** +****************************************************************************/ + +#ifndef QWAYLANDXCOMPOSITEEGLINTEGRATION_H +#define QWAYLANDXCOMPOSITEEGLINTEGRATION_H + +#include "gl_integration/qwaylandglintegration.h" +#include "wayland-client.h" + +#include <QtCore/QTextStream> +#include <QtCore/QDataStream> +#include <QtCore/QMetaType> +#include <QtCore/QVariant> +#include <QtGui/QWidget> + +#include <QWaitCondition> + +#include <X11/Xlib.h> +#include <EGL/egl.h> + +struct wl_xcomposite; + +class QWaylandXCompositeEGLIntegration : public QWaylandGLIntegration +{ +public: + QWaylandXCompositeEGLIntegration(QWaylandDisplay * waylandDispaly); + ~QWaylandXCompositeEGLIntegration(); + + void initialize(); + + QWaylandWindow *createEglWindow(QWidget *widget); + + QWaylandDisplay *waylandDisplay() const; + struct wl_xcomposite *waylandXComposite() const; + + Display *xDisplay() const; + EGLDisplay eglDisplay() const; + int screen() const; + Window rootWindow() const; + +private: + QWaylandDisplay *mWaylandDisplay; + struct wl_xcomposite *mWaylandComposite; + + Display *mDisplay; + EGLDisplay mEglDisplay; + int mScreen; + Window mRootWindow; + + static void wlDisplayHandleGlobal(struct wl_display *display, uint32_t id, + const char *interface, uint32_t version, void *data); + + static const struct wl_xcomposite_listener xcomposite_listener; + static void rootInformation(void *data, + struct wl_xcomposite *xcomposite, + const char *display_name, + uint32_t root_window); +}; + +#endif // QWAYLANDXCOMPOSITEEGLINTEGRATION_H diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.cpp b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.cpp new file mode 100644 index 0000000..1c9d36f --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.cpp @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 "qwaylandxcompositeeglwindow.h" + +#include <QtCore/QDebug> + +QWaylandXCompositeEGLWindow::QWaylandXCompositeEGLWindow(QWidget *window, QWaylandXCompositeEGLIntegration *glxIntegration) + : QWaylandWindow(window) + , mGlxIntegration(glxIntegration) + , mContext(0) +{ + +} + +QWaylandWindow::WindowType QWaylandXCompositeEGLWindow::windowType() const +{ + //yeah. this type needs a new name + return QWaylandWindow::Egl; +} + +QPlatformGLContext * QWaylandXCompositeEGLWindow::glContext() const +{ + if (!mContext) { + qDebug() << "creating glcontext;"; + QWaylandXCompositeEGLWindow *that = const_cast<QWaylandXCompositeEGLWindow *>(this); + that->mContext = new QWaylandXCompositeEGLContext(mGlxIntegration,that); + } + return mContext; +} + +void QWaylandXCompositeEGLWindow::setGeometry(const QRect &rect) +{ + QWaylandWindow::setGeometry(rect); + + if (mContext) { + mContext->geometryChanged(); + } +} diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.h b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.h new file mode 100644 index 0000000..fc33b32 --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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$ +** +****************************************************************************/ + +#ifndef QWAYLANDXCOMPOSITEEGLWINDOW_H +#define QWAYLANDXCOMPOSITEEGLWINDOW_H + +#include "qwaylandwindow.h" +#include "qwaylandxcompositeeglintegration.h" +#include "qwaylandxcompositeeglcontext.h" + +class QWaylandXCompositeEGLWindow : public QWaylandWindow +{ +public: + QWaylandXCompositeEGLWindow(QWidget *window, QWaylandXCompositeEGLIntegration *glxIntegration); + WindowType windowType() const; + + QPlatformGLContext *glContext() const; + + void setGeometry(const QRect &rect); + +private: + QWaylandXCompositeEGLIntegration *mGlxIntegration; + QWaylandXCompositeEGLContext *mContext; + +}; + +#endif // QWAYLANDXCOMPOSITEEGLWINDOW_H diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/xcomposite_egl.pri b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/xcomposite_egl.pri new file mode 100644 index 0000000..c3533f9 --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/xcomposite_egl.pri @@ -0,0 +1,15 @@ +include (../xcomposite_share/xcomposite_share.pri) +include (../../../eglconvenience/eglconvenience.pri) +include (../../../eglconvenience/xlibeglintegration.pri) + +LIBS += -lXcomposite -lEGL + +SOURCES += \ + $$PWD/qwaylandxcompositeeglcontext.cpp \ + $$PWD/qwaylandxcompositeeglintegration.cpp \ + $$PWD/qwaylandxcompositeeglwindow.cpp + +HEADERS += \ + $$PWD/qwaylandxcompositeeglcontext.h \ + $$PWD/qwaylandxcompositeeglintegration.h \ + $$PWD/qwaylandxcompositeeglwindow.h diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxcontext.cpp b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxcontext.cpp new file mode 100644 index 0000000..caf5117 --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxcontext.cpp @@ -0,0 +1,150 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 "qwaylandxcompositeglxcontext.h" + +#include "qwaylandxcompositeglxwindow.h" +#include "qwaylandxcompositebuffer.h" + +#include "wayland-xcomposite-client-protocol.h" +#include <QtCore/QDebug> + +#include <X11/extensions/Xcomposite.h> + +QWaylandXCompositeGLXContext::QWaylandXCompositeGLXContext(QWaylandXCompositeGLXIntegration *glxIntegration, QWaylandXCompositeGLXWindow *window) + : QPlatformGLContext() + , mGlxIntegration(glxIntegration) + , mWindow(window) + , mBuffer(0) + , mXWindow(0) + , mConfig(qglx_findConfig(glxIntegration->xDisplay(),glxIntegration->screen(),window->widget()->platformWindowFormat())) + , mWaitingForSyncCallback(false) +{ + XVisualInfo *visualInfo = glXGetVisualFromFBConfig(glxIntegration->xDisplay(),mConfig); + mContext = glXCreateContext(glxIntegration->xDisplay(),visualInfo,0,TRUE); + + geometryChanged(); +} + +void QWaylandXCompositeGLXContext::makeCurrent() +{ + QPlatformGLContext::makeCurrent(); + glXMakeCurrent(mGlxIntegration->xDisplay(),mXWindow,mContext); +} + +void QWaylandXCompositeGLXContext::doneCurrent() +{ + glXMakeCurrent(mGlxIntegration->xDisplay(),0,0); + QPlatformGLContext::doneCurrent(); +} + +void QWaylandXCompositeGLXContext::swapBuffers() +{ + QSize size = mWindow->geometry().size(); + + glXSwapBuffers(mGlxIntegration->xDisplay(),mXWindow); + mWindow->damage(QRegion(QRect(QPoint(0,0),size))); + mWindow->waitForFrameSync(); +} + +void * QWaylandXCompositeGLXContext::getProcAddress(const QString &procName) +{ + return (void *) glXGetProcAddress(reinterpret_cast<GLubyte *>(procName.toLatin1().data())); +} + +QPlatformWindowFormat QWaylandXCompositeGLXContext::platformWindowFormat() const +{ + return qglx_platformWindowFromGLXFBConfig(mGlxIntegration->xDisplay(),mConfig,mContext); +} + +void QWaylandXCompositeGLXContext::sync_function(void *data) +{ + QWaylandXCompositeGLXContext *that = static_cast<QWaylandXCompositeGLXContext *>(data); + that->mWaitingForSyncCallback = false; +} + +void QWaylandXCompositeGLXContext::waitForSync() +{ + wl_display_sync_callback(mGlxIntegration->waylandDisplay()->wl_display(), + QWaylandXCompositeGLXContext::sync_function, + this); + mWaitingForSyncCallback = true; + wl_display_sync(mGlxIntegration->waylandDisplay()->wl_display(),0); + mGlxIntegration->waylandDisplay()->flushRequests(); + while (mWaitingForSyncCallback) { + mGlxIntegration->waylandDisplay()->readEvents(); + } +} + +void QWaylandXCompositeGLXContext::geometryChanged() +{ + QSize size(mWindow->geometry().size()); + if (size.isEmpty()) { + //QGLWidget wants a context for a window without geometry + size = QSize(1,1); + } + + delete mBuffer; + //XFreePixmap deletes the glxPixmap as well + if (mXWindow) { + XDestroyWindow(mGlxIntegration->xDisplay(),mXWindow); + } + + XVisualInfo *visualInfo = glXGetVisualFromFBConfig(mGlxIntegration->xDisplay(),mConfig); + Colormap cmap = XCreateColormap(mGlxIntegration->xDisplay(),mGlxIntegration->rootWindow(),visualInfo->visual,AllocNone); + + XSetWindowAttributes a; + a.colormap = cmap; + mXWindow = XCreateWindow(mGlxIntegration->xDisplay(), mGlxIntegration->rootWindow(),0, 0, size.width(), size.height(), + 0, visualInfo->depth, InputOutput, visualInfo->visual, + CWColormap, &a); + + XCompositeRedirectWindow(mGlxIntegration->xDisplay(), mXWindow, CompositeRedirectManual); + XMapWindow(mGlxIntegration->xDisplay(), mXWindow); + + XSync(mGlxIntegration->xDisplay(),False); + mBuffer = new QWaylandXCompositeBuffer(mGlxIntegration->waylandXComposite(), + (uint32_t)mXWindow, + size, + mGlxIntegration->waylandDisplay()->argbVisual()); + mWindow->attach(mBuffer); + waitForSync(); +} diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxcontext.h b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxcontext.h new file mode 100644 index 0000000..eb2e5a5 --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxcontext.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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$ +** +****************************************************************************/ + +#ifndef QWAYLANDXCOMPOSITEGLXCONTEXT_H +#define QWAYLANDXCOMPOSITEGLXCONTEXT_H + +#include <QtGui/QPlatformGLContext> + +#include <QtCore/QWaitCondition> + +#include "qwaylandbuffer.h" +#include "qwaylandxcompositeglxintegration.h" + +#include "qglxconvenience.h" + +class QWaylandXCompositeGLXWindow; +class QWaylandShmBuffer; + +class QWaylandXCompositeGLXContext : public QPlatformGLContext +{ +public: + QWaylandXCompositeGLXContext(QWaylandXCompositeGLXIntegration *glxIntegration, QWaylandXCompositeGLXWindow *window); + + void makeCurrent(); + void doneCurrent(); + void swapBuffers(); + void* getProcAddress(const QString& procName); + + QPlatformWindowFormat platformWindowFormat() const; + + void geometryChanged(); + +private: + QWaylandXCompositeGLXIntegration *mGlxIntegration; + QWaylandXCompositeGLXWindow *mWindow; + QWaylandBuffer *mBuffer; + + Window mXWindow; + GLXFBConfig mConfig; + GLXContext mContext; + + static void sync_function(void *data); + void waitForSync(); + bool mWaitingForSyncCallback; +}; + +#endif // QWAYLANDXCOMPOSITEGLXCONTEXT_H diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxintegration.cpp b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxintegration.cpp new file mode 100644 index 0000000..43c0135 --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxintegration.cpp @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 "qwaylandxcompositeglxintegration.h" + +#include "qwaylandxcompositeglxwindow.h" + +#include <QtCore/QDebug> + +#include "wayland-xcomposite-client-protocol.h" + +QWaylandGLIntegration * QWaylandGLIntegration::createGLIntegration(QWaylandDisplay *waylandDisplay) +{ + return new QWaylandXCompositeGLXIntegration(waylandDisplay); +} + +QWaylandXCompositeGLXIntegration::QWaylandXCompositeGLXIntegration(QWaylandDisplay * waylandDispaly) + : QWaylandGLIntegration() + , mWaylandDisplay(waylandDispaly) +{ + qDebug() << "Using XComposite-GLX"; + wl_display_add_global_listener(waylandDispaly->wl_display(), QWaylandXCompositeGLXIntegration::wlDisplayHandleGlobal, + this); +} + +QWaylandXCompositeGLXIntegration::~QWaylandXCompositeGLXIntegration() +{ + XCloseDisplay(mDisplay); +} + +void QWaylandXCompositeGLXIntegration::initialize() +{ +} + +QWaylandWindow * QWaylandXCompositeGLXIntegration::createEglWindow(QWidget *widget) +{ + return new QWaylandXCompositeGLXWindow(widget,this); +} + +Display * QWaylandXCompositeGLXIntegration::xDisplay() const +{ + return mDisplay; +} + +int QWaylandXCompositeGLXIntegration::screen() const +{ + return mScreen; +} + +Window QWaylandXCompositeGLXIntegration::rootWindow() const +{ + return mRootWindow; +} + +QWaylandDisplay * QWaylandXCompositeGLXIntegration::waylandDisplay() const +{ + return mWaylandDisplay; +} +wl_xcomposite * QWaylandXCompositeGLXIntegration::waylandXComposite() const +{ + return mWaylandComposite; +} + +const struct wl_xcomposite_listener QWaylandXCompositeGLXIntegration::xcomposite_listener = { + QWaylandXCompositeGLXIntegration::rootInformation +}; + +void QWaylandXCompositeGLXIntegration::wlDisplayHandleGlobal(wl_display *display, uint32_t id, const char *interface, uint32_t version, void *data) +{ + Q_UNUSED(version); + if (strcmp(interface, "xcomposite") == 0) { + QWaylandXCompositeGLXIntegration *integration = static_cast<QWaylandXCompositeGLXIntegration *>(data); + integration->mWaylandComposite = wl_xcomposite_create(display,id); + wl_xcomposite_add_listener(integration->mWaylandComposite,&xcomposite_listener,integration); + } + +} + +void QWaylandXCompositeGLXIntegration::rootInformation(void *data, wl_xcomposite *xcomposite, const char *display_name, uint32_t root_window) +{ + Q_UNUSED(xcomposite); + QWaylandXCompositeGLXIntegration *integration = static_cast<QWaylandXCompositeGLXIntegration *>(data); + + integration->mDisplay = XOpenDisplay(display_name); + integration->mRootWindow = (Window) root_window; + integration->mScreen = XDefaultScreen(integration->mDisplay); +} + diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxintegration.h b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxintegration.h new file mode 100644 index 0000000..24a4016 --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxintegration.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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$ +** +****************************************************************************/ + +#ifndef QWAYLANDXCOMPOSITEGLXINTEGRATION_H +#define QWAYLANDXCOMPOSITEGLXINTEGRATION_H + +#include "gl_integration/qwaylandglintegration.h" +#include "wayland-client.h" + +#include <QtCore/QTextStream> +#include <QtCore/QDataStream> +#include <QtCore/QMetaType> +#include <QtCore/QVariant> +#include <QtGui/QWidget> + +#include <X11/Xlib.h> + +struct wl_xcomposite; + +class QWaylandXCompositeGLXIntegration : public QWaylandGLIntegration +{ +public: + QWaylandXCompositeGLXIntegration(QWaylandDisplay * waylandDispaly); + ~QWaylandXCompositeGLXIntegration(); + + void initialize(); + + QWaylandWindow *createEglWindow(QWidget *widget); + + QWaylandDisplay *waylandDisplay() const; + struct wl_xcomposite *waylandXComposite() const; + + Display *xDisplay() const; + int screen() const; + Window rootWindow() const; + +private: + QWaylandDisplay *mWaylandDisplay; + struct wl_xcomposite *mWaylandComposite; + + Display *mDisplay; + int mScreen; + Window mRootWindow; + + static void wlDisplayHandleGlobal(struct wl_display *display, uint32_t id, + const char *interface, uint32_t version, void *data); + + static const struct wl_xcomposite_listener xcomposite_listener; + static void rootInformation(void *data, + struct wl_xcomposite *xcomposite, + const char *display_name, + uint32_t root_window); +}; + +#endif // QWAYLANDXCOMPOSITEGLXINTEGRATION_H diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxwindow.cpp b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxwindow.cpp new file mode 100644 index 0000000..db0f254 --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxwindow.cpp @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 "qwaylandxcompositeglxwindow.h" + +#include <QtCore/QDebug> + +QWaylandXCompositeGLXWindow::QWaylandXCompositeGLXWindow(QWidget *window, QWaylandXCompositeGLXIntegration *glxIntegration) + : QWaylandWindow(window) + , mGlxIntegration(glxIntegration) + , mContext(0) +{ + +} + +QWaylandWindow::WindowType QWaylandXCompositeGLXWindow::windowType() const +{ + //yeah. this type needs a new name + return QWaylandWindow::Egl; +} + +QPlatformGLContext * QWaylandXCompositeGLXWindow::glContext() const +{ + if (!mContext) { + qDebug() << "creating glcontext;"; + QWaylandXCompositeGLXWindow *that = const_cast<QWaylandXCompositeGLXWindow *>(this); + that->mContext = new QWaylandXCompositeGLXContext(mGlxIntegration,that); + } + return mContext; +} + +void QWaylandXCompositeGLXWindow::setGeometry(const QRect &rect) +{ + QWaylandWindow::setGeometry(rect); + + if (mContext) { + mContext->geometryChanged(); + } +} diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxwindow.h b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxwindow.h new file mode 100644 index 0000000..536153d --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxwindow.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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$ +** +****************************************************************************/ + +#ifndef QWAYLANDXCOMPOSITEGLXWINDOW_H +#define QWAYLANDXCOMPOSITEGLXWINDOW_H + +#include "qwaylandwindow.h" +#include "qwaylandxcompositeglxintegration.h" +#include "qwaylandxcompositeglxcontext.h" + +class QWaylandXCompositeGLXWindow : public QWaylandWindow +{ +public: + QWaylandXCompositeGLXWindow(QWidget *window, QWaylandXCompositeGLXIntegration *glxIntegration); + WindowType windowType() const; + + QPlatformGLContext *glContext() const; + + void setGeometry(const QRect &rect); + +private: + QWaylandXCompositeGLXIntegration *mGlxIntegration; + QWaylandXCompositeGLXContext *mContext; + +}; + +#endif // QWAYLANDXCOMPOSITEGLXWINDOW_H diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/xcomposite_glx.pri b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/xcomposite_glx.pri new file mode 100644 index 0000000..43295e9 --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/xcomposite_glx.pri @@ -0,0 +1,13 @@ +include (../xcomposite_share/xcomposite_share.pri) +include (../../../glxconvenience/glxconvenience.pri) + +LIBS += -lXcomposite +SOURCES += \ + $$PWD/qwaylandxcompositeglxcontext.cpp \ + $$PWD/qwaylandxcompositeglxintegration.cpp \ + $$PWD/qwaylandxcompositeglxwindow.cpp + +HEADERS += \ + $$PWD/qwaylandxcompositeglxcontext.h \ + $$PWD/qwaylandxcompositeglxintegration.h \ + $$PWD/qwaylandxcompositeglxwindow.h diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_share/qwaylandxcompositebuffer.cpp b/src/plugins/platforms/wayland/gl_integration/xcomposite_share/qwaylandxcompositebuffer.cpp new file mode 100644 index 0000000..4b0d3a0 --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_share/qwaylandxcompositebuffer.cpp @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 "qwaylandxcompositebuffer.h" + +#include "wayland-client.h" + +QWaylandXCompositeBuffer::QWaylandXCompositeBuffer(wl_xcomposite *xcomposite, uint32_t window, const QSize &size, wl_visual *visual) + :mSize(size) +{ + mBuffer = wl_xcomposite_create_buffer(xcomposite, + window, + size.width(), + size.height(), + visual); +} + +QSize QWaylandXCompositeBuffer::size() const +{ + return mSize; +} diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_share/qwaylandxcompositebuffer.h b/src/plugins/platforms/wayland/gl_integration/xcomposite_share/qwaylandxcompositebuffer.h new file mode 100644 index 0000000..b346651 --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_share/qwaylandxcompositebuffer.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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$ +** +****************************************************************************/ + +#ifndef QWAYLANDXCOMPOSITEBUFFER_H +#define QWAYLANDXCOMPOSITEBUFFER_H + +#include "qwaylandbuffer.h" + +#include "wayland-xcomposite-client-protocol.h" + +class QWaylandXCompositeBuffer : public QWaylandBuffer +{ +public: + QWaylandXCompositeBuffer(struct wl_xcomposite *xcomposite, + uint32_t window, + const QSize &size, + struct wl_visual *visual); + + QSize size() const; +private: + QSize mSize; +}; + +#endif // QWAYLANDXCOMPOSITEBUFFER_H diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_share/wayland-xcomposite-client-protocol.h b/src/plugins/platforms/wayland/gl_integration/xcomposite_share/wayland-xcomposite-client-protocol.h new file mode 100644 index 0000000..72376e1 --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_share/wayland-xcomposite-client-protocol.h @@ -0,0 +1,145 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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$ +** +****************************************************************************/ + + +#ifndef XCOMPOSITE_CLIENT_PROTOCOL_H +#define XCOMPOSITE_CLIENT_PROTOCOL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> +#include <stddef.h> +#include "wayland-util.h" + +struct wl_client; + +struct wl_xcomposite; + +struct wl_proxy; + +extern void +wl_proxy_marshal(struct wl_proxy *p, uint32_t opcode, ...); +extern struct wl_proxy * +wl_proxy_create(struct wl_proxy *factory, + const struct wl_interface *interface); +extern struct wl_proxy * +wl_proxy_create_for_id(struct wl_display *display, + const struct wl_interface *interface, uint32_t id); +extern void +wl_proxy_destroy(struct wl_proxy *proxy); + +extern int +wl_proxy_add_listener(struct wl_proxy *proxy, + void (**implementation)(void), void *data); + +extern void +wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data); + +extern void * +wl_proxy_get_user_data(struct wl_proxy *proxy); + +extern const struct wl_interface wl_xcomposite_interface; + +struct wl_xcomposite_listener { + void (*root)(void *data, + struct wl_xcomposite *xcomposite, + const char *display_name, + uint32_t root_window); +}; + +static inline int +wl_xcomposite_add_listener(struct wl_xcomposite *xcomposite, + const struct wl_xcomposite_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) xcomposite, + (void (**)(void)) listener, data); +} + +#define WL_XCOMPOSITE_CREATE_BUFFER 0 + +static inline struct wl_xcomposite * +wl_xcomposite_create(struct wl_display *display, uint32_t id) +{ + return (struct wl_xcomposite *) + wl_proxy_create_for_id(display, &wl_xcomposite_interface, id); +} + +static inline void +wl_xcomposite_set_user_data(struct wl_xcomposite *xcomposite, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) xcomposite, user_data); +} + +static inline void * +wl_xcomposite_get_user_data(struct wl_xcomposite *xcomposite) +{ + return wl_proxy_get_user_data((struct wl_proxy *) xcomposite); +} + +static inline void +wl_xcomposite_destroy(struct wl_xcomposite *xcomposite) +{ + wl_proxy_destroy((struct wl_proxy *) xcomposite); +} + +static inline struct wl_buffer * +wl_xcomposite_create_buffer(struct wl_xcomposite *xcomposite, uint32_t x_window, int width, int height, struct wl_visual *visual) +{ + struct wl_proxy *id; + + id = wl_proxy_create((struct wl_proxy *) xcomposite, + &wl_buffer_interface); + if (!id) + return NULL; + + wl_proxy_marshal((struct wl_proxy *) xcomposite, + WL_XCOMPOSITE_CREATE_BUFFER, id, x_window, width, height, visual); + + return (struct wl_buffer *) id; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_share/wayland-xcomposite-protocol.c b/src/plugins/platforms/wayland/gl_integration/xcomposite_share/wayland-xcomposite-protocol.c new file mode 100644 index 0000000..5c966fd --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_share/wayland-xcomposite-protocol.c @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 <stdlib.h> +#include <stdint.h> +#include "wayland-util.h" + +static const struct wl_message xcomposite_requests[] = { + { "create_buffer", "nuiio" }, +}; + +static const struct wl_message xcomposite_events[] = { + { "root", "su" }, +}; + +WL_EXPORT const struct wl_interface wl_xcomposite_interface = { + "xcomposite", 1, + ARRAY_LENGTH(xcomposite_requests), xcomposite_requests, + ARRAY_LENGTH(xcomposite_events), xcomposite_events, +}; + diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_share/xcomposite_share.pri b/src/plugins/platforms/wayland/gl_integration/xcomposite_share/xcomposite_share.pri new file mode 100644 index 0000000..03b3521 --- /dev/null +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_share/xcomposite_share.pri @@ -0,0 +1,9 @@ +INCLUDEPATH += $$PWD + +HEADERS += \ + $$PWD/wayland-xcomposite-client-protocol.h \ + gl_integration/xcomposite_share/qwaylandxcompositebuffer.h + +SOURCES += \ + $$PWD/wayland-xcomposite-protocol.c \ + gl_integration/xcomposite_share/qwaylandxcompositebuffer.cpp diff --git a/src/plugins/platforms/wayland/qwaylandbuffer.h b/src/plugins/platforms/wayland/qwaylandbuffer.h index 643e89c..8779d5f 100644 --- a/src/plugins/platforms/wayland/qwaylandbuffer.h +++ b/src/plugins/platforms/wayland/qwaylandbuffer.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the config.tests of the Qt Toolkit. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp index 27f4334..1c56561 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp +++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp @@ -46,13 +46,23 @@ #include "qwaylandcursor.h" #include "qwaylandinputdevice.h" +#ifdef QT_WAYLAND_GL_SUPPORT +#include "gl_integration/qwaylandglintegration.h" +#endif + +#include <QtCore/QAbstractEventDispatcher> +#include <QtGui/QApplication> + #include <unistd.h> #include <fcntl.h> #include <stdio.h> +#include <errno.h> -struct wl_surface *QWaylandDisplay::createSurface() +struct wl_surface *QWaylandDisplay::createSurface(void *handle) { - return wl_compositor_create_surface(mCompositor); + struct wl_surface * surface = wl_compositor_create_surface(mCompositor); + wl_surface_set_user_data(surface, handle); + return surface; } struct wl_buffer *QWaylandDisplay::createShmBuffer(int fd, @@ -78,10 +88,12 @@ struct wl_visual *QWaylandDisplay::argbPremultipliedVisual() return wl_display_get_premultiplied_argb_visual(mDisplay); } -struct wl_egl_display *QWaylandDisplay::nativeDisplay() +#ifdef QT_WAYLAND_GL_SUPPORT +QWaylandGLIntegration * QWaylandDisplay::eglIntegration() { - return mNativeEglDisplay; + return mEglIntegration; } +#endif void QWaylandDisplay::shellHandleConfigure(void *data, struct wl_shell *shell, uint32_t time, uint32_t edges, @@ -101,147 +113,158 @@ const struct wl_shell_listener QWaylandDisplay::shellListener = { QWaylandDisplay::shellHandleConfigure, }; -void QWaylandDisplay::outputHandleGeometry(void *data, - struct wl_output *output, - int32_t x, int32_t y, - int32_t width, int32_t height) +QWaylandDisplay::QWaylandDisplay(void) { - QWaylandDisplay *waylandDisplay = (QWaylandDisplay *) data; + mDisplay = wl_display_connect(NULL); + if (mDisplay == NULL) { + qErrnoWarning(errno, "Failed to create display"); + qFatal("No wayland connection available."); + } - QRect outputRect = QRect(x, y, width, height); - waylandDisplay->createNewScreen(output, outputRect); -} + wl_display_add_global_listener(mDisplay, QWaylandDisplay::displayHandleGlobal, this); -const struct wl_output_listener QWaylandDisplay::outputListener = { - QWaylandDisplay::outputHandleGeometry -}; +#ifdef QT_WAYLAND_GL_SUPPORT + mEglIntegration = QWaylandGLIntegration::createGLIntegration(this); +#endif -void QWaylandDisplay::displayHandleGlobal(struct wl_display *display, - uint32_t id, - const char *interface, - uint32_t version, void *data) -{ - Q_UNUSED(version); - QWaylandDisplay *qwd = (QWaylandDisplay *) data; - - if (strcmp(interface, "compositor") == 0) { - qwd->mCompositor = wl_compositor_create(display, id); - } else if (strcmp(interface, "shm") == 0) { - qwd->mShm = wl_shm_create(display, id); - } else if (strcmp(interface, "shell") == 0) { - qwd->mShell = wl_shell_create(display, id); - wl_shell_add_listener(qwd->mShell, &shellListener, qwd); - } else if (strcmp(interface, "output") == 0) { - struct wl_output *output = wl_output_create(display, id); - wl_output_add_listener(output, &outputListener, qwd); - } else if (strcmp(interface, "input_device") == 0) { - QWaylandInputDevice *inputDevice = - new QWaylandInputDevice(display, id); - qwd->mInputDevices.append(inputDevice); - } + qRegisterMetaType<uint32_t>("uint32_t"); + +#ifdef QT_WAYLAND_GL_SUPPORT + mEglIntegration->initialize(); +#endif + + connect(QAbstractEventDispatcher::instance(), SIGNAL(aboutToBlock()), this, SLOT(flushRequests())); + + mFd = wl_display_get_fd(mDisplay, sourceUpdate, this); + + mReadNotifier = new QSocketNotifier(mFd, QSocketNotifier::Read, this); + connect(mReadNotifier, SIGNAL(activated(int)), this, SLOT(readEvents())); + + waitForScreens(); } -void QWaylandDisplay::iterate() +QWaylandDisplay::~QWaylandDisplay(void) { - wl_display_iterate(mDisplay, WL_DISPLAY_READABLE | WL_DISPLAY_WRITABLE); + close(mFd); +#ifdef QT_WAYLAND_GL_SUPPORT + delete mEglIntegration; +#endif + wl_display_destroy(mDisplay); } -void QWaylandDisplay::readEvents(void) +void QWaylandDisplay::createNewScreen(struct wl_output *output, QRect geometry) { - wl_display_iterate(mDisplay, WL_DISPLAY_READABLE); + QWaylandScreen *waylandScreen = new QWaylandScreen(this,output,geometry); + mScreens.append(waylandScreen); } -int -QWaylandDisplay::sourceUpdate(uint32_t mask, void *data) +void QWaylandDisplay::syncCallback(wl_display_sync_func_t func, void *data) { - QWaylandDisplay *qwd = (QWaylandDisplay *) data; - - /* FIXME: We get a callback here when we ask wl_display for the - * fd, but at that point we don't have the socket notifier as we - * need the fd to create that. We'll probably need to split that - * API into get_fd and set_update_func functions. */ - if (qwd->mWriteNotifier == NULL) - return 0; - - qwd->mWriteNotifier->setEnabled(mask & WL_DISPLAY_WRITABLE); + wl_display_sync_callback(mDisplay, func, data); +} - return 0; +void QWaylandDisplay::frameCallback(wl_display_frame_func_t func, struct wl_surface *surface, void *data) +{ + wl_display_frame_callback(mDisplay, surface, func, data); } -void QWaylandDisplay::flushRequests(void) +void QWaylandDisplay::flushRequests() { - wl_display_iterate(mDisplay, WL_DISPLAY_WRITABLE); + if (mSocketMask & WL_DISPLAY_WRITABLE) + wl_display_iterate(mDisplay, WL_DISPLAY_WRITABLE); } -QWaylandDisplay::QWaylandDisplay(void) - : mWriteNotifier(0) +void QWaylandDisplay::readEvents() { -#ifdef QT_WAYLAND_GL_SUPPORT - EGLint major, minor; -#endif - mDisplay = wl_display_connect(NULL); - if (mDisplay == NULL) { - fprintf(stderr, "failed to create display: %m\n"); +// verify that there is still data on the socket + fd_set fds; + FD_ZERO(&fds); + FD_SET(mFd, &fds); + fd_set nds; + FD_ZERO(&nds); + fd_set rs = fds; + fd_set ws = nds; + fd_set es = nds; + timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + int ret = ::select(mFd+1, &rs, &ws, &es, &timeout ); + + if (ret <= 0) { + //qDebug("QWaylandDisplay::readEvents() No data... blocking avoided"); return; } - wl_display_add_global_listener(mDisplay, - QWaylandDisplay::displayHandleGlobal, this); - -#ifdef QT_WAYLAND_GL_SUPPORT - mNativeEglDisplay = wl_egl_display_create(mDisplay); -#else - mNativeEglDisplay = 0; -#endif - - readEvents(); + wl_display_iterate(mDisplay, WL_DISPLAY_READABLE); +} -#ifdef QT_WAYLAND_GL_SUPPORT - mEglDisplay = eglGetDisplay((EGLNativeDisplayType)mNativeEglDisplay); - if (mEglDisplay == NULL) { - qWarning("EGL not available"); - } else { - if (!eglInitialize(mEglDisplay, &major, &minor)) { - qWarning("failed to initialize EGL display"); - return; - } - } -#else - mEglDisplay = 0; -#endif +void QWaylandDisplay::blockingReadEvents() +{ + wl_display_iterate(mDisplay, WL_DISPLAY_READABLE); +} - int fd = wl_display_get_fd(mDisplay, sourceUpdate, this); - mReadNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this); - connect(mReadNotifier, - SIGNAL(activated(int)), this, SLOT(readEvents())); +int QWaylandDisplay::sourceUpdate(uint32_t mask, void *data) +{ + QWaylandDisplay *waylandDisplay = static_cast<QWaylandDisplay *>(data); + waylandDisplay->mSocketMask = mask; - mWriteNotifier = new QSocketNotifier(fd, QSocketNotifier::Write, this); - connect(mWriteNotifier, - SIGNAL(activated(int)), this, SLOT(flushRequests())); - mWriteNotifier->setEnabled(false); + return 0; } -QWaylandDisplay::~QWaylandDisplay(void) +void QWaylandDisplay::outputHandleGeometry(void *data, + struct wl_output *output, + int32_t x, int32_t y, + int32_t width, int32_t height) { - close(mFd); -#ifdef QT_WAYLAND_GL_SUPPORT - eglTerminate(mEglDisplay); -#endif - wl_display_destroy(mDisplay); + //call back function called from another thread; + //but its safe to call createScreen from another thread since + //QWaylandScreen does a moveToThread + QWaylandDisplay *waylandDisplay = static_cast<QWaylandDisplay *>(data); + QRect outputRect = QRect(x, y, width, height); + waylandDisplay->createNewScreen(output,outputRect); } -void QWaylandDisplay::createNewScreen(struct wl_output *output, QRect geometry) +const struct wl_output_listener QWaylandDisplay::outputListener = { + QWaylandDisplay::outputHandleGeometry +}; + +void QWaylandDisplay::waitForScreens() { - QWaylandScreen *waylandScreen = new QWaylandScreen(this,output,geometry); - mScreens.append(waylandScreen); + flushRequests(); + while (mScreens.isEmpty()) + blockingReadEvents(); } -void QWaylandDisplay::syncCallback(wl_display_sync_func_t func, void *data) +void QWaylandDisplay::displayHandleGlobal(struct wl_display *display, + uint32_t id, + const char *interface, + uint32_t version, + void *data) { - wl_display_sync_callback(mDisplay, func, data); + Q_UNUSED(display); + QWaylandDisplay *that = static_cast<QWaylandDisplay *>(data); + that->displayHandleGlobal(id, QByteArray(interface), version); } -void QWaylandDisplay::frameCallback(wl_display_frame_func_t func, void *data) +void QWaylandDisplay::displayHandleGlobal(uint32_t id, + const QByteArray &interface, + uint32_t version) { - wl_display_frame_callback(mDisplay, func, data); + Q_UNUSED(version); + + if (interface == "output") { + struct wl_output *output = wl_output_create(mDisplay, id); + wl_output_add_listener(output, &outputListener, this); + } else if (interface == "compositor") { + mCompositor = wl_compositor_create(mDisplay, id); + } else if (interface == "shm") { + mShm = wl_shm_create(mDisplay, id); + } else if (interface == "shell"){ + mShell = wl_shell_create(mDisplay, id); + wl_shell_add_listener(mShell, &shellListener, this); + } else if (interface == "input_device") { + QWaylandInputDevice *inputDevice = + new QWaylandInputDevice(mDisplay, id); + mInputDevices.append(inputDevice); + } } diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.h b/src/plugins/platforms/wayland/qwaylanddisplay.h index d994ffe..a2cb1b2 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.h +++ b/src/plugins/platforms/wayland/qwaylanddisplay.h @@ -44,19 +44,17 @@ #include <QtCore/QObject> #include <QtCore/QRect> -#include <QtCore/QDataStream> -#include <QtCore/QTextStream> -#include <QtCore/QMetaType> -#include <QtGui> -#include "qwaylandinclude.h" +#include <QtCore/QWaitCondition> + +#include <wayland-client.h> class QWaylandInputDevice; class QSocketNotifier; class QWaylandBuffer; class QPlatformScreen; class QWaylandScreen; - +class QWaylandGLIntegration; class QWaylandDisplay : public QObject { Q_OBJECT @@ -64,61 +62,72 @@ public: QWaylandDisplay(void); ~QWaylandDisplay(void); - void createNewScreen(struct wl_output *output, QRect geometry); QList<QPlatformScreen *> screens() const { return mScreens; } - struct wl_surface *createSurface(); + struct wl_surface *createSurface(void *handle); struct wl_buffer *createShmBuffer(int fd, int width, int height, uint32_t stride, struct wl_visual *visual); struct wl_visual *rgbVisual(); struct wl_visual *argbVisual(); struct wl_visual *argbPremultipliedVisual(); - struct wl_egl_display *nativeDisplay(); - EGLDisplay eglDisplay() { return mEglDisplay; } +#ifdef QT_WAYLAND_GL_SUPPORT + QWaylandGLIntegration *eglIntegration(); +#endif void setCursor(QWaylandBuffer *buffer, int32_t x, int32_t y); void syncCallback(wl_display_sync_func_t func, void *data); - void frameCallback(wl_display_frame_func_t func, void *data); + void frameCallback(wl_display_frame_func_t func, struct wl_surface *surface, void *data); - void iterate(); + struct wl_display *wl_display() const { return mDisplay; } + + QList<QWaylandInputDevice *> inputDevices() const { return mInputDevices; } public slots: - void readEvents(void); - void flushRequests(void); + void createNewScreen(struct wl_output *output, QRect geometry); + void readEvents(); + void blockingReadEvents(); + void flushRequests(); private: + void waitForScreens(); + void displayHandleGlobal(uint32_t id, + const QByteArray &interface, + uint32_t version); + struct wl_display *mDisplay; struct wl_compositor *mCompositor; struct wl_shm *mShm; struct wl_shell *mShell; - char *mDeviceName; - int mFd; QList<QPlatformScreen *> mScreens; QList<QWaylandInputDevice *> mInputDevices; + QSocketNotifier *mReadNotifier; - QSocketNotifier *mWriteNotifier; - EGLDisplay mEglDisplay; - struct wl_egl_display *mNativeEglDisplay; + int mFd; + bool mScreensInitialized; + uint32_t mSocketMask; + + static const struct wl_output_listener outputListener; + static int sourceUpdate(uint32_t mask, void *data); static void displayHandleGlobal(struct wl_display *display, uint32_t id, const char *interface, uint32_t version, void *data); - static void outputHandleGeometry(void *data, struct wl_output *output, int32_t x, int32_t y, int32_t width, int32_t height); +#ifdef QT_WAYLAND_GL_SUPPORT + QWaylandGLIntegration *mEglIntegration; +#endif + static void shellHandleConfigure(void *data, struct wl_shell *shell, uint32_t time, uint32_t edges, struct wl_surface *surface, int32_t width, int32_t height); - static int sourceUpdate(uint32_t mask, void *data); - - static const struct wl_output_listener outputListener; static const struct wl_shell_listener shellListener; }; diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp index 47f9c91..6c2f341 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp @@ -83,6 +83,14 @@ QWaylandInputDevice::QWaylandInputDevice(struct wl_display *display, #endif } +void QWaylandInputDevice::handleWindowDestroyed(QWaylandWindow *window) +{ + if (window == mPointerFocus) + mPointerFocus = 0; + if (window == mKeyboardFocus) + mKeyboardFocus = 0; +} + void QWaylandInputDevice::inputHandleMotion(void *data, struct wl_input_device *input_device, uint32_t time, diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.h b/src/plugins/platforms/wayland/qwaylandinputdevice.h index 2328db8..3c83252 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice.h +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.h @@ -59,6 +59,7 @@ class QWaylandInputDevice { public: QWaylandInputDevice(struct wl_display *display, uint32_t id); void attach(QWaylandBuffer *buffer, int x, int y); + void handleWindowDestroyed(QWaylandWindow *window); private: struct wl_display *mDisplay; diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 267a037..3f3ee5e 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -43,9 +43,7 @@ #include "qwaylanddisplay.h" #include "qwaylandshmsurface.h" -#include "qwaylanddrmsurface.h" #include "qwaylandshmwindow.h" -#include "qwaylandeglwindow.h" #include "qgenericunixfontdatabase.h" @@ -55,6 +53,8 @@ #include <QtGui/private/qpixmap_raster_p.h> #ifdef QT_WAYLAND_GL_SUPPORT +#include "gl_integration/qwaylandglintegration.h" +#include "gl_integration/qwaylandglwindowsurface.h" #include <QtOpenGL/private/qpixmapdata_gl_p.h> #endif @@ -75,6 +75,7 @@ bool QWaylandIntegration::hasCapability(QPlatformIntegration::Capability cap) co { switch (cap) { case ThreadedPixmaps: return true; + case OpenGL: return hasOpenGL(); default: return QPlatformIntegration::hasCapability(cap); } } @@ -91,10 +92,11 @@ QPixmapData *QWaylandIntegration::createPixmapData(QPixmapData::PixelType type) QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWidget *widget, WId winId) const { Q_UNUSED(winId); +#ifdef QT_WAYLAND_GL_SUPPORT bool useOpenGL = mUseOpenGL || (widget->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenGL); if (useOpenGL) - return new QWaylandEglWindow(widget); - + return mDisplay->eglIntegration()->createEglWindow(widget); +#endif return new QWaylandShmWindow(widget); } @@ -102,10 +104,11 @@ QWindowSurface *QWaylandIntegration::createWindowSurface(QWidget *widget, WId wi { Q_UNUSED(winId); Q_UNUSED(winId); +#ifdef QT_WAYLAND_GL_SUPPORT bool useOpenGL = mUseOpenGL || (widget->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenGL); if (useOpenGL) - return new QWaylandDrmWindowSurface(widget); - + return new QWaylandGLWindowSurface(widget); +#endif return new QWaylandShmWindowSurface(widget); } @@ -113,3 +116,12 @@ QPlatformFontDatabase *QWaylandIntegration::fontDatabase() const { return mFontDb; } + +bool QWaylandIntegration::hasOpenGL() const +{ +#ifdef QT_WAYLAND_GL_SUPPORT + return true; +#else + return false; +#endif +} diff --git a/src/plugins/platforms/wayland/qwaylandintegration.h b/src/plugins/platforms/wayland/qwaylandintegration.h index 067b6e4..fc9b8d6 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.h +++ b/src/plugins/platforms/wayland/qwaylandintegration.h @@ -64,6 +64,8 @@ public: QPlatformFontDatabase *fontDatabase() const; private: + bool hasOpenGL() const; + QPlatformFontDatabase *mFontDb; QWaylandDisplay *mDisplay; bool mUseOpenGL; diff --git a/src/plugins/platforms/wayland/qwaylandscreen.cpp b/src/plugins/platforms/wayland/qwaylandscreen.cpp index 35e2532..4f50cb6 100644 --- a/src/plugins/platforms/wayland/qwaylandscreen.cpp +++ b/src/plugins/platforms/wayland/qwaylandscreen.cpp @@ -53,6 +53,7 @@ QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, struct wl_output , mFormat(QImage::Format_ARGB32_Premultiplied) , mWaylandCursor(new QWaylandCursor(this)) { + moveToThread(waylandDisplay->thread()); } QWaylandScreen::~QWaylandScreen() diff --git a/src/plugins/platforms/wayland/qwaylandshmsurface.cpp b/src/plugins/platforms/wayland/qwaylandshmsurface.cpp index 54da9a1..34f4436 100644 --- a/src/plugins/platforms/wayland/qwaylandshmsurface.cpp +++ b/src/plugins/platforms/wayland/qwaylandshmsurface.cpp @@ -95,7 +95,6 @@ QWaylandShmWindowSurface::QWaylandShmWindowSurface(QWidget *window) : QWindowSurface(window) , mBuffer(0) , mDisplay(QWaylandScreen::waylandScreenFromWidget(window)->display()) - , mWaitingForFrameSync(false) { } @@ -110,15 +109,9 @@ QPaintDevice *QWaylandShmWindowSurface::paintDevice() void QWaylandShmWindowSurface::beginPaint(const QRegion &) { - while (mWaitingForFrameSync) { - mDisplay->iterate(); - } -} - -void QWaylandShmWindowSurface::frameCallback(void *data, uint32_t time) -{ - QWaylandShmWindowSurface *self = static_cast<QWaylandShmWindowSurface*>(data); - self->mWaitingForFrameSync = false; + QWaylandShmWindow *waylandWindow = static_cast<QWaylandShmWindow *>(window()->platformWindow()); + Q_ASSERT(waylandWindow->windowType() == QWaylandWindow::Shm); + waylandWindow->waitForFrameSync(); } void QWaylandShmWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) @@ -127,13 +120,7 @@ void QWaylandShmWindowSurface::flush(QWidget *widget, const QRegion ®ion, con Q_UNUSED(offset); QWaylandShmWindow *waylandWindow = static_cast<QWaylandShmWindow *>(window()->platformWindow()); Q_ASSERT(waylandWindow->windowType() == QWaylandWindow::Shm); - - QVector<QRect> rects = region.rects(); - for (int i = 0; i < rects.size(); i++) { - waylandWindow->damage(rects.at(i)); - } - mWaitingForFrameSync = true; - mDisplay->frameCallback(QWaylandShmWindowSurface::frameCallback, this); + waylandWindow->damage(region); } void QWaylandShmWindowSurface::resize(const QSize &size) diff --git a/src/plugins/platforms/wayland/qwaylandshmsurface.h b/src/plugins/platforms/wayland/qwaylandshmsurface.h index 02b324a..b29ceaf 100644 --- a/src/plugins/platforms/wayland/qwaylandshmsurface.h +++ b/src/plugins/platforms/wayland/qwaylandshmsurface.h @@ -74,11 +74,8 @@ public: void beginPaint(const QRegion &); private: - static void frameCallback(void *data, uint32_t time);\ - QWaylandShmBuffer *mBuffer; QWaylandDisplay *mDisplay; - bool mWaitingForFrameSync; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandshmwindow.cpp b/src/plugins/platforms/wayland/qwaylandshmwindow.cpp index cafd2d0..c083e58 100644 --- a/src/plugins/platforms/wayland/qwaylandshmwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandshmwindow.cpp @@ -43,9 +43,12 @@ #include "qwaylandbuffer.h" +#include <QtCore/QVector> + +#include <QtCore/QDebug> + QWaylandShmWindow::QWaylandShmWindow(QWidget *widget) : QWaylandWindow(widget) - , mBuffer(0) { newSurfaceCreated(); } @@ -66,24 +69,3 @@ QPlatformGLContext * QWaylandShmWindow::glContext() const return 0; } -void QWaylandShmWindow::attach(QWaylandBuffer *buffer) -{ - mBuffer = buffer; - if (mSurface) { - wl_surface_attach(mSurface, buffer->buffer(),0,0); - } -} - - -void QWaylandShmWindow::damage(const QRect &rect) -{ - wl_surface_damage(mSurface, - rect.x(), rect.y(), rect.width(), rect.height()); -} - -void QWaylandShmWindow::newSurfaceCreated() -{ - if (mBuffer) { - wl_surface_attach(mSurface,mBuffer->buffer(),0,0); - } -} diff --git a/src/plugins/platforms/wayland/qwaylandshmwindow.h b/src/plugins/platforms/wayland/qwaylandshmwindow.h index 14a29d2..5dc6351 100644 --- a/src/plugins/platforms/wayland/qwaylandshmwindow.h +++ b/src/plugins/platforms/wayland/qwaylandshmwindow.h @@ -43,6 +43,7 @@ #define QWAYLANDSHMWINDOW_H #include "qwaylandwindow.h" +#include <QtGui/QRegion> class QWaylandShmWindow : public QWaylandWindow { @@ -52,12 +53,6 @@ public: WindowType windowType() const; QPlatformGLContext *glContext() const; - void attach(QWaylandBuffer *buffer); - void damage(const QRect &rect); -protected: - void newSurfaceCreated(); -private: - QWaylandBuffer *mBuffer; }; #endif // QWAYLANDSHMWINDOW_H diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp index a912a83..6f52291 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -41,7 +41,9 @@ #include "qwaylandwindow.h" +#include "qwaylandbuffer.h" #include "qwaylanddisplay.h" +#include "qwaylandinputdevice.h" #include "qwaylandscreen.h" #include <QtGui/QWidget> @@ -52,15 +54,23 @@ QWaylandWindow::QWaylandWindow(QWidget *window) : QPlatformWindow(window) , mDisplay(QWaylandScreen::waylandScreenFromWidget(window)->display()) + , mBuffer(0) + , mWaitingForFrameSync(false) { static WId id = 1; mWindowId = id++; - mSurface = mDisplay->createSurface(); + mSurface = mDisplay->createSurface(this); } QWaylandWindow::~QWaylandWindow() { + if (mSurface) + wl_surface_destroy(mSurface); + + QList<QWaylandInputDevice *> inputDevices = mDisplay->inputDevices(); + for (int i = 0; i < inputDevices.size(); ++i) + inputDevices.at(i)->handleWindowDestroyed(this); } WId QWaylandWindow::winId() const @@ -71,18 +81,17 @@ WId QWaylandWindow::winId() const void QWaylandWindow::setParent(const QPlatformWindow *parent) { Q_UNUSED(parent); - qWarning("Trying to add a raster window as a sub-window"); + qWarning("Sub window is not supported"); } void QWaylandWindow::setVisible(bool visible) { - if (!mSurface) { - mSurface = mDisplay->createSurface(); + if (!mSurface && visible) { + mSurface = mDisplay->createSurface(this); newSurfaceCreated(); } if (visible) { - wl_surface_set_user_data(mSurface, this); wl_surface_map_toplevel(mSurface); } else { wl_surface_destroy(mSurface); @@ -102,3 +111,48 @@ void QWaylandWindow::configure(uint32_t time, uint32_t edges, QWindowSystemInterface::handleGeometryChange(widget(), geometry); } + +void QWaylandWindow::attach(QWaylandBuffer *buffer) +{ + mBuffer = buffer; + if (mSurface) { + wl_surface_attach(mSurface, buffer->buffer(),0,0); + } +} + + +void QWaylandWindow::damage(const QRegion ®ion) +{ + //We have to do sync stuff before calling damage, or we might + //get a frame callback before we get the timestamp + mDisplay->frameCallback(QWaylandWindow::frameCallback, mSurface, this); + mWaitingForFrameSync = true; + + QVector<QRect> rects = region.rects(); + for (int i = 0; i < rects.size(); i++) { + const QRect rect = rects.at(i); + wl_surface_damage(mSurface, + rect.x(), rect.y(), rect.width(), rect.height()); + } +} + +void QWaylandWindow::newSurfaceCreated() +{ + if (mBuffer) { + wl_surface_attach(mSurface,mBuffer->buffer(),0,0); + } +} + +void QWaylandWindow::frameCallback(struct wl_surface *surface, void *data, uint32_t time) +{ + Q_UNUSED(time); + QWaylandWindow *self = static_cast<QWaylandWindow*>(data); + self->mWaitingForFrameSync = false; +} + +void QWaylandWindow::waitForFrameSync() +{ + mDisplay->flushRequests(); + while (mWaitingForFrameSync) + mDisplay->blockingReadEvents(); +} diff --git a/src/plugins/platforms/wayland/qwaylandwindow.h b/src/plugins/platforms/wayland/qwaylandwindow.h index 3b51ee7..1e60508 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.h +++ b/src/plugins/platforms/wayland/qwaylandwindow.h @@ -43,8 +43,8 @@ #define QWAYLANDWINDOW_H #include <QtGui/QPlatformWindow> +#include <QtCore/QWaitCondition> -#include <stdint.h> #include "qwaylanddisplay.h" class QWaylandDisplay; @@ -70,11 +70,21 @@ public: void configure(uint32_t time, uint32_t edges, int32_t x, int32_t y, int32_t width, int32_t height); + void attach(QWaylandBuffer *buffer); + void damage(const QRegion ®ion); + + void waitForFrameSync(); protected: struct wl_surface *mSurface; - virtual void newSurfaceCreated() = 0; + virtual void newSurfaceCreated(); QWaylandDisplay *mDisplay; + QWaylandBuffer *mBuffer; WId mWindowId; + bool mWaitingForFrameSync; + QWaitCondition mFrameSyncWait; + +private: + static void frameCallback(struct wl_surface *surface, void *data, uint32_t time); }; diff --git a/src/plugins/platforms/wayland/wayland.pro b/src/plugins/platforms/wayland/wayland.pro index face860..5945438 100644 --- a/src/plugins/platforms/wayland/wayland.pro +++ b/src/plugins/platforms/wayland/wayland.pro @@ -22,35 +22,16 @@ HEADERS = qwaylandintegration.h \ qwaylandwindow.h \ qwaylandscreen.h \ qwaylandshmsurface.h \ - qwaylanddrmsurface.h \ qwaylandbuffer.h \ - qwaylandinclude.h \ - qwaylandeglwindow.h \ qwaylandshmwindow.h INCLUDEPATH += $$QMAKE_INCDIR_WAYLAND LIBS += $$QMAKE_LIBS_WAYLAND QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_WAYLAND -contains(QT_CONFIG, opengles2) { - QT += opengl - LIBS += -lwayland-egl -lEGL +INCLUDEPATH += $$PWD - SOURCES += qwaylanddrmsurface.cpp \ - qwaylandglcontext.cpp \ - ../eglconvenience/qeglconvenience.cpp \ - qwaylandeglwindow.cpp - - HEADERS += qwaylandglcontext.h \ - ../eglconvenience/qeglconvenience.h \ - - DEFINES += QT_WAYLAND_GL_SUPPORT -} - -unix:isEmpty(QMAKE_INCDIR_WAYLAND) { - CONFIG += link_pkgconfig - PKGCONFIG += libdrm -} +include ($$PWD/gl_integration/gl_integration.pri) include (../fontdatabases/genericunix/genericunix.pri) diff --git a/src/plugins/platforms/xcb/README b/src/plugins/platforms/xcb/README index e88596b..17a86e6 100644 --- a/src/plugins/platforms/xcb/README +++ b/src/plugins/platforms/xcb/README @@ -1,2 +1,3 @@ Required packages: -libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm1 libxcb-icccm1-dev +libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm1 libxcb-icccm1-dev libxcb-sync0 libxcb-sync0-dev + diff --git a/src/plugins/platforms/xcb/qdri2context.cpp b/src/plugins/platforms/xcb/qdri2context.cpp index 0079f91..dbbfa67 100644 --- a/src/plugins/platforms/xcb/qdri2context.cpp +++ b/src/plugins/platforms/xcb/qdri2context.cpp @@ -266,6 +266,6 @@ xcb_dri2_dri2_buffer_t * QDri2Context::backBuffer() void * QDri2Context::eglContext() const { - Q_D(QDri2Context); + Q_D(const QDri2Context); return d->eglContext; } diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp index e94b6a6..190221c 100644 --- a/src/plugins/platforms/xcb/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/qglxintegration.cpp @@ -51,218 +51,29 @@ #include <GL/glx.h> #include "qglxintegration.h" +#include "qglxconvenience.h" #if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) #include <dlfcn.h> #endif -QMutex QGLXContext::m_defaultSharedContextMutex(QMutex::Recursive); - -QVector<int> QGLXContext::buildSpec(const QPlatformWindowFormat &format) -{ - QVector<int> spec(48); - int i = 0; - - spec[i++] = GLX_LEVEL; - spec[i++] = 0; - spec[i++] = GLX_DRAWABLE_TYPE; spec[i++] = GLX_WINDOW_BIT; - - if (format.rgba()) { - spec[i++] = GLX_RENDER_TYPE; spec[i++] = GLX_RGBA_BIT; - spec[i++] = GLX_RED_SIZE; spec[i++] = (format.redBufferSize() == -1) ? 1 : format.redBufferSize(); - spec[i++] = GLX_GREEN_SIZE; spec[i++] = (format.greenBufferSize() == -1) ? 1 : format.greenBufferSize(); - spec[i++] = GLX_BLUE_SIZE; spec[i++] = (format.blueBufferSize() == -1) ? 1 : format.blueBufferSize(); - if (format.alpha()) { - spec[i++] = GLX_ALPHA_SIZE; spec[i++] = (format.alphaBufferSize() == -1) ? 1 : format.alphaBufferSize(); - } - - spec[i++] = GLX_ACCUM_RED_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize(); - spec[i++] = GLX_ACCUM_GREEN_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize(); - spec[i++] = GLX_ACCUM_BLUE_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize(); - - if (format.alpha()) { - spec[i++] = GLX_ACCUM_ALPHA_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize(); - } - - } else { - spec[i++] = GLX_RENDER_TYPE; spec[i++] = GLX_COLOR_INDEX_BIT; //I'm really not sure if this works.... - spec[i++] = GLX_BUFFER_SIZE; spec[i++] = 8; - } - - spec[i++] = GLX_DOUBLEBUFFER; spec[i++] = format.doubleBuffer() ? True : False; - spec[i++] = GLX_STEREO; spec[i++] = format.stereo() ? True : False; - - if (format.depth()) { - spec[i++] = GLX_DEPTH_SIZE; spec[i++] = (format.depthBufferSize() == -1) ? 1 : format.depthBufferSize(); - } - - if (format.stencil()) { - spec[i++] = GLX_STENCIL_SIZE; spec[i++] = (format.stencilBufferSize() == -1) ? 1 : format.stencilBufferSize(); - } - if (format.sampleBuffers()) { - spec[i++] = GLX_SAMPLE_BUFFERS_ARB; - spec[i++] = 1; - spec[i++] = GLX_SAMPLES_ARB; - spec[i++] = format.samples() == -1 ? 4 : format.samples(); - } - - spec[i++] = None; - return spec; -} - -GLXFBConfig QGLXContext::findConfig(const QXcbScreen *screen, const QPlatformWindowFormat &format) -{ - bool reduced = true; - GLXFBConfig chosenConfig = 0; - QPlatformWindowFormat reducedFormat = format; - while (!chosenConfig && reduced) { - QVector<int> spec = buildSpec(reducedFormat); - int confcount = 0; - GLXFBConfig *configs; - configs = glXChooseFBConfig(DISPLAY_FROM_XCB(screen), screen->screenNumber(), spec.constData(), &confcount); - if (confcount) - { - for (int i = 0; i < confcount; i++) { - chosenConfig = configs[i]; - // Make sure we try to get an ARGB visual if the format asked for an alpha: - if (reducedFormat.alpha()) { - int alphaSize; - glXGetFBConfigAttrib(DISPLAY_FROM_XCB(screen), configs[i], GLX_ALPHA_SIZE, &alphaSize); - if (alphaSize > 0) - break; - } else { - break; // Just choose the first in the list if there's no alpha requested - } - } - - XFree(configs); - } - reducedFormat = reducePlatformWindowFormat(reducedFormat,&reduced); - } - - if (!chosenConfig) - qWarning("Warning no context created"); - - return chosenConfig; -} - -XVisualInfo *QGLXContext::findVisualInfo(const QXcbScreen *screen, const QPlatformWindowFormat &format) -{ - GLXFBConfig config = QGLXContext::findConfig(screen,format); - XVisualInfo *visualInfo = glXGetVisualFromFBConfig(DISPLAY_FROM_XCB(screen), config); - return visualInfo; -} - -QPlatformWindowFormat QGLXContext::platformWindowFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext ctx) -{ - QPlatformWindowFormat format; - int redSize = 0; - int greenSize = 0; - int blueSize = 0; - int alphaSize = 0; - int depthSize = 0; - int stencilSize = 0; - int sampleBuffers = 0; - int sampleCount = 0; - int level = 0; - int rgba = 0; - int stereo = 0; - int accumSizeA = 0; - int accumSizeR = 0; - int accumSizeG = 0; - int accumSizeB = 0; - - XVisualInfo *vi = glXGetVisualFromFBConfig(display,config); - glXGetConfig(display,vi,GLX_RGBA,&rgba); - XFree(vi); - glXGetFBConfigAttrib(display, config, GLX_RED_SIZE, &redSize); - glXGetFBConfigAttrib(display, config, GLX_GREEN_SIZE, &greenSize); - glXGetFBConfigAttrib(display, config, GLX_BLUE_SIZE, &blueSize); - glXGetFBConfigAttrib(display, config, GLX_ALPHA_SIZE, &alphaSize); - glXGetFBConfigAttrib(display, config, GLX_DEPTH_SIZE, &depthSize); - glXGetFBConfigAttrib(display, config, GLX_STENCIL_SIZE, &stencilSize); - glXGetFBConfigAttrib(display, config, GLX_SAMPLES, &sampleBuffers); - glXGetFBConfigAttrib(display, config, GLX_LEVEL, &level); - glXGetFBConfigAttrib(display, config, GLX_STEREO, &stereo); - glXGetFBConfigAttrib(display, config, GLX_ACCUM_ALPHA_SIZE, &accumSizeA); - glXGetFBConfigAttrib(display, config, GLX_ACCUM_RED_SIZE, &accumSizeR); - glXGetFBConfigAttrib(display, config, GLX_ACCUM_GREEN_SIZE, &accumSizeG); - glXGetFBConfigAttrib(display, config, GLX_ACCUM_BLUE_SIZE, &accumSizeB); - - format.setRedBufferSize(redSize); - format.setGreenBufferSize(greenSize); - format.setBlueBufferSize(blueSize); - format.setAlphaBufferSize(alphaSize); - format.setDepthBufferSize(depthSize); - format.setStencilBufferSize(stencilSize); - format.setSampleBuffers(sampleBuffers); - if (format.sampleBuffers()) { - glXGetFBConfigAttrib(display, config, GLX_SAMPLES_ARB, &sampleCount); - format.setSamples(sampleCount); - } - - format.setDirectRendering(glXIsDirect(display, ctx)); - format.setRgba(rgba); - format.setStereo(stereo); - format.setAccumBufferSize(accumSizeB); - - return format; -} - -QPlatformWindowFormat QGLXContext::reducePlatformWindowFormat(const QPlatformWindowFormat &format, bool *reduced) -{ - QPlatformWindowFormat retFormat = format; - *reduced = true; - - if (retFormat.sampleBuffers()) { - retFormat.setSampleBuffers(false); - } else if (retFormat.stereo()) { - retFormat.setStereo(false); - } else if (retFormat.accum()) { - retFormat.setAccum(false); - }else if (retFormat.stencil()) { - retFormat.setStencil(false); - }else if (retFormat.alpha()) { - retFormat.setAlpha(false); - }else if (retFormat.depth()) { - retFormat.setDepth(false); - }else if (retFormat.doubleBuffer()) { - retFormat.setDoubleBuffer(false); - }else{ - *reduced = false; - } - return retFormat; -} - QGLXContext::QGLXContext(Window window, QXcbScreen *screen, const QPlatformWindowFormat &format) : QPlatformGLContext() , m_screen(screen) , m_drawable((Drawable)window) , m_context(0) { - + Q_XCB_NOOP(m_screen->connection()); const QPlatformGLContext *sharePlatformContext; - if (format.useDefaultSharedContext()) { - if (!QPlatformGLContext::defaultSharedContext()) { - if (m_defaultSharedContextMutex.tryLock()){ - createDefaultSharedContex(screen); - m_defaultSharedContextMutex.unlock(); - } else { - m_defaultSharedContextMutex.lock(); //wait to the the shared context is created - m_defaultSharedContextMutex.unlock(); - } - } - sharePlatformContext = QPlatformGLContext::defaultSharedContext(); - } else { - sharePlatformContext = format.sharedGLContext(); - } + sharePlatformContext = format.sharedGLContext(); GLXContext shareGlxContext = 0; if (sharePlatformContext) shareGlxContext = static_cast<const QGLXContext*>(sharePlatformContext)->glxContext(); - GLXFBConfig config = findConfig(screen,format); + GLXFBConfig config = qglx_findConfig(DISPLAY_FROM_XCB(screen),screen->screenNumber(),format); m_context = glXCreateNewContext(DISPLAY_FROM_XCB(screen), config, GLX_RGBA_TYPE, shareGlxContext, TRUE); - m_windowFormat = QGLXContext::platformWindowFromGLXFBConfig(DISPLAY_FROM_XCB(screen), config, m_context); + m_windowFormat = qglx_platformWindowFromGLXFBConfig(DISPLAY_FROM_XCB(screen), config, m_context); + Q_XCB_NOOP(m_screen->connection()); } QGLXContext::QGLXContext(QXcbScreen *screen, Drawable drawable, GLXContext context) @@ -273,56 +84,39 @@ QGLXContext::QGLXContext(QXcbScreen *screen, Drawable drawable, GLXContext conte QGLXContext::~QGLXContext() { + Q_XCB_NOOP(m_screen->connection()); if (m_context) glXDestroyContext(DISPLAY_FROM_XCB(m_screen), m_context); -} - -void QGLXContext::createDefaultSharedContex(QXcbScreen *screen) -{ - int x = 0; - int y = 0; - int w = 3; - int h = 3; - - QPlatformWindowFormat format = QPlatformWindowFormat::defaultFormat(); - GLXContext context; - GLXFBConfig config = findConfig(screen,format); - if (config) { - XVisualInfo *visualInfo = glXGetVisualFromFBConfig(DISPLAY_FROM_XCB(screen), config); - Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(screen), screen->root(), visualInfo->visual, AllocNone); - XSetWindowAttributes a; - a.colormap = cmap; - Window sharedWindow = XCreateWindow(DISPLAY_FROM_XCB(screen), screen->root(), x, y, w, h, - 0, visualInfo->depth, InputOutput, visualInfo->visual, - CWColormap, &a); - - context = glXCreateNewContext(DISPLAY_FROM_XCB(screen), config, GLX_RGBA_TYPE, 0, TRUE); - QPlatformGLContext *sharedContext = new QGLXContext(screen, sharedWindow, context); - QPlatformGLContext::setDefaultSharedContext(sharedContext); - } else { - qWarning("Warning no shared context created"); - } + Q_XCB_NOOP(m_screen->connection()); } void QGLXContext::makeCurrent() { + Q_XCB_NOOP(m_screen->connection()); QPlatformGLContext::makeCurrent(); glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), m_drawable, m_context); + Q_XCB_NOOP(m_screen->connection()); } void QGLXContext::doneCurrent() { + Q_XCB_NOOP(m_screen->connection()); QPlatformGLContext::doneCurrent(); glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), 0, 0); + Q_XCB_NOOP(m_screen->connection()); } void QGLXContext::swapBuffers() { + Q_XCB_NOOP(m_screen->connection()); glXSwapBuffers(DISPLAY_FROM_XCB(m_screen), m_drawable); + doneCurrent(); + Q_XCB_NOOP(m_screen->connection()); } void* QGLXContext::getProcAddress(const QString& procName) { + Q_XCB_NOOP(m_screen->connection()); typedef void *(*qt_glXGetProcAddressARB)(const GLubyte *); static qt_glXGetProcAddressARB glXGetProcAddressARB = 0; static bool resolved = false; diff --git a/src/plugins/platforms/xcb/qglxintegration.h b/src/plugins/platforms/xcb/qglxintegration.h index f2e20c4..99b72a0 100644 --- a/src/plugins/platforms/xcb/qglxintegration.h +++ b/src/plugins/platforms/xcb/qglxintegration.h @@ -66,22 +66,13 @@ public: QPlatformWindowFormat platformWindowFormat() const; - static XVisualInfo *findVisualInfo(const QXcbScreen *xd, const QPlatformWindowFormat &format); - private: - static GLXFBConfig findConfig(const QXcbScreen *xd,const QPlatformWindowFormat &format); - static QVector<int> buildSpec(const QPlatformWindowFormat &format); - static QPlatformWindowFormat platformWindowFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext context); - static QPlatformWindowFormat reducePlatformWindowFormat(const QPlatformWindowFormat &format, bool *reduced); - QXcbScreen *m_screen; Drawable m_drawable; GLXContext m_context; QPlatformWindowFormat m_windowFormat; QGLXContext (QXcbScreen *screen, Drawable drawable, GLXContext context); - static QMutex m_defaultSharedContextMutex; - static void createDefaultSharedContex(QXcbScreen *xd); }; #endif diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 191699b..7ad12fe 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -47,6 +47,7 @@ #include <QtAlgorithms> #include <QSocketNotifier> #include <QtGui/private/qapplication_p.h> +#include <QAbstractEventDispatcher> #include <QtCore/QDebug> @@ -104,6 +105,8 @@ QXcbConnection::QXcbConnection(const char *displayName) #endif //XCB_USE_XLIB m_setup = xcb_get_setup(xcb_connection()); + initializeAllAtoms(); + xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup); int screenNumber = 0; @@ -112,16 +115,19 @@ QXcbConnection::QXcbConnection(const char *displayName) xcb_screen_next(&it); } - QSocketNotifier *socket = new QSocketNotifier(xcb_get_file_descriptor(xcb_connection()), QSocketNotifier::Read, this); - connect(socket, SIGNAL(activated(int)), this, SLOT(eventDispatcher())); - m_keyboard = new QXcbKeyboard(this); - initializeAllAtoms(); - #ifdef XCB_USE_DRI2 initializeDri2(); #endif + + QSocketNotifier *notifier = new QSocketNotifier(xcb_get_file_descriptor(xcb_connection()), QSocketNotifier::Read, this); + connect(notifier, SIGNAL(activated(int)), this, SLOT(processXcbEvents())); + + QAbstractEventDispatcher *dispatcher = QAbstractEventDispatcher::instance(qApp->thread()); + connect(dispatcher, SIGNAL(aboutToBlock()), this, SLOT(processXcbEvents())); + + sync(); } QXcbConnection::~QXcbConnection() @@ -148,8 +154,11 @@ QXcbWindow *platformWindowFromId(xcb_window_t id) #define HANDLE_PLATFORM_WINDOW_EVENT(event_t, window, handler) \ { \ event_t *e = (event_t *)event; \ - if (QXcbWindow *platformWindow = platformWindowFromId(e->window)) \ - platformWindow->handler(e); \ + if (QXcbWindow *platformWindow = platformWindowFromId(e->window)) { \ + QObjectPrivate *d = QObjectPrivate::get(platformWindow->widget()); \ + if (!d->wasDeleted) \ + platformWindow->handler(e); \ + } \ } \ break; @@ -166,9 +175,9 @@ break; void printXcbEvent(const char *message, xcb_generic_event_t *event) { #ifdef XCB_EVENT_DEBUG -#define PRINT_XCB_EVENT(event) \ - case event: \ - printf("%s: %d - %s\n", message, event, #event); \ +#define PRINT_XCB_EVENT(ev) \ + case ev: \ + printf("%s: %d - %s - sequence: %d\n", message, int(ev), #ev, event->sequence); \ break; switch (event->response_type & ~0x80) { @@ -205,7 +214,7 @@ void printXcbEvent(const char *message, xcb_generic_event_t *event) PRINT_XCB_EVENT(XCB_CLIENT_MESSAGE); PRINT_XCB_EVENT(XCB_MAPPING_NOTIFY); default: - printf("%s: %d - %s\n", message, event->response_type, "unknown"); + printf("%s: unknown event - response_type: %d - sequence: %d\n", message, int(event->response_type & ~0x80), int(event->sequence)); } #else Q_UNUSED(message); @@ -213,11 +222,216 @@ void printXcbEvent(const char *message, xcb_generic_event_t *event) #endif } -void QXcbConnection::eventDispatcher() +const char *xcb_errors[] = +{ + "Success", + "BadRequest", + "BadValue", + "BadWindow", + "BadPixmap", + "BadAtom", + "BadCursor", + "BadFont", + "BadMatch", + "BadDrawable", + "BadAccess", + "BadAlloc", + "BadColor", + "BadGC", + "BadIDChoice", + "BadName", + "BadLength", + "BadImplementation", + "Unknown" +}; + +const char *xcb_protocol_request_codes[] = +{ + "Null", + "CreateWindow", + "ChangeWindowAttributes", + "GetWindowAttributes", + "DestroyWindow", + "DestroySubwindows", + "ChangeSaveSet", + "ReparentWindow", + "MapWindow", + "MapSubwindows", + "UnmapWindow", + "UnmapSubwindows", + "ConfigureWindow", + "CirculateWindow", + "GetGeometry", + "QueryTree", + "InternAtom", + "GetAtomName", + "ChangeProperty", + "DeleteProperty", + "GetProperty", + "ListProperties", + "SetSelectionOwner", + "GetSelectionOwner", + "ConvertSelection", + "SendEvent", + "GrabPointer", + "UngrabPointer", + "GrabButton", + "UngrabButton", + "ChangeActivePointerGrab", + "GrabKeyboard", + "UngrabKeyboard", + "GrabKey", + "UngrabKey", + "AllowEvents", + "GrabServer", + "UngrabServer", + "QueryPointer", + "GetMotionEvents", + "TranslateCoords", + "WarpPointer", + "SetInputFocus", + "GetInputFocus", + "QueryKeymap", + "OpenFont", + "CloseFont", + "QueryFont", + "QueryTextExtents", + "ListFonts", + "ListFontsWithInfo", + "SetFontPath", + "GetFontPath", + "CreatePixmap", + "FreePixmap", + "CreateGC", + "ChangeGC", + "CopyGC", + "SetDashes", + "SetClipRectangles", + "FreeGC", + "ClearArea", + "CopyArea", + "CopyPlane", + "PolyPoint", + "PolyLine", + "PolySegment", + "PolyRectangle", + "PolyArc", + "FillPoly", + "PolyFillRectangle", + "PolyFillArc", + "PutImage", + "GetImage", + "PolyText8", + "PolyText16", + "ImageText8", + "ImageText16", + "CreateColormap", + "FreeColormap", + "CopyColormapAndFree", + "InstallColormap", + "UninstallColormap", + "ListInstalledColormaps", + "AllocColor", + "AllocNamedColor", + "AllocColorCells", + "AllocColorPlanes", + "FreeColors", + "StoreColors", + "StoreNamedColor", + "QueryColors", + "LookupColor", + "CreateCursor", + "CreateGlyphCursor", + "FreeCursor", + "RecolorCursor", + "QueryBestSize", + "QueryExtension", + "ListExtensions", + "ChangeKeyboardMapping", + "GetKeyboardMapping", + "ChangeKeyboardControl", + "GetKeyboardControl", + "Bell", + "ChangePointerControl", + "GetPointerControl", + "SetScreenSaver", + "GetScreenSaver", + "ChangeHosts", + "ListHosts", + "SetAccessControl", + "SetCloseDownMode", + "KillClient", + "RotateProperties", + "ForceScreenSaver", + "SetPointerMapping", + "GetPointerMapping", + "SetModifierMapping", + "GetModifierMapping", + "Unknown" +}; + +#ifdef Q_XCB_DEBUG +void QXcbConnection::log(const char *file, int line, int sequence) +{ + CallInfo info; + info.sequence = sequence; + info.file = file; + info.line = line; + m_callLog << info; +} +#endif + +void QXcbConnection::handleXcbError(xcb_generic_error_t *error) +{ + uint clamped_error_code = qMin<uint>(error->error_code, (sizeof(xcb_errors) / sizeof(xcb_errors[0])) - 1); + uint clamped_major_code = qMin<uint>(error->major_code, (sizeof(xcb_protocol_request_codes) / sizeof(xcb_protocol_request_codes[0])) - 1); + + printf("XCB error: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d\n", + int(error->error_code), xcb_errors[clamped_error_code], + int(error->sequence), int(error->resource_id), + int(error->major_code), xcb_protocol_request_codes[clamped_major_code], + int(error->minor_code)); +#ifdef Q_XCB_DEBUG + int i = 0; + for (; i < m_callLog.size(); ++i) { + if (m_callLog.at(i).sequence == error->sequence) { + printf("Caused by: %s:%d\n", qPrintable(m_callLog.at(i).file), m_callLog.at(i).line); + break; + } else if (m_callLog.at(i).sequence > error->sequence) { + printf("Caused some time before: %s:%d\n", qPrintable(m_callLog.at(i).file), m_callLog.at(i).line); + if (i > 0) + printf("and after: %s:%d\n", qPrintable(m_callLog.at(i-1).file), m_callLog.at(i-1).line); + break; + } + } + if (i == m_callLog.size() && !m_callLog.isEmpty()) + printf("Caused some time after: %s:%d\n", qPrintable(m_callLog.first().file), m_callLog.first().line); +#endif +} + +void QXcbConnection::processXcbEvents() { while (xcb_generic_event_t *event = xcb_poll_for_event(xcb_connection())) { bool handled = true; - switch (event->response_type & ~0x80) { + + uint response_type = event->response_type & ~0x80; + + if (!response_type) { + handleXcbError((xcb_generic_error_t *)event); + continue; + } + +#ifdef Q_XCB_DEBUG + { + int i = 0; + for (; i < m_callLog.size(); ++i) + if (m_callLog.at(i).sequence >= event->sequence) + break; + m_callLog.remove(0, i); + } +#endif + + switch (response_type) { case XCB_EXPOSE: HANDLE_PLATFORM_WINDOW_EVENT(xcb_expose_event_t, window, handleExposeEvent); case XCB_BUTTON_PRESS: @@ -247,13 +461,15 @@ void QXcbConnection::eventDispatcher() break; default: handled = false; - return; + break; } if (handled) printXcbEvent("Handled XCB event", event); else printXcbEvent("Unhandled XCB event", event); } + + xcb_flush(xcb_connection()); } static const char * xcb_atomnames = { @@ -447,6 +663,13 @@ void QXcbConnection::initializeAllAtoms() { m_allAtoms[i] = xcb_intern_atom_reply(xcb_connection(), cookies[i], 0)->atom; } +void QXcbConnection::sync() +{ + // from xcb_aux_sync + xcb_get_input_focus_cookie_t cookie = Q_XCB_CALL(xcb_get_input_focus(xcb_connection())); + free(xcb_get_input_focus_reply(xcb_connection(), cookie, 0)); +} + #if defined(XCB_USE_EGL) bool QXcbConnection::hasEgl() const { diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index e00fbb1..6b5f810 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -46,6 +46,9 @@ #include <QList> #include <QObject> +#include <QVector> + +#define Q_XCB_DEBUG class QXcbScreen; @@ -221,6 +224,8 @@ public: QXcbConnection(const char *displayName = 0); ~QXcbConnection(); + QXcbConnection *connection() const { return const_cast<QXcbConnection *>(this); } + QList<QXcbScreen *> screens() const { return m_screens; } int primaryScreen() const { return m_primaryScreen; } @@ -247,11 +252,15 @@ public: void *egl_display() const { return m_egl_display; } #endif + void sync(); + void handleXcbError(xcb_generic_error_t *error); + private slots: - void eventDispatcher(); + void processXcbEvents(); private: void initializeAllAtoms(); + void sendConnectionEvent(QXcbAtom::Atom atom, uint id = 0); #ifdef XCB_USE_DRI2 void initializeDri2(); #endif @@ -283,10 +292,38 @@ private: void *m_egl_display; bool m_has_egl; #endif +#ifdef Q_XCB_DEBUG + struct CallInfo { + int sequence; + QByteArray file; + int line; + }; + QVector<CallInfo> m_callLog; + void log(const char *file, int line, int sequence); + template <typename cookie_t> + friend cookie_t q_xcb_call_template(const cookie_t &cookie, QXcbConnection *connection, const char *file, int line); +#endif }; #define DISPLAY_FROM_XCB(object) ((Display *)(object->connection()->xlib_display())) +#ifdef Q_XCB_DEBUG +template <typename cookie_t> +cookie_t q_xcb_call_template(const cookie_t &cookie, QXcbConnection *connection, const char *file, int line) +{ + connection->log(file, line, cookie.sequence); + return cookie; +} +#define Q_XCB_CALL(x) q_xcb_call_template(x, connection(), __FILE__, __LINE__) +#define Q_XCB_CALL2(x, connection) q_xcb_call_template(x, connection, __FILE__, __LINE__) +#define Q_XCB_NOOP(c) q_xcb_call_template(xcb_no_operation(c->xcb_connection()), c, __FILE__, __LINE__); +#else +#define Q_XCB_CALL(x) x +#define Q_XCB_CALL2(x, connection) x +#define Q_XCB_NOOP(c) +#endif + + #if defined(XCB_USE_DRI2) || defined(XCB_USE_EGL) #define EGL_DISPLAY_FROM_XCB(object) ((EGLDisplay)(object->connection()->egl_display())) #endif //endifXCB_USE_DRI2 diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index 63c26a1..9df5f14 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -73,6 +73,15 @@ QXcbIntegration::~QXcbIntegration() delete m_connection; } +bool QXcbIntegration::hasCapability(QPlatformIntegration::Capability cap) const +{ + switch (cap) { + case ThreadedPixmaps: return true; + case OpenGL: return hasOpenGL(); + default: return QPlatformIntegration::hasCapability(cap); + } +} + QPixmapData *QXcbIntegration::createPixmapData(QPixmapData::PixelType type) const { return new QRasterPixmapData(type); diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h index 6c9634e..d27fd71 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.h +++ b/src/plugins/platforms/xcb/qxcbintegration.h @@ -55,6 +55,7 @@ public: QXcbIntegration(); ~QXcbIntegration(); + bool hasCapability(Capability cap) const; QPixmapData *createPixmapData(QPixmapData::PixelType type) const; QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId) const; QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; @@ -65,11 +66,11 @@ public: QPixmap grabWindow(WId window, int x, int y, int width, int height) const; QPlatformFontDatabase *fontDatabase() const; - bool hasOpenGL() const; QPlatformNativeInterface *nativeInterface()const; private: + bool hasOpenGL() const; QList<QPlatformScreen *> m_screens; QXcbConnection *m_connection; diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index ec9a009..f501c00 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -921,6 +921,8 @@ void QXcbKeyboard::handleKeyEvent(QWidget *widget, QEvent::Type type, xcb_keycod if (state & 128) col += altGrOffset; + Q_XCB_NOOP(connection()); + #ifdef XCB_KEYBOARD_DEBUG printf("key code: %d, state: %d, syms: ", code, state); for (int i = 0; i <= 5; ++i) { @@ -929,6 +931,8 @@ void QXcbKeyboard::handleKeyEvent(QWidget *widget, QEvent::Type type, xcb_keycod printf("\n"); #endif + Q_XCB_NOOP(connection()); + xcb_keysym_t sym = xcb_key_symbols_get_keysym(m_key_symbols, code, col); if (sym == XCB_NO_SYMBOL) sym = xcb_key_symbols_get_keysym(m_key_symbols, code, col ^ 0x1); @@ -940,6 +944,8 @@ void QXcbKeyboard::handleKeyEvent(QWidget *widget, QEvent::Type type, xcb_keycod sym = toupper(sym); } + Q_XCB_NOOP(connection()); + QByteArray chars; Qt::KeyboardModifiers modifiers; diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index fffeb2e..1c12ee3 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -60,13 +60,48 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, int num const quint32 mask = XCB_CW_EVENT_MASK; const quint32 values[] = { // XCB_CW_EVENT_MASK - XCB_EVENT_MASK_KEYMAP_STATE - | XCB_EVENT_MASK_ENTER_WINDOW + XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_PROPERTY_CHANGE }; xcb_change_window_attributes(xcb_connection(), screen->root, mask, values); + + xcb_generic_error_t *error; + + xcb_get_property_reply_t *reply = + xcb_get_property_reply(xcb_connection(), + xcb_get_property(xcb_connection(), false, screen->root, + atom(QXcbAtom::_NET_SUPPORTING_WM_CHECK), + XCB_ATOM_WINDOW, 0, 1024), &error); + + if (reply && reply->format == 32 && reply->type == XCB_ATOM_WINDOW) { + xcb_window_t windowManager = *((xcb_window_t *)xcb_get_property_value(reply)); + + if (windowManager != XCB_WINDOW_NONE) { + xcb_get_property_reply_t *windowManagerReply = + xcb_get_property_reply(xcb_connection(), + xcb_get_property(xcb_connection(), false, windowManager, + atom(QXcbAtom::_NET_WM_NAME), + atom(QXcbAtom::UTF8_STRING), 0, 1024), &error); + if (windowManagerReply && windowManagerReply->format == 8 && windowManagerReply->type == atom(QXcbAtom::UTF8_STRING)) { + m_windowManagerName = QString::fromUtf8((const char *)xcb_get_property_value(windowManagerReply), xcb_get_property_value_length(windowManagerReply)); + printf("Running window manager: %s\n", qPrintable(m_windowManagerName)); + } else if (error) { + connection->handleXcbError(error); + free(error); + } + + free(windowManagerReply); + } + } else if (error) { + connection->handleXcbError(error); + free(error); + } + + free(reply); + + m_syncRequestSupported = m_windowManagerName != QLatin1String("KWin"); } QXcbScreen::~QXcbScreen() diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h index 6f69fc7..9547d01 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.h +++ b/src/plugins/platforms/xcb/qxcbscreen.h @@ -43,6 +43,7 @@ #define QXCBSCREEN_H #include <QtGui/QPlatformScreen> +#include <QtCore/QString> #include <xcb/xcb.h> @@ -66,9 +67,14 @@ public: xcb_screen_t *screen() const { return m_screen; } xcb_window_t root() const { return m_screen->root; } + QString windowManagerName() const { return m_windowManagerName; } + bool syncRequestSupported() const { return m_syncRequestSupported; } + private: xcb_screen_t *m_screen; int m_number; + QString m_windowManagerName; + bool m_syncRequestSupported; }; #endif diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index cbf50f7..0456638 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -41,6 +41,8 @@ #include "qxcbwindow.h" +#include <QtDebug> + #include "qxcbconnection.h" #include "qxcbscreen.h" #ifdef XCB_USE_DRI2 @@ -63,6 +65,7 @@ #if defined(XCB_USE_GLX) #include "qglxintegration.h" +#include "qglxconvenience.h" #elif defined(XCB_USE_EGL) #include "../eglconvenience/qeglplatformcontext.h" #include "../eglconvenience/qeglconvenience.h" @@ -110,13 +113,14 @@ QXcbWindow::QXcbWindow(QWidget *tlw) #if defined(XCB_USE_GLX) || defined(XCB_USE_EGL) if (tlw->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenGL - && QApplicationPrivate::platformIntegration()->hasOpenGL() ) { + && QApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)) + { #if defined(XCB_USE_GLX) - XVisualInfo *visualInfo = QGLXContext::findVisualInfo(m_screen, tlw->platformWindowFormat()); + XVisualInfo *visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(m_screen),m_screen->screenNumber(), tlw->platformWindowFormat()); #elif defined(XCB_USE_EGL) - EGLDisplay eglDisplay = eglGetDisplay(DISPLAY_FROM_XCB(this)); + EGLDisplay eglDisplay = connection()->egl_display(); EGLConfig eglConfig = q_configFromQPlatformWindowFormat(eglDisplay,tlw->platformWindowFormat(),true); - VisualID id = QXlibEglIntegration::getCompatibleVisualId(DISPLAY_FROM_XCB(this),eglConfig); + VisualID id = QXlibEglIntegration::getCompatibleVisualId(DISPLAY_FROM_XCB(this), eglDisplay, eglConfig); XVisualInfo visualInfoTemplate; memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); @@ -126,42 +130,42 @@ QXcbWindow::QXcbWindow(QWidget *tlw) int matchingCount = 0; visualInfo = XGetVisualInfo(DISPLAY_FROM_XCB(this), VisualIDMask, &visualInfoTemplate, &matchingCount); #endif //XCB_USE_GLX - if (visualInfo) { - Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(this), m_screen->root(), visualInfo->visual, AllocNone); - - XSetWindowAttributes a; - a.colormap = cmap; - m_window = XCreateWindow(DISPLAY_FROM_XCB(this), m_screen->root(), tlw->x(), tlw->y(), tlw->width(), tlw->height(), - 0, visualInfo->depth, InputOutput, visualInfo->visual, - CWColormap, &a); - - printf("created GL window: %d\n", m_window); - } else { - qFatal("no window!"); - } + if (visualInfo) { + Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(this), m_screen->root(), visualInfo->visual, AllocNone); + + XSetWindowAttributes a; + a.colormap = cmap; + m_window = XCreateWindow(DISPLAY_FROM_XCB(this), m_screen->root(), tlw->x(), tlw->y(), tlw->width(), tlw->height(), + 0, visualInfo->depth, InputOutput, visualInfo->visual, + CWColormap, &a); + + printf("created GL window: %d\n", m_window); + } else { + qFatal("no window!"); + } } else #endif //defined(XCB_USE_GLX) || defined(XCB_USE_EGL) { m_window = xcb_generate_id(xcb_connection()); - xcb_create_window(xcb_connection(), - XCB_COPY_FROM_PARENT, // depth -- same as root - m_window, // window id - m_screen->root(), // parent window id - tlw->x(), - tlw->y(), - tlw->width(), - tlw->height(), - 0, // border width - XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class - m_screen->screen()->root_visual, // visual - 0, // value mask - 0); // value list + Q_XCB_CALL(xcb_create_window(xcb_connection(), + XCB_COPY_FROM_PARENT, // depth -- same as root + m_window, // window id + m_screen->root(), // parent window id + tlw->x(), + tlw->y(), + tlw->width(), + tlw->height(), + 0, // border width + XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class + m_screen->screen()->root_visual, // visual + 0, // value mask + 0)); // value list printf("created regular window: %d\n", m_window); } - xcb_change_window_attributes(xcb_connection(), m_window, mask, values); + Q_XCB_CALL(xcb_change_window_attributes(xcb_connection(), m_window, mask, values)); xcb_atom_t properties[4]; int propertyCount = 0; @@ -169,32 +173,60 @@ QXcbWindow::QXcbWindow(QWidget *tlw) properties[propertyCount++] = atom(QXcbAtom::WM_TAKE_FOCUS); properties[propertyCount++] = atom(QXcbAtom::_NET_WM_PING); + if (m_screen->syncRequestSupported()) + properties[propertyCount++] = atom(QXcbAtom::_NET_WM_SYNC_REQUEST); + if (tlw->windowFlags() & Qt::WindowContextHelpButtonHint) properties[propertyCount++] = atom(QXcbAtom::_NET_WM_CONTEXT_HELP); - xcb_change_property(xcb_connection(), - XCB_PROP_MODE_REPLACE, - m_window, - atom(QXcbAtom::WM_PROTOCOLS), - 4, - 32, - propertyCount, - properties); + Q_XCB_CALL(xcb_change_property(xcb_connection(), + XCB_PROP_MODE_REPLACE, + m_window, + atom(QXcbAtom::WM_PROTOCOLS), + XCB_ATOM_ATOM, + 32, + propertyCount, + properties)); + m_syncValue.hi = 0; + m_syncValue.lo = 0; + + if (m_screen->syncRequestSupported()) { + m_syncCounter = xcb_generate_id(xcb_connection()); + Q_XCB_CALL(xcb_sync_create_counter(xcb_connection(), m_syncCounter, m_syncValue)); + + Q_XCB_CALL(xcb_change_property(xcb_connection(), + XCB_PROP_MODE_REPLACE, + m_window, + atom(QXcbAtom::_NET_WM_SYNC_REQUEST_COUNTER), + XCB_ATOM_CARDINAL, + 32, + 1, + &m_syncCounter)); + } if (isTransient(tlw) && tlw->parentWidget()) { // ICCCM 4.1.2.6 QWidget *p = tlw->parentWidget()->window(); xcb_window_t parentWindow = p->winId(); - xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, - XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32, - 1, &parentWindow); + Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, + XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32, + 1, &parentWindow)); } + + // set the PID to let the WM kill the application if unresponsive + long pid = getpid(); + Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, + atom(QXcbAtom::_NET_WM_PID), XCB_ATOM_CARDINAL, 32, + 1, &pid)); } QXcbWindow::~QXcbWindow() { - xcb_destroy_window(xcb_connection(), m_window); + delete m_context; + if (m_screen->syncRequestSupported()) + Q_XCB_CALL(xcb_sync_destroy_counter(xcb_connection(), m_syncCounter)); + Q_XCB_CALL(xcb_destroy_window(xcb_connection(), m_window)); } void QXcbWindow::setGeometry(const QRect &rect) @@ -204,7 +236,7 @@ void QXcbWindow::setGeometry(const QRect &rect) const quint32 mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT; const quint32 values[] = { rect.x(), rect.y(), rect.width(), rect.height() }; - xcb_configure_window(xcb_connection(), m_window, mask, values); + Q_XCB_CALL(xcb_configure_window(xcb_connection(), m_window, mask, values)); } void QXcbWindow::setVisible(bool visible) @@ -216,9 +248,10 @@ void QXcbWindow::setVisible(bool visible) else xcb_wm_hints_set_normal(&hints); xcb_set_wm_hints(xcb_connection(), m_window, &hints); - xcb_map_window(xcb_connection(), m_window); + Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window)); + connection()->sync(); } else { - xcb_unmap_window(xcb_connection(), m_window); + Q_XCB_CALL(xcb_unmap_window(xcb_connection(), m_window)); // send synthetic UnmapNotify event according to icccm 4.1.4 xcb_unmap_notify_event_t event; @@ -227,8 +260,8 @@ void QXcbWindow::setVisible(bool visible) event.event = m_screen->root(); event.window = m_window; event.from_configure = false; - xcb_send_event(xcb_connection(), false, m_screen->root(), - XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event); + Q_XCB_CALL(xcb_send_event(xcb_connection(), false, m_screen->root(), + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event)); xcb_flush(xcb_connection()); } @@ -271,6 +304,8 @@ Qt::WindowFlags QXcbWindow::setWindowFlags(Qt::WindowFlags flags) { Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask)); + setNetWmWindowTypes(flags); + if (type == Qt::ToolTip) flags |= Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint; if (type == Qt::Popup) @@ -352,28 +387,64 @@ Qt::WindowFlags QXcbWindow::setWindowFlags(Qt::WindowFlags flags) } if (mwmhints.flags != 0l) { - xcb_change_property(xcb_connection(), - XCB_PROP_MODE_REPLACE, - m_window, - atom(QXcbAtom::_MOTIF_WM_HINTS), - atom(QXcbAtom::_MOTIF_WM_HINTS), - 32, - 5, - &mwmhints); + Q_XCB_CALL(xcb_change_property(xcb_connection(), + XCB_PROP_MODE_REPLACE, + m_window, + atom(QXcbAtom::_MOTIF_WM_HINTS), + atom(QXcbAtom::_MOTIF_WM_HINTS), + 32, + 5, + &mwmhints)); } else { - xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_MOTIF_WM_HINTS)); + Q_XCB_CALL(xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_MOTIF_WM_HINTS))); } if (popup || tooltip) { const quint32 mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_SAVE_UNDER; const quint32 values[] = { true, true }; - xcb_change_window_attributes(xcb_connection(), m_window, mask, values); + Q_XCB_CALL(xcb_change_window_attributes(xcb_connection(), m_window, mask, values)); } return QPlatformWindow::setWindowFlags(flags); } +void QXcbWindow::setNetWmWindowTypes(Qt::WindowFlags flags) +{ + // in order of decreasing priority + QVector<uint> windowTypes; + + Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask)); + + switch (type) { + case Qt::Dialog: + case Qt::Sheet: + windowTypes.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DIALOG)); + break; + case Qt::Tool: + case Qt::Drawer: + windowTypes.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_UTILITY)); + break; + case Qt::ToolTip: + windowTypes.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_TOOLTIP)); + break; + case Qt::SplashScreen: + windowTypes.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_SPLASH)); + break; + default: + break; + } + + if (flags & Qt::FramelessWindowHint) + windowTypes.append(atom(QXcbAtom::_KDE_NET_WM_WINDOW_TYPE_OVERRIDE)); + + windowTypes.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_NORMAL)); + + Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, + atom(QXcbAtom::_NET_WM_WINDOW_TYPE), XCB_ATOM_ATOM, 32, + windowTypes.count(), windowTypes.constData())); +} + WId QXcbWindow::winId() const { return m_window; @@ -382,56 +453,54 @@ WId QXcbWindow::winId() const void QXcbWindow::setParent(const QPlatformWindow *parent) { QPoint topLeft = geometry().topLeft(); - xcb_reparent_window(xcb_connection(), window(), static_cast<const QXcbWindow *>(parent)->window(), topLeft.x(), topLeft.y()); + Q_XCB_CALL(xcb_reparent_window(xcb_connection(), window(), static_cast<const QXcbWindow *>(parent)->window(), topLeft.x(), topLeft.y())); } void QXcbWindow::setWindowTitle(const QString &title) { QByteArray ba = title.toUtf8(); - xcb_change_property (xcb_connection(), - XCB_PROP_MODE_REPLACE, - m_window, - atom(QXcbAtom::_NET_WM_NAME), - atom(QXcbAtom::UTF8_STRING), - 8, - ba.length(), - ba.constData()); + Q_XCB_CALL(xcb_change_property(xcb_connection(), + XCB_PROP_MODE_REPLACE, + m_window, + atom(QXcbAtom::_NET_WM_NAME), + atom(QXcbAtom::UTF8_STRING), + 8, + ba.length(), + ba.constData())); } void QXcbWindow::raise() { const quint32 mask = XCB_CONFIG_WINDOW_STACK_MODE; const quint32 values[] = { XCB_STACK_MODE_ABOVE }; - xcb_configure_window(xcb_connection(), m_window, mask, values); + Q_XCB_CALL(xcb_configure_window(xcb_connection(), m_window, mask, values)); } void QXcbWindow::lower() { const quint32 mask = XCB_CONFIG_WINDOW_STACK_MODE; const quint32 values[] = { XCB_STACK_MODE_BELOW }; - xcb_configure_window(xcb_connection(), m_window, mask, values); + Q_XCB_CALL(xcb_configure_window(xcb_connection(), m_window, mask, values)); } void QXcbWindow::requestActivateWindow() { - xcb_set_input_focus(xcb_connection(), m_window, XCB_INPUT_FOCUS_PARENT, XCB_TIME_CURRENT_TIME); + Q_XCB_CALL(xcb_set_input_focus(xcb_connection(), XCB_INPUT_FOCUS_PARENT, m_window, XCB_TIME_CURRENT_TIME)); + connection()->sync(); } QPlatformGLContext *QXcbWindow::glContext() const { - if (!QApplicationPrivate::platformIntegration()->hasOpenGL()) { + if (!QApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)) { printf("no opengl\n"); return 0; } -#if defined(XCB_USE_GLX) if (!m_context) { +#if defined(XCB_USE_GLX) QXcbWindow *that = const_cast<QXcbWindow *>(this); that->m_context = new QGLXContext(m_window, m_screen, widget()->platformWindowFormat()); - } #elif defined(XCB_USE_EGL) - if (!m_context) { - EGLDisplay display = eglGetDisplay(DISPLAY_FROM_XCB(this)); - + EGLDisplay display = connection()->egl_display(); EGLConfig config = q_configFromQPlatformWindowFormat(display,widget()->platformWindowFormat(),true); QVector<EGLint> eglContextAttrs; eglContextAttrs.append(EGL_CONTEXT_CLIENT_VERSION); @@ -441,14 +510,11 @@ QPlatformGLContext *QXcbWindow::glContext() const EGLSurface eglSurface = eglCreateWindowSurface(display,config,(EGLNativeWindowType)m_window,0); QXcbWindow *that = const_cast<QXcbWindow *>(this); that->m_context = new QEGLPlatformContext(display, config, eglContextAttrs.data(), eglSurface, EGL_OPENGL_ES_API); - } #elif defined(XCB_USE_DRI2) - if (!m_context) { QXcbWindow *that = const_cast<QXcbWindow *>(this); that->m_context = new QDri2Context(that); - } - #endif + } return m_context; } @@ -467,6 +533,21 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even if (event->format == 32 && event->type == atom(QXcbAtom::WM_PROTOCOLS)) { if (event->data.data32[0] == atom(QXcbAtom::WM_DELETE_WINDOW)) { QWindowSystemInterface::handleCloseEvent(widget()); + } else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_PING)) { + xcb_client_message_event_t reply = *event; + + reply.response_type = XCB_CLIENT_MESSAGE; + reply.window = m_screen->root(); + + xcb_send_event(xcb_connection(), 0, m_screen->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&reply); + xcb_flush(xcb_connection()); + } else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_SYNC_REQUEST)) { + if (!m_hasReceivedSyncRequest) { + m_hasReceivedSyncRequest = true; + printf("Window manager supports _NET_WM_SYNC_REQUEST, syncing resizes\n"); + } + m_syncValue.lo = event->data.data32[2]; + m_syncValue.hi = event->data.data32[3]; } } } @@ -482,8 +563,11 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * } QRect rect(xpos, ypos, event->width, event->height); - QPlatformWindow::setGeometry(rect); + if (rect == geometry()) + return; + + QPlatformWindow::setGeometry(rect); QWindowSystemInterface::handleGeometryChange(widget(), rect); #if XCB_USE_DRI2 @@ -586,3 +670,14 @@ void QXcbWindow::handleFocusOutEvent(const xcb_focus_out_event_t *) QWindowSystemInterface::handleWindowActivated(0); } +void QXcbWindow::updateSyncRequestCounter() +{ + if (m_screen->syncRequestSupported() && (m_syncValue.lo != 0 || m_syncValue.hi != 0)) { + Q_XCB_CALL(xcb_sync_set_counter(xcb_connection(), m_syncCounter, m_syncValue)); + xcb_flush(xcb_connection()); + connection()->sync(); + + m_syncValue.lo = 0; + m_syncValue.hi = 0; + } +} diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 1e9930d..e049837 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -46,6 +46,7 @@ #include <QtGui/QPlatformWindowFormat> #include <xcb/xcb.h> +#include <xcb/sync.h> #include "qxcbobject.h" @@ -88,11 +89,20 @@ public: void handleMouseEvent(xcb_button_t detail, uint16_t state, xcb_timestamp_t time, const QPoint &local, const QPoint &global); + void updateSyncRequestCounter(); + private: + void setNetWmWindowTypes(Qt::WindowFlags flags); + QXcbScreen *m_screen; xcb_window_t m_window; QPlatformGLContext *m_context; + + xcb_sync_int64_t m_syncValue; + xcb_sync_counter_t m_syncCounter; + + bool m_hasReceivedSyncRequest; }; #endif diff --git a/src/plugins/platforms/xcb/qxcbwindowsurface.cpp b/src/plugins/platforms/xcb/qxcbwindowsurface.cpp index 7fed230..718f093 100644 --- a/src/plugins/platforms/xcb/qxcbwindowsurface.cpp +++ b/src/plugins/platforms/xcb/qxcbwindowsurface.cpp @@ -53,6 +53,8 @@ #include <stdio.h> +#include <qdebug.h> + class QXcbShmImage : public QXcbObject { public: @@ -84,6 +86,7 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size) , m_gc(0) , m_gc_window(0) { + Q_XCB_NOOP(connection()); m_xcb_image = xcb_image_create_native(xcb_connection(), size.width(), size.height(), @@ -92,38 +95,49 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size) 0, ~0, 0); + m_shm_info.shmid = shmget (IPC_PRIVATE, m_xcb_image->stride * m_xcb_image->height, IPC_CREAT|0777); m_shm_info.shmaddr = m_xcb_image->data = (quint8 *)shmat (m_shm_info.shmid, 0, 0); m_shm_info.shmseg = xcb_generate_id(xcb_connection()); - xcb_shm_attach(xcb_connection(), m_shm_info.shmseg, m_shm_info.shmid, false); + xcb_generic_error_t *error = xcb_request_check(xcb_connection(), xcb_shm_attach_checked(xcb_connection(), m_shm_info.shmseg, m_shm_info.shmid, false)); + if (error) { + qWarning() << "QXcbWindowSurface: Unable to attach to shared memory segment"; + free(error); + } + + if (shmctl(m_shm_info.shmid, IPC_RMID, 0) == -1) + qWarning() << "QXcbWindowSurface: Error while marking the shared memory segment to be destroyed"; m_qimage = QImage( (uchar*) m_xcb_image->data, m_xcb_image->width, m_xcb_image->height, m_xcb_image->stride, screen->format()); } void QXcbShmImage::destroy() { - xcb_shm_detach(xcb_connection(), m_shm_info.shmseg); + Q_XCB_CALL(xcb_shm_detach(xcb_connection(), m_shm_info.shmseg)); xcb_image_destroy(m_xcb_image); shmdt(m_shm_info.shmaddr); shmctl(m_shm_info.shmid, IPC_RMID, 0); - - xcb_free_gc(xcb_connection(), m_gc); + if (m_gc) + Q_XCB_CALL(xcb_free_gc(xcb_connection(), m_gc)); } void QXcbShmImage::put(xcb_window_t window, const QPoint &target, const QRect &source) { + Q_XCB_NOOP(connection()); if (m_gc_window != window) { - xcb_free_gc(xcb_connection(), m_gc); + if (m_gc) + Q_XCB_CALL(xcb_free_gc(xcb_connection(), m_gc)); m_gc = xcb_generate_id(xcb_connection()); - xcb_create_gc(xcb_connection(), m_gc, window, 0, 0); + Q_XCB_CALL(xcb_create_gc(xcb_connection(), m_gc, window, 0, 0)); m_gc_window = window; } + Q_XCB_NOOP(connection()); xcb_image_shm_put(xcb_connection(), window, m_gc, @@ -136,18 +150,19 @@ void QXcbShmImage::put(xcb_window_t window, const QPoint &target, const QRect &s source.width(), source.height(), false); + Q_XCB_NOOP(connection()); m_dirty = m_dirty | source; xcb_flush(xcb_connection()); + Q_XCB_NOOP(connection()); } void QXcbShmImage::preparePaint(const QRegion ®ion) { // to prevent X from reading from the image region while we're writing to it if (m_dirty.intersects(region)) { - // from xcb_aux_sync - free(xcb_get_input_focus_reply(xcb_connection(), xcb_get_input_focus(xcb_connection()), 0)); + connection()->sync(); m_dirty = QRegion(); } } @@ -155,16 +170,15 @@ void QXcbShmImage::preparePaint(const QRegion ®ion) QXcbWindowSurface::QXcbWindowSurface(QWidget *widget, bool setDefaultSurface) : QWindowSurface(widget, setDefaultSurface) , m_image(0) + , m_syncingResize(false) { - setStaticContentsSupport(false); - setPartialUpdateSupport(true); - QXcbScreen *screen = static_cast<QXcbScreen *>(QPlatformScreen::platformScreenForWidget(widget)); setConnection(screen->connection()); } QXcbWindowSurface::~QXcbWindowSurface() { + delete m_image; } QPaintDevice *QXcbWindowSurface::paintDevice() @@ -177,10 +191,18 @@ void QXcbWindowSurface::beginPaint(const QRegion ®ion) m_image->preparePaint(region); } +void QXcbWindowSurface::endPaint(const QRegion &) +{ +} + void QXcbWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) { - Q_UNUSED(region); - Q_UNUSED(offset); + QRect bounds = region.boundingRect(); + + if (size().isEmpty() || !geometry().contains(bounds)) + return; + + Q_XCB_NOOP(connection()); QXcbWindow *window = static_cast<QXcbWindow *>(widget->window()->platformWindow()); @@ -190,16 +212,32 @@ void QXcbWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoi QVector<QRect> rects = region.rects(); for (int i = 0; i < rects.size(); ++i) m_image->put(window->window(), rects.at(i).topLeft() - widgetOffset, rects.at(i).translated(offset)); + + Q_XCB_NOOP(connection()); + + if (m_syncingResize) { + xcb_flush(xcb_connection()); + connection()->sync(); + m_syncingResize = false; + window->updateSyncRequestCounter(); + } } void QXcbWindowSurface::resize(const QSize &size) { + if (size == QWindowSurface::size()) + return; + + Q_XCB_NOOP(connection()); QWindowSurface::resize(size); QXcbScreen *screen = static_cast<QXcbScreen *>(QPlatformScreen::platformScreenForWidget(window())); delete m_image; m_image = new QXcbShmImage(screen, size); + Q_XCB_NOOP(connection()); + + m_syncingResize = true; } extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset); diff --git a/src/plugins/platforms/xcb/qxcbwindowsurface.h b/src/plugins/platforms/xcb/qxcbwindowsurface.h index 61689b1..23d32ef 100644 --- a/src/plugins/platforms/xcb/qxcbwindowsurface.h +++ b/src/plugins/platforms/xcb/qxcbwindowsurface.h @@ -62,9 +62,11 @@ public: bool scroll(const QRegion &area, int dx, int dy); void beginPaint(const QRegion &); + void endPaint(const QRegion &); private: QXcbShmImage *m_image; + bool m_syncingResize; }; #endif diff --git a/src/plugins/platforms/xcb/xcb.pro b/src/plugins/platforms/xcb/xcb.pro index fdbe2cd..101bdcd 100644 --- a/src/plugins/platforms/xcb/xcb.pro +++ b/src/plugins/platforms/xcb/xcb.pro @@ -55,13 +55,14 @@ contains(QT_CONFIG, opengl) { LIBS += -lEGL } else { DEFINES += XCB_USE_GLX + include (../glxconvenience/glxconvenience.pri) HEADERS += qglxintegration.h SOURCES += qglxintegration.cpp } } } -LIBS += -lxcb -lxcb-image -lxcb-keysyms -lxcb-icccm +LIBS += -lxcb -lxcb-image -lxcb-keysyms -lxcb-icccm -lxcb-sync include (../fontdatabases/genericunix/genericunix.pri) diff --git a/src/plugins/platforms/xlib/qglxintegration.cpp b/src/plugins/platforms/xlib/qglxintegration.cpp index 80011d9..7a0f36d 100644 --- a/src/plugins/platforms/xlib/qglxintegration.cpp +++ b/src/plugins/platforms/xlib/qglxintegration.cpp @@ -51,6 +51,7 @@ #include <X11/Xlib.h> #include <X11/Xutil.h> #include <GL/glx.h> +#include "qglxconvenience.h" #include "qglxintegration.h" @@ -60,184 +61,6 @@ QT_BEGIN_NAMESPACE -QMutex QGLXContext::m_defaultSharedContextMutex(QMutex::Recursive); - -QVector<int> QGLXContext::buildSpec(const QPlatformWindowFormat &format) -{ - QVector<int> spec(48); - int i = 0; - - spec[i++] = GLX_LEVEL; - spec[i++] = 0; - spec[i++] = GLX_DRAWABLE_TYPE; spec[i++] = GLX_WINDOW_BIT; - - if (format.rgba()) { - spec[i++] = GLX_RENDER_TYPE; spec[i++] = GLX_RGBA_BIT; - spec[i++] = GLX_RED_SIZE; spec[i++] = (format.redBufferSize() == -1) ? 1 : format.redBufferSize(); - spec[i++] = GLX_GREEN_SIZE; spec[i++] = (format.greenBufferSize() == -1) ? 1 : format.greenBufferSize(); - spec[i++] = GLX_BLUE_SIZE; spec[i++] = (format.blueBufferSize() == -1) ? 1 : format.blueBufferSize(); - if (format.alpha()) { - spec[i++] = GLX_ALPHA_SIZE; spec[i++] = (format.alphaBufferSize() == -1) ? 1 : format.alphaBufferSize(); - } - - spec[i++] = GLX_ACCUM_RED_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize(); - spec[i++] = GLX_ACCUM_GREEN_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize(); - spec[i++] = GLX_ACCUM_BLUE_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize(); - - if (format.alpha()) { - spec[i++] = GLX_ACCUM_ALPHA_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize(); - } - - } else { - spec[i++] = GLX_RENDER_TYPE; spec[i++] = GLX_COLOR_INDEX_BIT; //I'm really not sure if this works.... - spec[i++] = GLX_BUFFER_SIZE; spec[i++] = 8; - } - - spec[i++] = GLX_DOUBLEBUFFER; spec[i++] = format.doubleBuffer() ? True : False; - spec[i++] = GLX_STEREO; spec[i++] = format.stereo() ? True : False; - - if (format.depth()) { - spec[i++] = GLX_DEPTH_SIZE; spec[i++] = (format.depthBufferSize() == -1) ? 1 : format.depthBufferSize(); - } - - if (format.stencil()) { - spec[i++] = GLX_STENCIL_SIZE; spec[i++] = (format.stencilBufferSize() == -1) ? 1 : format.stencilBufferSize(); - } - if (format.sampleBuffers()) { - spec[i++] = GLX_SAMPLE_BUFFERS_ARB; - spec[i++] = 1; - spec[i++] = GLX_SAMPLES_ARB; - spec[i++] = format.samples() == -1 ? 4 : format.samples(); - } - - spec[i++] = XNone; - return spec; -} - -GLXFBConfig QGLXContext::findConfig(const QXlibScreen *screen, const QPlatformWindowFormat &format) -{ - bool reduced = true; - GLXFBConfig chosenConfig = 0; - QPlatformWindowFormat reducedFormat = format; - while (!chosenConfig && reduced) { - QVector<int> spec = buildSpec(reducedFormat); - int confcount = 0; - GLXFBConfig *configs; - configs = glXChooseFBConfig(screen->display()->nativeDisplay(),screen->xScreenNumber(),spec.constData(),&confcount); - if (confcount) - { - for (int i = 0; i < confcount; i++) { - chosenConfig = configs[i]; - // Make sure we try to get an ARGB visual if the format asked for an alpha: - if (reducedFormat.alpha()) { - int alphaSize; - glXGetFBConfigAttrib(screen->display()->nativeDisplay(),configs[i],GLX_ALPHA_SIZE,&alphaSize); - if (alphaSize > 0) - break; - } else { - break; // Just choose the first in the list if there's no alpha requested - } - } - - XFree(configs); - } - reducedFormat = reducePlatformWindowFormat(reducedFormat,&reduced); - } - - if (!chosenConfig) - qWarning("Warning no context created"); - - return chosenConfig; -} - -XVisualInfo *QGLXContext::findVisualInfo(const QXlibScreen *screen, const QPlatformWindowFormat &format) -{ - GLXFBConfig config = QGLXContext::findConfig(screen,format); - XVisualInfo *visualInfo = glXGetVisualFromFBConfig(screen->display()->nativeDisplay(),config); - return visualInfo; -} - -QPlatformWindowFormat QGLXContext::platformWindowFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext ctx) -{ - QPlatformWindowFormat format; - int redSize = 0; - int greenSize = 0; - int blueSize = 0; - int alphaSize = 0; - int depthSize = 0; - int stencilSize = 0; - int sampleBuffers = 0; - int sampleCount = 0; - int level = 0; - int rgba = 0; - int stereo = 0; - int accumSizeA = 0; - int accumSizeR = 0; - int accumSizeG = 0; - int accumSizeB = 0; - - XVisualInfo *vi = glXGetVisualFromFBConfig(display,config); - glXGetConfig(display,vi,GLX_RGBA,&rgba); - XFree(vi); - glXGetFBConfigAttrib(display, config, GLX_RED_SIZE, &redSize); - glXGetFBConfigAttrib(display, config, GLX_GREEN_SIZE, &greenSize); - glXGetFBConfigAttrib(display, config, GLX_BLUE_SIZE, &blueSize); - glXGetFBConfigAttrib(display, config, GLX_ALPHA_SIZE, &alphaSize); - glXGetFBConfigAttrib(display, config, GLX_DEPTH_SIZE, &depthSize); - glXGetFBConfigAttrib(display, config, GLX_STENCIL_SIZE, &stencilSize); - glXGetFBConfigAttrib(display, config, GLX_SAMPLES, &sampleBuffers); - glXGetFBConfigAttrib(display, config, GLX_LEVEL, &level); - glXGetFBConfigAttrib(display, config, GLX_STEREO, &stereo); - glXGetFBConfigAttrib(display, config, GLX_ACCUM_ALPHA_SIZE, &accumSizeA); - glXGetFBConfigAttrib(display, config, GLX_ACCUM_RED_SIZE, &accumSizeR); - glXGetFBConfigAttrib(display, config, GLX_ACCUM_GREEN_SIZE, &accumSizeG); - glXGetFBConfigAttrib(display, config, GLX_ACCUM_BLUE_SIZE, &accumSizeB); - - format.setRedBufferSize(redSize); - format.setGreenBufferSize(greenSize); - format.setBlueBufferSize(blueSize); - format.setAlphaBufferSize(alphaSize); - format.setDepthBufferSize(depthSize); - format.setStencilBufferSize(stencilSize); - format.setSampleBuffers(sampleBuffers); - if (format.sampleBuffers()) { - glXGetFBConfigAttrib(display, config, GLX_SAMPLES_ARB, &sampleCount); - format.setSamples(sampleCount); - } - - format.setDirectRendering(glXIsDirect(display, ctx)); - format.setRgba(rgba); - format.setStereo(stereo); - format.setAccumBufferSize(accumSizeB); - - return format; -} - -QPlatformWindowFormat QGLXContext::reducePlatformWindowFormat(const QPlatformWindowFormat &format, bool *reduced) -{ - QPlatformWindowFormat retFormat = format; - *reduced = true; - - if (retFormat.sampleBuffers()) { - retFormat.setSampleBuffers(false); - } else if (retFormat.stereo()) { - retFormat.setStereo(false); - } else if (retFormat.accum()) { - retFormat.setAccum(false); - }else if (retFormat.stencil()) { - retFormat.setStencil(false); - }else if (retFormat.alpha()) { - retFormat.setAlpha(false); - }else if (retFormat.depth()) { - retFormat.setDepth(false); - }else if (retFormat.doubleBuffer()) { - retFormat.setDoubleBuffer(false); - }else{ - *reduced = false; - } - return retFormat; -} - QGLXContext::QGLXContext(Window window, QXlibScreen *screen, const QPlatformWindowFormat &format) : QPlatformGLContext() , m_screen(screen) @@ -246,27 +69,14 @@ QGLXContext::QGLXContext(Window window, QXlibScreen *screen, const QPlatformWind { const QPlatformGLContext *sharePlatformContext; - if (format.useDefaultSharedContext()) { - if (!QPlatformGLContext::defaultSharedContext()) { - if (m_defaultSharedContextMutex.tryLock()){ - createDefaultSharedContex(screen); - m_defaultSharedContextMutex.unlock(); - } else { - m_defaultSharedContextMutex.lock(); //wait to the the shared context is created - m_defaultSharedContextMutex.unlock(); - } - } - sharePlatformContext = QPlatformGLContext::defaultSharedContext(); - } else { - sharePlatformContext = format.sharedGLContext(); - } + sharePlatformContext = format.sharedGLContext(); GLXContext shareGlxContext = 0; if (sharePlatformContext) shareGlxContext = static_cast<const QGLXContext*>(sharePlatformContext)->glxContext(); - GLXFBConfig config = findConfig(screen,format); + GLXFBConfig config = qglx_findConfig(screen->display()->nativeDisplay(),screen->xScreenNumber(),format); m_context = glXCreateNewContext(screen->display()->nativeDisplay(),config,GLX_RGBA_TYPE,shareGlxContext,TRUE); - m_windowFormat = QGLXContext::platformWindowFromGLXFBConfig(screen->display()->nativeDisplay(),config,m_context); + m_windowFormat = qglx_platformWindowFromGLXFBConfig(screen->display()->nativeDisplay(),config,m_context); #ifdef MYX11_DEBUG qDebug() << "QGLXGLContext::create context" << m_context; @@ -287,33 +97,6 @@ QGLXContext::~QGLXContext() } } -void QGLXContext::createDefaultSharedContex(QXlibScreen *screen) -{ - int x = 0; - int y = 0; - int w = 3; - int h = 3; - - QPlatformWindowFormat format = QPlatformWindowFormat::defaultFormat(); - GLXContext context; - GLXFBConfig config = findConfig(screen,format); - if (config) { - XVisualInfo *visualInfo = glXGetVisualFromFBConfig(screen->display()->nativeDisplay(),config); - Colormap cmap = XCreateColormap(screen->display()->nativeDisplay(),screen->rootWindow(),visualInfo->visual,AllocNone); - XSetWindowAttributes a; - a.colormap = cmap; - Window sharedWindow = XCreateWindow(screen->display()->nativeDisplay(), screen->rootWindow(),x, y, w, h, - 0, visualInfo->depth, InputOutput, visualInfo->visual, - CWColormap, &a); - - context = glXCreateNewContext(screen->display()->nativeDisplay(),config,GLX_RGBA_TYPE,0,TRUE); - QPlatformGLContext *sharedContext = new QGLXContext(screen,sharedWindow,context); - QPlatformGLContext::setDefaultSharedContext(sharedContext); - } else { - qWarning("Warning no shared context created"); - } -} - void QGLXContext::makeCurrent() { QPlatformGLContext::makeCurrent(); diff --git a/src/plugins/platforms/xlib/qglxintegration.h b/src/plugins/platforms/xlib/qglxintegration.h index dbb5c2e..57c716b 100644 --- a/src/plugins/platforms/xlib/qglxintegration.h +++ b/src/plugins/platforms/xlib/qglxintegration.h @@ -69,22 +69,13 @@ public: QPlatformWindowFormat platformWindowFormat() const; - static XVisualInfo *findVisualInfo(const QXlibScreen *xd, const QPlatformWindowFormat &format); private: - static GLXFBConfig findConfig(const QXlibScreen *xd,const QPlatformWindowFormat &format); - static QVector<int> buildSpec(const QPlatformWindowFormat &format); - static QPlatformWindowFormat platformWindowFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext context); - static QPlatformWindowFormat reducePlatformWindowFormat(const QPlatformWindowFormat &format, bool *reduced); - - QXlibScreen *m_screen; Drawable m_drawable; GLXContext m_context; QPlatformWindowFormat m_windowFormat; QGLXContext (QXlibScreen *screen, Drawable drawable, GLXContext context); - static QMutex m_defaultSharedContextMutex; - static void createDefaultSharedContex(QXlibScreen *xd); }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/xlib/qxlibintegration.cpp b/src/plugins/platforms/xlib/qxlibintegration.cpp index 6733ed1..78f907a 100644 --- a/src/plugins/platforms/xlib/qxlibintegration.cpp +++ b/src/plugins/platforms/xlib/qxlibintegration.cpp @@ -49,6 +49,7 @@ #include "qxlibscreen.h" #include "qxlibclipboard.h" #include "qxlibdisplay.h" +#include "qxlibnativeinterface.h" #if !defined(QT_NO_OPENGL) #if !defined(QT_OPENGL_ES_2) @@ -66,11 +67,21 @@ QXlibIntegration::QXlibIntegration(bool useOpenGL) : mUseOpenGL(useOpenGL) , mFontDb(new QGenericUnixFontDatabase()) , mClipboard(0) + , mNativeInterface(new QXlibNativeInterface) { mPrimaryScreen = new QXlibScreen(); mScreens.append(mPrimaryScreen); } +bool QXlibIntegration::hasCapability(QPlatformIntegration::Capability cap) const +{ + switch (cap) { + case ThreadedPixmaps: return true; + case OpenGL: return hasOpenGL(); + default: return QPlatformIntegration::hasCapability(cap); + } +} + QPixmapData *QXlibIntegration::createPixmapData(QPixmapData::PixelType type) const { #ifndef QT_NO_OPENGL @@ -130,6 +141,11 @@ QPlatformClipboard * QXlibIntegration::clipboard() const return mClipboard; } +QPlatformNativeInterface * QXlibIntegration::nativeInterface() const +{ + return mNativeInterface; +} + bool QXlibIntegration::hasOpenGL() const { #if !defined(QT_NO_OPENGL) @@ -141,11 +157,12 @@ bool QXlibIntegration::hasOpenGL() const static bool wasEglInitialized = false; if (!eglHasbeenInitialized) { eglHasbeenInitialized = true; - const QXlibScreen *screen = static_cast<const QXlibScreen *>(mScreens.at(0)); + QXlibScreen *screen = static_cast<QXlibScreen *>(mScreens.at(0)); EGLint major, minor; eglBindAPI(EGL_OPENGL_ES_API); EGLDisplay disp = eglGetDisplay(screen->display()->nativeDisplay()); wasEglInitialized = eglInitialize(disp,&major,&minor); + screen->setEglDisplay(disp); } return wasEglInitialized; #endif @@ -153,5 +170,4 @@ bool QXlibIntegration::hasOpenGL() const return false; } - QT_END_NAMESPACE diff --git a/src/plugins/platforms/xlib/qxlibintegration.h b/src/plugins/platforms/xlib/qxlibintegration.h index 3bbf897..1a2515a 100644 --- a/src/plugins/platforms/xlib/qxlibintegration.h +++ b/src/plugins/platforms/xlib/qxlibintegration.h @@ -47,6 +47,7 @@ #include <QtGui/QPlatformIntegration> #include <QtGui/QPlatformScreen> +#include <QtGui/QPlatformNativeInterface> #include "qxlibstatic.h" @@ -59,6 +60,7 @@ class QXlibIntegration : public QPlatformIntegration public: QXlibIntegration(bool useOpenGL = false); + bool hasCapability(Capability cap) const; QPixmapData *createPixmapData(QPixmapData::PixelType type) const; QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId) const; QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; @@ -70,14 +72,17 @@ public: QPlatformFontDatabase *fontDatabase() const; QPlatformClipboard *clipboard() const; - bool hasOpenGL() const; + QPlatformNativeInterface *nativeInterface() const; private: + bool hasOpenGL() const; + bool mUseOpenGL; QXlibScreen *mPrimaryScreen; QList<QPlatformScreen *> mScreens; QPlatformFontDatabase *mFontDb; QPlatformClipboard *mClipboard; + QPlatformNativeInterface *mNativeInterface; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/xlib/qxlibnativeinterface.cpp b/src/plugins/platforms/xlib/qxlibnativeinterface.cpp new file mode 100644 index 0000000..4e950ff --- /dev/null +++ b/src/plugins/platforms/xlib/qxlibnativeinterface.cpp @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 "qxlibnativeinterface.h" + +#include "qxlibdisplay.h" +#include <QtGui/private/qapplication_p.h> + +class QXlibResourceMap : public QMap<QByteArray, QXlibNativeInterface::ResourceType> +{ +public: + QXlibResourceMap() + :QMap<QByteArray, QXlibNativeInterface::ResourceType>() + { + insert("display",QXlibNativeInterface::Display); + insert("egldisplay",QXlibNativeInterface::EglDisplay); + insert("connection",QXlibNativeInterface::Connection); + insert("screen",QXlibNativeInterface::Screen); + insert("graphicsdevice",QXlibNativeInterface::GraphicsDevice); + insert("eglcontext",QXlibNativeInterface::EglContext); + } +}; + +Q_GLOBAL_STATIC(QXlibResourceMap, qXlibResourceMap) + + +void * QXlibNativeInterface::nativeResourceForWidget(const QByteArray &resourceString, QWidget *widget) +{ + QByteArray lowerCaseResource = resourceString.toLower(); + ResourceType resource = qXlibResourceMap()->value(lowerCaseResource); + void *result = 0; + switch(resource) { + case Display: + result = displayForWidget(widget); + break; + case EglDisplay: + result = eglDisplayForWidget(widget); + break; + case Connection: + result = connectionForWidget(widget); + break; + case Screen: + result = reinterpret_cast<void *>(qPlatformScreenForWidget(widget)->xScreenNumber()); + break; + case GraphicsDevice: + result = graphicsDeviceForWidget(widget); + break; + case EglContext: + result = eglContextForWidget(widget); + break; + default: + result = 0; + } + return result; +} + +void * QXlibNativeInterface::displayForWidget(QWidget *widget) +{ + return qPlatformScreenForWidget(widget)->display()->nativeDisplay(); +} + +void * QXlibNativeInterface::eglDisplayForWidget(QWidget *widget) +{ + Q_UNUSED(widget); + return 0; +} + +void * QXlibNativeInterface::screenForWidget(QWidget *widget) +{ + Q_UNUSED(widget); + return 0; +} + +void * QXlibNativeInterface::graphicsDeviceForWidget(QWidget *widget) +{ + Q_UNUSED(widget); + return 0; +} + +void * QXlibNativeInterface::eglContextForWidget(QWidget *widget) +{ + Q_UNUSED(widget); + return 0; +} + +QXlibScreen * QXlibNativeInterface::qPlatformScreenForWidget(QWidget *widget) +{ + QXlibScreen *screen; + if (widget) { + screen = static_cast<QXlibScreen *>(QPlatformScreen::platformScreenForWidget(widget)); + }else { + screen = static_cast<QXlibScreen *>(QApplicationPrivate::platformIntegration()->screens()[0]); + } + return screen; +} diff --git a/src/plugins/platforms/xlib/qxlibnativeinterface.h b/src/plugins/platforms/xlib/qxlibnativeinterface.h new file mode 100644 index 0000000..5ba0768 --- /dev/null +++ b/src/plugins/platforms/xlib/qxlibnativeinterface.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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$ +** +****************************************************************************/ + +#ifndef QXLIBNATIVEINTERFACE_H +#define QXLIBNATIVEINTERFACE_H + +#include "qxlibscreen.h" + +#include <QtGui/QPlatformNativeInterface> + +class QXlibNativeInterface : public QPlatformNativeInterface +{ +public: + enum ResourceType { + Display, + EglDisplay, + Connection, + Screen, + GraphicsDevice, + EglContext + }; + + void *nativeResourceForWidget(const QByteArray &resourceString, QWidget *widget); + + void *displayForWidget(QWidget *widget); + void *eglDisplayForWidget(QWidget *widget); + void *connectionForWidget(QWidget *widget); + void *screenForWidget(QWidget *widget); + void *graphicsDeviceForWidget(QWidget *widget); + void *eglContextForWidget(QWidget *widget); + +private: + static QXlibScreen *qPlatformScreenForWidget(QWidget *widget); +}; + + +#endif // QXLIBNATIVEINTERFACE_H diff --git a/src/plugins/platforms/xlib/qxlibscreen.cpp b/src/plugins/platforms/xlib/qxlibscreen.cpp index 23a2d07..7c8a367 100644 --- a/src/plugins/platforms/xlib/qxlibscreen.cpp +++ b/src/plugins/platforms/xlib/qxlibscreen.cpp @@ -191,6 +191,9 @@ qDebug() << "qt_x_errhandler" << err->error_code; QXlibScreen::QXlibScreen() : mFormat(QImage::Format_RGB32) +#if !defined(QT_NO_OPENGL) && defined(QT_OPENGL_ES_2) + , mEGLDisplay(0) +#endif { char *display_name = getenv("DISPLAY"); Display *display = XOpenDisplay(display_name); @@ -467,7 +470,7 @@ int QXlibScreen::xScreenNumber() const Visual * QXlibScreen::defaultVisual() const { - DefaultVisual(display()->nativeDisplay(), xScreenNumber()); + return DefaultVisual(display()->nativeDisplay(), xScreenNumber()); } QXlibKeyboard * QXlibScreen::keyboard() const diff --git a/src/plugins/platforms/xlib/qxlibscreen.h b/src/plugins/platforms/xlib/qxlibscreen.h index 35c0141..8c04c0f 100644 --- a/src/plugins/platforms/xlib/qxlibscreen.h +++ b/src/plugins/platforms/xlib/qxlibscreen.h @@ -82,6 +82,11 @@ public: QXlibKeyboard *keyboard() const; +#if !defined(QT_NO_OPENGL) && defined(QT_OPENGL_ES_2) + void *eglDisplay() const { return mEGLDisplay; } + void setEglDisplay(void *display) { mEGLDisplay = display; } +#endif + public slots: void eventDispatcher(); @@ -96,6 +101,9 @@ private: QXlibKeyboard *mKeyboard; QXlibDisplay * mDisplay; +#if !defined(QT_NO_OPENGL) && defined(QT_OPENGL_ES_2) + void *mEGLDisplay; +#endif int mScreen; }; diff --git a/src/plugins/platforms/xlib/qxlibwindow.cpp b/src/plugins/platforms/xlib/qxlibwindow.cpp index a7bc53c..9a05fc6 100644 --- a/src/plugins/platforms/xlib/qxlibwindow.cpp +++ b/src/plugins/platforms/xlib/qxlibwindow.cpp @@ -58,6 +58,7 @@ #if !defined(QT_NO_OPENGL) #if !defined(QT_OPENGL_ES_2) #include "qglxintegration.h" +#include "qglxconvenience.h" #else #include "../eglconvenience/qeglconvenience.h" #include "../eglconvenience/qeglplatformcontext.h" @@ -80,16 +81,16 @@ QXlibWindow::QXlibWindow(QWidget *window) int h = window->height(); if(window->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenGL - && QApplicationPrivate::platformIntegration()->hasOpenGL() ) { + && QApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL) ) { #if !defined(QT_NO_OPENGL) #if !defined(QT_OPENGL_ES_2) - XVisualInfo *visualInfo = QGLXContext::findVisualInfo(mScreen,window->platformWindowFormat()); + XVisualInfo *visualInfo = qglx_findVisualInfo(mScreen->display()->nativeDisplay(),mScreen->xScreenNumber(),window->platformWindowFormat()); #else QPlatformWindowFormat windowFormat = correctColorBuffers(window->platformWindowFormat()); - EGLDisplay eglDisplay = eglGetDisplay(mScreen->display()->nativeDisplay()); + EGLDisplay eglDisplay = mScreen->eglDisplay(); EGLConfig eglConfig = q_configFromQPlatformWindowFormat(eglDisplay,windowFormat); - VisualID id = QXlibEglIntegration::getCompatibleVisualId(mScreen->display()->nativeDisplay(),eglConfig); + VisualID id = QXlibEglIntegration::getCompatibleVisualId(mScreen->display()->nativeDisplay(), eglDisplay, eglConfig); XVisualInfo visualInfoTemplate; memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); @@ -136,7 +137,7 @@ QXlibWindow::QXlibWindow(QWidget *window) int n = 0; protocols[n++] = QXlibStatic::atom(QXlibStatic::WM_DELETE_WINDOW); // support del window protocol protocols[n++] = QXlibStatic::atom(QXlibStatic::WM_TAKE_FOCUS); // support take focus window protocol - protocols[n++] = QXlibStatic::atom(QXlibStatic::_NET_WM_PING); // support _NET_WM_PING protocol +// protocols[n++] = QXlibStatic::atom(QXlibStatic::_NET_WM_PING); // support _NET_WM_PING protocol #ifndef QT_NO_XSYNC protocols[n++] = QXlibStatic::atom(QXlibStatic::_NET_WM_SYNC_REQUEST); // support _NET_WM_SYNC_REQUEST protocol #endif // QT_NO_XSYNC @@ -655,7 +656,7 @@ void QXlibWindow::setCursor(const Cursor &cursor) QPlatformGLContext *QXlibWindow::glContext() const { - if (!QApplicationPrivate::platformIntegration()->hasOpenGL()) + if (!QApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)) return 0; if (!mGLContext) { QXlibWindow *that = const_cast<QXlibWindow *>(this); @@ -663,7 +664,7 @@ QPlatformGLContext *QXlibWindow::glContext() const #if !defined(QT_OPENGL_ES_2) that->mGLContext = new QGLXContext(x_window, mScreen,widget()->platformWindowFormat()); #else - EGLDisplay display = eglGetDisplay(mScreen->display()->nativeDisplay()); + EGLDisplay display = mScreen->eglDisplay(); QPlatformWindowFormat windowFormat = correctColorBuffers(widget()->platformWindowFormat()); diff --git a/src/plugins/platforms/xlib/xlib.pro b/src/plugins/platforms/xlib/xlib.pro index 159fdbe..ea77a29 100644 --- a/src/plugins/platforms/xlib/xlib.pro +++ b/src/plugins/platforms/xlib/xlib.pro @@ -14,7 +14,8 @@ SOURCES = \ qxlibclipboard.cpp \ qxlibmime.cpp \ qxlibstatic.cpp \ - qxlibdisplay.cpp + qxlibdisplay.cpp \ + qxlibnativeinterface.cpp HEADERS = \ qxlibintegration.h \ @@ -26,7 +27,8 @@ HEADERS = \ qxlibclipboard.h \ qxlibmime.h \ qxlibstatic.h \ - qxlibdisplay.h + qxlibdisplay.h \ + qxlibnativeinterface.h LIBS += -lX11 -lXext @@ -39,6 +41,7 @@ include (../fontdatabases/genericunix/genericunix.pri) contains(QT_CONFIG, opengl) { QT += opengl !contains(QT_CONFIG, opengles2) { + include (../glxconvenience/glxconvenience.pri) HEADERS += qglxintegration.h SOURCES += qglxintegration.cpp } else { # There is no easy way to detect if we'r suppose to use glx or not |