bool GlxBackend::initBuffer() { if (!initFbConfig()) return false; if (overlayWindow()->create()) { // Try to create double-buffered window in the overlay XVisualInfo* visual = glXGetVisualFromFBConfig(display(), fbconfig); if (!visual) { qCritical() << "Failed to get visual from fbconfig"; return false; } XSetWindowAttributes attrs; attrs.colormap = XCreateColormap(display(), rootWindow(), visual->visual, AllocNone); window = XCreateWindow(display(), overlayWindow()->window(), 0, 0, displayWidth(), displayHeight(), 0, visual->depth, InputOutput, visual->visual, CWColormap, &attrs); glxWindow = glXCreateWindow(display(), fbconfig, window, NULL); overlayWindow()->setup(window); XFree(visual); } else { qCritical() << "Failed to create overlay window"; return false; } int vis_buffer; glXGetFBConfigAttrib(display(), fbconfig, GLX_VISUAL_ID, &vis_buffer); XVisualInfo* visinfo_buffer = glXGetVisualFromFBConfig(display(), fbconfig); qDebug() << "Buffer visual (depth " << visinfo_buffer->depth << "): 0x" << QString::number(vis_buffer, 16); XFree(visinfo_buffer); return true; }
GlxBackend::~GlxBackend() { if (isFailed()) { m_overlayWindow->destroy(); } // TODO: cleanup in error case // do cleanup after initBuffer() cleanupGL(); doneCurrent(); gs_tripleBufferUndetected = true; gs_tripleBufferNeedsDetection = false; if (ctx) glXDestroyContext(display(), ctx); if (glxWindow) glXDestroyWindow(display(), glxWindow); if (window) XDestroyWindow(display(), window); overlayWindow()->destroy(); delete m_overlayWindow; }
EglOnXBackend::~EglOnXBackend() { if (isFailed()) { m_overlayWindow->destroy(); } cleanupGL(); checkGLError("Cleanup"); doneCurrent(); eglDestroyContext(dpy, ctx); eglDestroySurface(dpy, surface); eglTerminate(dpy); eglReleaseThread(); if (overlayWindow()->window()) { overlayWindow()->destroy(); } delete m_overlayWindow; }
void EglOnXBackend::endRenderingFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) { if (damagedRegion.isEmpty()) { setLastDamage(QRegion()); // If the damaged region of a window is fully occluded, the only // rendering done, if any, will have been to repair a reused back // buffer, making it identical to the front buffer. // // In this case we won't post the back buffer. Instead we'll just // set the buffer age to 1, so the repaired regions won't be // rendered again in the next frame. if (!renderedRegion.isEmpty()) glFlush(); m_bufferAge = 1; return; } setLastDamage(renderedRegion); if (!blocksForRetrace()) { // This also sets lastDamage to empty which prevents the frame from // being posted again when prepareRenderingFrame() is called. present(); } else { // Make sure that the GPU begins processing the command stream // now and not the next time prepareRenderingFrame() is called. glFlush(); } if (overlayWindow()->window()) // show the window only after the first pass, overlayWindow()->show(); // since that pass may take long // Save the damaged region to history if (supportsBufferAge()) addToDamageHistory(damagedRegion); }
bool GlxBackend::initBuffer() { if (!initFbConfig()) return false; if (overlayWindow()->create()) { xcb_connection_t * const c = connection(); // Try to create double-buffered window in the overlay xcb_visualid_t visual; glXGetFBConfigAttrib(display(), fbconfig, GLX_VISUAL_ID, (int *) &visual); if (!visual) { qCCritical(KWIN_CORE) << "The GLXFBConfig does not have an associated X visual"; return false; } xcb_colormap_t colormap = xcb_generate_id(c); xcb_create_colormap(c, false, colormap, rootWindow(), visual); const QSize size = screens()->size(); window = xcb_generate_id(c); xcb_create_window(c, visualDepth(visual), window, overlayWindow()->window(), 0, 0, size.width(), size.height(), 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, visual, XCB_CW_COLORMAP, &colormap); glxWindow = glXCreateWindow(display(), fbconfig, window, NULL); overlayWindow()->setup(window); } else { qCCritical(KWIN_CORE) << "Failed to create overlay window"; return false; } return true; }
GlxBackend::~GlxBackend() { if (isFailed()) { m_overlayWindow->destroy(); } // TODO: cleanup in error case // do cleanup after initBuffer() cleanupGL(); checkGLError("Cleanup"); doneCurrent(); if (ctx) glXDestroyContext(display(), ctx); if (glxWindow) glXDestroyWindow(display(), glxWindow); if (window) XDestroyWindow(display(), window); overlayWindow()->destroy(); delete m_overlayWindow; }
bool EglOnXBackend::initRenderingContext() { dpy = eglGetDisplay(display()); if (dpy == EGL_NO_DISPLAY) return false; EGLint major, minor; if (eglInitialize(dpy, &major, &minor) == EGL_FALSE) return false; #ifdef KWIN_HAVE_OPENGLES eglBindAPI(EGL_OPENGL_ES_API); #else if (eglBindAPI(EGL_OPENGL_API) == EGL_FALSE) { qCritical() << "bind OpenGL API failed"; return false; } #endif initBufferConfigs(); if (!overlayWindow()->create()) { qCritical() << "Could not get overlay window"; return false; } else { overlayWindow()->setup(None); } surface = eglCreateWindowSurface(dpy, config, overlayWindow()->window(), 0); #ifdef KWIN_HAVE_OPENGLES const EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; ctx = eglCreateContext(dpy, config, EGL_NO_CONTEXT, context_attribs); #else const EGLint context_attribs_31_core[] = { EGL_CONTEXT_MAJOR_VERSION_KHR, 3, EGL_CONTEXT_MINOR_VERSION_KHR, 1, EGL_NONE }; const EGLint context_attribs_legacy[] = { EGL_NONE }; const QByteArray eglExtensions = eglQueryString(dpy, EGL_EXTENSIONS); const QList<QByteArray> extensions = eglExtensions.split(' '); // Try to create a 3.1 core context if (options->glCoreProfile() && extensions.contains("EGL_KHR_create_context")) ctx = eglCreateContext(dpy, config, EGL_NO_CONTEXT, context_attribs_31_core); if (ctx == EGL_NO_CONTEXT) ctx = eglCreateContext(dpy, config, EGL_NO_CONTEXT, context_attribs_legacy); #endif if (ctx == EGL_NO_CONTEXT) { qCritical() << "Create Context failed"; return false; } if (eglMakeCurrent(dpy, surface, surface, ctx) == EGL_FALSE) { qCritical() << "Make Context Current failed"; return false; } qDebug() << "EGL version: " << major << "." << minor; EGLint error = eglGetError(); if (error != EGL_SUCCESS) { qWarning() << "Error occurred while creating context " << error; return false; } return true; }