summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Spilsbury <smspillaz@gmail.com>2009-08-30 17:09:40 +0800
committerSam Spilsbury <smspillaz@gmail.com>2009-08-30 17:09:40 +0800
commita1c6811bc7b9ee218cb6cd7f4c84472ea44d327d (patch)
treeebea1414a6bc90a5521940a7ba338bab2abbeb85
parente1c1da459349d3050303259fbfe21d0451263b77 (diff)
downloadbicubic-a1c6811bc7b9ee218cb6cd7f4c84472ea44d327d.tar.gz
bicubic-a1c6811bc7b9ee218cb6cd7f4c84472ea44d327d.tar.bz2
Add files in C++ port
-rw-r--r--src/bicubic.cpp316
-rw-r--r--src/bicubic.h94
2 files changed, 410 insertions, 0 deletions
diff --git a/src/bicubic.cpp b/src/bicubic.cpp
new file mode 100644
index 0000000..7523738
--- /dev/null
+++ b/src/bicubic.cpp
@@ -0,0 +1,316 @@
+/*
+ *
+ * Compiz bicubic filter plugin
+ *
+ * bicubic.c
+ *
+ * Copyright : (C) 2008 by Dennis Kasprzyk
+ * E-mail : onestone@opencompositing.org
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "bicubic.h"
+
+COMPIZ_PLUGIN_20090315 (bicubic, BicubicPluginVTable);
+
+int
+BicubicScreen::getBicubicFragmentFunction (GLTexture *texture,
+ int param,
+ int unit)
+{
+ GLFragment::FunctionData *data;
+ int target;
+ char *targetString;
+
+ if (texture->target () == GL_TEXTURE_2D)
+ {
+ target = COMP_FETCH_TARGET_2D;
+ targetString = "2D";
+ }
+ else
+ {
+ target = COMP_FETCH_TARGET_RECT;
+ targetString = "RECT";
+ }
+
+ foreach (BicubicFunction *function, func)
+ if (function->param == param &&
+ function->target == target &&
+ function->unit == unit)
+ return function->handle;
+
+ data = new GLFragment::FunctionData ();
+ if (data)
+ {
+ int handle = 0;
+ BicubicFunction *function = NULL;
+
+ static char *filterTemp[] = {
+ "hgX", "hgY", "cs00", "cs01", "cs10", "cs11"
+ };
+
+ for (int i = 0; i < sizeof (filterTemp) / sizeof (filterTemp[0]); i++)
+ data->addTempHeaderOp (filterTemp[i]);
+
+
+ data->addDataOp (
+ "MAD cs00, fragment.texcoord[0], program.env[%d],"
+ "{-0.5, -0.5, 0.0, 0.0};", param + 2);
+
+ data->addDataOp (
+ "TEX hgX, cs00.x, texture[%d], 1D;", unit);
+ data->addDataOp (
+ "TEX hgY, cs00.y, texture[%d], 1D;", unit);
+
+ data->addDataOp (
+ "MUL cs10, program.env[%d], hgX.y;", param);
+ data->addDataOp (
+ "MUL cs00, program.env[%d], -hgX.x;", param);
+ data->addDataOp (
+ "MAD cs11, program.env[%d], hgY.y, cs10;", param + 1);
+ data->addDataOp (
+ "MAD cs01, program.env[%d], hgY.y, cs00;", param + 1);
+ data->addDataOp (
+ "MAD cs10, program.env[%d], -hgY.x, cs10;", param + 1);
+ data->addDataOp (
+ "MAD cs00, program.env[%d], -hgY.x, cs00;", param + 1);
+
+ data->addDataOp (
+ "ADD cs00, cs00, fragment.texcoord[0];");
+ data->addDataOp (
+ "ADD cs01, cs01, fragment.texcoord[0];");
+ data->addDataOp (
+ "ADD cs10, cs10, fragment.texcoord[0];");
+ data->addDataOp (
+ "ADD cs11, cs11, fragment.texcoord[0];");
+
+ data->addDataOp (
+ "TEX cs00, cs00, texture[0], %s;", targetString);
+ data->addDataOp (
+ "TEX cs01, cs01, texture[0], %s;", targetString);
+ data->addDataOp (
+ "TEX cs10, cs10, texture[0], %s;", targetString);
+ data->addDataOp (
+ "TEX cs11, cs11, texture[0], %s;", targetString);
+
+ data->addDataOp ( "LRP cs00, hgY.z, cs00, cs01;");
+ data->addDataOp ( "LRP cs10, hgY.z, cs10, cs11;");
+
+ data->addDataOp ( "LRP output, hgX.z, cs00, cs10;");
+
+ data->addColorOp ( "output", "output");
+ if (!data->status ())
+ {
+ delete data;
+ return 0;
+ }
+
+ function = new BicubicFunction ();
+ if (function)
+ {
+ handle = data->createFragmentFunction ("bicubic");
+
+ function->handle = handle;
+ function->target = target;
+ function->param = param;
+ function->unit = unit;
+
+ func.push_back (function);
+ }
+
+ delete data;
+
+ return handle;
+ }
+
+ return 0;
+}
+
+void
+BicubicWindow::glDrawTexture (GLTexture *texture,
+ GLFragment::Attrib &attrib,
+ unsigned int mask)
+{
+ BICUBIC_SCREEN (screen);
+
+ if ((mask & (PAINT_WINDOW_TRANSFORMED_MASK |
+ PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK)) &&
+ bs->gScreen->textureFilter () == GLTexture::Good)
+ {
+ GLFragment::Attrib fa = attrib;
+ int function, param;
+ int unit = 0;
+
+ param = fa.allocParameters (3);
+ unit = fa.allocTextureUnits (1);
+
+ function = bs->getBicubicFragmentFunction (texture, param, unit);
+
+ if (function)
+ {
+ fa.addFunction (function);
+
+ GL::activeTexture (GL_TEXTURE0_ARB + unit);
+ glBindTexture (GL_TEXTURE_1D, bs->lTexture);
+ GL::activeTexture (GL_TEXTURE0_ARB);
+
+
+ GL::programEnvParameter4f (GL_FRAGMENT_PROGRAM_ARB, param,
+ texture->matrix ().xx, 0.0f,
+ 0.0f, 0.0f);
+ GL::programEnvParameter4f (GL_FRAGMENT_PROGRAM_ARB,
+ param + 1,
+ 0.0f, -texture->matrix ().yy,
+ 0.0f, 0.0f);
+ GL::programEnvParameter4f (GL_FRAGMENT_PROGRAM_ARB,
+ param + 2,
+ 1.0 / texture->matrix ().xx,
+ 1.0 / -texture->matrix ().yy,
+ 0.0f, 0.0f);
+ }
+
+ gWindow->glDrawTexture (texture, fa, mask);
+
+ if (unit)
+ {
+ GL::activeTexture (GL_TEXTURE0_ARB + unit);
+ glBindTexture (GL_TEXTURE_1D, 0);
+ GL::activeTexture (GL_TEXTURE0_ARB);
+ }
+ }
+ else
+ {
+ gWindow->glDrawTexture (texture, attrib, mask);
+ }
+}
+
+void
+BicubicScreen::generateLookupTexture (GLenum format)
+{
+ GLfloat values[512];
+ float a, a2, a3, w0, w1, w2, w3;
+
+ for (int i = 0; i < 512; i += 4)
+ {
+ a = (float)i / 512.0;
+ a2 = a * a;
+ a3 = a2 * a;
+
+ w0 = (1.0 / 6.0) * ((-a3) + (3.0 * a2) + (-3.0 * a) + 1.0);
+ w1 = (1.0 / 6.0) * ((3.0 * a3) + (-6.0 * a2) + 4.0);
+ w2 = (1.0 / 6.0) * ((-3.0 * a3) + (3.0 * a2) + (3.0 * a) + 1.0);
+ w3 = (1.0 / 6.0) * a3;
+
+ values[i] = 1.0 - (w1 / (w0 + w1)) + a;
+ values[i + 1] = 1.0 + (w3 / (w2 + w3)) - a;
+ values[i + 2] = w0 + w1;
+ values[i + 3] = w2 + w3;
+ }
+
+ glGenTextures (1, &lTexture);
+
+ glBindTexture (GL_TEXTURE_1D, lTexture);
+
+ glTexImage1D (GL_TEXTURE_1D, 0, format, 128, 0, GL_RGBA,
+ GL_FLOAT, values);
+
+ glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+ glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+ glBindTexture (GL_TEXTURE_1D, 0);
+}
+
+
+BicubicScreen::BicubicScreen (CompScreen *screen) :
+ PluginClassHandler <BicubicScreen, CompScreen> (screen),
+ gScreen (GLScreen::get (screen)),
+ cScreen (CompositeScreen::get (screen))
+{
+ bool failed = false;
+ const char *glExtensions;
+ GLenum format = GL_RGBA16F_ARB;
+
+ if (!GL::fragmentProgram)
+ {
+ compLogMessage ("bicube", CompLogLevelFatal,
+ "GL_ARB_fragment_program not supported.");
+ setFailed ();
+ failed = true;
+ }
+
+ if (!failed)
+ {
+
+ glExtensions = (const char *) glGetString (GL_EXTENSIONS);
+ if (!glExtensions)
+ {
+ compLogMessage ("bicubic", CompLogLevelFatal,
+ "No valid GL extensions string found.");
+ setFailed ();
+ failed = true;
+ }
+
+ }
+
+ if (!failed)
+ {
+
+ if (!strstr (glExtensions, "GL_ARB_texture_float"))
+ {
+ compLogMessage ("bicubic", CompLogLevelFatal,
+ "GL_ARB_texture_float not supported. "
+ "This can lead to visual artifacts.");
+ format = GL_RGBA;
+ }
+ }
+
+ generateLookupTexture (format);
+}
+
+BicubicScreen::~BicubicScreen ()
+{
+ BicubicFunction *f;
+ while (func.size ())
+ {
+ f = func.front ();
+ GLFragment::destroyFragmentFunction (f->handle);
+ func.remove (f);
+ }
+
+ glDeleteTextures (1, &lTexture);
+}
+
+BicubicWindow::BicubicWindow (CompWindow *window) :
+ PluginClassHandler <BicubicWindow, CompWindow> (window),
+ cWindow (CompositeWindow::get (window)),
+ gWindow (GLWindow::get (window))
+{
+ GLWindowInterface::setHandler (gWindow);
+}
+
+bool
+BicubicPluginVTable::init ()
+{
+ if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION))
+ return false;
+ if (!CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI))
+ return false;
+ if (!CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))
+ return false;
+
+ return true;
+}
diff --git a/src/bicubic.h b/src/bicubic.h
new file mode 100644
index 0000000..4d7e0d5
--- /dev/null
+++ b/src/bicubic.h
@@ -0,0 +1,94 @@
+/*
+ *
+ * Compiz bicubic filter plugin
+ *
+ * bicubic.h
+ *
+ * Copyright : (C) 2008 by Dennis Kasprzyk
+ * E-mail : onestone@opencompositing.org
+ *
+ * Ported to Compiz 0.9 by:
+ * Copyright : (C) 2008 by Sam Spilsbury
+ * E-mail : smspillaz@gmail.com
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <core/core.h>
+#include <composite/composite.h>
+#include <opengl/opengl.h>
+
+#include "bicubic_options.h"
+
+class BicubicFunction
+{
+ public:
+ int handle;
+ int target;
+ int param;
+ int unit;
+};
+
+class BicubicScreen :
+ public PluginClassHandler <BicubicScreen, CompScreen>,
+ public BicubicOptions
+{
+ public:
+ BicubicScreen (CompScreen *screen);
+ ~BicubicScreen ();
+
+ GLScreen *gScreen;
+ CompositeScreen *cScreen;
+
+ std::list <BicubicFunction *> func;
+
+ GLenum lTexture;
+
+ int
+ getBicubicFragmentFunction (GLTexture *texture,
+ int param,
+ int unit);
+
+ void
+ generateLookupTexture (GLenum format);
+};
+
+class BicubicWindow :
+ public PluginClassHandler <BicubicWindow, CompWindow>,
+ public GLWindowInterface
+{
+ public:
+ BicubicWindow (CompWindow *);
+
+ CompositeWindow *cWindow;
+ GLWindow *gWindow;
+
+ void
+ glDrawTexture (GLTexture *texture,
+ GLFragment::Attrib &,
+ unsigned int);
+};
+
+#define BICUBIC_SCREEN(s) \
+ BicubicScreen *bs = BicubicScreen::get (s)
+
+#define BICUBIC_WINDOW(w) \
+ BicubicWindow *bw = BicubicWindow::get (w)
+
+class BicubicPluginVTable :
+ public CompPlugin::VTableForScreenAndWindow <BicubicScreen, BicubicWindow>
+{
+ public:
+
+ bool init ();
+};