diff options
7 files changed, 75 insertions, 17 deletions
diff --git a/src/platformsupport/platformcompositor/qopenglcompositor.cpp b/src/platformsupport/platformcompositor/qopenglcompositor.cpp index 610619a4e4..0f4946f81a 100644 --- a/src/platformsupport/platformcompositor/qopenglcompositor.cpp +++ b/src/platformsupport/platformcompositor/qopenglcompositor.cpp @@ -40,7 +40,6 @@ #include <QtGui/QOpenGLContext> #include <QtGui/QOpenGLFramebufferObject> #include <QtGui/QWindow> -#include <QtGui/QMatrix4x4> #include <qpa/qplatformbackingstore.h> #include "qopenglcompositor_p.h" @@ -78,7 +77,8 @@ static QOpenGLCompositor *compositor = 0; QOpenGLCompositor::QOpenGLCompositor() : m_context(0), - m_targetWindow(0) + m_targetWindow(0), + m_rotation(0) { Q_ASSERT(!compositor); m_updateTimer.setSingleShot(true); @@ -93,10 +93,19 @@ QOpenGLCompositor::~QOpenGLCompositor() compositor = 0; } -void QOpenGLCompositor::setTarget(QOpenGLContext *context, QWindow *targetWindow) +void QOpenGLCompositor::setTarget(QOpenGLContext *context, QWindow *targetWindow, + const QRect &nativeTargetGeometry) { m_context = context; m_targetWindow = targetWindow; + m_nativeTargetGeometry = nativeTargetGeometry; +} + +void QOpenGLCompositor::setRotation(int degrees) +{ + m_rotation = degrees; + m_rotationMatrix.setToIdentity(); + m_rotationMatrix.rotate(degrees, 0, 0, 1); } void QOpenGLCompositor::update() @@ -109,7 +118,7 @@ QImage QOpenGLCompositor::grab() { Q_ASSERT(m_context && m_targetWindow); m_context->makeCurrent(m_targetWindow); - QScopedPointer<QOpenGLFramebufferObject> fbo(new QOpenGLFramebufferObject(m_targetWindow->geometry().size())); + QScopedPointer<QOpenGLFramebufferObject> fbo(new QOpenGLFramebufferObject(m_nativeTargetGeometry.size())); renderAll(fbo.data()); return fbo->toImage(); } @@ -127,9 +136,7 @@ void QOpenGLCompositor::renderAll(QOpenGLFramebufferObject *fbo) fbo->bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - - const QRect targetWindowRect(QPoint(0, 0), m_targetWindow->geometry().size()); - glViewport(0, 0, targetWindowRect.width(), targetWindowRect.height()); + glViewport(0, 0, m_nativeTargetGeometry.width(), m_nativeTargetGeometry.height()); if (!m_blitter.isCreated()) m_blitter.create(); @@ -181,7 +188,8 @@ static inline QRect toBottomLeftRect(const QRect &topLeftRect, int windowHeight) topLeftRect.width(), topLeftRect.height()); } -static void clippedBlit(const QPlatformTextureList *textures, int idx, const QRect &targetWindowRect, QOpenGLTextureBlitter *blitter) +static void clippedBlit(const QPlatformTextureList *textures, int idx, const QRect &targetWindowRect, + QOpenGLTextureBlitter *blitter, QMatrix4x4 *rotationMatrix) { const QRect clipRect = textures->clipRect(idx); if (clipRect.isEmpty()) @@ -191,7 +199,10 @@ static void clippedBlit(const QPlatformTextureList *textures, int idx, const QRe const QRect clippedRectInWindow = rectInWindow & clipRect.translated(rectInWindow.topLeft()); const QRect srcRect = toBottomLeftRect(clipRect, rectInWindow.height()); - const QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(clippedRectInWindow, targetWindowRect); + QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(clippedRectInWindow, targetWindowRect); + if (rotationMatrix) + target = *rotationMatrix * target; + const QMatrix3x3 source = QOpenGLTextureBlitter::sourceTransform(srcRect, rectInWindow.size(), QOpenGLTextureBlitter::OriginBottomLeft); @@ -219,25 +230,29 @@ void QOpenGLCompositor::render(QOpenGLCompositorWindow *window) if (textures->count() > 1 && i == textures->count() - 1) { // Backingstore for a widget with QOpenGLWidget subwidgets blend.set(true); - const QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), targetWindowRect); + QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), targetWindowRect); + if (m_rotation) + target = m_rotationMatrix * target; m_blitter.blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft); } else if (textures->count() == 1) { // A regular QWidget window const bool translucent = window->sourceWindow()->requestedFormat().alphaBufferSize() > 0; blend.set(translucent); - const QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), targetWindowRect); + QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), targetWindowRect); + if (m_rotation) + target = m_rotationMatrix * target; m_blitter.blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft); } else if (!textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) { // Texture from an FBO belonging to a QOpenGLWidget blend.set(false); - clippedBlit(textures, i, targetWindowRect, &m_blitter); + clippedBlit(textures, i, targetWindowRect, &m_blitter, m_rotation ? &m_rotationMatrix : nullptr); } } for (int i = 0; i < textures->count(); ++i) { if (textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) { blend.set(true); - clippedBlit(textures, i, targetWindowRect, &m_blitter); + clippedBlit(textures, i, targetWindowRect, &m_blitter, m_rotation ? &m_rotationMatrix : nullptr); } } diff --git a/src/platformsupport/platformcompositor/qopenglcompositor_p.h b/src/platformsupport/platformcompositor/qopenglcompositor_p.h index 90651b807f..dece41f676 100644 --- a/src/platformsupport/platformcompositor/qopenglcompositor_p.h +++ b/src/platformsupport/platformcompositor/qopenglcompositor_p.h @@ -53,6 +53,7 @@ #include <QtCore/QTimer> #include <QtGui/QOpenGLTextureBlitter> +#include <QtGui/QMatrix4x4> QT_BEGIN_NAMESPACE @@ -78,7 +79,8 @@ public: static QOpenGLCompositor *instance(); static void destroy(); - void setTarget(QOpenGLContext *context, QWindow *window); + void setTarget(QOpenGLContext *context, QWindow *window, const QRect &nativeTargetGeometry); + void setRotation(int degrees); QOpenGLContext *context() const { return m_context; } QWindow *targetWindow() const { return m_targetWindow; } @@ -106,6 +108,9 @@ private: QOpenGLContext *m_context; QWindow *m_targetWindow; + QRect m_nativeTargetGeometry; + int m_rotation; + QMatrix4x4 m_rotationMatrix; QTimer m_updateTimer; QOpenGLTextureBlitter m_blitter; QList<QOpenGLCompositorWindow *> m_windows; diff --git a/src/plugins/platforms/eglfs/api/qeglfscursor.cpp b/src/plugins/platforms/eglfs/api/qeglfscursor.cpp index ffee21a9b0..7c1f11372a 100644 --- a/src/plugins/platforms/eglfs/api/qeglfscursor.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfscursor.cpp @@ -72,6 +72,10 @@ QEglFSCursor::QEglFSCursor(QPlatformScreen *screen) if (!m_visible) return; + int rotation = qEnvironmentVariableIntValue("QT_QPA_EGLFS_ROTATION"); + if (rotation) + m_rotationMatrix.rotate(rotation, 0, 0, 1); + // Try to load the cursor atlas. If this fails, m_visible is set to false and // paintOnScreen() and setCurrentCursor() become no-ops. initCursorAtlas(); @@ -129,9 +133,10 @@ void QEglFSCursor::createShaderPrograms() "attribute highp vec2 vertexCoordEntry;\n" "attribute highp vec2 textureCoordEntry;\n" "varying highp vec2 textureCoord;\n" + "uniform highp mat4 mat;\n" "void main() {\n" " textureCoord = textureCoordEntry;\n" - " gl_Position = vec4(vertexCoordEntry, 1.0, 1.0);\n" + " gl_Position = mat * vec4(vertexCoordEntry, 1.0, 1.0);\n" "}\n"; static const char *textureFragmentProgram = @@ -149,6 +154,7 @@ void QEglFSCursor::createShaderPrograms() m_program->link(); m_textureEntry = m_program->uniformLocation("texture"); + m_matEntry = m_program->uniformLocation("mat"); } void QEglFSCursor::createCursorTexture(uint *texture, const QImage &image) @@ -492,6 +498,7 @@ void QEglFSCursor::draw(const QRectF &r) m_program->setAttributeArray(1, textureCoordinates, 2); m_program->setUniformValue(m_textureEntry, 0); + m_program->setUniformValue(m_matEntry, m_rotationMatrix); glDisable(GL_CULL_FACE); glFrontFace(GL_CCW); diff --git a/src/plugins/platforms/eglfs/api/qeglfscursor_p.h b/src/plugins/platforms/eglfs/api/qeglfscursor_p.h index bb30d53d6c..f72e4c0374 100644 --- a/src/plugins/platforms/eglfs/api/qeglfscursor_p.h +++ b/src/plugins/platforms/eglfs/api/qeglfscursor_p.h @@ -54,6 +54,7 @@ #include "qeglfsglobal.h" #include <qpa/qplatformcursor.h> #include <qpa/qplatformscreen.h> +#include <QtGui/QMatrix4x4> #include <QtGui/QOpenGLFunctions> #include <QtGui/private/qinputdevicemanager_p.h> @@ -138,8 +139,10 @@ private: QEglFSScreen *m_screen; QOpenGLShaderProgram *m_program; int m_textureEntry; + int m_matEntry; QEglFSCursorDeviceListener *m_deviceListener; bool m_updateRequested; + QMatrix4x4 m_rotationMatrix; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/api/qeglfsscreen.cpp b/src/plugins/platforms/eglfs/api/qeglfsscreen.cpp index d636a783ec..47ef2f64e7 100644 --- a/src/plugins/platforms/eglfs/api/qeglfsscreen.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfsscreen.cpp @@ -65,6 +65,31 @@ QEglFSScreen::~QEglFSScreen() QRect QEglFSScreen::geometry() const { + QRect r = geometryForSurface(); + + static int rotation = qEnvironmentVariableIntValue("QT_QPA_EGLFS_ROTATION"); + switch (rotation) { + case 0: + case 180: + case -180: + break; + case 90: + case -90: { + int h = r.height(); + r.setHeight(r.width()); + r.setWidth(h); + break; + } + default: + qWarning("Invalid rotation %d specified in QT_QPA_EGLFS_ROTATION", rotation); + break; + } + + return r; +} + +QRect QEglFSScreen::geometryForSurface() const +{ return QRect(QPoint(0, 0), qt_egl_device_integration()->screenSize()); } diff --git a/src/plugins/platforms/eglfs/api/qeglfsscreen_p.h b/src/plugins/platforms/eglfs/api/qeglfsscreen_p.h index 092d853ffd..232525fae3 100644 --- a/src/plugins/platforms/eglfs/api/qeglfsscreen_p.h +++ b/src/plugins/platforms/eglfs/api/qeglfsscreen_p.h @@ -68,6 +68,7 @@ public: ~QEglFSScreen(); QRect geometry() const Q_DECL_OVERRIDE; + QRect geometryForSurface() const; int depth() const Q_DECL_OVERRIDE; QImage::Format format() const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/eglfs/api/qeglfswindow.cpp b/src/plugins/platforms/eglfs/api/qeglfswindow.cpp index f602c1b976..74723955c6 100644 --- a/src/plugins/platforms/eglfs/api/qeglfswindow.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfswindow.cpp @@ -142,7 +142,8 @@ void QEglFSWindow::create() context->setScreen(window()->screen()); if (Q_UNLIKELY(!context->create())) qFatal("EGLFS: Failed to create compositing context"); - compositor->setTarget(context, window()); + compositor->setTarget(context, window(), screen->geometryForSurface()); + compositor->setRotation(qEnvironmentVariableIntValue("QT_QPA_EGLFS_ROTATION")); // If there is a "root" window into which raster and QOpenGLWidget content is // composited, all other contexts must share with its context. if (!qt_gl_global_share_context()) { @@ -189,7 +190,8 @@ void QEglFSWindow::resetSurface() m_config = QEglFSDeviceIntegration::chooseConfig(display, platformFormat); m_format = q_glFormatFromConfig(display, m_config, platformFormat); - m_window = qt_egl_device_integration()->createNativeWindow(this, screen()->geometry().size(), m_format); + const QSize surfaceSize = screen()->geometryForSurface().size(); + m_window = qt_egl_device_integration()->createNativeWindow(this, surfaceSize, m_format); m_surface = eglCreateWindowSurface(display, m_config, m_window, NULL); } |