eglfs: Introduce way of filtering out unwanted EGL configs.
Some times a platform might want to exclude certain configs, for example based on EGL_NATIVE_VISUAL_ID. This patch introduces a new QEglConfigChooser class which has a virtual filterConfig() function which can be re-implemented in a sub-class to give finer control of how configs are chosen. Change-Id: I8b684f01be95a47307b1e429857f01337a9a38d8 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com> Reviewed-by: Gunnar Sletta <gunnar.sletta@digia.com>
This commit is contained in:
parent
ac9ab9703f
commit
d29aabbca9
@ -210,75 +210,106 @@ bool q_reduceConfigAttributes(QVector<EGLint> *configAttributes)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
EGLConfig q_configFromGLFormat(EGLDisplay display, const QSurfaceFormat &format, bool highestPixelFormat, int surfaceType)
|
QEglConfigChooser::QEglConfigChooser(EGLDisplay display)
|
||||||
|
: m_display(display)
|
||||||
|
, m_surfaceType(EGL_WINDOW_BIT)
|
||||||
|
, m_ignore(false)
|
||||||
|
, m_confAttrRed(0)
|
||||||
|
, m_confAttrGreen(0)
|
||||||
|
, m_confAttrBlue(0)
|
||||||
|
, m_confAttrAlpha(0)
|
||||||
{
|
{
|
||||||
EGLConfig cfg = 0;
|
}
|
||||||
QVector<EGLint> configureAttributes = q_createConfigAttributesFromFormat(format);
|
|
||||||
|
QEglConfigChooser::~QEglConfigChooser()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
EGLConfig QEglConfigChooser::chooseConfig()
|
||||||
|
{
|
||||||
|
QVector<EGLint> configureAttributes = q_createConfigAttributesFromFormat(m_format);
|
||||||
configureAttributes.append(EGL_SURFACE_TYPE);
|
configureAttributes.append(EGL_SURFACE_TYPE);
|
||||||
configureAttributes.append(surfaceType);
|
configureAttributes.append(surfaceType());
|
||||||
|
|
||||||
configureAttributes.append(EGL_RENDERABLE_TYPE);
|
configureAttributes.append(EGL_RENDERABLE_TYPE);
|
||||||
if (format.renderableType() == QSurfaceFormat::OpenVG)
|
if (m_format.renderableType() == QSurfaceFormat::OpenVG)
|
||||||
configureAttributes.append(EGL_OPENVG_BIT);
|
configureAttributes.append(EGL_OPENVG_BIT);
|
||||||
#ifdef EGL_VERSION_1_4
|
#ifdef EGL_VERSION_1_4
|
||||||
else if (format.renderableType() == QSurfaceFormat::OpenGL)
|
else if (m_format.renderableType() == QSurfaceFormat::OpenGL)
|
||||||
configureAttributes.append(EGL_OPENGL_BIT);
|
configureAttributes.append(EGL_OPENGL_BIT);
|
||||||
#endif
|
#endif
|
||||||
else if (format.majorVersion() == 1)
|
else if (m_format.majorVersion() == 1)
|
||||||
configureAttributes.append(EGL_OPENGL_ES_BIT);
|
configureAttributes.append(EGL_OPENGL_ES_BIT);
|
||||||
else
|
else
|
||||||
configureAttributes.append(EGL_OPENGL_ES2_BIT);
|
configureAttributes.append(EGL_OPENGL_ES2_BIT);
|
||||||
|
|
||||||
configureAttributes.append(EGL_NONE);
|
configureAttributes.append(EGL_NONE);
|
||||||
|
|
||||||
|
EGLConfig cfg;
|
||||||
do {
|
do {
|
||||||
// Get the number of matching configurations for this set of properties.
|
// Get the number of matching configurations for this set of properties.
|
||||||
EGLint matching = 0;
|
EGLint matching = 0;
|
||||||
if (!eglChooseConfig(display, configureAttributes.constData(), 0, 0, &matching) || !matching)
|
if (!eglChooseConfig(display(), configureAttributes.constData(), 0, 0, &matching) || !matching)
|
||||||
continue;
|
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
|
// Fetch all of the matching configurations and find the
|
||||||
// first that matches the pixel format we wanted.
|
// first that matches the pixel format we wanted.
|
||||||
int i = configureAttributes.indexOf(EGL_RED_SIZE);
|
int i = configureAttributes.indexOf(EGL_RED_SIZE);
|
||||||
int confAttrRed = configureAttributes.at(i+1);
|
m_confAttrRed = configureAttributes.at(i+1);
|
||||||
i = configureAttributes.indexOf(EGL_GREEN_SIZE);
|
i = configureAttributes.indexOf(EGL_GREEN_SIZE);
|
||||||
int confAttrGreen = configureAttributes.at(i+1);
|
m_confAttrGreen = configureAttributes.at(i+1);
|
||||||
i = configureAttributes.indexOf(EGL_BLUE_SIZE);
|
i = configureAttributes.indexOf(EGL_BLUE_SIZE);
|
||||||
int confAttrBlue = configureAttributes.at(i+1);
|
m_confAttrBlue = configureAttributes.at(i+1);
|
||||||
i = configureAttributes.indexOf(EGL_ALPHA_SIZE);
|
i = configureAttributes.indexOf(EGL_ALPHA_SIZE);
|
||||||
int confAttrAlpha = i == -1 ? 0 : configureAttributes.at(i+1);
|
m_confAttrAlpha = i == -1 ? 0 : configureAttributes.at(i+1);
|
||||||
|
|
||||||
EGLint size = matching;
|
QVector<EGLConfig> configs(matching);
|
||||||
EGLConfig *configs = new EGLConfig [size];
|
eglChooseConfig(display(), configureAttributes.constData(), configs.data(), configs.size(), &matching);
|
||||||
eglChooseConfig(display, configureAttributes.constData(), configs, size, &matching);
|
if (!cfg && matching > 0)
|
||||||
for (EGLint index = 0; index < size; ++index) {
|
cfg = configs.first();
|
||||||
EGLint red, green, blue, alpha;
|
|
||||||
eglGetConfigAttrib(display, configs[index], EGL_RED_SIZE, &red);
|
for (int i = 0; i < configs.size(); ++i) {
|
||||||
eglGetConfigAttrib(display, configs[index], EGL_GREEN_SIZE, &green);
|
if (filterConfig(configs[i]))
|
||||||
eglGetConfigAttrib(display, configs[index], EGL_BLUE_SIZE, &blue);
|
return configs.at(i);
|
||||||
eglGetConfigAttrib(display, configs[index], EGL_ALPHA_SIZE, &alpha);
|
|
||||||
if ((confAttrRed == 0 || red == confAttrRed) &&
|
|
||||||
(confAttrGreen == 0 || green == confAttrGreen) &&
|
|
||||||
(confAttrBlue == 0 || blue == confAttrBlue) &&
|
|
||||||
(confAttrAlpha == 0 || alpha == confAttrAlpha)) {
|
|
||||||
cfg = configs[index];
|
|
||||||
delete [] configs;
|
|
||||||
return cfg;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
delete [] configs;
|
|
||||||
} while (q_reduceConfigAttributes(&configureAttributes));
|
} while (q_reduceConfigAttributes(&configureAttributes));
|
||||||
qWarning("Cant find EGLConfig, returning null config");
|
|
||||||
return 0;
|
if (!cfg)
|
||||||
|
qWarning("Cant find EGLConfig, returning null config");
|
||||||
|
return cfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QEglConfigChooser::filterConfig(EGLConfig config) const
|
||||||
|
{
|
||||||
|
if (m_ignore)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
EGLint red = 0;
|
||||||
|
EGLint green = 0;
|
||||||
|
EGLint blue = 0;
|
||||||
|
EGLint alpha = 0;
|
||||||
|
|
||||||
|
if (m_confAttrRed)
|
||||||
|
eglGetConfigAttrib(display(), config, EGL_RED_SIZE, &red);
|
||||||
|
if (m_confAttrGreen)
|
||||||
|
eglGetConfigAttrib(display(), config, EGL_GREEN_SIZE, &green);
|
||||||
|
if (m_confAttrBlue)
|
||||||
|
eglGetConfigAttrib(display(), config, EGL_BLUE_SIZE, &blue);
|
||||||
|
if (m_confAttrAlpha)
|
||||||
|
eglGetConfigAttrib(display(), config, EGL_ALPHA_SIZE, &alpha);
|
||||||
|
|
||||||
|
return red == m_confAttrRed && green == m_confAttrGreen
|
||||||
|
&& blue == m_confAttrBlue && alpha == m_confAttrAlpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
EGLConfig q_configFromGLFormat(EGLDisplay display, const QSurfaceFormat &format, bool highestPixelFormat, int surfaceType)
|
||||||
|
{
|
||||||
|
QEglConfigChooser chooser(display);
|
||||||
|
chooser.setSurfaceFormat(format);
|
||||||
|
chooser.setSurfaceType(surfaceType);
|
||||||
|
chooser.setIgnoreColorChannels(highestPixelFormat);
|
||||||
|
|
||||||
|
return chooser.chooseConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
QSurfaceFormat q_glFormatFromConfig(EGLDisplay display, const EGLConfig config, const QSurfaceFormat &referenceFormat)
|
QSurfaceFormat q_glFormatFromConfig(EGLDisplay display, const EGLConfig config, const QSurfaceFormat &referenceFormat)
|
||||||
|
@ -56,6 +56,41 @@ QSurfaceFormat q_glFormatFromConfig(EGLDisplay display, const EGLConfig config,
|
|||||||
bool q_hasEglExtension(EGLDisplay display,const char* extensionName);
|
bool q_hasEglExtension(EGLDisplay display,const char* extensionName);
|
||||||
void q_printEglConfig(EGLDisplay display, EGLConfig config);
|
void q_printEglConfig(EGLDisplay display, EGLConfig config);
|
||||||
|
|
||||||
|
class QEglConfigChooser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QEglConfigChooser(EGLDisplay display);
|
||||||
|
virtual ~QEglConfigChooser();
|
||||||
|
|
||||||
|
EGLDisplay display() const { return m_display; }
|
||||||
|
|
||||||
|
void setSurfaceType(EGLint surfaceType) { m_surfaceType = surfaceType; }
|
||||||
|
EGLint surfaceType() const { return m_surfaceType; }
|
||||||
|
|
||||||
|
void setSurfaceFormat(const QSurfaceFormat &format) { m_format = format; }
|
||||||
|
QSurfaceFormat surfaceFormat() const { return m_format; }
|
||||||
|
|
||||||
|
void setIgnoreColorChannels(bool ignore) { m_ignore = ignore; }
|
||||||
|
bool ignoreColorChannels() const { return m_ignore; }
|
||||||
|
|
||||||
|
EGLConfig chooseConfig();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool filterConfig(EGLConfig config) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSurfaceFormat m_format;
|
||||||
|
EGLDisplay m_display;
|
||||||
|
EGLint m_surfaceType;
|
||||||
|
bool m_ignore;
|
||||||
|
|
||||||
|
int m_confAttrRed;
|
||||||
|
int m_confAttrGreen;
|
||||||
|
int m_confAttrBlue;
|
||||||
|
int m_confAttrAlpha;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#endif //QEGLCONVENIENCE_H
|
#endif //QEGLCONVENIENCE_H
|
||||||
|
@ -64,8 +64,22 @@ QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatform
|
|||||||
: m_eglDisplay(display)
|
: m_eglDisplay(display)
|
||||||
, m_eglApi(eglApi)
|
, m_eglApi(eglApi)
|
||||||
, m_eglConfig(q_configFromGLFormat(display, format, true))
|
, m_eglConfig(q_configFromGLFormat(display, format, true))
|
||||||
, m_format(q_glFormatFromConfig(display, m_eglConfig))
|
|
||||||
{
|
{
|
||||||
|
init(format, share);
|
||||||
|
}
|
||||||
|
|
||||||
|
QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display,
|
||||||
|
EGLConfig config, EGLenum eglApi)
|
||||||
|
: m_eglDisplay(display)
|
||||||
|
, m_eglApi(eglApi)
|
||||||
|
, m_eglConfig(config)
|
||||||
|
{
|
||||||
|
init(format, share);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLContext *share)
|
||||||
|
{
|
||||||
|
m_format = q_glFormatFromConfig(m_eglDisplay, m_eglConfig);
|
||||||
m_shareContext = share ? static_cast<QEGLPlatformContext *>(share)->m_eglContext : 0;
|
m_shareContext = share ? static_cast<QEGLPlatformContext *>(share)->m_eglContext : 0;
|
||||||
|
|
||||||
QVector<EGLint> contextAttrs;
|
QVector<EGLint> contextAttrs;
|
||||||
|
@ -51,6 +51,8 @@ class QEGLPlatformContext : public QPlatformOpenGLContext
|
|||||||
public:
|
public:
|
||||||
QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display,
|
QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display,
|
||||||
EGLenum eglApi = EGL_OPENGL_ES_API);
|
EGLenum eglApi = EGL_OPENGL_ES_API);
|
||||||
|
QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display,
|
||||||
|
EGLConfig config, EGLenum eglApi = EGL_OPENGL_ES_API);
|
||||||
~QEGLPlatformContext();
|
~QEGLPlatformContext();
|
||||||
|
|
||||||
bool makeCurrent(QPlatformSurface *surface);
|
bool makeCurrent(QPlatformSurface *surface);
|
||||||
@ -70,12 +72,14 @@ protected:
|
|||||||
virtual EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) = 0;
|
virtual EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void init(const QSurfaceFormat &format, QPlatformOpenGLContext *share);
|
||||||
|
|
||||||
EGLContext m_eglContext;
|
EGLContext m_eglContext;
|
||||||
EGLContext m_shareContext;
|
EGLContext m_shareContext;
|
||||||
EGLDisplay m_eglDisplay;
|
EGLDisplay m_eglDisplay;
|
||||||
EGLenum m_eglApi;
|
EGLenum m_eglApi;
|
||||||
EGLConfig m_eglConfig;
|
EGLConfig m_eglConfig;
|
||||||
const QSurfaceFormat m_format;
|
QSurfaceFormat m_format;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //QEGLPLATFORMCONTEXT_H
|
#endif //QEGLPLATFORMCONTEXT_H
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#include "qeglfswindow.h"
|
#include "qeglfswindow.h"
|
||||||
#include "qeglfscursor.h"
|
#include "qeglfscursor.h"
|
||||||
#include "qeglfshooks.h"
|
#include "qeglfshooks.h"
|
||||||
|
#include "qeglfsintegration.h"
|
||||||
|
|
||||||
#include <QtDebug>
|
#include <QtDebug>
|
||||||
|
|
||||||
@ -50,7 +51,7 @@ QT_BEGIN_NAMESPACE
|
|||||||
|
|
||||||
QEglFSContext::QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share,
|
QEglFSContext::QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share,
|
||||||
EGLDisplay display, EGLenum eglApi)
|
EGLDisplay display, EGLenum eglApi)
|
||||||
: QEGLPlatformContext(hooks->surfaceFormatFor(format), share, display, eglApi)
|
: QEGLPlatformContext(format, share, display, QEglFSIntegration::chooseConfig(display, format), eglApi)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,6 +67,7 @@ public:
|
|||||||
virtual void destroyNativeWindow(EGLNativeWindowType window);
|
virtual void destroyNativeWindow(EGLNativeWindowType window);
|
||||||
virtual bool hasCapability(QPlatformIntegration::Capability cap) const;
|
virtual bool hasCapability(QPlatformIntegration::Capability cap) const;
|
||||||
virtual QEglFSCursor *createCursor(QEglFSScreen *screen) const;
|
virtual QEglFSCursor *createCursor(QEglFSScreen *screen) const;
|
||||||
|
virtual bool filterConfig(EGLDisplay display, EGLConfig config) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef EGLFS_PLATFORM_HOOKS
|
#ifdef EGLFS_PLATFORM_HOOKS
|
||||||
|
@ -134,6 +134,11 @@ QSurfaceFormat QEglFSHooks::surfaceFormatFor(const QSurfaceFormat &inputFormat)
|
|||||||
return inputFormat;
|
return inputFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool QEglFSHooks::filterConfig(EGLDisplay, EGLConfig) const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
EGLNativeWindowType QEglFSHooks::createNativeWindow(const QSize &size, const QSurfaceFormat &format)
|
EGLNativeWindowType QEglFSHooks::createNativeWindow(const QSize &size, const QSurfaceFormat &format)
|
||||||
{
|
{
|
||||||
Q_UNUSED(size);
|
Q_UNUSED(size);
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
|
|
||||||
#include <QtPlatformSupport/private/qgenericunixfontdatabase_p.h>
|
#include <QtPlatformSupport/private/qgenericunixfontdatabase_p.h>
|
||||||
#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
|
#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
|
||||||
|
#include <QtPlatformSupport/private/qeglconvenience_p.h>
|
||||||
#include <QtPlatformSupport/private/qeglplatformcontext_p.h>
|
#include <QtPlatformSupport/private/qeglplatformcontext_p.h>
|
||||||
|
|
||||||
#if !defined(QT_NO_EVDEV)
|
#if !defined(QT_NO_EVDEV)
|
||||||
@ -150,7 +151,7 @@ QPlatformBackingStore *QEglFSIntegration::createPlatformBackingStore(QWindow *wi
|
|||||||
|
|
||||||
QPlatformOpenGLContext *QEglFSIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
|
QPlatformOpenGLContext *QEglFSIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
|
||||||
{
|
{
|
||||||
return new QEglFSContext(context->format(), 0 /*share*/, mDisplay);
|
return new QEglFSContext(hooks->surfaceFormatFor(context->format()), 0 /*share*/, mDisplay);
|
||||||
}
|
}
|
||||||
|
|
||||||
QPlatformFontDatabase *QEglFSIntegration::fontDatabase() const
|
QPlatformFontDatabase *QEglFSIntegration::fontDatabase() const
|
||||||
@ -201,4 +202,29 @@ void *QEglFSIntegration::nativeResourceForContext(const QByteArray &resource, QO
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EGLConfig QEglFSIntegration::chooseConfig(EGLDisplay display, const QSurfaceFormat &format)
|
||||||
|
{
|
||||||
|
class Chooser : public QEglConfigChooser {
|
||||||
|
public:
|
||||||
|
Chooser(EGLDisplay display, QEglFSHooks *hooks)
|
||||||
|
: QEglConfigChooser(display)
|
||||||
|
, m_hooks(hooks)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool filterConfig(EGLConfig config) const
|
||||||
|
{
|
||||||
|
return m_hooks->filterConfig(display(), config) && QEglConfigChooser::filterConfig(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QEglFSHooks *m_hooks;
|
||||||
|
};
|
||||||
|
|
||||||
|
Chooser chooser(display, hooks);
|
||||||
|
chooser.setSurfaceFormat(format);
|
||||||
|
return chooser.chooseConfig();
|
||||||
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -75,6 +75,8 @@ public:
|
|||||||
void *nativeResourceForIntegration(const QByteArray &resource);
|
void *nativeResourceForIntegration(const QByteArray &resource);
|
||||||
void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context);
|
void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context);
|
||||||
|
|
||||||
|
static EGLConfig chooseConfig(EGLDisplay display, const QSurfaceFormat &format);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EGLDisplay mDisplay;
|
EGLDisplay mDisplay;
|
||||||
QAbstractEventDispatcher *mEventDispatcher;
|
QAbstractEventDispatcher *mEventDispatcher;
|
||||||
|
@ -84,7 +84,8 @@ void QEglFSWindow::create()
|
|||||||
|
|
||||||
EGLDisplay display = (static_cast<QEglFSScreen *>(window()->screen()->handle()))->display();
|
EGLDisplay display = (static_cast<QEglFSScreen *>(window()->screen()->handle()))->display();
|
||||||
QSurfaceFormat platformFormat = hooks->surfaceFormatFor(window()->requestedFormat());
|
QSurfaceFormat platformFormat = hooks->surfaceFormatFor(window()->requestedFormat());
|
||||||
EGLConfig config = q_configFromGLFormat(display, platformFormat);
|
EGLConfig config = QEglFSIntegration::chooseConfig(display, platformFormat);
|
||||||
|
|
||||||
m_format = q_glFormatFromConfig(display, config);
|
m_format = q_glFormatFromConfig(display, config);
|
||||||
m_window = hooks->createNativeWindow(hooks->screenSize(), m_format);
|
m_window = hooks->createNativeWindow(hooks->screenSize(), m_format);
|
||||||
m_surface = eglCreateWindowSurface(display, config, m_window, NULL);
|
m_surface = eglCreateWindowSurface(display, config, m_window, NULL);
|
||||||
|
Loading…
Reference in New Issue
Block a user