Refactoring of EglOnXBackend to allow implementing subclasses

The aim is to allow having an implementing subclass which uses
multiple windows to render to.
This commit is contained in:
Martin Gräßlin 2015-11-25 13:32:36 +01:00
parent b1914b4b2c
commit f8e7d58dea
2 changed files with 78 additions and 38 deletions

View file

@ -172,6 +172,7 @@ bool EglOnXBackend::initRenderingContext()
// Use eglGetPlatformDisplayEXT() to get the display pointer
// if the implementation supports it.
const bool havePlatformBase = hasClientExtension(QByteArrayLiteral("EGL_EXT_platform_base"));
setHavePlatformBase(havePlatformBase);
if (havePlatformBase) {
// Make sure that the X11 platform is supported
if (!hasClientExtension(QByteArrayLiteral("EGL_EXT_platform_x11")))
@ -202,38 +203,17 @@ bool EglOnXBackend::initRenderingContext()
overlayWindow()->setup(None);
}
}
xcb_window_t window = XCB_WINDOW_NONE;
if (m_overlayWindow) {
window = m_overlayWindow->window();
} else if (m_renderingWindow) {
window = m_renderingWindow;
}
if (window == XCB_WINDOW_NONE) {
if (!createSurfaces()) {
qCCritical(KWIN_CORE) << "Creating egl surface failed";
return false;
}
EGLSurface surface = EGL_NO_SURFACE;
if (havePlatformBase) {
// Note: Window is 64 bits on a 64-bit architecture whereas xcb_window_t is
// always 32 bits. eglCreatePlatformWindowSurfaceEXT() expects the
// native_window parameter to be pointer to a Window, so this variable
// cannot be an xcb_window_t.
surface = eglCreatePlatformWindowSurfaceEXT(dpy, config(), (void *) &window, nullptr);
} else {
surface = eglCreateWindowSurface(dpy, config(), window, nullptr);
}
if (surface == EGL_NO_SURFACE) {
return false;
}
setSurface(surface);
if (!createContext()) {
qCCritical(KWIN_CORE) << "Create OpenGL context failed";
return false;
}
if (eglMakeCurrent(dpy, surface, surface, context()) == EGL_FALSE) {
if (!makeContextCurrent(surface())) {
qCCritical(KWIN_CORE) << "Make Context Current failed";
return false;
}
@ -247,6 +227,44 @@ bool EglOnXBackend::initRenderingContext()
return true;
}
bool EglOnXBackend::createSurfaces()
{
xcb_window_t window = XCB_WINDOW_NONE;
if (m_overlayWindow) {
window = m_overlayWindow->window();
} else if (m_renderingWindow) {
window = m_renderingWindow;
}
EGLSurface surface = createSurface(window);
if (surface == EGL_NO_SURFACE) {
return false;
}
setSurface(surface);
return true;
}
EGLSurface EglOnXBackend::createSurface(xcb_window_t window)
{
if (window == XCB_WINDOW_NONE) {
return EGL_NO_SURFACE;
}
EGLSurface surface = EGL_NO_SURFACE;
if (havePlatformBase()) {
// Note: Window is 64 bits on a 64-bit architecture whereas xcb_window_t is
// always 32 bits. eglCreatePlatformWindowSurfaceEXT() expects the
// native_window parameter to be pointer to a Window, so this variable
// cannot be an xcb_window_t.
surface = eglCreatePlatformWindowSurfaceEXT(eglDisplay(), config(), (void *) &window, nullptr);
} else {
surface = eglCreateWindowSurface(eglDisplay(), config(), window, nullptr);
}
return surface;
}
bool EglOnXBackend::initBufferConfigs()
{
const EGLint config_attribs[] = {
@ -294,9 +312,21 @@ void EglOnXBackend::present()
if (lastDamage().isEmpty())
return;
const QSize screenSize = screens()->size();
const QRegion displayRegion(0, 0, screenSize.width(), screenSize.height());
const bool fullRepaint = supportsBufferAge() || (lastDamage() == displayRegion);
presentSurface(surface(), lastDamage(), screens()->geometry());
setLastDamage(QRegion());
if (!supportsBufferAge()) {
eglWaitGL();
xcb_flush(m_connection);
}
}
void EglOnXBackend::presentSurface(EGLSurface surface, const QRegion &damage, const QRect &screenGeometry)
{
if (damage.isEmpty()) {
return;
}
const bool fullRepaint = supportsBufferAge() || (damage == screenGeometry);
if (fullRepaint || !surfaceHasSubPost) {
if (gs_tripleBufferNeedsDetection) {
@ -304,7 +334,7 @@ void EglOnXBackend::present()
m_swapProfiler.begin();
}
// the entire screen changed, or we cannot do partial updates (which implies we enabled surface preservation)
eglSwapBuffers(eglDisplay(), surface());
eglSwapBuffers(eglDisplay(), surface);
if (gs_tripleBufferNeedsDetection) {
eglWaitGL();
if (char result = m_swapProfiler.end()) {
@ -326,20 +356,14 @@ void EglOnXBackend::present()
}
}
if (supportsBufferAge()) {
eglQuerySurface(eglDisplay(), surface(), EGL_BUFFER_AGE_EXT, &m_bufferAge);
eglQuerySurface(eglDisplay(), surface, EGL_BUFFER_AGE_EXT, &m_bufferAge);
}
} else {
// a part of the screen changed, and we can use eglPostSubBufferNV to copy the updated area
foreach (const QRect & r, lastDamage().rects()) {
eglPostSubBufferNV(eglDisplay(), surface(), r.left(), screenSize.height() - r.bottom() - 1, r.width(), r.height());
foreach (const QRect & r, damage.rects()) {
eglPostSubBufferNV(eglDisplay(), surface, r.left(), screenGeometry.height() - r.bottom() - 1, r.width(), r.height());
}
}
setLastDamage(QRegion());
if (!supportsBufferAge()) {
eglWaitGL();
xcb_flush(m_connection);
}
}
void EglOnXBackend::screenGeometryChanged(const QSize &size)
@ -430,6 +454,11 @@ OverlayWindow* EglOnXBackend::overlayWindow()
return m_overlayWindow;
}
bool EglOnXBackend::makeContextCurrent(const EGLSurface &surface)
{
return eglMakeCurrent(eglDisplay(), surface, surface, context()) == EGL_TRUE;
}
/************************************************
* EglTexture
************************************************/

View file

@ -44,6 +44,16 @@ public:
protected:
virtual void present();
void presentSurface(EGLSurface surface, const QRegion &damage, const QRect &screenGeometry);
virtual bool createSurfaces();
EGLSurface createSurface(xcb_window_t window);
void setHavePlatformBase(bool have) {
m_havePlatformBase = have;
}
bool havePlatformBase() const {
return m_havePlatformBase;
}
bool makeContextCurrent(const EGLSurface &surface);
private:
bool initBufferConfigs();
@ -60,6 +70,7 @@ private:
xcb_window_t m_rootWindow;
int m_x11ScreenNumber;
xcb_window_t m_renderingWindow = XCB_WINDOW_NONE;
bool m_havePlatformBase = false;
friend class EglTexture;
};