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:
Samuel Rødal 2012-10-25 16:53:18 +02:00 committed by The Qt Project
parent ac9ab9703f
commit d29aabbca9
10 changed files with 166 additions and 46 deletions

View File

@ -210,75 +210,106 @@ bool q_reduceConfigAttributes(QVector<EGLint> *configAttributes)
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(surfaceType);
configureAttributes.append(surfaceType());
configureAttributes.append(EGL_RENDERABLE_TYPE);
if (format.renderableType() == QSurfaceFormat::OpenVG)
if (m_format.renderableType() == QSurfaceFormat::OpenVG)
configureAttributes.append(EGL_OPENVG_BIT);
#ifdef EGL_VERSION_1_4
else if (format.renderableType() == QSurfaceFormat::OpenGL)
else if (m_format.renderableType() == QSurfaceFormat::OpenGL)
configureAttributes.append(EGL_OPENGL_BIT);
#endif
else if (format.majorVersion() == 1)
else if (m_format.majorVersion() == 1)
configureAttributes.append(EGL_OPENGL_ES_BIT);
else
configureAttributes.append(EGL_OPENGL_ES2_BIT);
configureAttributes.append(EGL_NONE);
EGLConfig cfg;
do {
// Get the number of matching configurations for this set of properties.
EGLint matching = 0;
if (!eglChooseConfig(display, configureAttributes.constData(), 0, 0, &matching) || !matching)
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);
m_confAttrRed = configureAttributes.at(i+1);
i = configureAttributes.indexOf(EGL_GREEN_SIZE);
int confAttrGreen = configureAttributes.at(i+1);
m_confAttrGreen = configureAttributes.at(i+1);
i = configureAttributes.indexOf(EGL_BLUE_SIZE);
int confAttrBlue = configureAttributes.at(i+1);
m_confAttrBlue = configureAttributes.at(i+1);
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;
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 ((confAttrRed == 0 || red == confAttrRed) &&
(confAttrGreen == 0 || green == confAttrGreen) &&
(confAttrBlue == 0 || blue == confAttrBlue) &&
(confAttrAlpha == 0 || alpha == confAttrAlpha)) {
cfg = configs[index];
delete [] configs;
QVector<EGLConfig> configs(matching);
eglChooseConfig(display(), configureAttributes.constData(), configs.data(), configs.size(), &matching);
if (!cfg && matching > 0)
cfg = configs.first();
for (int i = 0; i < configs.size(); ++i) {
if (filterConfig(configs[i]))
return configs.at(i);
}
} while (q_reduceConfigAttributes(&configureAttributes));
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;
}
delete [] configs;
} while (q_reduceConfigAttributes(&configureAttributes));
qWarning("Cant find EGLConfig, returning null config");
return 0;
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)

View File

@ -56,6 +56,41 @@ QSurfaceFormat q_glFormatFromConfig(EGLDisplay display, const EGLConfig config,
bool q_hasEglExtension(EGLDisplay display,const char* extensionName);
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
#endif //QEGLCONVENIENCE_H

View File

@ -64,8 +64,22 @@ QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatform
: m_eglDisplay(display)
, m_eglApi(eglApi)
, 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;
QVector<EGLint> contextAttrs;

View File

@ -51,6 +51,8 @@ class QEGLPlatformContext : public QPlatformOpenGLContext
public:
QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display,
EGLenum eglApi = EGL_OPENGL_ES_API);
QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display,
EGLConfig config, EGLenum eglApi = EGL_OPENGL_ES_API);
~QEGLPlatformContext();
bool makeCurrent(QPlatformSurface *surface);
@ -70,12 +72,14 @@ protected:
virtual EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) = 0;
private:
void init(const QSurfaceFormat &format, QPlatformOpenGLContext *share);
EGLContext m_eglContext;
EGLContext m_shareContext;
EGLDisplay m_eglDisplay;
EGLenum m_eglApi;
EGLConfig m_eglConfig;
const QSurfaceFormat m_format;
QSurfaceFormat m_format;
};
#endif //QEGLPLATFORMCONTEXT_H

View File

@ -43,6 +43,7 @@
#include "qeglfswindow.h"
#include "qeglfscursor.h"
#include "qeglfshooks.h"
#include "qeglfsintegration.h"
#include <QtDebug>
@ -50,7 +51,7 @@ QT_BEGIN_NAMESPACE
QEglFSContext::QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share,
EGLDisplay display, EGLenum eglApi)
: QEGLPlatformContext(hooks->surfaceFormatFor(format), share, display, eglApi)
: QEGLPlatformContext(format, share, display, QEglFSIntegration::chooseConfig(display, format), eglApi)
{
}

View File

@ -67,6 +67,7 @@ public:
virtual void destroyNativeWindow(EGLNativeWindowType window);
virtual bool hasCapability(QPlatformIntegration::Capability cap) const;
virtual QEglFSCursor *createCursor(QEglFSScreen *screen) const;
virtual bool filterConfig(EGLDisplay display, EGLConfig config) const;
};
#ifdef EGLFS_PLATFORM_HOOKS

View File

@ -134,6 +134,11 @@ QSurfaceFormat QEglFSHooks::surfaceFormatFor(const QSurfaceFormat &inputFormat)
return inputFormat;
}
bool QEglFSHooks::filterConfig(EGLDisplay, EGLConfig) const
{
return true;
}
EGLNativeWindowType QEglFSHooks::createNativeWindow(const QSize &size, const QSurfaceFormat &format)
{
Q_UNUSED(size);

View File

@ -49,6 +49,7 @@
#include <QtPlatformSupport/private/qgenericunixfontdatabase_p.h>
#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
#include <QtPlatformSupport/private/qeglconvenience_p.h>
#include <QtPlatformSupport/private/qeglplatformcontext_p.h>
#if !defined(QT_NO_EVDEV)
@ -150,7 +151,7 @@ QPlatformBackingStore *QEglFSIntegration::createPlatformBackingStore(QWindow *wi
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
@ -201,4 +202,29 @@ void *QEglFSIntegration::nativeResourceForContext(const QByteArray &resource, QO
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

View File

@ -75,6 +75,8 @@ public:
void *nativeResourceForIntegration(const QByteArray &resource);
void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context);
static EGLConfig chooseConfig(EGLDisplay display, const QSurfaceFormat &format);
private:
EGLDisplay mDisplay;
QAbstractEventDispatcher *mEventDispatcher;

View File

@ -84,7 +84,8 @@ void QEglFSWindow::create()
EGLDisplay display = (static_cast<QEglFSScreen *>(window()->screen()->handle()))->display();
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_window = hooks->createNativeWindow(hooks->screenSize(), m_format);
m_surface = eglCreateWindowSurface(display, config, m_window, NULL);