Better handling for making the compositing OpenGL context current
With QtQuick2 it's possible that the scene graph rendering context either lives in an own thread or uses the main GUI thread. In the latter case it's the same thread as our compositing OpenGL context lives in. This means our basic assumption that between two rendering passes the context stays current does not hold. The code already ensured that before we start a rendering pass the context is made current, but there are many more possible cases. If we use OpenGL in areas not triggered by the rendering loop but in response to other events the context needs to be made current. This includes the loading and unloading of effects (some effects use OpenGL in the static effect check, in the ctor and dtor), background loading of texture data, lazy loading after first usage invoked by shortcut, etc. etc. To properly handle these cases new methods are added to EffectsHandler to make the compositing OpenGL context current. These calls delegate down into the scene. On non-OpenGL scenes they are noop, but on OpenGL they go into the backend and make the context current. In addition they ensure that Qt doesn't think that it's QOpenGLContext is current by calling doneCurrent() on the QOpenGLContext::currentContext(). This unfortunately causes an additional call to makeCurrent with a null context, but there is no other way to tell Qt - it doesn't notice when a different context is made current with low level API calls. In the multi-threaded architecture this doesn't matter as ::currentContext() returns null. A short evaluation showed that a transition to QOpenGLContext doesn't seem feasible. Qt only supports either GLX or EGL while KWin supports both and when entering the transition phase for Wayland, it would become extremely tricky if our native platform is X11, but we want a Wayland EGL context. A future solution might be to have a "KWin-QPA plugin" which uses either xcb or Wayland and hides everything from Qt. The API documentation is extended to describe when the effects-framework ensures that an OpenGL context is current. The effects are changed to make the context current in cases where it's not guaranteed. This has been done by looking for creation or deletion of GLTextures and Shaders. If there are other OpenGL usages outside the rendering loop, ctor/dtor this needs to be changed, too.
This commit is contained in:
parent
551988ebd4
commit
b7be3cb621
18 changed files with 170 additions and 16 deletions
15
effects.cpp
15
effects.cpp
|
@ -259,6 +259,7 @@ EffectsHandlerImpl::EffectsHandlerImpl(Compositor *compositor, Scene *scene)
|
|||
|
||||
EffectsHandlerImpl::~EffectsHandlerImpl()
|
||||
{
|
||||
makeOpenGLContextCurrent();
|
||||
if (keyboard_grab_effect != NULL)
|
||||
ungrabKeyboard();
|
||||
setActiveFullScreenEffect(nullptr);
|
||||
|
@ -326,6 +327,7 @@ void EffectsHandlerImpl::slotEffectsQueried()
|
|||
QStringList checkDefault;
|
||||
KConfigGroup conf(KSharedConfig::openConfig(), "Plugins");
|
||||
|
||||
makeOpenGLContextCurrent();
|
||||
// First unload necessary effects
|
||||
for (const KService::Ptr & service : offers) {
|
||||
KPluginInfo plugininfo(service);
|
||||
|
@ -1338,6 +1340,7 @@ QStringList EffectsHandlerImpl::listOfEffects() const
|
|||
|
||||
bool EffectsHandlerImpl::loadEffect(const QString& name, bool checkDefault)
|
||||
{
|
||||
makeOpenGLContextCurrent();
|
||||
m_compositor->addRepaintFull();
|
||||
|
||||
if (!name.startsWith(QLatin1String("kwin4_effect_")))
|
||||
|
@ -1482,6 +1485,7 @@ bool EffectsHandlerImpl::loadScriptedEffect(const QString& name, KService *servi
|
|||
|
||||
void EffectsHandlerImpl::unloadEffect(const QString& name)
|
||||
{
|
||||
makeOpenGLContextCurrent();
|
||||
m_compositor->addRepaintFull();
|
||||
|
||||
for (QMap< int, EffectPair >::iterator it = effect_order.begin(); it != effect_order.end(); ++it) {
|
||||
|
@ -1513,6 +1517,7 @@ void EffectsHandlerImpl::reconfigureEffect(const QString& name)
|
|||
{
|
||||
for (QVector< EffectPair >::const_iterator it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it)
|
||||
if ((*it).first == name) {
|
||||
makeOpenGLContextCurrent();
|
||||
(*it).second->reconfigure(Effect::ReconfigureAll);
|
||||
return;
|
||||
}
|
||||
|
@ -1627,6 +1632,16 @@ QString EffectsHandlerImpl::debug(const QString& name, const QString& parameter)
|
|||
return QString();
|
||||
}
|
||||
|
||||
bool EffectsHandlerImpl::makeOpenGLContextCurrent()
|
||||
{
|
||||
return m_scene->makeOpenGLContextCurrent();
|
||||
}
|
||||
|
||||
void EffectsHandlerImpl::doneOpenGLContextCurrent()
|
||||
{
|
||||
m_scene->doneOpenGLContextCurrent();
|
||||
}
|
||||
|
||||
//****************************************
|
||||
// EffectWindowImpl
|
||||
//****************************************
|
||||
|
|
|
@ -177,6 +177,9 @@ public:
|
|||
virtual QVariant kwinOption(KWinOption kwopt);
|
||||
virtual bool isScreenLocked() const;
|
||||
|
||||
virtual bool makeOpenGLContextCurrent() override;
|
||||
virtual void doneOpenGLContextCurrent() override;
|
||||
|
||||
// internal (used by kwin core or compositing code)
|
||||
void startPaint();
|
||||
void grabbedKeyboardEvent(QKeyEvent* e);
|
||||
|
|
|
@ -258,6 +258,7 @@ void CubeEffect::slotCubeCapLoaded()
|
|||
}
|
||||
QImage img = watcher->result();
|
||||
if (!img.isNull()) {
|
||||
effects->makeOpenGLContextCurrent();
|
||||
capTexture = new GLTexture(img);
|
||||
capTexture->setFilter(GL_LINEAR);
|
||||
#ifndef KWIN_HAVE_OPENGLES
|
||||
|
@ -285,6 +286,7 @@ void CubeEffect::slotWallPaperLoaded()
|
|||
}
|
||||
QImage img = watcher->result();
|
||||
if (!img.isNull()) {
|
||||
effects->makeOpenGLContextCurrent();
|
||||
wallpaper = new GLTexture(img);
|
||||
effects->addRepaintFull();
|
||||
}
|
||||
|
@ -301,6 +303,7 @@ void CubeEffect::slotResetShaders()
|
|||
|
||||
bool CubeEffect::loadShader()
|
||||
{
|
||||
effects->makeOpenGLContextCurrent();
|
||||
if (!(GLPlatform::instance()->supports(GLSL) &&
|
||||
(effects->compositingType() == OpenGL2Compositing)))
|
||||
return false;
|
||||
|
|
|
@ -263,6 +263,7 @@ void MagnifierEffect::zoomIn()
|
|||
effects->startMousePolling();
|
||||
}
|
||||
if (effects->isOpenGLCompositing() && !m_texture) {
|
||||
effects->makeOpenGLContextCurrent();
|
||||
m_texture = new GLTexture(magnifier_size.width(), magnifier_size.height());
|
||||
m_texture->setYInverted(false);
|
||||
m_fbo = new GLRenderTarget(*m_texture);
|
||||
|
@ -280,6 +281,7 @@ void MagnifierEffect::zoomOut()
|
|||
effects->stopMousePolling();
|
||||
}
|
||||
if (zoom == target_zoom) {
|
||||
effects->makeOpenGLContextCurrent();
|
||||
delete m_fbo;
|
||||
delete m_texture;
|
||||
m_fbo = NULL;
|
||||
|
@ -301,6 +303,7 @@ void MagnifierEffect::toggle()
|
|||
effects->startMousePolling();
|
||||
}
|
||||
if (effects->isOpenGLCompositing() && !m_texture) {
|
||||
effects->makeOpenGLContextCurrent();
|
||||
m_texture = new GLTexture(magnifier_size.width(), magnifier_size.height());
|
||||
m_texture->setYInverted(false);
|
||||
m_fbo = new GLRenderTarget(*m_texture);
|
||||
|
|
|
@ -182,6 +182,7 @@ Glow *ScreenEdgeEffect::createGlow(ElectricBorder border, qreal factor, const QR
|
|||
|
||||
// render the glow image
|
||||
if (effects->isOpenGLCompositing()) {
|
||||
effects->makeOpenGLContextCurrent();
|
||||
if (border == ElectricTopLeft || border == ElectricTopRight || border == ElectricBottomRight || border == ElectricBottomLeft) {
|
||||
glow->texture.reset(createCornerGlow<GLTexture>(border));
|
||||
} else {
|
||||
|
|
|
@ -320,6 +320,7 @@ void StartupFeedbackEffect::stop()
|
|||
if (m_active)
|
||||
effects->stopMousePolling();
|
||||
m_active = false;
|
||||
effects->makeOpenGLContextCurrent();
|
||||
switch(m_type) {
|
||||
case BouncingFeedback:
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
|
@ -342,6 +343,7 @@ void StartupFeedbackEffect::stop()
|
|||
|
||||
void StartupFeedbackEffect::prepareTextures(const QPixmap& pix)
|
||||
{
|
||||
effects->makeOpenGLContextCurrent();
|
||||
switch(m_type) {
|
||||
case BouncingFeedback:
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
|
|
|
@ -194,6 +194,7 @@ void TrackMouseEffect::postPaintScreen()
|
|||
|
||||
bool TrackMouseEffect::init()
|
||||
{
|
||||
effects->makeOpenGLContextCurrent();
|
||||
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
|
||||
if (!(m_texture[0] || m_picture[0])) {
|
||||
loadTexture();
|
||||
|
|
|
@ -175,6 +175,7 @@ void ZoomEffect::hideCursor()
|
|||
|
||||
void ZoomEffect::recreateTexture()
|
||||
{
|
||||
effects->makeOpenGLContextCurrent();
|
||||
// read details about the mouse-cursor theme define per default
|
||||
KConfigGroup mousecfg(KSharedConfig::openConfig(QStringLiteral("kcminputrc")), "Mouse");
|
||||
QString theme = mousecfg.readEntry("cursorTheme", QString());
|
||||
|
|
|
@ -26,6 +26,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <kwinglplatform.h>
|
||||
// Qt
|
||||
#include <QDebug>
|
||||
#include <QOpenGLContext>
|
||||
// system
|
||||
#include <unistd.h>
|
||||
|
||||
|
@ -45,7 +46,7 @@ EglOnXBackend::EglOnXBackend()
|
|||
EglOnXBackend::~EglOnXBackend()
|
||||
{
|
||||
cleanupGL();
|
||||
eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
doneCurrent();
|
||||
eglDestroyContext(dpy, ctx);
|
||||
eglDestroySurface(dpy, surface);
|
||||
eglTerminate(dpy);
|
||||
|
@ -267,9 +268,6 @@ void EglOnXBackend::present()
|
|||
if (lastDamage().isEmpty())
|
||||
return;
|
||||
|
||||
// a different context might have been current
|
||||
eglMakeCurrent(dpy, surface, surface, ctx);
|
||||
|
||||
const QRegion displayRegion(0, 0, displayWidth(), displayHeight());
|
||||
const bool fullRepaint = (lastDamage() == displayRegion);
|
||||
|
||||
|
@ -334,8 +332,6 @@ void EglOnXBackend::prepareRenderingFrame()
|
|||
usleep(1000);
|
||||
}
|
||||
present();
|
||||
// different context might have been bound as present() can block
|
||||
eglMakeCurrent(dpy, surface, surface, ctx);
|
||||
startRenderTimer();
|
||||
eglWaitNative(EGL_CORE_NATIVE_ENGINE);
|
||||
}
|
||||
|
@ -352,6 +348,21 @@ void EglOnXBackend::endRenderingFrame(const QRegion &damage)
|
|||
overlayWindow()->show(); // since that pass may take long
|
||||
}
|
||||
|
||||
bool EglOnXBackend::makeCurrent()
|
||||
{
|
||||
if (QOpenGLContext *context = QOpenGLContext::currentContext()) {
|
||||
// Workaround to tell Qt that no QOpenGLContext is current
|
||||
context->doneCurrent();
|
||||
}
|
||||
const bool current = eglMakeCurrent(dpy, surface, surface, ctx);
|
||||
return current;
|
||||
}
|
||||
|
||||
void EglOnXBackend::doneCurrent()
|
||||
{
|
||||
eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
}
|
||||
|
||||
/************************************************
|
||||
* EglTexture
|
||||
************************************************/
|
||||
|
|
|
@ -36,6 +36,8 @@ public:
|
|||
virtual SceneOpenGL::TexturePrivate *createBackendTexture(SceneOpenGL::Texture *texture);
|
||||
virtual void prepareRenderingFrame();
|
||||
virtual void endRenderingFrame(const QRegion &damage);
|
||||
virtual bool makeCurrent() override;
|
||||
virtual void doneCurrent() override;
|
||||
|
||||
protected:
|
||||
virtual void present();
|
||||
|
|
|
@ -34,6 +34,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <kwinglplatform.h>
|
||||
// Qt
|
||||
#include <QDebug>
|
||||
#include <QOpenGLContext>
|
||||
// system
|
||||
#include <unistd.h>
|
||||
|
||||
|
@ -55,7 +56,7 @@ GlxBackend::~GlxBackend()
|
|||
// TODO: cleanup in error case
|
||||
// do cleanup after initBuffer()
|
||||
cleanupGL();
|
||||
glXMakeCurrent(display(), None, NULL);
|
||||
doneCurrent();
|
||||
|
||||
if (ctx)
|
||||
glXDestroyContext(display(), ctx);
|
||||
|
@ -425,9 +426,6 @@ void GlxBackend::present()
|
|||
if (lastDamage().isEmpty())
|
||||
return;
|
||||
|
||||
// a different context might have been current
|
||||
glXMakeCurrent(display(), glxWindow, ctx);
|
||||
|
||||
const QRegion displayRegion(0, 0, displayWidth(), displayHeight());
|
||||
const bool fullRepaint = (lastDamage() == displayRegion);
|
||||
|
||||
|
@ -480,13 +478,13 @@ void GlxBackend::present()
|
|||
|
||||
void GlxBackend::screenGeometryChanged(const QSize &size)
|
||||
{
|
||||
glXMakeCurrent(display(), None, NULL);
|
||||
doneCurrent();
|
||||
|
||||
XMoveResizeWindow(display(), window, 0, 0, size.width(), size.height());
|
||||
overlayWindow()->setup(window);
|
||||
Xcb::sync();
|
||||
|
||||
glXMakeCurrent(display(), glxWindow, ctx);
|
||||
makeCurrent();
|
||||
glViewport(0, 0, size.width(), size.height());
|
||||
}
|
||||
|
||||
|
@ -507,8 +505,6 @@ void GlxBackend::prepareRenderingFrame()
|
|||
}
|
||||
present();
|
||||
startRenderTimer();
|
||||
// different context might have been bound as present() can block
|
||||
glXMakeCurrent(display(), glxWindow, ctx);
|
||||
glXWaitX();
|
||||
}
|
||||
|
||||
|
@ -524,6 +520,20 @@ void GlxBackend::endRenderingFrame(const QRegion &damage)
|
|||
overlayWindow()->show(); // since that pass may take long
|
||||
}
|
||||
|
||||
bool GlxBackend::makeCurrent()
|
||||
{
|
||||
if (QOpenGLContext *context = QOpenGLContext::currentContext()) {
|
||||
// Workaround to tell Qt that no QOpenGLContext is current
|
||||
context->doneCurrent();
|
||||
}
|
||||
const bool current = glXMakeCurrent(display(), glxWindow, ctx);
|
||||
return current;
|
||||
}
|
||||
|
||||
void GlxBackend::doneCurrent()
|
||||
{
|
||||
glXMakeCurrent(display(), None, nullptr);
|
||||
}
|
||||
|
||||
/********************************************************
|
||||
* GlxTexture
|
||||
|
|
|
@ -46,6 +46,8 @@ public:
|
|||
virtual SceneOpenGL::TexturePrivate *createBackendTexture(SceneOpenGL::Texture *texture);
|
||||
virtual void prepareRenderingFrame();
|
||||
virtual void endRenderingFrame(const QRegion &damage);
|
||||
virtual bool makeCurrent() override;
|
||||
virtual void doneCurrent() override;
|
||||
|
||||
protected:
|
||||
virtual void present();
|
||||
|
|
|
@ -277,6 +277,21 @@ QRect infiniteRegion()
|
|||
* For each stage there are *Screen() and *Window() methods. The window method
|
||||
* is called for every window which the screen method is usually called just
|
||||
* once.
|
||||
*
|
||||
* @section OpenGL
|
||||
* Effects can use OpenGL if EffectsHandler::isOpenGLCompositing() returns @c true.
|
||||
* The OpenGL context may not always be current when code inside the effect is
|
||||
* executed. The framework ensures that the OpenGL context is current when the Effect
|
||||
* gets created, destroyed or reconfigured and during the painting stages. All virtual
|
||||
* methods which have the OpenGL context current are documented.
|
||||
*
|
||||
* If OpenGL code is going to be executed outside the painting stages, e.g. in reaction
|
||||
* to a global shortcut, it is the task of the Effect to make the OpenGL context current:
|
||||
* @code
|
||||
* effects->makeOpenGLContextCurrent();
|
||||
* @endcode
|
||||
*
|
||||
* There is in general no need to call the matching doneCurrent method.
|
||||
**/
|
||||
class KWIN_EXPORT Effect : public QObject
|
||||
{
|
||||
|
@ -330,10 +345,16 @@ public:
|
|||
|
||||
/**
|
||||
* Constructs new Effect object.
|
||||
*
|
||||
* In OpenGL based compositing, the frameworks ensures that the context is current
|
||||
* when the Effect is constructed.
|
||||
**/
|
||||
Effect();
|
||||
/**
|
||||
* Destructs the Effect object.
|
||||
*
|
||||
* In OpenGL based compositing, the frameworks ensures that the context is current
|
||||
* when the Effect is destroyed.
|
||||
**/
|
||||
virtual ~Effect();
|
||||
|
||||
|
@ -347,6 +368,10 @@ public:
|
|||
|
||||
/**
|
||||
* Called when configuration changes (either the effect's or KWin's global).
|
||||
*
|
||||
* In OpenGL based compositing, the frameworks ensures that the context is current
|
||||
* when the Effect is reconfigured. If this method is called from within the Effect it is
|
||||
* required to ensure that the context is current if the implementation does OpenGL calls.
|
||||
*/
|
||||
virtual void reconfigure(ReconfigureFlags flags);
|
||||
|
||||
|
@ -362,6 +387,9 @@ public:
|
|||
* @li change the region of the screen that will be painted
|
||||
* @li do various housekeeping tasks such as initing your effect's variables
|
||||
for the upcoming paint pass or updating animation's progress
|
||||
*
|
||||
* In OpenGL based compositing, the frameworks ensures that the context is current
|
||||
* when this method is invoked.
|
||||
**/
|
||||
virtual void prePaintScreen(ScreenPrePaintData& data, int time);
|
||||
/**
|
||||
|
@ -370,6 +398,9 @@ public:
|
|||
* effects->paintScreen())
|
||||
* @li paint multiple desktops and/or multiple copies of the same desktop
|
||||
* by calling effects->paintScreen() multiple times
|
||||
*
|
||||
* In OpenGL based compositing, the frameworks ensures that the context is current
|
||||
* when this method is invoked.
|
||||
**/
|
||||
virtual void paintScreen(int mask, QRegion region, ScreenPaintData& data);
|
||||
/**
|
||||
|
@ -377,6 +408,9 @@ public:
|
|||
* In this method you can:
|
||||
* @li schedule next repaint in case of animations
|
||||
* You shouldn't paint anything here.
|
||||
*
|
||||
* In OpenGL based compositing, the frameworks ensures that the context is current
|
||||
* when this method is invoked.
|
||||
**/
|
||||
virtual void postPaintScreen();
|
||||
|
||||
|
@ -387,6 +421,9 @@ public:
|
|||
* @li set window to be painted with translucency
|
||||
* @li set window to be transformed
|
||||
* @li request the window to be divided into multiple parts
|
||||
*
|
||||
* In OpenGL based compositing, the frameworks ensures that the context is current
|
||||
* when this method is invoked.
|
||||
**/
|
||||
virtual void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time);
|
||||
/**
|
||||
|
@ -395,6 +432,9 @@ public:
|
|||
* @li do various transformations
|
||||
* @li change opacity of the window
|
||||
* @li change brightness and/or saturation, if it's supported
|
||||
*
|
||||
* In OpenGL based compositing, the frameworks ensures that the context is current
|
||||
* when this method is invoked.
|
||||
**/
|
||||
virtual void paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data);
|
||||
/**
|
||||
|
@ -402,6 +442,9 @@ public:
|
|||
* In this method you can:
|
||||
* @li schedule next repaint for individual window(s) in case of animations
|
||||
* You shouldn't paint anything here.
|
||||
*
|
||||
* In OpenGL based compositing, the frameworks ensures that the context is current
|
||||
* when this method is invoked.
|
||||
**/
|
||||
virtual void postPaintWindow(EffectWindow* w);
|
||||
|
||||
|
@ -414,6 +457,9 @@ public:
|
|||
* @param opacity Opacity of text/icon
|
||||
* @param frameOpacity Opacity of background
|
||||
* @since 4.6
|
||||
*
|
||||
* In OpenGL based compositing, the frameworks ensures that the context is current
|
||||
* when this method is invoked.
|
||||
**/
|
||||
virtual void paintEffectFrame(EffectFrame* frame, QRegion region, double opacity, double frameOpacity);
|
||||
|
||||
|
@ -426,7 +472,10 @@ public:
|
|||
/**
|
||||
* Can be called to draw multiple copies (e.g. thumbnails) of a window.
|
||||
* You can change window's opacity/brightness/etc here, but you can't
|
||||
* do any transformations
|
||||
* do any transformations.
|
||||
*
|
||||
* In OpenGL based compositing, the frameworks ensures that the context is current
|
||||
* when this method is invoked.
|
||||
**/
|
||||
virtual void drawWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data);
|
||||
|
||||
|
@ -921,6 +970,24 @@ public:
|
|||
**/
|
||||
virtual bool isScreenLocked() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Makes the OpenGL compositing context current.
|
||||
*
|
||||
* If the compositing backend is not using OpenGL, this method returns @c false.
|
||||
*
|
||||
* @return bool @c true if the context became current, @c false otherwise.
|
||||
*/
|
||||
virtual bool makeOpenGLContextCurrent() = 0;
|
||||
/**
|
||||
* @brief Makes a null OpenGL context current resulting in no context
|
||||
* being current.
|
||||
*
|
||||
* If the compositing backend is not OpenGL based, this method is a noop.
|
||||
*
|
||||
* There is normally no reason for an Effect to call this method.
|
||||
*/
|
||||
virtual void doneOpenGLContextCurrent() = 0;
|
||||
|
||||
/**
|
||||
* Sends message over DCOP to reload given effect.
|
||||
* @param effectname effect's name without "kwin4_effect_" prefix.
|
||||
|
|
|
@ -347,6 +347,7 @@ void OpenGLPaintRedirector::resizePixmaps(const QRect *rects)
|
|||
size[TopBottom] = QSize(align(qMax(rects[TopPixmap].width(), rects[BottomPixmap].width()), 128),
|
||||
rects[TopPixmap].height() + rects[BottomPixmap].height());
|
||||
|
||||
effects->makeOpenGLContextCurrent();
|
||||
if (!GLTexture::NPOTTextureSupported()) {
|
||||
for (int i = 0; i < 2; i++) {
|
||||
size[i].rwidth() = nearestPowerOfTwo(size[i].width());
|
||||
|
|
|
@ -527,6 +527,15 @@ void Scene::screenGeometryChanged(const QSize &size)
|
|||
overlayWindow()->resize(size);
|
||||
}
|
||||
|
||||
bool Scene::makeOpenGLContextCurrent()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void Scene::doneOpenGLContextCurrent()
|
||||
{
|
||||
}
|
||||
|
||||
//****************************************
|
||||
// Scene::Window
|
||||
//****************************************
|
||||
|
|
4
scene.h
4
scene.h
|
@ -102,6 +102,10 @@ public:
|
|||
virtual bool blocksForRetrace() const;
|
||||
virtual bool syncsToVBlank() const;
|
||||
virtual OverlayWindow* overlayWindow() = 0;
|
||||
|
||||
virtual bool makeOpenGLContextCurrent();
|
||||
virtual void doneOpenGLContextCurrent();
|
||||
|
||||
public Q_SLOTS:
|
||||
// a window has been destroyed
|
||||
virtual void windowDeleted(KWin::Deleted*) = 0;
|
||||
|
|
|
@ -103,8 +103,10 @@ void OpenGLBackend::setFailed(const QString &reason)
|
|||
|
||||
void OpenGLBackend::idle()
|
||||
{
|
||||
if (hasPendingFlush())
|
||||
if (hasPendingFlush()) {
|
||||
effects->makeOpenGLContextCurrent();
|
||||
present();
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************
|
||||
|
@ -340,6 +342,7 @@ qint64 SceneOpenGL::paint(QRegion damage, ToplevelList toplevels)
|
|||
stacking_order.append(windows[ c ]);
|
||||
}
|
||||
|
||||
m_backend->makeCurrent();
|
||||
m_backend->prepareRenderingFrame();
|
||||
|
||||
const GLenum status = glGetGraphicsResetStatus();
|
||||
|
@ -599,6 +602,16 @@ void SceneOpenGL::paintDesktop(int desktop, int mask, const QRegion ®ion, Scr
|
|||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
bool SceneOpenGL::makeOpenGLContextCurrent()
|
||||
{
|
||||
return m_backend->makeCurrent();
|
||||
}
|
||||
|
||||
void SceneOpenGL::doneOpenGLContextCurrent()
|
||||
{
|
||||
m_backend->doneCurrent();
|
||||
}
|
||||
|
||||
//****************************************
|
||||
// SceneOpenGL2
|
||||
//****************************************
|
||||
|
@ -2355,6 +2368,7 @@ SceneOpenGLShadow::SceneOpenGLShadow(Toplevel *toplevel)
|
|||
|
||||
SceneOpenGLShadow::~SceneOpenGLShadow()
|
||||
{
|
||||
effects->makeOpenGLContextCurrent();
|
||||
delete m_texture;
|
||||
}
|
||||
|
||||
|
@ -2495,6 +2509,7 @@ bool SceneOpenGLShadow::prepareBackend()
|
|||
p.drawPixmap(bottomLeft.width() + bottom.width(), topRight.height() + right.height(), shadowPixmap(ShadowElementBottomRight));
|
||||
p.end();
|
||||
|
||||
effects->makeOpenGLContextCurrent();
|
||||
delete m_texture;
|
||||
m_texture = new GLTexture(image);
|
||||
|
||||
|
|
|
@ -54,6 +54,8 @@ public:
|
|||
virtual OverlayWindow *overlayWindow();
|
||||
virtual bool blocksForRetrace() const;
|
||||
virtual bool syncsToVBlank() const;
|
||||
virtual bool makeOpenGLContextCurrent() override;
|
||||
virtual void doneOpenGLContextCurrent() override;
|
||||
|
||||
void idle();
|
||||
|
||||
|
@ -472,6 +474,8 @@ public:
|
|||
* @param damage The actual updated region in this frame
|
||||
**/
|
||||
virtual void endRenderingFrame(const QRegion &damage) = 0;
|
||||
virtual bool makeCurrent() = 0;
|
||||
virtual void doneCurrent() = 0;
|
||||
/**
|
||||
* @brief Compositor is going into idle mode, flushes any pending paints.
|
||||
**/
|
||||
|
|
Loading…
Reference in a new issue