summaryrefslogtreecommitdiff
path: root/surface.c
diff options
context:
space:
mode:
authorAaron Plattner <aplattner@nvidia.com>2009-11-29 14:43:11 -0800
committerAaron Plattner <aplattner@nvidia.com>2009-11-29 14:43:11 -0800
commit22eaa2e3cdb42fdb8dc391e786ae272212b90f20 (patch)
tree52b0dc1b3435313b961ca283954fea7ca5869212 /surface.c
parent2d33078e72a251cc9fa99f71220342fc436932d3 (diff)
Add a convolution test
Diffstat (limited to 'surface.c')
-rw-r--r--surface.c79
1 files changed, 79 insertions, 0 deletions
diff --git a/surface.c b/surface.c
index 022a935..ad60e32 100644
--- a/surface.c
+++ b/surface.c
@@ -1,5 +1,7 @@
#include "surface.h"
+#include <assert.h>
+#include <math.h>
#include <stdlib.h>
#include <stdio.h>
@@ -78,6 +80,80 @@ xrender_surf_populate(Display *disp, XRenderSurf *rs, int w, int h,
XFreeGC(disp, gc);
}
+/* this is similar to create_gaussian_kernel_1d() except for the fact that I use
+** a naive (or let's call it: brute-force) 2d implementation of a gaussian-blur
+** to be able to compare the performance... and the performance non-surprisingly
+** sucks... 2 pass 1d gauss. blur is faster than 1 pass 2d gauss. blur */
+static XFixed*
+create_gaussian_kernel_2d (int iRadius,
+ int* piSize)
+{
+ double fSigma = (double) iRadius / 2.0f;
+ double fScale1;
+ double fScale2;
+ double* pTmpKernel = NULL;
+ XFixed* pKernel = NULL;
+ double fU;
+ double fV;
+ int iX;
+ int iY;
+ double fSum = 0.0f;
+
+ assert (piSize != NULL);
+
+ fScale2 = 2.0f * fSigma * fSigma;
+ fScale1 = 1.0f / (M_PI * fScale2);
+
+ *piSize = (2 * iRadius+1) * (2 * iRadius+1);
+ pTmpKernel = (double*) calloc (*piSize, sizeof (double));
+ if (!pTmpKernel)
+ return NULL;
+
+ for (iX = 0; iX < 2 * iRadius+1; iX++)
+ {
+ for (iY = 0; iY < 2 * iRadius+1; iY++)
+ {
+ fU = (double) iX;
+ fV = (double) iY;
+ pTmpKernel[iX+iY*(2*iRadius+1)] = fScale1 * exp (-(fU*fU+fV*fV) / fScale2);
+ }
+ }
+
+ for (iX = 0; iX < *piSize; iX++)
+ fSum += pTmpKernel[iX];
+
+ for (iX = 0; iX < *piSize; iX++)
+ pTmpKernel[iX] /= fSum;
+
+ pKernel = (XFixed*) calloc (*piSize + 2, sizeof (XFixed));
+ if (!pKernel)
+ {
+ free (pTmpKernel);
+ return NULL;
+ }
+
+ for (iX = 0; iX < *piSize; iX++)
+ pKernel[iX + 2] = XDoubleToFixed (pTmpKernel[iX]);
+
+ free (pTmpKernel);
+
+ *piSize += 2;
+ pKernel[0] = (2 * iRadius + 1) <<16;
+ pKernel[1] = (2 * iRadius + 1) << 16;
+
+ return pKernel;
+}
+
+static void
+set_convolution(Display *disp, XRenderSurf *rs)
+{
+ int kernel_size;
+ XFixed *blur_kernel = create_gaussian_kernel_2d(20, &kernel_size);
+
+ XRenderSetPictureFilter(disp, rs->pic, FilterConvolution, blur_kernel,
+ kernel_size);
+}
+
void
xrender_surf_prepare(Display *disp, XRenderSurf *src, int w, int h,
int transformations, SurfaceFilter filter)
@@ -98,6 +174,9 @@ xrender_surf_prepare(Display *disp, XRenderSurf *src, int w, int h,
case SurfaceNearest:
XRenderSetPictureFilter(disp, src->pic, "nearest", NULL, 0);
break;
+ case SurfaceConvolution:
+ set_convolution(disp, src);
+ break;
default:
break;
}