Merge branch 'master' into master-deco
commit
984f6d6305
|
@ -68,7 +68,7 @@ bool LiquidEffect::loadData()
|
|||
mTexture->setFilter(GL_LINEAR_MIPMAP_LINEAR);
|
||||
mTexture->setWrapMode(GL_CLAMP);
|
||||
|
||||
mRenderTarget = new GLRenderTarget(mTexture);
|
||||
mRenderTarget = new GLRenderTarget(*mTexture);
|
||||
if (!mRenderTarget->valid())
|
||||
return false;
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ TestFBOEffect::TestFBOEffect() : Effect()
|
|||
mTexture = new GLTexture(displayWidth(), displayHeight());
|
||||
mTexture->setFilter(GL_LINEAR_MIPMAP_LINEAR);
|
||||
|
||||
mRenderTarget = new GLRenderTarget(mTexture);
|
||||
mRenderTarget = new GLRenderTarget(*mTexture);
|
||||
|
||||
mValid = mRenderTarget->valid();
|
||||
}
|
||||
|
|
|
@ -40,9 +40,9 @@ BlurEffect::BlurEffect()
|
|||
|
||||
// Offscreen texture that's used as the target for the horizontal blur pass
|
||||
// and the source for the vertical pass.
|
||||
tex = new GLTexture(displayWidth(), displayHeight());
|
||||
tex->setFilter(GL_LINEAR);
|
||||
tex->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||
tex = GLTexture(displayWidth(), displayHeight());
|
||||
tex.setFilter(GL_LINEAR);
|
||||
tex.setWrapMode(GL_CLAMP_TO_EDGE);
|
||||
|
||||
target = new GLRenderTarget(tex);
|
||||
|
||||
|
@ -60,6 +60,7 @@ BlurEffect::BlurEffect()
|
|||
XDeleteProperty(display(), rootWindow(), net_wm_blur_region);
|
||||
}
|
||||
connect(effects, SIGNAL(windowAdded(EffectWindow*)), this, SLOT(slotWindowAdded(EffectWindow*)));
|
||||
connect(effects, SIGNAL(windowDeleted(EffectWindow*)), this, SLOT(slotWindowDeleted(EffectWindow*)));
|
||||
connect(effects, SIGNAL(propertyNotify(EffectWindow*,long)), this, SLOT(slotPropertyNotify(EffectWindow*,long)));
|
||||
}
|
||||
|
||||
|
@ -68,9 +69,10 @@ BlurEffect::~BlurEffect()
|
|||
effects->registerPropertyType(net_wm_blur_region, false);
|
||||
XDeleteProperty(display(), rootWindow(), net_wm_blur_region);
|
||||
|
||||
windows.clear();
|
||||
|
||||
delete shader;
|
||||
delete target;
|
||||
delete tex;
|
||||
}
|
||||
|
||||
void BlurEffect::reconfigure(ReconfigureFlags flags)
|
||||
|
@ -81,6 +83,10 @@ void BlurEffect::reconfigure(ReconfigureFlags flags)
|
|||
int radius = qBound(2, cg.readEntry("BlurRadius", 12), 14);
|
||||
shader->setRadius(radius);
|
||||
|
||||
m_shouldCache = cg.readEntry("CacheTexture", true);
|
||||
|
||||
windows.clear();
|
||||
|
||||
if (!shader->isValid())
|
||||
XDeleteProperty(display(), rootWindow(), net_wm_blur_region);
|
||||
}
|
||||
|
@ -115,6 +121,13 @@ void BlurEffect::slotWindowAdded(EffectWindow *w)
|
|||
updateBlurRegion(w);
|
||||
}
|
||||
|
||||
void BlurEffect::slotWindowDeleted(EffectWindow *w)
|
||||
{
|
||||
if (windows.contains(w)) {
|
||||
windows.remove(w);
|
||||
}
|
||||
}
|
||||
|
||||
void BlurEffect::slotPropertyNotify(EffectWindow *w, long atom)
|
||||
{
|
||||
if (w && atom == net_wm_blur_region)
|
||||
|
@ -177,7 +190,8 @@ QRegion BlurEffect::blurRegion(const EffectWindow *w) const
|
|||
region |= appRegion.translated(w->contentsRect().topLeft()) &
|
||||
w->contentsRect();
|
||||
} else
|
||||
region = appRegion & w->contentsRect();
|
||||
region = appRegion.translated(w->contentsRect().topLeft()) &
|
||||
w->contentsRect();
|
||||
} else {
|
||||
// An empty region means that the blur effect should be enabled
|
||||
// for the whole window.
|
||||
|
@ -217,8 +231,16 @@ void BlurEffect::drawRegion(const QRegion ®ion)
|
|||
void BlurEffect::prePaintScreen(ScreenPrePaintData &data, int time)
|
||||
{
|
||||
m_damagedArea = QRegion();
|
||||
m_paintedArea = QRegion();
|
||||
m_currentBlur = QRegion();
|
||||
|
||||
#ifdef KWIN_HAVE_OPENGLES
|
||||
// HACK: with GLES the screen does not get updated correctly.
|
||||
// as a workaround we trigger full repaints on GLES
|
||||
// we need to find a proper solution or default to blur off on GLES.
|
||||
data.mask |= PAINT_SCREEN_TRANSFORMED;
|
||||
#endif
|
||||
|
||||
effects->prePaintScreen(data, time);
|
||||
}
|
||||
|
||||
|
@ -241,6 +263,8 @@ void BlurEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int t
|
|||
}
|
||||
data.clip = newClip;
|
||||
|
||||
const QRegion oldPaint = data.paint;
|
||||
|
||||
// we don't have to blur a region we don't see
|
||||
m_currentBlur -= newClip;
|
||||
// if we have to paint a non-opaque part of this window that intersects with the
|
||||
|
@ -253,21 +277,57 @@ void BlurEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int t
|
|||
// in case this window has regions to be blurred
|
||||
const QRegion blurArea = blurRegion(w).translated(w->pos());
|
||||
const QRegion expandedBlur = expand(blurArea);
|
||||
// if this window or an window underneath the blurred area is damaged we have to
|
||||
// blur everything
|
||||
if (m_damagedArea.intersects(blurArea) || data.paint.intersects(blurArea)) {
|
||||
data.paint |= expandedBlur;
|
||||
// we have to check again whether we do not damage an already blurred area
|
||||
if (expandedBlur.intersects(m_currentBlur)) {
|
||||
data.paint |= m_currentBlur;
|
||||
|
||||
if (m_shouldCache) {
|
||||
// we are caching the horizontally blurred background texture
|
||||
|
||||
// if a window underneath the blurred area is damaged we have to
|
||||
// blur everything
|
||||
if (m_damagedArea.intersects(blurArea)) {
|
||||
data.paint |= expandedBlur;
|
||||
// we keep track of the "damage propagation"
|
||||
m_damagedArea |= expand(blurArea & m_damagedArea);
|
||||
// we have to check again whether we do not damage a blurred area
|
||||
// of a window we do not cache
|
||||
if (expandedBlur.intersects(m_currentBlur)) {
|
||||
data.paint |= m_currentBlur;
|
||||
}
|
||||
if (windows.contains(w)) {
|
||||
windows[w].textureValid = false;
|
||||
}
|
||||
|
||||
// Normally we would have shrink the clip of the following windows to get a
|
||||
// full cached copy of the background of this window. But we do not do a full
|
||||
// cache of the background and rely on the KWin behavior that transformed windows
|
||||
// are painted with paintGenericScreen.
|
||||
}
|
||||
} else {
|
||||
// we are not caching the window
|
||||
|
||||
// if this window or an window underneath the blurred area is painted again we have to
|
||||
// blur everything
|
||||
if (m_paintedArea.intersects(blurArea) || data.paint.intersects(blurArea)) {
|
||||
data.paint |= expandedBlur;
|
||||
// we keep track of the "damage propagation"
|
||||
m_damagedArea |= expand(blurArea & m_damagedArea);
|
||||
// we have to check again whether we do not damage a blurred area
|
||||
// of a window we do not cache
|
||||
if (expandedBlur.intersects(m_currentBlur)) {
|
||||
data.paint |= m_currentBlur;
|
||||
}
|
||||
}
|
||||
|
||||
m_currentBlur |= expandedBlur;
|
||||
}
|
||||
m_currentBlur |= expandedBlur;
|
||||
|
||||
// we don't consider damaged areas which are occluded and are not
|
||||
// explicitly damaged by this window
|
||||
m_damagedArea -= data.clip;
|
||||
m_damagedArea |= data.paint;
|
||||
m_damagedArea |= oldPaint;
|
||||
|
||||
// in contrast to m_damagedArea does m_paintedArea keep track of all repainted areas
|
||||
m_paintedArea -= data.clip;
|
||||
m_paintedArea |= data.paint;
|
||||
}
|
||||
|
||||
bool BlurEffect::shouldBlur(const EffectWindow *w, int mask, const WindowPaintData &data) const
|
||||
|
@ -302,8 +362,13 @@ void BlurEffect::drawWindow(EffectWindow *w, int mask, QRegion region, WindowPai
|
|||
const QRect screen(0, 0, displayWidth(), displayHeight());
|
||||
const QRegion shape = region & blurRegion(w).translated(w->pos()) & screen;
|
||||
|
||||
if (!shape.isEmpty() && region.intersects(shape.boundingRect()))
|
||||
doBlur(shape, screen, data.opacity * data.contents_opacity);
|
||||
if (!shape.isEmpty()) {
|
||||
if (m_shouldCache) {
|
||||
doCachedBlur(w, region, data.opacity * data.contents_opacity);
|
||||
} else {
|
||||
doBlur(shape, screen, data.opacity * data.contents_opacity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the window over the blurred area
|
||||
|
@ -337,6 +402,7 @@ void BlurEffect::doBlur(const QRegion& shape, const QRect& screen, const float o
|
|||
r.width(), r.height());
|
||||
|
||||
// Draw the texture on the offscreen framebuffer object, while blurring it horizontally
|
||||
target->attachTexture(tex);
|
||||
GLRenderTarget::pushRenderTarget(target);
|
||||
|
||||
shader->bind();
|
||||
|
@ -363,10 +429,10 @@ void BlurEffect::doBlur(const QRegion& shape, const QRect& screen, const float o
|
|||
|
||||
// Now draw the horizontally blurred area back to the backbuffer, while
|
||||
// blurring it vertically and clipping it to the window shape.
|
||||
tex->bind();
|
||||
tex.bind();
|
||||
|
||||
shader->setDirection(Qt::Vertical);
|
||||
shader->setPixelDistance(1.0 / tex->height());
|
||||
shader->setPixelDistance(1.0 / tex.height());
|
||||
|
||||
// Modulate the blurred texture with the window opacity if the window isn't opaque
|
||||
if (opacity < 1.0) {
|
||||
|
@ -381,8 +447,8 @@ void BlurEffect::doBlur(const QRegion& shape, const QRect& screen, const float o
|
|||
// Set the up the texture matrix to transform from screen coordinates
|
||||
// to texture coordinates.
|
||||
textureMatrix.setToIdentity();
|
||||
textureMatrix.scale(1.0 / tex->width(), -1.0 / tex->height(), 1);
|
||||
textureMatrix.translate(0, -tex->height(), 0);
|
||||
textureMatrix.scale(1.0 / tex.width(), -1.0 / tex.height(), 1);
|
||||
textureMatrix.translate(0, -tex.height(), 0);
|
||||
loadMatrix(textureMatrix);
|
||||
shader->setTextureMatrix(textureMatrix);
|
||||
|
||||
|
@ -400,7 +466,143 @@ void BlurEffect::doBlur(const QRegion& shape, const QRect& screen, const float o
|
|||
#endif
|
||||
}
|
||||
|
||||
tex->unbind();
|
||||
tex.unbind();
|
||||
shader->unbind();
|
||||
}
|
||||
|
||||
void BlurEffect::doCachedBlur(EffectWindow *w, const QRegion& region, const float opacity)
|
||||
{
|
||||
const QRect screen(0, 0, displayWidth(), displayHeight());
|
||||
const QRegion blurredRegion = blurRegion(w).translated(w->pos()) & screen;
|
||||
const QRegion expanded = expand(blurredRegion) & screen;
|
||||
const QRect r = expanded.boundingRect();
|
||||
|
||||
// The background texture we get is only partially valid, because we might be
|
||||
// painting opaque areas top to bottom such that we accidentally blur these areas.
|
||||
// Anyway this behavior is more performant than shrinking the clipping area of the
|
||||
// higher windows in order to get a fully valid background texture.
|
||||
|
||||
if (!windows.contains(w)) {
|
||||
BlurWindowInfo bwi;
|
||||
bwi.blurredBackground = GLTexture(r.width(),r.height());
|
||||
bwi.textureValid = false;
|
||||
windows[w] = bwi;
|
||||
}
|
||||
|
||||
if (windows[w].blurredBackground.size() != r.size()) {
|
||||
windows[w].blurredBackground = GLTexture(r.width(),r.height());
|
||||
windows[w].textureValid = false;
|
||||
}
|
||||
|
||||
GLTexture targetTexture = windows[w].blurredBackground;
|
||||
targetTexture.setFilter(GL_LINEAR);
|
||||
targetTexture.setWrapMode(GL_CLAMP_TO_EDGE);
|
||||
shader->bind();
|
||||
QMatrix4x4 textureMatrix;
|
||||
QMatrix4x4 modelViewProjectionMatrix;
|
||||
#ifndef KWIN_HAVE_OPENGLES
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
pushMatrix();
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
pushMatrix();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
pushMatrix();
|
||||
#endif
|
||||
|
||||
if (!windows[w].textureValid) {
|
||||
// Create a scratch texture and copy the area in the back buffer that we're
|
||||
// going to blur into it
|
||||
GLTexture scratch(r.width(), r.height());
|
||||
scratch.setFilter(GL_LINEAR);
|
||||
scratch.setWrapMode(GL_CLAMP_TO_EDGE);
|
||||
scratch.bind();
|
||||
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r.x(), displayHeight() - r.y() - r.height(),
|
||||
r.width(), r.height());
|
||||
|
||||
// Draw the texture on the offscreen framebuffer object, while blurring it horizontally
|
||||
target->attachTexture(targetTexture);
|
||||
GLRenderTarget::pushRenderTarget(target);
|
||||
|
||||
shader->setDirection(Qt::Horizontal);
|
||||
shader->setPixelDistance(1.0 / r.width());
|
||||
|
||||
modelViewProjectionMatrix.ortho(0, r.width(), r.height(), 0 , 0, 65535);
|
||||
modelViewProjectionMatrix.translate(-r.x(), -r.y(), 0);
|
||||
loadMatrix(modelViewProjectionMatrix);
|
||||
shader->setModelViewProjectionMatrix(modelViewProjectionMatrix);
|
||||
|
||||
// Set up the texture matrix to transform from screen coordinates
|
||||
// to texture coordinates.
|
||||
textureMatrix.scale(1.0 / scratch.width(), -1.0 / scratch.height(), 1);
|
||||
textureMatrix.translate(-r.x(), -scratch.height() - r.y(), 0);
|
||||
#ifndef KWIN_HAVE_OPENGLES
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
loadMatrix(textureMatrix);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
#endif
|
||||
shader->setTextureMatrix(textureMatrix);
|
||||
|
||||
drawRegion(expanded);
|
||||
|
||||
GLRenderTarget::popRenderTarget();
|
||||
scratch.unbind();
|
||||
windows[w].textureValid = true;
|
||||
}
|
||||
|
||||
// Now draw the horizontally blurred area back to the backbuffer, while
|
||||
// blurring it vertically and clipping it to the window shape.
|
||||
targetTexture.bind();
|
||||
|
||||
shader->setDirection(Qt::Vertical);
|
||||
shader->setPixelDistance(1.0 / targetTexture.height());
|
||||
|
||||
// Modulate the blurred texture with the window opacity if the window isn't opaque
|
||||
if (opacity < 1.0) {
|
||||
#ifndef KWIN_HAVE_OPENGLES
|
||||
glPushAttrib(GL_COLOR_BUFFER_BIT);
|
||||
#endif
|
||||
glEnable(GL_BLEND);
|
||||
glBlendColor(0, 0, 0, opacity);
|
||||
glBlendFunc(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA);
|
||||
}
|
||||
|
||||
modelViewProjectionMatrix.setToIdentity();
|
||||
modelViewProjectionMatrix.ortho(0, displayWidth(), displayHeight(), 0, 0, 65535);
|
||||
loadMatrix(modelViewProjectionMatrix);
|
||||
shader->setModelViewProjectionMatrix(modelViewProjectionMatrix);
|
||||
|
||||
// Set the up the texture matrix to transform from screen coordinates
|
||||
// to texture coordinates.
|
||||
textureMatrix.setToIdentity();
|
||||
textureMatrix.scale(1.0 / targetTexture.width(), -1.0 / targetTexture.height(), 1);
|
||||
textureMatrix.translate(-r.x(), -targetTexture.height() - r.y(), 0);
|
||||
#ifndef KWIN_HAVE_OPENGLES
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
loadMatrix(textureMatrix);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
#endif
|
||||
shader->setTextureMatrix(textureMatrix);
|
||||
|
||||
drawRegion(blurredRegion & region);
|
||||
|
||||
#ifndef KWIN_HAVE_OPENGLES
|
||||
popMatrix();
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
popMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
popMatrix();
|
||||
#endif
|
||||
|
||||
if (opacity < 1.0) {
|
||||
glDisable(GL_BLEND);
|
||||
#ifndef KWIN_HAVE_OPENGLES
|
||||
glPopAttrib();
|
||||
#endif
|
||||
}
|
||||
|
||||
targetTexture.unbind();
|
||||
shader->unbind();
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ public:
|
|||
|
||||
public Q_SLOTS:
|
||||
void slotWindowAdded(EffectWindow *w);
|
||||
void slotWindowDeleted(EffectWindow *w);
|
||||
void slotPropertyNotify(EffectWindow *w, long atom);
|
||||
|
||||
private:
|
||||
|
@ -60,15 +61,25 @@ private:
|
|||
void updateBlurRegion(EffectWindow *w) const;
|
||||
void drawRegion(const QRegion ®ion);
|
||||
void doBlur(const QRegion &shape, const QRect &screen, const float opacity);
|
||||
void doCachedBlur(EffectWindow *w, const QRegion& region, const float opacity);
|
||||
|
||||
private:
|
||||
BlurShader *shader;
|
||||
QVector<QVector2D> vertices;
|
||||
GLRenderTarget *target;
|
||||
GLTexture *tex;
|
||||
GLTexture tex;
|
||||
long net_wm_blur_region;
|
||||
QRegion m_damagedArea; // keeps track of the area which has been damaged (from bottom to top)
|
||||
QRegion m_paintedArea; // actually painted area which is greater than m_damagedArea
|
||||
QRegion m_currentBlur; // keeps track of the currently blured area (from bottom to top)
|
||||
bool m_shouldCache;
|
||||
|
||||
struct BlurWindowInfo {
|
||||
GLTexture blurredBackground; // keeps the horizontally blurred background
|
||||
bool textureValid;
|
||||
};
|
||||
|
||||
QHash< const EffectWindow*, BlurWindowInfo > windows;
|
||||
};
|
||||
|
||||
} // namespace KWin
|
||||
|
|
|
@ -31,6 +31,7 @@ BlurEffectConfig::BlurEffectConfig(QWidget *parent, const QVariantList &args)
|
|||
{
|
||||
ui.setupUi(this);
|
||||
connect(ui.slider, SIGNAL(valueChanged(int)), SLOT(valueChanged(int)));
|
||||
connect(ui.checkBox, SIGNAL(stateChanged(int)), SLOT(valueChanged(int)));
|
||||
|
||||
load();
|
||||
}
|
||||
|
@ -44,6 +45,7 @@ void BlurEffectConfig::load()
|
|||
KCModule::load();
|
||||
KConfigGroup cg = EffectsHandler::effectConfig("Blur");
|
||||
ui.slider->setValue(cg.readEntry("BlurRadius", 12) / 2);
|
||||
ui.checkBox->setChecked(cg.readEntry("CacheTexture", true));
|
||||
emit changed(false);
|
||||
}
|
||||
|
||||
|
@ -53,6 +55,7 @@ void BlurEffectConfig::save()
|
|||
|
||||
KConfigGroup cg = EffectsHandler::effectConfig("Blur");
|
||||
cg.writeEntry("BlurRadius", ui.slider->value() * 2);
|
||||
cg.writeEntry("CacheTexture", ui.checkBox->isChecked());
|
||||
cg.sync();
|
||||
|
||||
emit changed(false);
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>206</width>
|
||||
<height>72</height>
|
||||
<width>396</width>
|
||||
<height>103</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
|
@ -74,11 +74,27 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox">
|
||||
<property name="toolTip">
|
||||
<string extracomment="Enables an internal texture cache which saves the background of the blurred area. This results in less repaints and in a slightly higher memory usage."/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Safe intermediate rendering results.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
|
|
|
@ -178,6 +178,14 @@ void GLSLBlurShader::setTextureMatrix(const QMatrix4x4 &matrix)
|
|||
shader->setUniform("u_textureMatrix", matrix);
|
||||
}
|
||||
|
||||
void GLSLBlurShader::setModelViewProjectionMatrix(const QMatrix4x4 &matrix)
|
||||
{
|
||||
if (!isValid()) {
|
||||
return;
|
||||
}
|
||||
shader->setUniform("u_modelViewProjectionMatrix", matrix);
|
||||
}
|
||||
|
||||
void GLSLBlurShader::bind()
|
||||
{
|
||||
if (!isValid())
|
||||
|
|
|
@ -54,6 +54,7 @@ public:
|
|||
// Sets the distance between two pixels
|
||||
virtual void setPixelDistance(float val) = 0;
|
||||
virtual void setTextureMatrix(const QMatrix4x4 &matrix) = 0;
|
||||
virtual void setModelViewProjectionMatrix(const QMatrix4x4 &matrix) = 0;
|
||||
|
||||
virtual void bind() = 0;
|
||||
virtual void unbind() = 0;
|
||||
|
@ -89,6 +90,7 @@ public:
|
|||
void bind();
|
||||
void unbind();
|
||||
void setTextureMatrix(const QMatrix4x4 &matrix);
|
||||
void setModelViewProjectionMatrix(const QMatrix4x4 &matrix);
|
||||
|
||||
static bool supported();
|
||||
|
||||
|
@ -116,7 +118,8 @@ public:
|
|||
void setPixelDistance(float val);
|
||||
void bind();
|
||||
void unbind();
|
||||
void setTextureMatrix(const QMatrix4x4 &) {};
|
||||
void setTextureMatrix(const QMatrix4x4 &) {}
|
||||
void setModelViewProjectionMatrix(const QMatrix4x4 &matrix) {}
|
||||
|
||||
static bool supported();
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ void LogoutEffect::prePaintScreen(ScreenPrePaintData& data, int time)
|
|||
blurTexture->setFilter(GL_LINEAR_MIPMAP_LINEAR);
|
||||
blurTexture->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||
|
||||
blurTarget = new GLRenderTarget(blurTexture);
|
||||
blurTarget = new GLRenderTarget(*blurTexture);
|
||||
if (blurTarget->valid())
|
||||
blurSupported = true;
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ bool LookingGlassEffect::loadData()
|
|||
m_texture->setFilter(GL_LINEAR_MIPMAP_LINEAR);
|
||||
m_texture->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||
|
||||
m_fbo = new GLRenderTarget(m_texture);
|
||||
m_fbo = new GLRenderTarget(*m_texture);
|
||||
if (!m_fbo->valid()) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -182,7 +182,7 @@ void MagnifierEffect::zoomIn()
|
|||
if (!m_texture) {
|
||||
m_texture = new GLTexture(magnifier_size);
|
||||
m_texture->setYInverted(false);
|
||||
m_fbo = new GLRenderTarget(m_texture);
|
||||
m_fbo = new GLRenderTarget(*m_texture);
|
||||
}
|
||||
effects->addRepaint(magnifierArea().adjusted(-FRAME_WIDTH, -FRAME_WIDTH, FRAME_WIDTH, FRAME_WIDTH));
|
||||
}
|
||||
|
@ -217,7 +217,7 @@ void MagnifierEffect::toggle()
|
|||
if (!m_texture) {
|
||||
m_texture = new GLTexture(magnifier_size);
|
||||
m_texture->setYInverted(false);
|
||||
m_fbo = new GLRenderTarget(m_texture);
|
||||
m_fbo = new GLRenderTarget(*m_texture);
|
||||
}
|
||||
} else {
|
||||
target_zoom = 1;
|
||||
|
|
|
@ -65,7 +65,7 @@ void ScreenShotEffect::postPaintScreen()
|
|||
GLTexture* offscreenTexture = new GLTexture(w, h);
|
||||
offscreenTexture->setFilter(GL_LINEAR);
|
||||
offscreenTexture->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||
GLRenderTarget* target = new GLRenderTarget(offscreenTexture);
|
||||
GLRenderTarget* target = new GLRenderTarget(*offscreenTexture);
|
||||
if (target->valid()) {
|
||||
WindowPaintData d(m_scheduledScreenshot);
|
||||
double left = 0;
|
||||
|
@ -184,7 +184,7 @@ QString ScreenShotEffect::blitScreenshot(const QRect &geometry)
|
|||
return QString();
|
||||
#else
|
||||
GLTexture tex(geometry.width(), geometry.height());
|
||||
GLRenderTarget target(&tex);
|
||||
GLRenderTarget target(tex);
|
||||
target.blitFromFramebuffer(geometry);
|
||||
// copy content from framebuffer into image
|
||||
tex.bind();
|
||||
|
|
|
@ -93,7 +93,7 @@ void LanczosFilter::updateOffscreenSurfaces()
|
|||
m_offscreenTex = new GLTexture(w, h);
|
||||
m_offscreenTex->setFilter(GL_LINEAR);
|
||||
m_offscreenTex->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||
m_offscreenTarget = new GLRenderTarget(m_offscreenTex);
|
||||
m_offscreenTarget = new GLRenderTarget(*m_offscreenTex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -871,6 +871,7 @@ void ShaderManager::resetShader(ShaderType type)
|
|||
bool GLRenderTarget::sSupported = false;
|
||||
bool GLRenderTarget::s_blitSupported = false;
|
||||
QStack<GLRenderTarget*> GLRenderTarget::s_renderTargets = QStack<GLRenderTarget*>();
|
||||
QSize GLRenderTarget::s_oldViewport;
|
||||
|
||||
void GLRenderTarget::initStatic()
|
||||
{
|
||||
|
@ -895,6 +896,12 @@ bool GLRenderTarget::blitSupported()
|
|||
|
||||
void GLRenderTarget::pushRenderTarget(GLRenderTarget* target)
|
||||
{
|
||||
if (s_renderTargets.isEmpty()) {
|
||||
GLint params[4];
|
||||
glGetIntegerv(GL_VIEWPORT, params);
|
||||
s_oldViewport = QSize(params[2], params[3]);
|
||||
}
|
||||
|
||||
target->enable();
|
||||
s_renderTargets.push(target);
|
||||
}
|
||||
|
@ -903,12 +910,15 @@ GLRenderTarget* GLRenderTarget::popRenderTarget()
|
|||
{
|
||||
GLRenderTarget* ret = s_renderTargets.pop();
|
||||
ret->disable();
|
||||
if (!s_renderTargets.isEmpty())
|
||||
if (!s_renderTargets.isEmpty()) {
|
||||
s_renderTargets.top()->enable();
|
||||
} else if (!s_oldViewport.isEmpty()) {
|
||||
glViewport (0, 0, s_oldViewport.width(), s_oldViewport.height());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
GLRenderTarget::GLRenderTarget(GLTexture* color)
|
||||
GLRenderTarget::GLRenderTarget(const GLTexture& color)
|
||||
{
|
||||
// Reset variables
|
||||
mValid = false;
|
||||
|
@ -916,7 +926,7 @@ GLRenderTarget::GLRenderTarget(GLTexture* color)
|
|||
mTexture = color;
|
||||
|
||||
// Make sure FBO is supported
|
||||
if (sSupported && mTexture && !mTexture->isNull()) {
|
||||
if (sSupported && !mTexture.isNull()) {
|
||||
initFBO();
|
||||
} else
|
||||
kError(1212) << "Render targets aren't supported!" << endl;
|
||||
|
@ -937,7 +947,8 @@ bool GLRenderTarget::enable()
|
|||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
|
||||
mTexture->setDirty();
|
||||
glViewport(0, 0, mTexture.width(), mTexture.height());
|
||||
mTexture.setDirty();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -950,7 +961,7 @@ bool GLRenderTarget::disable()
|
|||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
mTexture->setDirty();
|
||||
mTexture.setDirty();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1017,7 +1028,7 @@ void GLRenderTarget::initFBO()
|
|||
#endif
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
mTexture->target(), mTexture->texture(), 0);
|
||||
mTexture.target(), mTexture.texture(), 0);
|
||||
|
||||
#if DEBUG_GLRENDERTARGET
|
||||
if ((err = glGetError()) != GL_NO_ERROR) {
|
||||
|
@ -1055,15 +1066,29 @@ void GLRenderTarget::blitFromFramebuffer(const QRect &source, const QRect &desti
|
|||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebuffer);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
const QRect s = source.isNull() ? QRect(0, 0, displayWidth(), displayHeight()) : source;
|
||||
const QRect d = destination.isNull() ? QRect(0, 0, mTexture->width(), mTexture->height()) : destination;
|
||||
const QRect d = destination.isNull() ? QRect(0, 0, mTexture.width(), mTexture.height()) : destination;
|
||||
|
||||
glBlitFramebuffer(s.x(), displayHeight() - s.y() - s.height(), s.x() + s.width(), displayHeight() - s.y(),
|
||||
d.x(), mTexture->height() - d.y() - d.height(), d.x() + d.width(), mTexture->height() - d.y(),
|
||||
d.x(), mTexture.height() - d.y() - d.height(), d.x() + d.width(), mTexture.height() - d.y(),
|
||||
GL_COLOR_BUFFER_BIT, filter);
|
||||
GLRenderTarget::popRenderTarget();
|
||||
#endif
|
||||
}
|
||||
|
||||
void GLRenderTarget::attachTexture(const GLTexture& target)
|
||||
{
|
||||
if (!mValid || mTexture.texture() == target.texture()) {
|
||||
return;
|
||||
}
|
||||
|
||||
pushRenderTarget(this);
|
||||
|
||||
mTexture = target;
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
mTexture.target(), mTexture.texture(), 0);
|
||||
|
||||
popRenderTarget();
|
||||
}
|
||||
|
||||
//*********************************
|
||||
// GLVertexBufferPrivate
|
||||
|
|
|
@ -386,7 +386,7 @@ public:
|
|||
* Constructs a GLRenderTarget
|
||||
* @param color texture where the scene will be rendered onto
|
||||
**/
|
||||
GLRenderTarget(GLTexture* color);
|
||||
GLRenderTarget(const GLTexture& color);
|
||||
~GLRenderTarget();
|
||||
|
||||
/**
|
||||
|
@ -401,6 +401,13 @@ public:
|
|||
**/
|
||||
bool disable();
|
||||
|
||||
/**
|
||||
* Sets the target texture
|
||||
* @param target texture where the scene will be rendered on
|
||||
* @since 4.8
|
||||
**/
|
||||
void attachTexture(const GLTexture& target);
|
||||
|
||||
bool valid() const {
|
||||
return mValid;
|
||||
}
|
||||
|
@ -443,8 +450,9 @@ private:
|
|||
static bool sSupported;
|
||||
static bool s_blitSupported;
|
||||
static QStack<GLRenderTarget*> s_renderTargets;
|
||||
static QSize s_oldViewport;
|
||||
|
||||
GLTexture* mTexture;
|
||||
GLTexture mTexture;
|
||||
bool mValid;
|
||||
|
||||
GLuint mFramebuffer;
|
||||
|
|
Loading…
Reference in New Issue