LookingGlass ported to GLES.

LookingGlass does not inherit ShaderEffect any more and uses just a
fragment shader. It still renders to a FBO, this could probably be
improved.
This commit is contained in:
Martin Gräßlin 2011-01-06 17:18:27 +01:00
parent 75e926a6d7
commit 863726a085
7 changed files with 158 additions and 59 deletions

View file

@ -93,6 +93,7 @@ if( KWIN_HAVE_OPENGL_COMPOSITING )
include( cube/CMakeLists.txt )
include( flipswitch/CMakeLists.txt )
include( glide/CMakeLists.txt )
include( lookingglass/CMakeLists.txt )
include( magnifier/CMakeLists.txt )
include( mousemark/CMakeLists.txt )
include( screenshot/CMakeLists.txt )
@ -106,7 +107,6 @@ if( KWIN_HAVE_OPENGL_COMPOSITING AND NOT KWIN_HAVE_OPENGLES_COMPOSITING )
include( blur/CMakeLists.txt )
include( explosion/CMakeLists.txt )
include( invert/CMakeLists.txt )
include( lookingglass/CMakeLists.txt )
include( sharpen/CMakeLists.txt )
include( snow/CMakeLists.txt )
endif( KWIN_HAVE_OPENGL_COMPOSITING AND NOT KWIN_HAVE_OPENGLES_COMPOSITING )

View file

