diff options
Diffstat (limited to 'src/plugins/platforms/eglconvenience')
8 files changed, 863 insertions, 0 deletions
diff --git a/src/plugins/platforms/eglconvenience/eglconvenience.pri b/src/plugins/platforms/eglconvenience/eglconvenience.pri new file mode 100644 index 0000000000..322d4e4633 --- /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 new file mode 100644 index 0000000000..df7abc1401 --- /dev/null +++ b/src/plugins/platforms/eglconvenience/qeglconvenience.cpp @@ -0,0 +1,324 @@ +/**************************************************************************** +** +** 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 "qeglconvenience.h" + +QT_BEGIN_NAMESPACE + +QVector<EGLint> q_createConfigAttributesFromFormat(const QPlatformWindowFormat &format) +{ + int redSize = format.redBufferSize(); + int greenSize = format.greenBufferSize(); + int blueSize = format.blueBufferSize(); + int alphaSize = format.alphaBufferSize(); + int depthSize = format.depthBufferSize(); + int stencilSize = format.stencilBufferSize(); + int sampleCount = format.samples(); + + // QPlatformWindowFormat uses a magic value of -1 to indicate "don't care", even when a buffer of that + // type has been requested. So we must check QPlatformWindowFormat's booleans too if size is -1: + if (format.alpha() && alphaSize <= 0) + alphaSize = 1; + if (format.depth() && depthSize <= 0) + depthSize = 1; + if (format.stencil() && stencilSize <= 0) + stencilSize = 1; + if (format.sampleBuffers() && sampleCount <= 0) + sampleCount = 1; + + // We want to make sure 16-bit configs are chosen over 32-bit configs as they will provide + // the best performance. The EGL config selection algorithm is a bit stange in this regard: + // The selection criteria for EGL_BUFFER_SIZE is "AtLeast", so we can't use it to discard + // 32-bit configs completely from the selection. So it then comes to the sorting algorithm. + // The red/green/blue sizes have a sort priority of 3, so they are sorted by first. The sort + // order is special and described as "by larger _total_ number of color bits.". So EGL will + // put 32-bit configs in the list before the 16-bit configs. However, the spec also goes on + // to say "If the requested number of bits in attrib_list for a particular component is 0, + // then the number of bits for that component is not considered". This part of the spec also + // seems to imply that setting the red/green/blue bits to zero means none of the components + // are considered and EGL disregards the entire sorting rule. It then looks to the next + // highest priority rule, which is EGL_BUFFER_SIZE. Despite the selection criteria being + // "AtLeast" for EGL_BUFFER_SIZE, it's sort order is "smaller" meaning 16-bit configs are + // put in the list before 32-bit configs. So, to make sure 16-bit is preffered over 32-bit, + // we must set the red/green/blue sizes to zero. This has an unfortunate consequence that + // if the application sets the red/green/blue size to 5/6/5 on the QPlatformWindowFormat, + // they will probably get a 32-bit config, even when there's an RGB565 config available. + + // Now normalize the values so -1 becomes 0 + redSize = redSize > 0 ? redSize : 0; + greenSize = greenSize > 0 ? greenSize : 0; + blueSize = blueSize > 0 ? blueSize : 0; + alphaSize = alphaSize > 0 ? alphaSize : 0; + depthSize = depthSize > 0 ? depthSize : 0; + stencilSize = stencilSize > 0 ? stencilSize : 0; + sampleCount = sampleCount > 0 ? sampleCount : 0; + + QVector<EGLint> configAttributes; + + configAttributes.append(EGL_RED_SIZE); + configAttributes.append(redSize); + + configAttributes.append(EGL_GREEN_SIZE); + configAttributes.append(greenSize); + + configAttributes.append(EGL_BLUE_SIZE); + configAttributes.append(blueSize); + + configAttributes.append(EGL_ALPHA_SIZE); + configAttributes.append(alphaSize); + + configAttributes.append(EGL_DEPTH_SIZE); + configAttributes.append(depthSize); + + configAttributes.append(EGL_STENCIL_SIZE); + configAttributes.append(stencilSize); + + configAttributes.append(EGL_SAMPLES); + configAttributes.append(sampleCount); + + configAttributes.append(EGL_SAMPLE_BUFFERS); + configAttributes.append(sampleCount? 1:0); + + return configAttributes; +} + +bool q_reduceConfigAttributes(QVector<EGLint> *configAttributes) +{ + int i = -1; + // Reduce the complexity of a configuration request to ask for less + // because the previous request did not result in success. Returns + // true if the complexity was reduced, or false if no further + // reductions in complexity are possible. + + i = configAttributes->indexOf(EGL_SWAP_BEHAVIOR); + if (i >= 0) { + configAttributes->remove(i,2); + } + +#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT + // For OpenVG, we sometimes try to create a surface using a pre-multiplied format. If we can't + // find a config which supports pre-multiplied formats, remove the flag on the surface type: + + i = configAttributes->indexOf(EGL_SURFACE_TYPE); + if (i >= 0) { + EGLint surfaceType = configAttributes->at(i +1); + if (surfaceType & EGL_VG_ALPHA_FORMAT_PRE_BIT) { + surfaceType ^= EGL_VG_ALPHA_FORMAT_PRE_BIT; + configAttributes->replace(i+1,surfaceType); + return true; + } + } +#endif + + // EGL chooses configs with the highest color depth over + // those with smaller (but faster) lower color depths. One + // way around this is to set EGL_BUFFER_SIZE to 16, which + // trumps the others. Of course, there may not be a 16-bit + // config available, so it's the first restraint we remove. + i = configAttributes->indexOf(EGL_BUFFER_SIZE); + if (i >= 0) { + if (configAttributes->at(i+1) == 16) { + configAttributes->remove(i,2); + return true; + } + } + + i = configAttributes->indexOf(EGL_SAMPLE_BUFFERS); + if (i >= 0) { + configAttributes->remove(i,2); + i = configAttributes->indexOf(EGL_SAMPLES); + if (i >= 0) { + configAttributes->remove(i,2); + } + return true; + } + + i = configAttributes->indexOf(EGL_ALPHA_SIZE); + if (i >= 0) { + configAttributes->remove(i,2); +#if defined(EGL_BIND_TO_TEXTURE_RGBA) && defined(EGL_BIND_TO_TEXTURE_RGB) + i = configAttributes->indexOf(EGL_BIND_TO_TEXTURE_RGBA); + if (i >= 0) { + configAttributes->replace(i,EGL_BIND_TO_TEXTURE_RGB); + configAttributes->replace(i+1,TRUE); + + } +#endif + return true; + } + + i = configAttributes->indexOf(EGL_STENCIL_SIZE); + if (i >= 0) { + configAttributes->remove(i,2); + return true; + } + i = configAttributes->indexOf(EGL_DEPTH_SIZE); + if (i >= 0) { + configAttributes->remove(i,2); + return true; + } +#ifdef EGL_BIND_TO_TEXTURE_RGB + i = configAttributes->indexOf(EGL_BIND_TO_TEXTURE_RGB); + if (i >= 0) { + configAttributes->remove(i,2); + return true; + } +#endif + + return false; +} + +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(surfaceType); + + configureAttributes.append(EGL_RENDERABLE_TYPE); + if (format.windowApi() == QPlatformWindowFormat::OpenVG) { + configureAttributes.append(EGL_OPENVG_BIT); + } else { + configureAttributes.append(EGL_OPENGL_ES2_BIT); + } + configureAttributes.append(EGL_NONE); + + do { + // Get the number of matching configurations for this set of properties. + EGLint matching = 0; + if (!eglChooseConfig(display, configureAttributes.constData(), 0, 0, &matching) || !matching) + continue; + + // If we want the best pixel format, then return the first + // matching configuration. + if (highestPixelFormat) { + eglChooseConfig(display, configureAttributes.constData(), &cfg, 1, &matching); + if (matching < 1) + continue; + return cfg; + } + + // Fetch all of the matching configurations and find the + // first that matches the pixel format we wanted. + int i = configureAttributes.indexOf(EGL_RED_SIZE); + int confAttrRed = configureAttributes.at(i+1); + i = configureAttributes.indexOf(EGL_GREEN_SIZE); + int confAttrGreen = configureAttributes.at(i+1); + i = configureAttributes.indexOf(EGL_BLUE_SIZE); + int confAttrBlue = configureAttributes.at(i+1); + i = configureAttributes.indexOf(EGL_ALPHA_SIZE); + int confAttrAlpha = configureAttributes.at(i+1); + + EGLint size = matching; + EGLConfig *configs = new EGLConfig [size]; + eglChooseConfig(display, configureAttributes.constData(), configs, size, &matching); + for (EGLint index = 0; index < size; ++index) { + EGLint red, green, blue, alpha; + eglGetConfigAttrib(display, configs[index], EGL_RED_SIZE, &red); + eglGetConfigAttrib(display, configs[index], EGL_GREEN_SIZE, &green); + eglGetConfigAttrib(display, configs[index], EGL_BLUE_SIZE, &blue); + eglGetConfigAttrib(display, configs[index], EGL_ALPHA_SIZE, &alpha); + if (red == confAttrRed && + green == confAttrGreen && + blue == confAttrBlue && + (confAttrAlpha == 0 || + alpha == confAttrAlpha)) { + cfg = configs[index]; + delete [] configs; + return cfg; + } + } + delete [] configs; + } while (q_reduceConfigAttributes(&configureAttributes)); + qWarning("Cant find EGLConfig, returning null config"); + return 0; +} + +QPlatformWindowFormat qt_qPlatformWindowFormatFromConfig(EGLDisplay display, const EGLConfig config) +{ + QPlatformWindowFormat format; + EGLint redSize = 0; + EGLint greenSize = 0; + EGLint blueSize = 0; + EGLint alphaSize = 0; + EGLint depthSize = 0; + EGLint stencilSize = 0; + EGLint sampleCount = 0; + EGLint level = 0; + + eglGetConfigAttrib(display, config, EGL_RED_SIZE, &redSize); + eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &greenSize); + eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &blueSize); + eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &alphaSize); + eglGetConfigAttrib(display, config, EGL_DEPTH_SIZE, &depthSize); + eglGetConfigAttrib(display, config, EGL_STENCIL_SIZE, &stencilSize); + eglGetConfigAttrib(display, config, EGL_SAMPLES, &sampleCount); + eglGetConfigAttrib(display, config, EGL_LEVEL, &level); + + format.setRedBufferSize(redSize); + format.setGreenBufferSize(greenSize); + format.setBlueBufferSize(blueSize); + format.setAlphaBufferSize(alphaSize); + format.setDepthBufferSize(depthSize); + format.setStencilBufferSize(stencilSize); + format.setSamples(sampleCount); + format.setDirectRendering(true); // All EGL contexts are direct-rendered + format.setRgba(true); // EGL doesn't support colour index rendering + format.setStereo(false); // EGL doesn't support stereo buffers + format.setAccumBufferSize(0); // EGL doesn't support accululation buffers + + // Clear the EGL error state because some of the above may + // have errored out because the attribute is not applicable + // to the surface type. Such errors don't matter. + eglGetError(); + + return format; +} + +bool q_hasEglExtension(EGLDisplay display, const char* extensionName) +{ + QList<QByteArray> extensions = + QByteArray(reinterpret_cast<const char *> + (eglQueryString(display, EGL_EXTENSIONS))).split(' '); + return extensions.contains(extensionName); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglconvenience/qeglconvenience.h b/src/plugins/platforms/eglconvenience/qeglconvenience.h new file mode 100644 index 0000000000..c7d3d61ae5 --- /dev/null +++ b/src/plugins/platforms/eglconvenience/qeglconvenience.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** 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 QEGLCONVENIENCE_H +#define QEGLCONVENIENCE_H + + +#include <QtGui/QPlatformWindowFormat> +#include <QtCore/QVector> + +#include <EGL/egl.h> +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, int surfaceType = EGL_WINDOW_BIT); +QPlatformWindowFormat qt_qPlatformWindowFormatFromConfig(EGLDisplay display, const EGLConfig config); +bool q_hasEglExtension(EGLDisplay display,const char* extensionName); + +QT_END_NAMESPACE + +#endif //QEGLCONVENIENCE_H diff --git a/src/plugins/platforms/eglconvenience/qeglplatformcontext.cpp b/src/plugins/platforms/eglconvenience/qeglplatformcontext.cpp new file mode 100644 index 0000000000..ae5215f320 --- /dev/null +++ b/src/plugins/platforms/eglconvenience/qeglplatformcontext.cpp @@ -0,0 +1,157 @@ +/**************************************************************************** +** +** 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 "qeglplatformcontext.h" + + +#include <QtGui/QPlatformWindow> + +#include "qeglconvenience.h" + +#include <EGL/egl.h> + +QEGLPlatformContext::QEGLPlatformContext(EGLDisplay display, EGLConfig config, EGLint contextAttrs[], EGLSurface surface, EGLenum eglApi) + : QPlatformGLContext() + , m_eglDisplay(display) + , m_eglSurface(surface) + , m_eglApi(eglApi) +{ + if (m_eglSurface == EGL_NO_SURFACE) { + qWarning("Createing QEGLPlatformContext with no surface"); + } + + eglBindAPI(m_eglApi); + m_eglContext = eglCreateContext(m_eglDisplay,config, 0,contextAttrs); + if (m_eglContext == EGL_NO_CONTEXT) { + qWarning("Could not create the egl context\n"); + eglTerminate(m_eglDisplay); + qFatal("EGL error"); + } + + m_windowFormat = qt_qPlatformWindowFormatFromConfig(display,config); +} + +QEGLPlatformContext::~QEGLPlatformContext() +{ +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglContext::~QEglContext(): %p\n",this); +#endif + if (m_eglSurface != EGL_NO_SURFACE) { + doneCurrent(); + eglDestroySurface(m_eglDisplay, m_eglSurface); + m_eglSurface = EGL_NO_SURFACE; + } + + if (m_eglContext != EGL_NO_CONTEXT) { + eglDestroyContext(m_eglDisplay, m_eglContext); + m_eglContext = EGL_NO_CONTEXT; + } +} + +void QEGLPlatformContext::makeCurrent() +{ + QPlatformGLContext::makeCurrent(); +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglContext::makeCurrent: %p\n",this); +#endif + eglBindAPI(m_eglApi); + bool ok = eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext); + if (!ok) + qWarning("QEGLPlatformContext::makeCurrent: eglError: %d, this: %p \n", eglGetError(), this); +#ifdef QEGL_EXTRA_DEBUG + static bool showDebug = true; + if (showDebug) { + showDebug = false; + const char *str = (const char*)glGetString(GL_VENDOR); + qWarning("Vendor %s\n", str); + str = (const char*)glGetString(GL_RENDERER); + qWarning("Renderer %s\n", str); + str = (const char*)glGetString(GL_VERSION); + qWarning("Version %s\n", str); + + str = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION); + qWarning("Extensions %s\n",str); + + str = (const char*)glGetString(GL_EXTENSIONS); + qWarning("Extensions %s\n", str); + + } +#endif +} +void QEGLPlatformContext::doneCurrent() +{ + QPlatformGLContext::doneCurrent(); +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglContext::doneCurrent:%p\n",this); +#endif + eglBindAPI(m_eglApi); + bool ok = eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (!ok) + qWarning("QEGLPlatformContext::doneCurrent(): eglError: %d, this: %p \n", eglGetError(), this); +} +void QEGLPlatformContext::swapBuffers() +{ +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglContext::swapBuffers:%p\n",this); +#endif + eglBindAPI(m_eglApi); + bool ok = eglSwapBuffers(m_eglDisplay, m_eglSurface); + if (!ok) + qWarning("QEGLPlatformContext::swapBuffers(): eglError: %d, this: %p \n", eglGetError(), this); +} +void* QEGLPlatformContext::getProcAddress(const QString& procName) +{ +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglContext::getProcAddress%p\n",this); +#endif + eglBindAPI(m_eglApi); + return (void *)eglGetProcAddress(qPrintable(procName)); +} + +QPlatformWindowFormat QEGLPlatformContext::platformWindowFormat() const +{ + return m_windowFormat; +} + +EGLContext QEGLPlatformContext::eglContext() const +{ + return m_eglContext; +} diff --git a/src/plugins/platforms/eglconvenience/qeglplatformcontext.h b/src/plugins/platforms/eglconvenience/qeglplatformcontext.h new file mode 100644 index 0000000000..69835d7eb4 --- /dev/null +++ b/src/plugins/platforms/eglconvenience/qeglplatformcontext.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** 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 QOPENKODEGLINTEGRATION_H +#define QOPENKODEGLINTEGRATION_H + +#include <QtGui/QPlatformGLContext> +#include <EGL/egl.h> + +class QEGLPlatformContext : public QPlatformGLContext +{ +public: + QEGLPlatformContext(EGLDisplay display, EGLConfig config, EGLint contextAttrs[], EGLSurface surface, EGLenum eglApi); + ~QEGLPlatformContext(); + + void makeCurrent(); + void doneCurrent(); + void swapBuffers(); + void* getProcAddress(const QString& procName); + + QPlatformWindowFormat platformWindowFormat() const; + + EGLContext eglContext() const; +private: + EGLContext m_eglContext; + EGLDisplay m_eglDisplay; + EGLSurface m_eglSurface; + EGLenum m_eglApi; + + QPlatformWindowFormat m_windowFormat; +}; + +#endif //QOPENKODEGLINTEGRATION_H diff --git a/src/plugins/platforms/eglconvenience/qxlibeglintegration.cpp b/src/plugins/platforms/eglconvenience/qxlibeglintegration.cpp new file mode 100644 index 0000000000..45746e99a7 --- /dev/null +++ b/src/plugins/platforms/eglconvenience/qxlibeglintegration.cpp @@ -0,0 +1,184 @@ +/**************************************************************************** +** +** 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 "qxlibeglintegration.h" + +static int countBits(unsigned long mask) +{ + int count = 0; + while (mask != 0) { + if (mask & 1) + ++count; + mask >>= 1; + } + return count; +} + +VisualID QXlibEglIntegration::getCompatibleVisualId(Display *display, EGLDisplay eglDisplay, EGLConfig config) +{ + VisualID visualId = 0; + EGLint eglValue = 0; + + EGLint configRedSize = 0; + eglGetConfigAttrib(eglDisplay, config, EGL_RED_SIZE, &configRedSize); + + EGLint configGreenSize = 0; + eglGetConfigAttrib(eglDisplay, config, EGL_GREEN_SIZE, &configGreenSize); + + EGLint configBlueSize = 0; + eglGetConfigAttrib(eglDisplay, config, EGL_BLUE_SIZE, &configBlueSize); + + EGLint configAlphaSize = 0; + eglGetConfigAttrib(eglDisplay, config, EGL_ALPHA_SIZE, &configAlphaSize); + + eglGetConfigAttrib(eglDisplay, config, EGL_CONFIG_ID, &eglValue); + int configId = eglValue; + + // See if EGL provided a valid VisualID: + eglGetConfigAttrib(eglDisplay, config, EGL_NATIVE_VISUAL_ID, &eglValue); + visualId = (VisualID)eglValue; + if (visualId) { + // EGL has suggested a visual id, so get the rest of the visual info for that id: + XVisualInfo visualInfoTemplate; + memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); + visualInfoTemplate.visualid = visualId; + + XVisualInfo *chosenVisualInfo; + int matchingCount = 0; + chosenVisualInfo = XGetVisualInfo(display, VisualIDMask, &visualInfoTemplate, &matchingCount); + if (chosenVisualInfo) { + // Skip size checks if implementation supports non-matching visual + // and config (http://bugreports.qt.nokia.com/browse/QTBUG-9444). + if (q_hasEglExtension(eglDisplay,"EGL_NV_post_convert_rounding")) { + XFree(chosenVisualInfo); + return visualId; + } + + int visualRedSize = countBits(chosenVisualInfo->red_mask); + int visualGreenSize = countBits(chosenVisualInfo->green_mask); + int visualBlueSize = countBits(chosenVisualInfo->blue_mask); + int visualAlphaSize = -1; // Need XRender to tell us the alpha channel size + + bool visualMatchesConfig = false; + if ( visualRedSize == configRedSize && + visualGreenSize == configGreenSize && + visualBlueSize == configBlueSize ) + { + // We need XRender to check the alpha channel size of the visual. If we don't have + // the alpha size, we don't check it against the EGL config's alpha size. + if (visualAlphaSize >= 0) + visualMatchesConfig = visualAlphaSize == configAlphaSize; + else + visualMatchesConfig = true; + } + + if (!visualMatchesConfig) { + if (visualAlphaSize >= 0) { + qWarning("Warning: EGL suggested using X Visual ID %d (ARGB%d%d%d%d) for EGL config %d (ARGB%d%d%d%d), but this is incompatable", + (int)visualId, visualAlphaSize, visualRedSize, visualGreenSize, visualBlueSize, + configId, configAlphaSize, configRedSize, configGreenSize, configBlueSize); + } else { + qWarning("Warning: EGL suggested using X Visual ID %d (RGB%d%d%d) for EGL config %d (RGB%d%d%d), but this is incompatable", + (int)visualId, visualRedSize, visualGreenSize, visualBlueSize, + configId, configRedSize, configGreenSize, configBlueSize); + } + visualId = 0; + } + } else { + qWarning("Warning: EGL suggested using X Visual ID %d for EGL config %d, but that isn't a valid ID", + (int)visualId, configId); + visualId = 0; + } + XFree(chosenVisualInfo); + } +#ifdef QT_DEBUG_X11_VISUAL_SELECTION + else + qDebug("EGL did not suggest a VisualID (EGL_NATIVE_VISUAL_ID was zero) for EGLConfig %d", configId); +#endif + + if (visualId) { +#ifdef QT_DEBUG_X11_VISUAL_SELECTION + if (configAlphaSize > 0) + qDebug("Using ARGB Visual ID %d provided by EGL for config %d", (int)visualId, configId); + else + qDebug("Using Opaque Visual ID %d provided by EGL for config %d", (int)visualId, configId); +#endif + return visualId; + } + + // Finally, try to + // use XGetVisualInfo and only use the bit depths to match on: + if (!visualId) { + XVisualInfo visualInfoTemplate; + memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); + XVisualInfo *matchingVisuals; + int matchingCount = 0; + + visualInfoTemplate.depth = configRedSize + configGreenSize + configBlueSize + configAlphaSize; + matchingVisuals = XGetVisualInfo(display, + VisualDepthMask, + &visualInfoTemplate, + &matchingCount); + if (!matchingVisuals) { + // Try again without taking the alpha channel into account: + visualInfoTemplate.depth = configRedSize + configGreenSize + configBlueSize; + matchingVisuals = XGetVisualInfo(display, + VisualDepthMask, + &visualInfoTemplate, + &matchingCount); + } + + if (matchingVisuals) { + visualId = matchingVisuals[0].visualid; + XFree(matchingVisuals); + } + } + + if (visualId) { +#ifdef QT_DEBUG_X11_VISUAL_SELECTION + qDebug("Using Visual ID %d provided by XGetVisualInfo for EGL config %d", (int)visualId, configId); +#endif + return visualId; + } + + qWarning("Unable to find an X11 visual which matches EGL config %d", configId); + return (VisualID)0; +} diff --git a/src/plugins/platforms/eglconvenience/qxlibeglintegration.h b/src/plugins/platforms/eglconvenience/qxlibeglintegration.h new file mode 100644 index 0000000000..6c2e266cbc --- /dev/null +++ b/src/plugins/platforms/eglconvenience/qxlibeglintegration.h @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** 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 QTESTLITEEGLINTEGRATION_H +#define QTESTLITEEGLINTEGRATION_H + +#include "qeglconvenience.h" + +class QXlibEglIntegration +{ +public: + 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 0000000000..9404a70373 --- /dev/null +++ b/src/plugins/platforms/eglconvenience/xlibeglintegration.pri @@ -0,0 +1,7 @@ +INCLUDEPATH += $$PWD + +HEADERS += \ + $$PWD/qxlibeglintegration.h + +SOURCES += \ + $$PWD/qxlibeglintegration.cpp |