1
// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
3
* Copyright (C) 2010 Canonical Ltd
5
* This program is free software: you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License version 3 as
7
* published by the Free Software Foundation.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17
* Authored by: Jay Taoko <jay.taoko@canonical.com>
20
#include "BackgroundEffectHelper.h"
22
using namespace unity;
24
std::list<BackgroundEffectHelper*> BackgroundEffectHelper::registered_list_;
26
nux::Property<BlurType> BackgroundEffectHelper::blur_type (BLUR_ACTIVE);
27
nux::Property<float> BackgroundEffectHelper::sigma_high (5.0f);
28
nux::Property<float> BackgroundEffectHelper::sigma_med (4.0f);
29
nux::Property<float> BackgroundEffectHelper::sigma_low (1.0f);
30
nux::Property<bool> BackgroundEffectHelper::updates_enabled (true);
33
BackgroundEffectHelper::BackgroundEffectHelper()
35
noise_texture_ = nux::CreateTextureFromFile(PKGDATADIR"/dash_noise.png");
39
BackgroundEffectHelper::~BackgroundEffectHelper()
44
void BackgroundEffectHelper::QueueDrawOnOwners ()
46
for (BackgroundEffectHelper* helper : registered_list_)
48
nux::View *owner = helper->owner();
54
void BackgroundEffectHelper::Register (BackgroundEffectHelper *self)
56
registered_list_.push_back(self);
59
void BackgroundEffectHelper::Unregister (BackgroundEffectHelper *self)
61
registered_list_.remove(self);
64
void BackgroundEffectHelper::DirtyCache ()
66
if (blur_texture_.IsValid ())
67
blur_texture_.Release ();
70
nux::ObjectPtr<nux::IOpenGLBaseTexture> BackgroundEffectHelper::GetBlurRegion(nux::Geometry geo, bool force_update)
72
nux::GraphicsEngine* graphics_engine = nux::GetGraphicsDisplay()->GetGraphicsEngine();
74
bool should_update = updates_enabled() || force_update;
76
if ((blur_type != BLUR_ACTIVE || !should_update)
77
&& blur_texture_.IsValid()
78
&& (geo == blur_geometry_))
83
blur_geometry_ = nux::Geometry(0, 0, graphics_engine->GetWindowWidth(), graphics_engine->GetWindowHeight()).Intersect(geo);
85
if (blur_geometry_.IsNull() || blur_type == BLUR_NONE || !nux::GetGraphicsDisplay()->GetGpuDevice()->backup_texture0_.IsValid())
87
return nux::ObjectPtr<nux::IOpenGLBaseTexture>(NULL);
90
// save the current fbo
91
nux::ObjectPtr<nux::IOpenGLFrameBufferObject> current_fbo = nux::GetGraphicsDisplay()->GetGpuDevice()->GetCurrentFrameBufferObject();
92
nux::GetGraphicsDisplay ()->GetGpuDevice ()->DeactivateFrameBuffer ();
94
// Set a viewport to the requested size
95
graphics_engine->SetViewport (0, 0, blur_geometry_.width, blur_geometry_.height);
96
graphics_engine->SetScissor (0, 0, blur_geometry_.width, blur_geometry_.height);
97
// Disable nux scissoring
98
graphics_engine->GetRenderStates ().EnableScissor (false);
100
// The background texture is the same size as the monitor where we are rendering.
101
nux::TexCoordXForm texxform__bg;
102
texxform__bg.flip_v_coord = false;
103
texxform__bg.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD);
104
texxform__bg.uoffset = ((float) blur_geometry_.x) / graphics_engine->GetWindowWidth ();
105
texxform__bg.voffset = ((float) graphics_engine->GetWindowHeight () - blur_geometry_.y - blur_geometry_.height) / graphics_engine->GetWindowHeight ();
107
int opengl_version = nux::GetGraphicsDisplay()->GetGpuDevice()->GetOpenGLMajorVersion();
108
bool support_frag = nux::GetGraphicsDisplay()->GetGpuDevice()->GetGpuInfo().Support_ARB_Fragment_Shader();
109
bool support_vert = nux::GetGraphicsDisplay()->GetGpuDevice()->GetGpuInfo().Support_ARB_Vertex_Shader();
111
if (support_vert && support_frag && opengl_version >= 2)
113
float noise_factor = 1.2f;
114
float gaussian_sigma = opengl_version >= 3 ? sigma_high : sigma_med;
117
nux::ObjectPtr<nux::IOpenGLBaseTexture> device_texture = nux::GetGraphicsDisplay()->GetGpuDevice()->backup_texture0_;
118
nux::ObjectPtr<nux::CachedBaseTexture> noise_device_texture = graphics_engine->CacheResource(noise_texture_);
120
int down_size_factor = 1;
121
unsigned int buffer_width = blur_geometry_.width;
122
unsigned int buffer_height = blur_geometry_.height;
127
unsigned int down_size_width = buffer_width / down_size_factor;
128
unsigned int down_size_height = buffer_height / down_size_factor;
130
nux::TexCoordXForm texxform;
131
nux::TexCoordXForm noise_texxform;
133
texxform.SetFilter(nux::TEXFILTER_LINEAR, nux::TEXFILTER_LINEAR);
135
noise_texxform.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD);
136
noise_texxform.SetWrap(nux::TEXWRAP_REPEAT, nux::TEXWRAP_REPEAT);
137
noise_texxform.SetFilter(nux::TEXFILTER_NEAREST, nux::TEXFILTER_NEAREST);
140
graphics_engine->QRP_GetCopyTexture(down_size_width, down_size_height, temp_device_texture0_,
141
device_texture, texxform__bg, nux::color::White);
143
// Blur at a lower resolution (less pixels to process)
144
temp_device_texture1_ = graphics_engine->QRP_GetHQBlur(x, y, down_size_width, down_size_height,
145
temp_device_texture0_, texxform, nux::color::White,
146
gaussian_sigma, blur_passes);
149
graphics_engine->QRP_GetCopyTexture(buffer_width, buffer_height, temp_device_texture0_,
150
temp_device_texture1_, texxform, nux::color::White);
153
blur_texture_ = graphics_engine->QRP_GLSL_GetDisturbedTexture(
154
0, 0, buffer_width, buffer_height,
155
noise_device_texture->m_Texture, noise_texxform, nux::Color (
156
noise_factor * 1.0f/buffer_width,
157
noise_factor * 1.0f/buffer_height, 1.0f, 1.0f),
158
temp_device_texture0_, texxform, nux::color::White);
162
// GPUs with only ARB support are treated here
164
float gaussian_sigma = sigma_low;
167
nux::ObjectPtr<nux::IOpenGLBaseTexture> device_texture = nux::GetGraphicsDisplay()->GetGpuDevice()->backup_texture0_;
168
nux::ObjectPtr<nux::CachedBaseTexture> noise_device_texture = graphics_engine->CacheResource(noise_texture_);
170
unsigned int offset = 0;
171
int quad_width = blur_geometry_.width;
172
int quad_height = blur_geometry_.height;
174
int down_size_factor = 4;
175
unsigned int buffer_width = quad_width + 2 * offset;
176
unsigned int buffer_height = quad_height + 2 * offset;
178
int x = (buffer_width - quad_width) / 2;
179
int y = (buffer_height - quad_height) / 2;
181
unsigned int down_size_width = buffer_width / down_size_factor;
182
unsigned int down_size_height = buffer_height / down_size_factor;
184
nux::TexCoordXForm texxform;
185
nux::TexCoordXForm noise_texxform;
187
texxform.SetFilter(nux::TEXFILTER_LINEAR, nux::TEXFILTER_LINEAR);
189
noise_texxform.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD);
190
noise_texxform.SetWrap(nux::TEXWRAP_REPEAT, nux::TEXWRAP_REPEAT);
191
noise_texxform.SetFilter(nux::TEXFILTER_NEAREST, nux::TEXFILTER_NEAREST);
193
// Copy source texture
194
graphics_engine->QRP_GetCopyTexture(buffer_width, buffer_height, temp_device_texture0_,
195
device_texture, texxform__bg, nux::color::White);
198
graphics_engine->QRP_GetCopyTexture(down_size_width, down_size_height, ds_temp_device_texture1_,
199
temp_device_texture0_, texxform, nux::color::White);
201
// Blur at a lower resolution (less pixels to process)
202
ds_temp_device_texture0_ = graphics_engine->QRP_GetBlurTexture(x, y, down_size_width, down_size_height,
203
ds_temp_device_texture1_, texxform, nux::color::White,
204
gaussian_sigma, blur_passes);
206
// // Copy to new texture
207
// graphics_engine->QRP_GetCopyTexture(down_size_width, down_size_height, temp_device_texture1_, temp_device_texture0_, texxform, nux::color::White);
210
graphics_engine->QRP_GetCopyTexture(buffer_width, buffer_height, temp_device_texture1_,
211
ds_temp_device_texture0_, texxform, nux::color::White);
213
blur_texture_ = temp_device_texture1_;
216
if (current_fbo.IsValid())
218
current_fbo->Activate(true);
219
graphics_engine->Push2DWindow(current_fbo->GetWidth(), current_fbo->GetHeight());
220
graphics_engine->GetRenderStates ().EnableScissor (true);
224
graphics_engine->SetViewport(0, 0, graphics_engine->GetWindowWidth(), graphics_engine->GetWindowHeight());
225
graphics_engine->Push2DWindow(graphics_engine->GetWindowWidth(), graphics_engine->GetWindowHeight());
226
graphics_engine->ApplyClippingRectangle();
229
return blur_texture_;