@ -44,6 +44,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "cube/cubeslide_config.h"
#include "flipswitch/flipswitch_config.h"
#include "glide/glide_config.h"
#include "lookingglass/lookingglass_config.h"
#include "magnifier/magnifier_config.h"
#include "mousemark/mousemark_config.h"
#include "trackmouse/trackmouse_config.h"
@ -51,7 +52,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef KWIN_HAVE_OPENGLES
#include "blur/blur_config.h"
#include "invert/invert_config.h"
#include "lookingglass/lookingglass_config.h"
#include "sharpen/sharpen_config.h"
#include "snow/snow_config.h"
#endif
@ -86,6 +86,7 @@ KWIN_EFFECT_CONFIG_MULTIPLE( builtins,
KWIN_EFFECT_CONFIG_SINGLE( cubeslide, CubeSlideEffectConfig )
KWIN_EFFECT_CONFIG_SINGLE( flipswitch, FlipSwitchEffectConfig )
KWIN_EFFECT_CONFIG_SINGLE( glide, GlideEffectConfig )
KWIN_EFFECT_CONFIG_SINGLE( lookingglass, LookingGlassEffectConfig )
KWIN_EFFECT_CONFIG_SINGLE( magnifier, MagnifierEffectConfig )
KWIN_EFFECT_CONFIG_SINGLE( mousemark, MouseMarkEffectConfig )
KWIN_EFFECT_CONFIG_SINGLE( trackmouse, TrackMouseEffectConfig )
@ -93,7 +94,6 @@ KWIN_EFFECT_CONFIG_MULTIPLE( builtins,
#ifndef KWIN_HAVE_OPENGLES
KWIN_EFFECT_CONFIG_SINGLE( blur, BlurEffectConfig )
KWIN_EFFECT_CONFIG_SINGLE( invert, InvertEffectConfig )
KWIN_EFFECT_CONFIG_SINGLE( lookingglass, LookingGlassEffectConfig )
KWIN_EFFECT_CONFIG_SINGLE( sharpen, SharpenEffectConfig )
KWIN_EFFECT_CONFIG_SINGLE( snow, SnowEffectConfig )
#endif

View file

@ -14,7 +14,6 @@ install( FILES
# Data files
install( FILES
lookingglass/data/lookingglass.frag
lookingglass/data/lookingglass.vert
DESTINATION ${DATA_INSTALL_DIR}/kwin )
#######################################

View file

@ -1,33 +1,25 @@
uniform sampler2D sceneTex;
uniform float textureWidth;
uniform float textureHeight;
uniform float cursorX;
uniform float cursorY;
uniform float zoom;
uniform float radius;
uniform sampler2D sample;
uniform vec2 u_cursor;
uniform float u_zoom;
uniform float u_radius;
uniform vec2 u_textureSize;
varying vec2 varyingTexCoords;
#define PI 3.14159
// Converts pixel coordinates to texture coordinates
vec2 pix2tex(vec2 pix)
{
return vec2(pix.x / textureWidth, 1.0 - pix.y / textureHeight);
}
void main()
{
vec2 texcoord = gl_TexCoord[0].xy;
float dx = cursorX - texcoord.x;
float dy = cursorY - texcoord.y;
float dist = sqrt(dx*dx + dy*dy);
if(dist < radius)
{
float disp = sin(dist / radius * PI) * (zoom - 1.0) * 20.0;
texcoord.x += dx / dist * disp;
texcoord.y += dy / dist * disp;
vec2 d = u_cursor - varyingTexCoords;
float dist = sqrt(d.x*d.x + d.y*d.y);
vec2 texcoord = varyingTexCoords;
if (dist < u_radius) {
float disp = sin(dist / u_radius * PI) * (u_zoom - 1.0) * 20.0;
texcoord += d / dist * disp;
}
gl_FragColor = texture2D(sceneTex, pix2tex(texcoord));
texcoord = texcoord/u_textureSize;
texcoord.t = 1.0 - texcoord.t;
gl_FragColor = texture2D(sample, texcoord);
}

View file

@ -1,6 +0,0 @@
void main()
{
gl_TexCoord[0].xy = gl_Vertex.xy;
gl_Position = ftransform();
}

View file

@ -28,6 +28,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <kconfiggroup.h>
#include <klocale.h>
#include <kdebug.h>
#include <KDE/KGlobal>
#include <KDE/KStandardDirs>
#include <QVector2D>
#include <kmessagebox.h>
@ -35,15 +38,21 @@ namespace KWin
{
KWIN_EFFECT( lookingglass, LookingGlassEffect )
KWIN_EFFECT_SUPPORTED( lookingglass, ShaderEffect::supported() )
KWIN_EFFECT_SUPPORTED( lookingglass, LookingGlassEffect::supported() )
LookingGlassEffect::LookingGlassEffect() : QObject(), ShaderEffect("lookingglass")
LookingGlassEffect::LookingGlassEffect()
: QObject()
, zoom( 1.0f )
, target_zoom( 1.0f )
, polling( false )
, m_texture( NULL )
, m_fbo( NULL )
, m_vbo( NULL )
, m_shader( NULL )
, m_enabled( false )
, m_valid( false )
{
zoom = 1.0f;
target_zoom = 1.0f;
polling = false;
actionCollection = new KActionCollection( this );
actionCollection->setConfigGlobal(true);
actionCollection->setConfigGroup("LookingGlass");
@ -60,8 +69,19 @@ LookingGlassEffect::LookingGlassEffect() : QObject(), ShaderEffect("lookingglass
LookingGlassEffect::~LookingGlassEffect()
{
delete m_texture;
delete m_fbo;
delete m_shader;
delete m_vbo;
}
bool LookingGlassEffect::supported()
{
return GLRenderTarget::supported() &&
GLShader::fragmentShaderSupported() &&
(effects->compositingType() == OpenGLCompositing);
}
void LookingGlassEffect::reconfigure( ReconfigureFlags )
{
KConfigGroup conf = EffectsHandler::effectConfig("LookingGlass");
@ -69,8 +89,61 @@ void LookingGlassEffect::reconfigure( ReconfigureFlags )
radius = initialradius;
kDebug(1212) << QString("Radius from config: %1").arg(radius) << endl;
actionCollection->readSettings();
m_valid = loadData();
}
bool LookingGlassEffect::loadData()
{
// If NPOT textures are not supported, use nearest power-of-two sized
// texture. It wastes memory, but it's possible to support systems without
// NPOT textures that way
int texw = displayWidth();
int texh = displayHeight();
if (!GLTexture::NPOTTextureSupported()) {
kWarning( 1212 ) << "NPOT textures not supported, wasting some memory" ;
texw = nearestPowerOfTwo(texw);
texh = nearestPowerOfTwo(texh);
}
// Create texture and render target
m_texture = new GLTexture(texw, texh);
m_texture->setFilter(GL_LINEAR_MIPMAP_LINEAR);
m_texture->setWrapMode(GL_CLAMP_TO_EDGE);
m_fbo = new GLRenderTarget(m_texture);
if (!m_fbo->valid()) {
return false;
}
const QString fragmentshader = KGlobal::dirs()->findResource("data", "kwin/lookingglass.frag");
m_shader = ShaderManager::instance()->loadFragmentShader(ShaderManager::SimpleShader, fragmentshader);
if (m_shader->isValid()) {
ShaderManager::instance()->pushShader(m_shader);
m_shader->setUniform("u_textureSize", QVector2D(displayWidth(), displayHeight()));
ShaderManager::instance()->popShader();
} else {
kError(1212) << "The shader failed to load!" << endl;
return false;
}
m_vbo = new GLVertexBuffer(GLVertexBuffer::Static);
QVector<float> verts;
QVector<float> texcoords;
texcoords << displayWidth() << 0.0;
verts << displayWidth() << 0.0;
texcoords << 0.0 << 0.0;
verts << 0.0 << 0.0;
texcoords << 0.0 << displayHeight();
verts << 0.0 << displayHeight();
texcoords << 0.0 << displayHeight();
verts << 0.0 << displayHeight();
texcoords << displayWidth() << displayHeight();
verts << displayWidth() << displayHeight();
texcoords << displayWidth() << 0.0;
verts << displayWidth() << 0.0;
m_vbo->setData(6, 2, verts.constData(), texcoords.constData());
return true;
}
void LookingGlassEffect::toggle()
{
if( target_zoom == 1.0f )
@ -81,7 +154,7 @@ void LookingGlassEffect::toggle()
polling = true;
effects->startMousePolling();
}
setEnabled( true );
m_enabled = true;
}
else
{
@ -91,14 +164,14 @@ void LookingGlassEffect::toggle()
polling = false;
effects->stopMousePolling();
}
setEnabled( false );
m_enabled = false;
}
}
void LookingGlassEffect::zoomIn()
{
target_zoom = qMin(7.0, target_zoom + 0.5);
setEnabled( true );
m_enabled = true;
if( !polling )
{
polling = true;
@ -113,7 +186,7 @@ void LookingGlassEffect::zoomOut()
if( target_zoom < 1 )
{
target_zoom = 1;
setEnabled( false );
m_enabled = false;
if( polling )
{
polling = false;
@ -135,34 +208,60 @@ void LookingGlassEffect::prePaintScreen( ScreenPrePaintData& data, int time )
kDebug(1212) << "zoom is now " << zoom;
radius = qBound((double)initialradius, initialradius * zoom, 3.5*initialradius);
if( zoom > 1.0f )
{
shader()->bind();
shader()->setUniform("zoom", (float)zoom);
shader()->setUniform("radius", (float)radius);
shader()->unbind();
}
else
{
setEnabled( false );
}
if( zoom <= 1.0f ) {
m_enabled = false;
}
effects->addRepaint( cursorPos().x() - radius, cursorPos().y() - radius, 2*radius, 2*radius );
}
if (m_valid && m_enabled) {
data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
// Start rendering to texture
effects->pushRenderTarget(m_fbo);
checkGLError("push Render Target");
}
ShaderEffect::prePaintScreen( data, time );
effects->prePaintScreen( data, time );
}
void LookingGlassEffect::mouseChanged( const QPoint& pos, const QPoint& old, Qt::MouseButtons,
Qt::MouseButtons, Qt::KeyboardModifiers, Qt::KeyboardModifiers )
{
if( pos != old && isEnabled() )
if( pos != old && m_enabled )
{
effects->addRepaint( pos.x() - radius, pos.y() - radius, 2*radius, 2*radius );
effects->addRepaint( old.x() - radius, old.y() - radius, 2*radius, 2*radius );
}
}
void LookingGlassEffect::postPaintScreen()
{
// Call the next effect.
effects->postPaintScreen();
if (m_valid && m_enabled) {
// Disable render texture
checkGLError("Before Pop Render Target");
GLRenderTarget* target = effects->popRenderTarget();
checkGLError("Pop Render Target");
assert( target == m_fbo );
Q_UNUSED( target );
m_texture->bind();
checkGLError("Bind Texture");
// Use the shader
ShaderManager::instance()->pushShader(m_shader);
m_shader->setUniform("u_zoom", (float)zoom);
m_shader->setUniform("u_radius", (float)radius);
checkGLError("Bind Shader");
m_shader->setUniform("u_cursor", QVector2D(cursorPos().x(), cursorPos().y()));
m_vbo->render(GL_TRIANGLES);
checkGLError("Render VBO");
ShaderManager::instance()->popShader();
checkGLError("Pop Shader");
m_texture->unbind();
}
}
} // namespace
#include "lookingglass.moc"

View file

@ -22,17 +22,22 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef KWIN_LOOKINGGLASS_H
#define KWIN_LOOKINGGLASS_H
#include <kwinshadereffect.h>
#include <kwineffects.h>
class KActionCollection;
namespace KWin
{
class GLRenderTarget;
class GLShader;
class GLTexture;
class GLVertexBuffer;
/**
* Enhanced magnifier
**/
class LookingGlassEffect : public QObject, public ShaderEffect
class LookingGlassEffect : public QObject, public Effect
{
Q_OBJECT
public:
@ -45,6 +50,9 @@ class LookingGlassEffect : public QObject, public ShaderEffect
Qt::KeyboardModifiers modifiers, Qt::KeyboardModifiers oldmodifiers );
virtual void prePaintScreen( ScreenPrePaintData& data, int time );
virtual void postPaintScreen();
static bool supported();
public slots:
void toggle();
@ -52,12 +60,19 @@ class LookingGlassEffect : public QObject, public ShaderEffect
void zoomOut();
private:
bool loadData();
double zoom;
double target_zoom;
bool polling; // Mouse polling
int radius;
int initialradius;
KActionCollection* actionCollection;
GLTexture *m_texture;
GLRenderTarget *m_fbo;
GLVertexBuffer *m_vbo;
GLShader *m_shader;
bool m_enabled;
bool m_valid;
};
} // namespace