Merge branch 'master' of git://anongit.kde.org/kde-workspace

icc-effect-5.14.5
Sebastian Kügler 2011-09-19 17:09:26 +02:00
commit 224f8a78e7
15 changed files with 320 additions and 44 deletions

View File

@ -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;

View File

@ -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();
}

View File

@ -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 &region)
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();
}

View File

@ -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 &region);
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

View File

@ -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);

View File

@ -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>

View File

@ -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())

View File

@ -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();

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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();

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;