X11: Better support non-32bit visuals
This patch improves support for non-32bit screen configurations on X. The patch mostly touches the xcb platform plugin but the changes to the glx convenience functions do affect e.g. the offscreen plugin as well. Since QWindow instances are now by default of type RasterGL instead of Raster the majority of all windows are in fact instances of QXcbGlxWindow. This means that the eventual QSurfaceFormat that we use is chosen based on the available OpenGL configurations. Here the GLX config resolution code did not do a very good job in trying to find the closest match relative to the requested QSurfaceFormat, instead preferring higher bit depths. This is an issue since many configurations support 32-bit windows even if the screen itself has a root window with depth 16. In particular, servers supporting both GLX and Render are very likely to have such visuals. Particularly affected are remote X connections - even if the application itself makes no use of OpenGL at all! The changes introduced by this patch are as follows: 1. Improve the GLX visual selection logic 2. Improve the xcb visual selection logic 3. Remove duplicated visual lookup for OpenGL-enabled windows 4. Configure the default QSurfaceFormat to match the primary screen depth Change-Id: Id1c176359e63a4581410e20350db5ac2c083e1cf Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com> Reviewed-by: Laszlo Agocs <laszlo.agocs@theqtcompany.com>bb10
parent
8903460093
commit
5f39a0ef8d
|
|
@ -40,6 +40,7 @@
|
|||
// We have to include this before the X11 headers dragged in by
|
||||
// qglxconvenience_p.h.
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QScopedPointer>
|
||||
|
||||
#include "qglxconvenience_p.h"
|
||||
|
||||
|
|
@ -77,173 +78,181 @@ enum {
|
|||
|
||||
QVector<int> qglx_buildSpec(const QSurfaceFormat &format, int drawableBit)
|
||||
{
|
||||
QVector<int> spec(48);
|
||||
int i = 0;
|
||||
QVector<int> spec;
|
||||
|
||||
spec[i++] = GLX_LEVEL;
|
||||
spec[i++] = 0;
|
||||
spec[i++] = GLX_DRAWABLE_TYPE; spec[i++] = drawableBit;
|
||||
spec << GLX_LEVEL
|
||||
<< 0
|
||||
|
||||
spec[i++] = GLX_RENDER_TYPE; spec[i++] = GLX_RGBA_BIT;
|
||||
<< GLX_RENDER_TYPE
|
||||
<< 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.hasAlpha()) {
|
||||
spec[i++] = GLX_ALPHA_SIZE; spec[i++] = format.alphaBufferSize();
|
||||
}
|
||||
<< GLX_RED_SIZE
|
||||
<< qMax(1, format.redBufferSize())
|
||||
|
||||
spec[i++] = GLX_DOUBLEBUFFER; spec[i++] = format.swapBehavior() != QSurfaceFormat::SingleBuffer ? True : False;
|
||||
<< GLX_GREEN_SIZE
|
||||
<< qMax(1, format.greenBufferSize())
|
||||
|
||||
spec[i++] = GLX_STEREO; spec[i++] = format.stereo() ? True : False;
|
||||
<< GLX_BLUE_SIZE
|
||||
<< qMax(1, format.blueBufferSize())
|
||||
|
||||
if (format.depthBufferSize() > 0) {
|
||||
spec[i++] = GLX_DEPTH_SIZE; spec[i++] = format.depthBufferSize();
|
||||
}
|
||||
<< GLX_ALPHA_SIZE
|
||||
<< qMax(0, format.alphaBufferSize());
|
||||
|
||||
if (format.stencilBufferSize() > 0) {
|
||||
spec[i++] = GLX_STENCIL_SIZE; spec[i++] = (format.stencilBufferSize() == -1) ? 1 : format.stencilBufferSize();
|
||||
}
|
||||
if (format.swapBehavior() != QSurfaceFormat::SingleBuffer)
|
||||
spec << GLX_DOUBLEBUFFER
|
||||
<< True;
|
||||
|
||||
if (format.samples() > 1) {
|
||||
spec[i++] = GLX_SAMPLE_BUFFERS_ARB;
|
||||
spec[i++] = 1;
|
||||
spec[i++] = GLX_SAMPLES_ARB;
|
||||
spec[i++] = format.samples();
|
||||
}
|
||||
if (format.stereo())
|
||||
spec << GLX_STEREO
|
||||
<< True;
|
||||
|
||||
if (format.depthBufferSize() != -1)
|
||||
spec << GLX_DEPTH_SIZE
|
||||
<< format.depthBufferSize();
|
||||
|
||||
if (format.stencilBufferSize() != -1)
|
||||
spec << GLX_STENCIL_SIZE
|
||||
<< format.stencilBufferSize();
|
||||
|
||||
if (format.samples() > 1)
|
||||
spec << GLX_SAMPLE_BUFFERS_ARB
|
||||
<< 1
|
||||
<< GLX_SAMPLES_ARB
|
||||
<< format.samples();
|
||||
|
||||
spec << GLX_DRAWABLE_TYPE
|
||||
<< drawableBit
|
||||
|
||||
<< XNone;
|
||||
|
||||
spec[i++] = XNone;
|
||||
return spec;
|
||||
}
|
||||
|
||||
GLXFBConfig qglx_findConfig(Display *display, int screen , const QSurfaceFormat &format, int drawableBit)
|
||||
{
|
||||
// Allow forcing LIBGL_ALWAYS_SOFTWARE for Qt 5 applications only.
|
||||
// This is most useful with drivers that only support OpenGL 1.
|
||||
// We need OpenGL 2, but the user probably doesn't want
|
||||
// LIBGL_ALWAYS_SOFTWARE in OpenGL 1 apps.
|
||||
static bool checkedForceSoftwareOpenGL = false;
|
||||
static bool forceSoftwareOpenGL = false;
|
||||
if (!checkedForceSoftwareOpenGL) {
|
||||
// If LIBGL_ALWAYS_SOFTWARE is already set, don't mess with it.
|
||||
// We want to unset LIBGL_ALWAYS_SOFTWARE at the end so it does not
|
||||
// get inherited by other processes, of course only if it wasn't
|
||||
// already set before.
|
||||
if (!qEnvironmentVariableIsEmpty("QT_XCB_FORCE_SOFTWARE_OPENGL")
|
||||
&& !qEnvironmentVariableIsSet("LIBGL_ALWAYS_SOFTWARE"))
|
||||
forceSoftwareOpenGL = true;
|
||||
namespace {
|
||||
struct QXcbSoftwareOpenGLEnforcer {
|
||||
QXcbSoftwareOpenGLEnforcer() {
|
||||
// Allow forcing LIBGL_ALWAYS_SOFTWARE for Qt 5 applications only.
|
||||
// This is most useful with drivers that only support OpenGL 1.
|
||||
// We need OpenGL 2, but the user probably doesn't want
|
||||
// LIBGL_ALWAYS_SOFTWARE in OpenGL 1 apps.
|
||||
|
||||
checkedForceSoftwareOpenGL = true;
|
||||
}
|
||||
if (!checkedForceSoftwareOpenGL) {
|
||||
// If LIBGL_ALWAYS_SOFTWARE is already set, don't mess with it.
|
||||
// We want to unset LIBGL_ALWAYS_SOFTWARE at the end so it does not
|
||||
// get inherited by other processes, of course only if it wasn't
|
||||
// already set before.
|
||||
if (!qEnvironmentVariableIsEmpty("QT_XCB_FORCE_SOFTWARE_OPENGL")
|
||||
&& !qEnvironmentVariableIsSet("LIBGL_ALWAYS_SOFTWARE"))
|
||||
forceSoftwareOpenGL = true;
|
||||
|
||||
if (forceSoftwareOpenGL)
|
||||
qputenv("LIBGL_ALWAYS_SOFTWARE", QByteArrayLiteral("1"));
|
||||
|
||||
bool reduced = true;
|
||||
GLXFBConfig chosenConfig = 0;
|
||||
QSurfaceFormat 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.hasAlpha()) {
|
||||
int alphaSize;
|
||||
glXGetFBConfigAttrib(display,configs[i],GLX_ALPHA_SIZE,&alphaSize);
|
||||
if (alphaSize > 0) {
|
||||
XVisualInfo *visual = glXGetVisualFromFBConfig(display, chosenConfig);
|
||||
bool hasAlpha = false;
|
||||
|
||||
#if !defined(QT_NO_XRENDER)
|
||||
XRenderPictFormat *pictFormat = XRenderFindVisualFormat(display, visual->visual);
|
||||
hasAlpha = pictFormat->direct.alphaMask > 0;
|
||||
#else
|
||||
hasAlpha = visual->depth == 32;
|
||||
#endif
|
||||
|
||||
XFree(visual);
|
||||
|
||||
if (hasAlpha)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break; // Just choose the first in the list if there's no alpha requested
|
||||
}
|
||||
}
|
||||
|
||||
XFree(configs);
|
||||
checkedForceSoftwareOpenGL = true;
|
||||
}
|
||||
if (!chosenConfig)
|
||||
reducedFormat = qglx_reduceSurfaceFormat(reducedFormat,&reduced);
|
||||
|
||||
if (forceSoftwareOpenGL)
|
||||
qputenv("LIBGL_ALWAYS_SOFTWARE", QByteArrayLiteral("1"));
|
||||
}
|
||||
|
||||
// unset LIBGL_ALWAYS_SOFTWARE now so other processes don't inherit it
|
||||
if (forceSoftwareOpenGL)
|
||||
qunsetenv("LIBGL_ALWAYS_SOFTWARE");
|
||||
~QXcbSoftwareOpenGLEnforcer() {
|
||||
// unset LIBGL_ALWAYS_SOFTWARE now so other processes don't inherit it
|
||||
if (forceSoftwareOpenGL)
|
||||
qunsetenv("LIBGL_ALWAYS_SOFTWARE");
|
||||
}
|
||||
|
||||
return chosenConfig;
|
||||
static bool checkedForceSoftwareOpenGL;
|
||||
static bool forceSoftwareOpenGL;
|
||||
};
|
||||
|
||||
bool QXcbSoftwareOpenGLEnforcer::checkedForceSoftwareOpenGL = false;
|
||||
bool QXcbSoftwareOpenGLEnforcer::forceSoftwareOpenGL = false;
|
||||
|
||||
template <class T>
|
||||
struct QXlibScopedPointerDeleter {
|
||||
static inline void cleanup(T *pointer) {
|
||||
XFree(pointer);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
using QXlibPointer = QScopedPointer<T, QXlibScopedPointerDeleter<T>>;
|
||||
|
||||
template <class T>
|
||||
using QXlibArrayPointer = QScopedArrayPointer<T, QXlibScopedPointerDeleter<T>>;
|
||||
}
|
||||
|
||||
XVisualInfo *qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *format)
|
||||
GLXFBConfig qglx_findConfig(Display *display, int screen , QSurfaceFormat format, bool highestPixelFormat, int drawableBit)
|
||||
{
|
||||
QXcbSoftwareOpenGLEnforcer softwareOpenGLEnforcer;
|
||||
|
||||
GLXFBConfig config = 0;
|
||||
|
||||
do {
|
||||
const QVector<int> spec = qglx_buildSpec(format, drawableBit);
|
||||
|
||||
int confcount = 0;
|
||||
QXlibArrayPointer<GLXFBConfig> configs(glXChooseFBConfig(display, screen, spec.constData(), &confcount));
|
||||
|
||||
if (!config && confcount > 0) {
|
||||
config = configs[0];
|
||||
if (highestPixelFormat && !format.hasAlpha())
|
||||
break;
|
||||
}
|
||||
|
||||
const int requestedRed = qMax(0, format.redBufferSize());
|
||||
const int requestedGreen = qMax(0, format.greenBufferSize());
|
||||
const int requestedBlue = qMax(0, format.blueBufferSize());
|
||||
const int requestedAlpha = qMax(0, format.alphaBufferSize());
|
||||
|
||||
for (int i = 0; i < confcount; i++) {
|
||||
GLXFBConfig candidate = configs[i];
|
||||
|
||||
QXlibPointer<XVisualInfo> visual(glXGetVisualFromFBConfig(display, candidate));
|
||||
|
||||
const int actualRed = qPopulationCount(visual->red_mask);
|
||||
const int actualGreen = qPopulationCount(visual->green_mask);
|
||||
const int actualBlue = qPopulationCount(visual->blue_mask);
|
||||
const int actualAlpha = visual->depth - actualRed - actualGreen - actualBlue;
|
||||
|
||||
if (requestedRed && actualRed != requestedRed)
|
||||
continue;
|
||||
if (requestedGreen && actualGreen != requestedGreen)
|
||||
continue;
|
||||
if (requestedBlue && actualBlue != requestedBlue)
|
||||
continue;
|
||||
if (requestedAlpha && actualAlpha != requestedAlpha)
|
||||
continue;
|
||||
|
||||
return candidate;
|
||||
}
|
||||
} while (qglx_reduceFormat(&format));
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
XVisualInfo *qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *format, int drawableBit)
|
||||
{
|
||||
Q_ASSERT(format);
|
||||
|
||||
XVisualInfo *visualInfo = 0;
|
||||
|
||||
GLXFBConfig config = qglx_findConfig(display,screen,*format);
|
||||
if (config) {
|
||||
GLXFBConfig config = qglx_findConfig(display, screen, *format, false, drawableBit);
|
||||
if (config)
|
||||
visualInfo = glXGetVisualFromFBConfig(display, config);
|
||||
|
||||
if (visualInfo) {
|
||||
qglx_surfaceFormatFromGLXFBConfig(format, display, config);
|
||||
return visualInfo;
|
||||
}
|
||||
|
||||
// attempt to fall back to glXChooseVisual
|
||||
bool reduced = true;
|
||||
QSurfaceFormat reducedFormat = *format;
|
||||
while (!visualInfo && reduced) {
|
||||
QVarLengthArray<int, 13> attribs;
|
||||
attribs.append(GLX_RGBA);
|
||||
|
||||
if (reducedFormat.redBufferSize() > 0) {
|
||||
attribs.append(GLX_RED_SIZE);
|
||||
attribs.append(reducedFormat.redBufferSize());
|
||||
}
|
||||
|
||||
if (reducedFormat.greenBufferSize() > 0) {
|
||||
attribs.append(GLX_GREEN_SIZE);
|
||||
attribs.append(reducedFormat.greenBufferSize());
|
||||
}
|
||||
|
||||
if (reducedFormat.blueBufferSize() > 0) {
|
||||
attribs.append(GLX_BLUE_SIZE);
|
||||
attribs.append(reducedFormat.blueBufferSize());
|
||||
}
|
||||
|
||||
if (reducedFormat.stencilBufferSize() > 0) {
|
||||
attribs.append(GLX_STENCIL_SIZE);
|
||||
attribs.append(reducedFormat.stencilBufferSize());
|
||||
}
|
||||
|
||||
if (reducedFormat.depthBufferSize() > 0) {
|
||||
attribs.append(GLX_DEPTH_SIZE);
|
||||
attribs.append(reducedFormat.depthBufferSize());
|
||||
}
|
||||
|
||||
if (reducedFormat.swapBehavior() != QSurfaceFormat::SingleBuffer)
|
||||
attribs.append(GLX_DOUBLEBUFFER);
|
||||
|
||||
attribs.append(XNone);
|
||||
|
||||
do {
|
||||
QVector<int> attribs = qglx_buildSpec(*format, drawableBit);
|
||||
visualInfo = glXChooseVisual(display, screen, attribs.data());
|
||||
if (visualInfo)
|
||||
*format = reducedFormat;
|
||||
|
||||
reducedFormat = qglx_reduceSurfaceFormat(reducedFormat, &reduced);
|
||||
}
|
||||
if (visualInfo) {
|
||||
qglx_surfaceFormatFromVisualInfo(format, display, visualInfo);
|
||||
return visualInfo;
|
||||
}
|
||||
} while (qglx_reduceFormat(format));
|
||||
|
||||
return visualInfo;
|
||||
}
|
||||
|
|
@ -318,33 +327,64 @@ void qglx_surfaceFormatFromVisualInfo(QSurfaceFormat *format, Display *display,
|
|||
format->setStereo(stereo);
|
||||
}
|
||||
|
||||
QSurfaceFormat qglx_reduceSurfaceFormat(const QSurfaceFormat &format, bool *reduced)
|
||||
bool qglx_reduceFormat(QSurfaceFormat *format)
|
||||
{
|
||||
QSurfaceFormat retFormat = format;
|
||||
*reduced = true;
|
||||
Q_ASSERT(format);
|
||||
|
||||
if (retFormat.depthBufferSize() >= 32) {
|
||||
retFormat.setDepthBufferSize(24);
|
||||
} else if (retFormat.depthBufferSize() > 0) {
|
||||
retFormat.setDepthBufferSize(0);
|
||||
} else if (retFormat.redBufferSize() > 1) {
|
||||
retFormat.setRedBufferSize(1);
|
||||
} else if (retFormat.greenBufferSize() > 1) {
|
||||
retFormat.setGreenBufferSize(1);
|
||||
} else if (retFormat.blueBufferSize() > 1) {
|
||||
retFormat.setBlueBufferSize(1);
|
||||
} else if (retFormat.samples() > 1) {
|
||||
retFormat.setSamples(qMin(retFormat.samples() / 2, 16));
|
||||
} else if (retFormat.stereo()) {
|
||||
retFormat.setStereo(false);
|
||||
}else if (retFormat.stencilBufferSize() > 0) {
|
||||
retFormat.setStencilBufferSize(0);
|
||||
}else if (retFormat.hasAlpha()) {
|
||||
retFormat.setAlphaBufferSize(0);
|
||||
}else if (retFormat.swapBehavior() != QSurfaceFormat::SingleBuffer) {
|
||||
retFormat.setSwapBehavior(QSurfaceFormat::SingleBuffer);
|
||||
}else{
|
||||
*reduced = false;
|
||||
if (format->redBufferSize() > 1) {
|
||||
format->setRedBufferSize(1);
|
||||
return true;
|
||||
}
|
||||
return retFormat;
|
||||
|
||||
if (format->greenBufferSize() > 1) {
|
||||
format->setGreenBufferSize(1);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (format->blueBufferSize() > 1) {
|
||||
format->setBlueBufferSize(1);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (format->swapBehavior() != QSurfaceFormat::SingleBuffer){
|
||||
format->setSwapBehavior(QSurfaceFormat::SingleBuffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (format->samples() > 1) {
|
||||
format->setSamples(qMin(16, format->samples() / 2));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (format->depthBufferSize() >= 32) {
|
||||
format->setDepthBufferSize(24);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (format->depthBufferSize() > 1) {
|
||||
format->setDepthBufferSize(1);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (format->depthBufferSize() > 0) {
|
||||
format->setDepthBufferSize(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (format->hasAlpha()) {
|
||||
format->setAlphaBufferSize(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (format->stencilBufferSize() > 1) {
|
||||
format->setStencilBufferSize(1);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (format->stencilBufferSize() > 0) {
|
||||
format->setStencilBufferSize(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,11 +57,11 @@
|
|||
#include <X11/Xlib.h>
|
||||
#include <GL/glx.h>
|
||||
|
||||
XVisualInfo *qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *format);
|
||||
GLXFBConfig qglx_findConfig(Display *display, int screen, const QSurfaceFormat &format, int drawableBit = GLX_WINDOW_BIT);
|
||||
QVector<int> qglx_buildSpec(const QSurfaceFormat &format, int drawableBit = GLX_WINDOW_BIT);
|
||||
XVisualInfo *qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *format, int drawableBit = GLX_WINDOW_BIT);
|
||||
GLXFBConfig qglx_findConfig(Display *display, int screen, QSurfaceFormat format, bool highestPixelFormat = false, int drawableBit = GLX_WINDOW_BIT);
|
||||
void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display, GLXFBConfig config);
|
||||
void qglx_surfaceFormatFromVisualInfo(QSurfaceFormat *format, Display *display, XVisualInfo *visualInfo);
|
||||
QVector<int> qglx_buildSpec(const QSurfaceFormat &format, int drawableBit = GLX_WINDOW_BIT);
|
||||
QSurfaceFormat qglx_reduceSurfaceFormat(const QSurfaceFormat &format, bool *reduced);
|
||||
bool qglx_reduceFormat(QSurfaceFormat *format);
|
||||
|
||||
#endif // QGLXCONVENIENCE_H
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ QXcbWindow *QXcbEglIntegration::createWindow(QWindow *window) const
|
|||
QPlatformOpenGLContext *QXcbEglIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
|
||||
{
|
||||
QXcbScreen *screen = static_cast<QXcbScreen *>(context->screen()->handle());
|
||||
QXcbEglContext *platformContext = new QXcbEglContext(context->format(),
|
||||
QXcbEglContext *platformContext = new QXcbEglContext(screen->surfaceFormatFor(context->format()),
|
||||
context->shareHandle(),
|
||||
eglDisplay(),
|
||||
screen->connection(),
|
||||
|
|
@ -98,7 +98,8 @@ QPlatformOpenGLContext *QXcbEglIntegration::createPlatformOpenGLContext(QOpenGLC
|
|||
|
||||
QPlatformOffscreenSurface *QXcbEglIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const
|
||||
{
|
||||
return new QEGLPbuffer(eglDisplay(), surface->requestedFormat(), surface);
|
||||
QXcbScreen *screen = static_cast<QXcbScreen *>(surface->screen()->handle());
|
||||
return new QEGLPbuffer(eglDisplay(), screen->surfaceFormatFor(surface->requestedFormat()), surface);
|
||||
}
|
||||
|
||||
void *QXcbEglIntegration::xlib_display() const
|
||||
|
|
|
|||
|
|
@ -59,15 +59,19 @@ QXcbEglWindow::~QXcbEglWindow()
|
|||
eglDestroySurface(m_glIntegration->eglDisplay(), m_surface);
|
||||
}
|
||||
|
||||
void QXcbEglWindow::resolveFormat()
|
||||
void QXcbEglWindow::resolveFormat(const QSurfaceFormat &format)
|
||||
{
|
||||
m_config = q_configFromGLFormat(m_glIntegration->eglDisplay(), window()->requestedFormat(), true);
|
||||
m_format = q_glFormatFromConfig(m_glIntegration->eglDisplay(), m_config, m_format);
|
||||
m_config = q_configFromGLFormat(m_glIntegration->eglDisplay(), format);
|
||||
m_format = q_glFormatFromConfig(m_glIntegration->eglDisplay(), m_config, format);
|
||||
}
|
||||
|
||||
void *QXcbEglWindow::createVisual()
|
||||
{
|
||||
#ifdef XCB_USE_XLIB
|
||||
const xcb_visualtype_t *QXcbEglWindow::createVisual()
|
||||
{
|
||||
QXcbScreen *scr = xcbScreen();
|
||||
if (!scr)
|
||||
return QXcbWindow::createVisual();
|
||||
|
||||
Display *xdpy = static_cast<Display *>(m_glIntegration->xlib_display());
|
||||
VisualID id = QXlibEglIntegration::getCompatibleVisualId(xdpy, m_glIntegration->eglDisplay(), m_config);
|
||||
|
||||
|
|
@ -78,11 +82,12 @@ void *QXcbEglWindow::createVisual()
|
|||
XVisualInfo *visualInfo;
|
||||
int matchingCount = 0;
|
||||
visualInfo = XGetVisualInfo(xdpy, VisualIDMask, &visualInfoTemplate, &matchingCount);
|
||||
return visualInfo;
|
||||
#else
|
||||
return QXcbWindow::createVisual();
|
||||
#endif
|
||||
const xcb_visualtype_t *xcb_visualtype = scr->visualForId(visualInfo->visualid);
|
||||
XFree(visualInfo);
|
||||
|
||||
return xcb_visualtype;
|
||||
}
|
||||
#endif
|
||||
|
||||
void QXcbEglWindow::create()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -60,8 +60,11 @@ public:
|
|||
|
||||
protected:
|
||||
void create() Q_DECL_OVERRIDE;
|
||||
void resolveFormat() Q_DECL_OVERRIDE;
|
||||
void *createVisual() Q_DECL_OVERRIDE;
|
||||
void resolveFormat(const QSurfaceFormat &format) Q_DECL_OVERRIDE;
|
||||
|
||||
#ifdef XCB_USE_XLIB
|
||||
const xcb_visualtype_t *createVisual() Q_DECL_OVERRIDE;
|
||||
#endif
|
||||
|
||||
private:
|
||||
QXcbEglIntegration *m_glIntegration;
|
||||
|
|
|
|||
|
|
@ -715,8 +715,8 @@ bool QGLXContext::supportsThreading()
|
|||
|
||||
QGLXPbuffer::QGLXPbuffer(QOffscreenSurface *offscreenSurface)
|
||||
: QPlatformOffscreenSurface(offscreenSurface)
|
||||
, m_format(offscreenSurface->requestedFormat())
|
||||
, m_screen(static_cast<QXcbScreen *>(offscreenSurface->screen()->handle()))
|
||||
, m_format(m_screen->surfaceFormatFor(offscreenSurface->requestedFormat()))
|
||||
, m_pbuffer(0)
|
||||
{
|
||||
GLXFBConfig config = qglx_findConfig(DISPLAY_FROM_XCB(m_screen), m_screen->screenNumber(), m_format);
|
||||
|
|
|
|||
|
|
@ -106,8 +106,8 @@ public:
|
|||
GLXPbuffer pbuffer() const { return m_pbuffer; }
|
||||
|
||||
private:
|
||||
QSurfaceFormat m_format;
|
||||
QXcbScreen *m_screen;
|
||||
QSurfaceFormat m_format;
|
||||
GLXPbuffer m_pbuffer;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ QXcbWindow *QXcbGlxIntegration::createWindow(QWindow *window) const
|
|||
QPlatformOpenGLContext *QXcbGlxIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
|
||||
{
|
||||
QXcbScreen *screen = static_cast<QXcbScreen *>(context->screen()->handle());
|
||||
QGLXContext *platformContext = new QGLXContext(screen, context->format(),
|
||||
QGLXContext *platformContext = new QGLXContext(screen, screen->surfaceFormatFor(context->format()),
|
||||
context->shareHandle(), context->nativeHandle());
|
||||
context->setNativeHandle(platformContext->nativeHandle());
|
||||
return platformContext;
|
||||
|
|
|
|||
|
|
@ -53,17 +53,15 @@ QXcbGlxWindow::~QXcbGlxWindow()
|
|||
{
|
||||
}
|
||||
|
||||
void QXcbGlxWindow::resolveFormat()
|
||||
{
|
||||
m_format = window()->requestedFormat(); //qglx_findVisualInfo sets the resovled format
|
||||
}
|
||||
|
||||
void *QXcbGlxWindow::createVisual()
|
||||
const xcb_visualtype_t *QXcbGlxWindow::createVisual()
|
||||
{
|
||||
QXcbScreen *scr = xcbScreen();
|
||||
if (!scr)
|
||||
return Q_NULLPTR;
|
||||
return qglx_findVisualInfo(DISPLAY_FROM_XCB(scr), scr->screenNumber(), &m_format);
|
||||
XVisualInfo *visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(scr), scr->screenNumber(), &m_format);
|
||||
const xcb_visualtype_t *xcb_visualtype = scr->visualForId(visualInfo->visualid);
|
||||
XFree(visualInfo);
|
||||
return xcb_visualtype;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -52,8 +52,7 @@ public:
|
|||
~QXcbGlxWindow();
|
||||
|
||||
protected:
|
||||
void resolveFormat() Q_DECL_OVERRIDE;
|
||||
void *createVisual() Q_DECL_OVERRIDE;
|
||||
const xcb_visualtype_t *createVisual() Q_DECL_OVERRIDE;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QtAlgorithms>
|
||||
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
#include <private/qmath_p.h>
|
||||
|
|
@ -359,6 +360,69 @@ void QXcbScreen::windowShown(QXcbWindow *window)
|
|||
}
|
||||
}
|
||||
|
||||
QSurfaceFormat QXcbScreen::surfaceFormatFor(const QSurfaceFormat &format) const
|
||||
{
|
||||
const xcb_visualid_t xcb_visualid = connection()->hasDefaultVisualId() ? connection()->defaultVisualId()
|
||||
: screen()->root_visual;
|
||||
const xcb_visualtype_t *xcb_visualtype = visualForId(xcb_visualid);
|
||||
|
||||
const int redSize = qPopulationCount(xcb_visualtype->red_mask);
|
||||
const int greenSize = qPopulationCount(xcb_visualtype->green_mask);
|
||||
const int blueSize = qPopulationCount(xcb_visualtype->blue_mask);
|
||||
|
||||
QSurfaceFormat result = format;
|
||||
|
||||
if (result.redBufferSize() < 0)
|
||||
result.setRedBufferSize(redSize);
|
||||
|
||||
if (result.greenBufferSize() < 0)
|
||||
result.setGreenBufferSize(greenSize);
|
||||
|
||||
if (result.blueBufferSize() < 0)
|
||||
result.setBlueBufferSize(blueSize);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const xcb_visualtype_t *QXcbScreen::visualForFormat(const QSurfaceFormat &format) const
|
||||
{
|
||||
QVector<const xcb_visualtype_t *> candidates;
|
||||
|
||||
for (auto ii = m_visuals.constBegin(); ii != m_visuals.constEnd(); ++ii) {
|
||||
const xcb_visualtype_t &xcb_visualtype = ii.value();
|
||||
|
||||
const int redSize = qPopulationCount(xcb_visualtype.red_mask);
|
||||
const int greenSize = qPopulationCount(xcb_visualtype.green_mask);
|
||||
const int blueSize = qPopulationCount(xcb_visualtype.blue_mask);
|
||||
const int alphaSize = depthOfVisual(xcb_visualtype.visual_id) - redSize - greenSize - blueSize;
|
||||
|
||||
if (format.redBufferSize() != -1 && redSize != format.redBufferSize())
|
||||
continue;
|
||||
|
||||
if (format.greenBufferSize() != -1 && greenSize != format.greenBufferSize())
|
||||
continue;
|
||||
|
||||
if (format.blueBufferSize() != -1 && blueSize != format.blueBufferSize())
|
||||
continue;
|
||||
|
||||
if (format.alphaBufferSize() != -1 && alphaSize != format.alphaBufferSize())
|
||||
continue;
|
||||
|
||||
candidates.append(&xcb_visualtype);
|
||||
}
|
||||
|
||||
if (candidates.isEmpty())
|
||||
return nullptr;
|
||||
|
||||
// Try to find a RGB visual rather than e.g. BGR or GBR
|
||||
for (const xcb_visualtype_t *candidate : qAsConst(candidates))
|
||||
if (qCountTrailingZeroBits(candidate->blue_mask) == 0)
|
||||
return candidate;
|
||||
|
||||
// Did not find anything we like, just grab the first one and hope for the best
|
||||
return candidates.first();
|
||||
}
|
||||
|
||||
void QXcbScreen::sendStartupMessage(const QByteArray &message) const
|
||||
{
|
||||
xcb_window_t rootWindow = root();
|
||||
|
|
@ -403,7 +467,7 @@ quint8 QXcbScreen::depthOfVisual(xcb_visualid_t visualid) const
|
|||
|
||||
QImage::Format QXcbScreen::format() const
|
||||
{
|
||||
return QImage::Format_RGB32;
|
||||
return qt_xcb_imageFormatForVisual(connection(), screen()->root_depth, visualForId(screen()->root_visual));
|
||||
}
|
||||
|
||||
QDpi QXcbScreen::virtualDpi() const
|
||||
|
|
|
|||
|
|
@ -155,6 +155,9 @@ public:
|
|||
QString windowManagerName() const { return m_windowManagerName; }
|
||||
bool syncRequestSupported() const { return m_syncRequestSupported; }
|
||||
|
||||
QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &format) const;
|
||||
|
||||
const xcb_visualtype_t *visualForFormat(const QSurfaceFormat &format) const;
|
||||
const xcb_visualtype_t *visualForId(xcb_visualid_t) const;
|
||||
quint8 depthOfVisual(xcb_visualid_t) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -382,18 +382,6 @@ void QXcbWindow::create()
|
|||
return;
|
||||
}
|
||||
|
||||
const quint32 mask = XCB_CW_BACK_PIXMAP | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_SAVE_UNDER | XCB_CW_EVENT_MASK;
|
||||
const quint32 values[] = {
|
||||
// XCB_CW_BACK_PIXMAP
|
||||
XCB_NONE,
|
||||
// XCB_CW_OVERRIDE_REDIRECT
|
||||
type == Qt::Popup || type == Qt::ToolTip || (window()->flags() & Qt::BypassWindowManagerHint),
|
||||
// XCB_CW_SAVE_UNDER
|
||||
type == Qt::Popup || type == Qt::Tool || type == Qt::SplashScreen || type == Qt::ToolTip || type == Qt::Drawer,
|
||||
// XCB_CW_EVENT_MASK
|
||||
defaultEventMask
|
||||
};
|
||||
|
||||
// Parameters to XCreateWindow() are frame corner + inner size.
|
||||
// This fits in case position policy is frame inclusive. There is
|
||||
// currently no way to implement it for frame-exclusive geometries.
|
||||
|
|
@ -424,108 +412,76 @@ void QXcbWindow::create()
|
|||
}
|
||||
}
|
||||
|
||||
resolveFormat();
|
||||
resolveFormat(platformScreen->surfaceFormatFor(window()->requestedFormat()));
|
||||
|
||||
#ifdef XCB_USE_XLIB
|
||||
if (window()->surfaceType() != QSurface::RasterSurface
|
||||
&& QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)) {
|
||||
XVisualInfo *visualInfo = Q_NULLPTR;
|
||||
if (connection()->hasDefaultVisualId())
|
||||
visualInfo = CREATE_VISUALINFO_FROM_DEFAULT_VISUALID(this);
|
||||
if (!visualInfo)
|
||||
visualInfo = static_cast<XVisualInfo *>(createVisual());
|
||||
const xcb_visualtype_t *visual = Q_NULLPTR;
|
||||
|
||||
if (Q_UNLIKELY(!visualInfo && window()->surfaceType() == QSurface::OpenGLSurface))
|
||||
qFatal("Could not initialize OpenGL");
|
||||
|
||||
if (!visualInfo && window()->surfaceType() == QSurface::RasterGLSurface) {
|
||||
qWarning("Could not initialize OpenGL for RasterGLSurface, reverting to RasterSurface.");
|
||||
window()->setSurfaceType(QSurface::RasterSurface);
|
||||
}
|
||||
|
||||
if (visualInfo) {
|
||||
m_depth = visualInfo->depth;
|
||||
m_imageFormat = imageFormatForVisual(visualInfo->depth, visualInfo->red_mask, visualInfo->blue_mask, &m_imageRgbSwap);
|
||||
Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(this), xcb_parent_id, visualInfo->visual, AllocNone);
|
||||
|
||||
XSetWindowAttributes a;
|
||||
a.background_pixel = WhitePixel(DISPLAY_FROM_XCB(this), platformScreen->screenNumber());
|
||||
a.border_pixel = BlackPixel(DISPLAY_FROM_XCB(this), platformScreen->screenNumber());
|
||||
a.colormap = cmap;
|
||||
|
||||
m_visualId = visualInfo->visualid;
|
||||
|
||||
m_window = XCreateWindow(DISPLAY_FROM_XCB(this), xcb_parent_id, rect.x(), rect.y(), rect.width(), rect.height(),
|
||||
0, visualInfo->depth, InputOutput, visualInfo->visual,
|
||||
CWBackPixel|CWBorderPixel|CWColormap, &a);
|
||||
|
||||
XFree(visualInfo);
|
||||
}
|
||||
if (connection()->hasDefaultVisualId()) {
|
||||
visual = platformScreen->visualForId(connection()->defaultVisualId());
|
||||
if (!visual)
|
||||
qWarning() << "Failed to use requested visual id.";
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!m_window)
|
||||
{
|
||||
m_window = xcb_generate_id(xcb_connection());
|
||||
m_visualId = UINT_MAX;
|
||||
const xcb_visualtype_t *visual = Q_NULLPTR;
|
||||
m_depth = platformScreen->screen()->root_depth;
|
||||
if (!visual)
|
||||
visual = createVisual();
|
||||
|
||||
uint32_t mask = 0;
|
||||
uint32_t values[3];
|
||||
|
||||
if (connection()->hasDefaultVisualId()) {
|
||||
m_visualId = connection()->defaultVisualId();
|
||||
visual = platformScreen->visualForId(m_visualId);
|
||||
}
|
||||
|
||||
if (!visual) {
|
||||
if (connection()->hasDefaultVisualId())
|
||||
qWarning("Failed to use default visual id. Falling back to using screens root_visual");
|
||||
|
||||
m_visualId = platformScreen->screen()->root_visual;
|
||||
|
||||
if (m_format.alphaBufferSize() == 8) {
|
||||
xcb_depth_iterator_t depthIter = xcb_screen_allowed_depths_iterator(platformScreen->screen());
|
||||
while (depthIter.rem) {
|
||||
if (depthIter.data->depth == 32) {
|
||||
xcb_visualtype_iterator_t visualIter = xcb_depth_visuals_iterator(depthIter.data);
|
||||
if (visualIter.rem) {
|
||||
m_visualId = visualIter.data->visual_id;
|
||||
m_depth = 32;
|
||||
uint32_t colormap = xcb_generate_id(xcb_connection());
|
||||
xcb_create_colormap(xcb_connection(), XCB_COLORMAP_ALLOC_NONE, colormap,
|
||||
xcb_parent_id, m_visualId);
|
||||
mask |= XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_COLORMAP;
|
||||
values[0] = platformScreen->screen()->white_pixel;
|
||||
values[1] = platformScreen->screen()->black_pixel;
|
||||
values[2] = colormap;
|
||||
break;
|
||||
}
|
||||
}
|
||||
xcb_depth_next(&depthIter);
|
||||
}
|
||||
}
|
||||
|
||||
visual = platformScreen->visualForId(m_visualId);
|
||||
}
|
||||
|
||||
m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask, &m_imageRgbSwap);
|
||||
Q_XCB_CALL(xcb_create_window(xcb_connection(),
|
||||
m_depth,
|
||||
m_window, // window id
|
||||
xcb_parent_id, // parent window id
|
||||
rect.x(),
|
||||
rect.y(),
|
||||
rect.width(),
|
||||
rect.height(),
|
||||
0, // border width
|
||||
XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class
|
||||
m_visualId, // visual
|
||||
mask,
|
||||
values));
|
||||
if (!visual) {
|
||||
qWarning() << "Falling back to using screens root_visual.";
|
||||
visual = platformScreen->visualForId(platformScreen->screen()->root_visual);
|
||||
}
|
||||
|
||||
Q_ASSERT(visual);
|
||||
|
||||
m_visualId = visual->visual_id;
|
||||
m_depth = platformScreen->depthOfVisual(m_visualId);
|
||||
m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask, &m_imageRgbSwap);
|
||||
xcb_colormap_t colormap = 0;
|
||||
|
||||
quint32 mask = XCB_CW_BACK_PIXMAP
|
||||
| XCB_CW_BORDER_PIXEL
|
||||
| XCB_CW_BIT_GRAVITY
|
||||
| XCB_CW_OVERRIDE_REDIRECT
|
||||
| XCB_CW_SAVE_UNDER
|
||||
| XCB_CW_EVENT_MASK;
|
||||
|
||||
static const bool haveOpenGL = QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL);
|
||||
|
||||
if ((window()->supportsOpenGL() && haveOpenGL) || m_format.hasAlpha()) {
|
||||
colormap = xcb_generate_id(xcb_connection());
|
||||
Q_XCB_CALL(xcb_create_colormap(xcb_connection(),
|
||||
XCB_COLORMAP_ALLOC_NONE,
|
||||
colormap,
|
||||
xcb_parent_id,
|
||||
m_visualId));
|
||||
|
||||
mask |= XCB_CW_COLORMAP;
|
||||
}
|
||||
|
||||
quint32 values[] = {
|
||||
XCB_BACK_PIXMAP_NONE,
|
||||
platformScreen->screen()->black_pixel,
|
||||
XCB_GRAVITY_NORTH_WEST,
|
||||
type == Qt::Popup || type == Qt::ToolTip || (window()->flags() & Qt::BypassWindowManagerHint),
|
||||
type == Qt::Popup || type == Qt::Tool || type == Qt::SplashScreen || type == Qt::ToolTip || type == Qt::Drawer,
|
||||
defaultEventMask,
|
||||
colormap
|
||||
};
|
||||
|
||||
m_window = xcb_generate_id(xcb_connection());
|
||||
Q_XCB_CALL(xcb_create_window(xcb_connection(),
|
||||
m_depth,
|
||||
m_window, // window id
|
||||
xcb_parent_id, // parent window id
|
||||
rect.x(),
|
||||
rect.y(),
|
||||
rect.width(),
|
||||
rect.height(),
|
||||
0, // border width
|
||||
XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class
|
||||
m_visualId, // visual
|
||||
mask,
|
||||
values));
|
||||
|
||||
connection()->addWindowEventListener(m_window, this);
|
||||
|
||||
Q_XCB_CALL(xcb_change_window_attributes(xcb_connection(), m_window, mask, values));
|
||||
|
|
@ -2560,6 +2516,12 @@ void QXcbWindow::updateSyncRequestCounter()
|
|||
}
|
||||
}
|
||||
|
||||
const xcb_visualtype_t *QXcbWindow::createVisual()
|
||||
{
|
||||
return xcbScreen() ? xcbScreen()->visualForFormat(m_format)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
bool QXcbWindow::setKeyboardGrabEnabled(bool grab)
|
||||
{
|
||||
if (grab && !connection()->canGrab())
|
||||
|
|
@ -2831,3 +2793,4 @@ QXcbScreen *QXcbWindow::xcbScreen() const
|
|||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
|
|
|
|||
|
|
@ -182,8 +182,8 @@ public Q_SLOTS:
|
|||
void updateSyncRequestCounter();
|
||||
|
||||
protected:
|
||||
virtual void resolveFormat() { m_format = window()->requestedFormat(); }
|
||||
virtual void *createVisual() { return Q_NULLPTR; }
|
||||
virtual void resolveFormat(const QSurfaceFormat &format) { m_format = format; }
|
||||
virtual const xcb_visualtype_t *createVisual();
|
||||
|
||||
QXcbScreen *parentScreen();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue