Skip to content

Commit

Permalink
Performance|Widgets|libappfw: Update background blur only when needed
Browse files Browse the repository at this point in the history
GuiWidget was redrawing the blur FBO even when no one needed it.
Now it gets updated just-in-time when someone wants it.
  • Loading branch information
skyjake committed Feb 26, 2017
1 parent cd16838 commit 3180b05
Showing 1 changed file with 43 additions and 30 deletions.
73 changes: 43 additions & 30 deletions doomsday/sdk/libappfw/src/guiwidget.cpp
Expand Up @@ -73,6 +73,7 @@ DENG2_PIMPL(GuiWidget)
// Background blurring.
struct BlurState
{
Time updatedAt;
Vector2ui size;
QScopedPointer<GLTextureFramebuffer> fb[2];
Drawable drawable;
Expand Down Expand Up @@ -244,45 +245,31 @@ DENG2_PIMPL(GuiWidget)
}
}

void drawBlurredBackground()
void updateBlurredBackground()
{
if (background.type == Background::SharedBlur ||
background.type == Background::SharedBlurWithBorderGlow)
{
// Use another widget's blur.
DENG2_ASSERT(background.blur != 0);
if (background.blur)
{
self().root().painter().flush();
background.blur->drawBlurredRect(self().rule().recti(), background.solidFill);
}
return;
}
// Make sure blurring is initialized.
initBlur();

if (background.type != Background::Blurred &&
background.type != Background::BlurredWithBorderGlow &&
background.type != Background::BlurredWithSolidFill)
auto const now = Time::currentHighPerformanceTime();
if (blur->updatedAt == now)
{
deinitBlur();
return;
}

blur->updatedAt = now;

// Ensure normal drawing is complete.
auto &painter = self().root().painter();
painter.flush();

auto const oldClip = painter.normalizedScissor();

// Make sure blurring is initialized.
initBlur();

DENG2_ASSERT(blur->fb[0]->isReady());

// Pass 1: render all the widgets behind this one onto the first blur
// texture, downsampled.
GLState::push()
.setTarget(*blur->fb[0])
.setViewport(Rectangleui::fromSize(blur->size));
.setTarget(*blur->fb[0])
.setViewport(Rectangleui::fromSize(blur->size));
blur->fb[0]->clear(GLFramebuffer::Depth);
self().root().drawUntil(self());
GLState::pop();
Expand All @@ -292,8 +279,8 @@ DENG2_PIMPL(GuiWidget)
// Pass 2: apply the horizontal blur filter to draw the background
// contents onto the second blur texture.
GLState::push()
.setTarget(*blur->fb[1])
.setViewport(Rectangleui::fromSize(blur->size));
.setTarget(*blur->fb[1])
.setViewport(Rectangleui::fromSize(blur->size));
blur->uTex = blur->fb[0]->colorTexture();
blur->uMvpMatrix = Matrix4f::ortho(0, 1, 0, 1);
blur->uWindow = Vector4f(0, 0, 1, 1);
Expand All @@ -303,6 +290,33 @@ DENG2_PIMPL(GuiWidget)

blur->fb[1]->resolveSamples();

painter.setNormalizedScissor(oldClip);
}

void drawBlurredBackground()
{
if (background.type == Background::SharedBlur ||
background.type == Background::SharedBlurWithBorderGlow)
{
// Use another widget's blur.
DENG2_ASSERT(background.blur != 0);
if (background.blur)
{
self().root().painter().flush();
background.blur->d->updateBlurredBackground();
background.blur->drawBlurredRect(self().rule().recti(), background.solidFill);
}
return;
}

if (background.type != Background::Blurred &&
background.type != Background::BlurredWithBorderGlow &&
background.type != Background::BlurredWithSolidFill)
{
deinitBlur();
return;
}

// Pass 3: apply the vertical blur filter, drawing the final result
// into the original target.
Vector4f blurColor = background.solidFill;
Expand All @@ -311,12 +325,11 @@ DENG2_PIMPL(GuiWidget)
{
blurColor.w = 1;
}
if (!attribs.testFlag(DontDrawContent) && blurColor.w > 0 && blurOpacity > 0)
if (blurColor.w > 0 && blurOpacity > 0)
{
updateBlurredBackground();
self().drawBlurredRect(self().rule().recti(), blurColor, blurOpacity);
}

painter.setNormalizedScissor(oldClip);
}

inline float currentOpacity() const
Expand Down Expand Up @@ -908,10 +921,10 @@ void GuiWidget::draw()
// Detect mistakes in GLState stack usage.
dsize const depthBeforeDrawingWidget = GLState::stackDepth();
#endif
d->drawBlurredBackground();

if (!d->attribs.testFlag(DontDrawContent))
{
d->drawBlurredBackground();

auto &painter = root().painter();
painter.setSaturation(d->saturation);

Expand Down

0 comments on commit 3180b05

Please sign in to comment.