/*
* Beryl blur and reflection effect plugin
*
* blurfx.c
*
* Copyright : (C) 2006 by Dennis Kasprzyk
* E-mail : onestone@beryl-project.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 <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xrender.h>
#include <sys/stat.h>
#include <unistd.h>
#include <beryl.h>
#include <beryl_helpers.h>
#include "blurfx.h"
// return plugin data
CompPluginVTable *getCompPluginInfo(void)
{
return &blurfxVTable;
}
static Bool blurfxInit(CompPlugin * p)
{
blurShader[0][0] = gaussian5x5_V;
blurShader[0][1] = gaussian5x5_H;
blurShader[1][0] = linear5x5_V;
blurShader[1][1] = linear5x5_H;
blurShader[2][0] = gaussian9x9_V;
blurShader[2][1] = gaussian9x9_H;
blurShader[3][0] = linear9x9_V;
blurShader[3][1] = linear9x9_H;
blurShader[4][0] = gaussian13x13_V;
blurShader[4][1] = gaussian13x13_H;
blurShader[5][0] = linear13x13_V;
blurShader[5][1] = linear13x13_H;
blurShader[6][0] = gaussian17x17_V;
blurShader[6][1] = gaussian17x17_H;
blurShader[7][0] = linear17x17_V;
blurShader[7][1] = linear17x17_H;
blurShader[8][0] = gaussian21x21_V;
blurShader[8][1] = gaussian21x21_H;
blurShader[9][0] = linear21x21_V;
blurShader[9][1] = linear21x21_H;
displayPrivateIndex = allocateDisplayPrivateIndex();
if (displayPrivateIndex < 0)
return FALSE;
return TRUE;
}
static void blurfxFini(CompPlugin * p)
{
if (displayPrivateIndex >= 0)
freeDisplayPrivateIndex(displayPrivateIndex);
}
static Bool blurfxInitDisplay(CompPlugin * p, CompDisplay * d)
{
//Generate a blur display
BlurfxDisplay *bd = (BlurfxDisplay *) calloc(1, sizeof(BlurfxDisplay));
//Allocate a private index
bd->screenPrivateIndex = allocateScreenPrivateIndex(d);
//Check if its valid
if (bd->screenPrivateIndex < 0)
{
//Its invalid so free memory and return
free(bd);
return FALSE;
}
blurfxDisplayInitOptions(bd);
//Record the display
d->privates[displayPrivateIndex].ptr = bd;
return TRUE;
}
static void blurfxFiniDisplay(CompPlugin * p, CompDisplay * d)
{
BLURFX_DISPLAY(d);
//Free the private index
freeScreenPrivateIndex(d, bd->screenPrivateIndex);
//Free the pointer
free(bd);
}
static Bool blurfxInitScreen(CompPlugin * p, CompScreen * s)
{
BLURFX_DISPLAY(s->display);
// Create a blur screen
BlurfxScreen *bs = (BlurfxScreen *) calloc(1, sizeof(BlurfxScreen));
s->privates[bd->screenPrivateIndex].ptr = bs;
bs->blur_supported = TRUE;
bs->fboBlur_supported = TRUE;
bs->mblur_supported = TRUE;
bs->reflection_supported = TRUE;
// Check for extensions and disable unsupported features
if (!s->fbo)
{
fprintf(stderr,
"No framebuffer_object support! (only simple Blur aviable).\n");
bs->fboBlur_supported = FALSE;
}
if (!s->fragmentProgram)
{
fprintf(stderr,
"No fragment_program support! (only simple Blur aviable).\n");
bs->fboBlur_supported = FALSE;
}
if (!s->textureRectangle)
{
fprintf(stderr,
"No texture_rectangle support! (Blur effects disabled).\n");
bs->blur_supported = FALSE;
bs->fboBlur_supported = FALSE;
bs->mblur_supported = FALSE;
}
if (!s->textureEnvCombine)
{
fprintf(stderr,
"No texture_env_combine support! (Blur and Reflection effects disabled).\n");
bs->blur_supported = FALSE;
bs->fboBlur_supported = FALSE;
bs->reflection_supported = FALSE;
}
// initialize all variables
bs->windowPrivateIndex = allocateWindowPrivateIndex(s);
bs->vertArray.vertices = 0;
bs->vertArray.vCount = 0;
bs->vertArray.vertexSize = 0;
bs->screenDamage = XCreateRegion();
bs->occlusion = XCreateRegion();
bs->blurredRegion = XCreateRegion();
bs->mb_activated = FALSE;
bs->mb_update = TRUE;
bs->noBlurWMask = 0;
bs->noReflectionWMask = 0;
// setup settings
blurfxScreenInitOptions(bs);
int i = 0;
for (i = 0; i < LIST_SIZE(mBlurModes); i++)
if (strcmp
(bs->opt[BLURFX_SCREEN_OPTION_MOTION_BLUR_MODE].value.
s, mBlurModes[i]) == 0)
bs->mb_mode = i;
for (i = 0; i < LIST_SIZE(blurShaderNames); i++)
if (strcmp
(bs->opt[BLURFX_SCREEN_OPTION_BLUR_SHADER].value.s,
blurShaderNames[i]) == 0)
bs->blur_shader = i;
addScreenAction(s,
&bd->opt[BLURFX_DISPLAY_OPTION_MOTION_BLUR_TOGGLE].
value.action);
//Take over the window draw function
WRAP(bs, s, drawWindowTexture, blurfxDrawWindowTexture);
WRAP(bs, s, drawWindow, blurfxDrawWindow);
WRAP(bs, s, damageWindowRect, blurfxDamageWindowRect);
WRAP(bs, s, paintScreen, blurfxPaintScreen);
WRAP(bs, s, addWindowGeometry, blurfxAddWindowGeometry);
WRAP(bs, s, preparePaintScreen, blurfxPreparePaintScreen);
WRAP(bs, s, paintTransformedScreen, blurfxPaintTransformedScreen);
damageScreen(s);
bs->ipcs_disable_blur =
IPCS_GetAtom(IPCS_OBJECT(s), IPCS_BOOL, "DISABLE_BLUR", TRUE);
bs->ipcs_disable_reflection =
IPCS_GetAtom(IPCS_OBJECT(s), IPCS_BOOL, "DISABLE_REFLECTION",
TRUE);
bs->ipcs_disable_mblur =
IPCS_GetAtom(IPCS_OBJECT(s), IPCS_BOOL, "DISABLE_MOTION_BLUR",
TRUE);
return TRUE;
}
static void blurfxFiniScreen(CompPlugin * p, CompScreen * s)
{
BLURFX_SCREEN(s);
BLURFX_DISPLAY(s->display);
// delete shaders
if (bs->blurShaderV)
(*s->deletePrograms) (1, &bs->blurShaderV);
if (bs->blurShaderH)
(*s->deletePrograms) (1, &bs->blurShaderH);
// delete the textures
if (bs->backTex.handle)
glDeleteTextures(1, &bs->backTex.handle);
if (bs->motionTex.handle)
glDeleteTextures(1, &bs->motionTex.handle);
if (bs->blurTempTexV.handle)
glDeleteTextures(1, &bs->blurTempTexV.handle);
if (bs->blurTempTexH.handle)
glDeleteTextures(1, &bs->blurTempTexH.handle);
if (bs->modTex.handle)
glDeleteTextures(1, &bs->modTex.handle);
// delete framebuffer object
if (bs->fbo)
{
s->deleteFramebuffers(1, &bs->fbo);
}
// free some pointers
free(bs->vertArray.vertices);
freeWindowPrivateIndex(s, bs->windowPrivateIndex);
XDestroyRegion(bs->screenDamage);
XDestroyRegion(bs->occlusion);
XDestroyRegion(bs->blurredRegion);
// restore the original function
UNWRAP(bs, s, drawWindowTexture);
UNWRAP(bs, s, drawWindow);
UNWRAP(bs, s, damageWindowRect);
UNWRAP(bs, s, paintScreen);
UNWRAP(bs, s, addWindowGeometry);
UNWRAP(bs, s, preparePaintScreen);
UNWRAP(bs, s, paintTransformedScreen);
removeScreenAction(s,
&bd->
opt[BLURFX_DISPLAY_OPTION_MOTION_BLUR_TOGGLE].
value.action);
// free the screen pointer
free(bs);
}
static Bool blurfxInitWindow(CompPlugin * p, CompWindow * w)
{
BlurfxWindow *bw;
BLURFX_SCREEN(w->screen);
// create window
bw = calloc(1, sizeof(BlurfxWindow));
if (!bw)
return FALSE;
// initialize variables
bw->my_next = w->next;
bw->lastX = w->attrib.x;
bw->lastY = w->attrib.y;
bw->lastPAttrib = w->lastPaint;
bw->decoArray.vertices = NULL;
bw->decoArray.indices = NULL;
bw->decoArray.vCount = 0;
bw->decoArray.vertexSize = 0;
bw->decoArray.indexSize = 0;
bw->decoArray.indexCount = 0;
bw->paintRegion = XCreateRegion();
bw->damageRegion = XCreateRegion();
bw->texDamage = XCreateRegion();
bw->bTexRegion = XCreateRegion();
bw->clip = XCreateRegion();
bw->hasTexture = FALSE;
bw->vertArray.vertices = 0;
bw->vertArray.vCount = 0;
bw->vertArray.vertexSize = 0;
bw->isSwitcher = FALSE;
Atom type;
int format;
unsigned long nitems;
unsigned long bytes_after;
Window *xw;
int result = XGetWindowProperty(w->screen->display->display, w->id,
XInternAtom(w->screen->display->display,
"_SWITCH_SELECT_WINDOW",
0),
0L, 1L,
False, XA_WINDOW, &type, &format,
&nitems,
&bytes_after, (void *)&xw);
if (result == Success && type == XA_WINDOW)
bw->isSwitcher = TRUE;
w->privates[bs->windowPrivateIndex].ptr = bw;
damageScreen(w->screen);
bw->ipcs_disable_blur =
IPCS_GetAtom(IPCS_OBJECT(w), IPCS_BOOL, "DISABLE_BLUR", TRUE);
bw->ipcs_disable_reflection =
IPCS_GetAtom(IPCS_OBJECT(w), IPCS_BOOL, "DISABLE_REFLECTION",
TRUE);
return TRUE;
}
static void blurfxFiniWindow(CompPlugin * p, CompWindow * w)
{
BLURFX_WINDOW(w);
// free regions
XDestroyRegion(bw->paintRegion);
XDestroyRegion(bw->damageRegion);
XDestroyRegion(bw->texDamage);
XDestroyRegion(bw->bTexRegion);
XDestroyRegion(bw->clip);
// delete blur cache texture
if (bw->hasTexture)
glDeleteTextures(1, &bw->blurTex.handle);
// free used memory
if (bw->decoArray.vertices)
free(bw->decoArray.vertices);
if (bw->decoArray.indices)
free(bw->decoArray.indices);
if (bw->vertArray.vertices)
free(bw->vertArray.vertices);
// free window pointer
free(bw);
}
static CompOption *blurfxGetDisplayOptions(CompDisplay * display, int *count)
{
if (display)
{
BLURFX_DISPLAY(display);
*count = NUM_OPTIONS(bd);
return bd->opt;
}
else
{
BlurfxDisplay *bd =
(BlurfxDisplay *) calloc(1, sizeof(BlurfxDisplay));
blurfxDisplayInitOptions(bd);
*count = NUM_OPTIONS(bd);
return bd->opt;
}
}
static Bool
blurfxSetDisplayOption(CompDisplay * display, char *name,
CompOptionValue * value)
{
CompOption *o;
int index;
BLURFX_DISPLAY(display);
o = compFindOption(bd->opt, NUM_OPTIONS(bd), name, &index);
if (!o)
return FALSE;
switch (index)
{
case BLURFX_DISPLAY_OPTION_MOTION_BLUR_TOGGLE:
if (setDisplayAction(display, o, value))
return TRUE;
break;
default:
break;
}
return FALSE;
}
static void blurfxDisplayInitOptions(BlurfxDisplay * bd)
{
CompOption *o;
o = &bd->opt[BLURFX_DISPLAY_OPTION_MOTION_BLUR_TOGGLE];
o->advanced = False;
o->name = "motion_blur_toggle";
o->group = N_("Motion Blur");
o->subGroup = N_("Activate");
o->displayHints = "";
o->shortDesc = N_("Toggle Motion Blur");
o->longDesc = N_("Toggle motion Blur effect.");
o->type = CompOptionTypeAction;
o->value.action.initiate = blurfxToggleMotionBlur;
o->value.action.terminate = 0;
o->value.action.bell = FALSE;
o->value.action.edgeMask = 0;
o->value.action.type = CompBindingTypeKey;
o->value.action.state = CompActionStateInitKey;
o->value.action.key.modifiers =
BLURFX_DISPLAY_OPTION_MOTION_BLUR_TOGGLE_MOD_DEFAULT;
o->value.action.key.keysym =
XStringToKeysym
(BLURFX_DISPLAY_OPTION_MOTION_BLUR_TOGGLE_KEY_DEFAULT);
}
static Bool
blurfxSetScreenOption(CompScreen * s, char *name, CompOptionValue * value)
{
CompOption *o;
int index;
BLURFX_SCREEN(s);
o = compFindOption(bs->opt, NUM_OPTIONS(bs), name, &index);
if (!o)
return FALSE;
switch (index)
{
case BLURFX_SCREEN_OPTION_BLUR_WINDOWS:
case BLURFX_SCREEN_OPTION_BLUR_DECORATION:
case BLURFX_SCREEN_OPTION_REFLECTION_WINDOWS:
case BLURFX_SCREEN_OPTION_REFLECTION_DECORATION:
case BLURFX_SCREEN_OPTION_BLUR_ON_TRANSFORMED_SCREEN:
case BLURFX_SCREEN_OPTION_BLUR_TRANSFORMED_WINDOW:
case BLURFX_SCREEN_OPTION_REFLECTION_ON_TRANSFORMED_SCREEN:
case BLURFX_SCREEN_OPTION_REFLECTION_TRANSFORMED_WINDOW:
case BLURFX_SCREEN_OPTION_REFLECTION_SCALE:
case BLURFX_SCREEN_OPTION_REFLECTION_PROPORTIONAL:
case BLURFX_SCREEN_OPTION_MOTION_BLUR_ON_TRANSFORMED_SCREEN:
case BLURFX_SCREEN_OPTION_DISABLE_DECORATION_ALPHADEP:
case BLURFX_SCREEN_OPTION_NO_BLUR_CACHE_ON_TRANSFORMED_SCREEN:
if (compSetBoolOption(o, value))
{
damageScreen(s);
return TRUE;
}
break;
case BLURFX_SCREEN_OPTION_BLUR_CACHE_TEXTURES:
if (compSetBoolOption(o, value))
{
if (!value->b)
{
CompWindow *w;
for (w = s->windows; w; w = w->next)
{
BLURFX_WINDOW(w);
if (bw->hasTexture)
{
bw->hasTexture = FALSE;
glDeleteTextures(1, &bw->blurTex.handle);
bw->blurTex.handle = 0;
}
}
}
damageScreen(s);
return TRUE;
}
break;
case BLURFX_SCREEN_OPTION_BLUR_SHADER:
if (compSetStringOption(o, value))
{
int i = 0;
for (i = 0; i < LIST_SIZE(blurShaderNames); i++)
if (strcmp(value->s, blurShaderNames[i]) == 0)
bs->blur_shader = i;
if (bs->fboBlur_supported && bs->hasInit
&& !bs->opt[BLURFX_SCREEN_OPTION_FORCE_NON_FBO_BLUR].value.b)
{
loadShader(GL_FRAGMENT_PROGRAM_ARB, s,
&bs->blurShaderV, blurShader[bs->blur_shader][0]);
loadShader(GL_FRAGMENT_PROGRAM_ARB, s,
&bs->blurShaderH, blurShader[bs->blur_shader][1]);
damageScreen(s);
CompWindow *w;
for (w = s->windows; w; w = w->next)
{
BLURFX_WINDOW(w);
if (bw->hasTexture)
{
bw->hasTexture = FALSE;
glDeleteTextures(1, &bw->blurTex.handle);
bw->blurTex.handle = 0;
}
}
}
return TRUE;
}
break;
case BLURFX_SCREEN_OPTION_DISABLE_BLUR_ON_SCREENGRAB_OF:
case BLURFX_SCREEN_OPTION_DISABLE_REFLECTION_ON_SCREENGRAB_OF:
case BLURFX_SCREEN_OPTION_MOTION_BLUR_ON_SCREENGRAB_OF:
if (compSetOptionList(o, value))
{
damageScreen(s);
return TRUE;
}
break;
case BLURFX_SCREEN_OPTION_REFLECTION_FILE:
if (compSetStringOption(o, value))
{
if (bs->reflection_supported)
{
loadPngToTexture2D(s, &bs->modTex, value->s);
damageScreen(s);
}
return TRUE;
}
break;
case BLURFX_SCREEN_OPTION_REFLECTION_USE_IMAGE_COLOR:
case BLURFX_SCREEN_OPTION_REFLECTION_USE_IMAGE_ALPHA:
if (compSetBoolOption(o, value))
{
if (bs->reflection_supported)
{
loadPngToTexture2D(s, &bs->modTex,
bs->
opt
[BLURFX_SCREEN_OPTION_REFLECTION_FILE].
value.s);
damageScreen(s);
}
damageScreen(s);
return TRUE;
}
break;
case BLURFX_SCREEN_OPTION_BLUR_SATURATION:
case BLURFX_SCREEN_OPTION_MOTION_BLUR_STRENGTH:
if (compSetFloatOption(o, value))
{
damageScreen(s);
return TRUE;
}
break;
case BLURFX_SCREEN_OPTION_DISABLE_BLUR_WINDOW_TYPE:
if (compSetOptionList(o, value))
{
bs->noBlurWMask = compWindowTypeMaskFromStringList(&o->value);
damageScreen(s);
return TRUE;
}
break;
case BLURFX_SCREEN_OPTION_DISABLE_REFLECTION_WINDOW_TYPE:
if (compSetOptionList(o, value))
{
bs->noReflectionWMask =
compWindowTypeMaskFromStringList(&o->value);
damageScreen(s);
return TRUE;
}
break;
case BLURFX_SCREEN_OPTION_MOTION_BLUR_MODE:
if (compSetStringOption(o, value))
{
int i;
for (i = 0; i < LIST_SIZE(mBlurModes); i++)
if (strcmp(value->s, mBlurModes[i]) == 0)
bs->mb_mode = i;
if (bs->hasInit && bs->mblur_supported && bs->motionTex.handle)
{
glDeleteTextures(1, &bs->motionTex.handle);
bs->motionTex.handle = 0;
}
if (bs->hasInit && bs->mblur_supported
&& (bs->mb_mode == 0 || bs->mb_mode == 2))
{
genBlurTexture(bs, &bs->motionTex,
s->width, s->height, bs->mb_mode);
}
bs->mb_update = TRUE;
damageScreen(s);
return TRUE;
}
break;
case BLURFX_SCREEN_OPTION_FORCE_NON_FBO_BLUR:
if (compSetBoolOption(o, value))
{
if (!bs->hasInit)
return TRUE;
if (bs->fboBlur_supported && !value->b)
{
// load shaders
loadShader(GL_FRAGMENT_PROGRAM_ARB, s,
&bs->blurShaderV, blurShader[bs->blur_shader][0]);
loadShader(GL_FRAGMENT_PROGRAM_ARB, s,
&bs->blurShaderH, blurShader[bs->blur_shader][1]);
bs->downSample = 1.0;
}
CompWindow *w;
for (w = s->windows; w; w = w->next)
{
BLURFX_WINDOW(w);
if (bw->hasTexture)
{
bw->hasTexture = FALSE;
glDeleteTextures(1, &bw->blurTex.handle);
bw->blurTex.handle = 0;
}
}
damageScreen(s);
return TRUE;
}
break;
case BLURFX_SCREEN_OPTION_NON_FBO_BLUR_STRENGTH:
if (compSetIntOption(o, value))
{
if (!bs->hasInit)
return TRUE;
if (!bs->fboBlur_supported
|| bs->opt[BLURFX_SCREEN_OPTION_FORCE_NON_FBO_BLUR].value.b)
{
bs->downSample =
bs->
opt[BLURFX_SCREEN_OPTION_NON_FBO_BLUR_STRENGTH].value.
i;
CompWindow *w;
for (w = s->windows; w; w = w->next)
{
BLURFX_WINDOW(w);
if (bw->hasTexture)
{
bw->hasTexture = FALSE;
glDeleteTextures(1, &bw->blurTex.handle);
bw->blurTex.handle = 0;
}
}
}
damageScreen(s);
return TRUE;
}
break;
default:
break;
}
return FALSE;
}
static CompOption *blurfxGetScreenOptions(CompScreen * s, int *count)
{
if (s)
{
BLURFX_SCREEN(s);
*count = NUM_OPTIONS(bs);
return bs->opt;
}
else
{
BlurfxScreen *bs = (BlurfxScreen *) calloc(1, sizeof(BlurfxScreen));
blurfxScreenInitOptions(bs);
*count = NUM_OPTIONS(bs);
return bs->opt;
}
}
static void blurfxScreenInitOptions(BlurfxScreen * bs)
{
CompOption *o;
int i;
o = &bs->opt[BLURFX_SCREEN_OPTION_BLUR_DECORATION];
o->advanced = False;
o->name = "blur_decoration";
o->group = N_("Blur");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Blur Decorations");
o->longDesc = N_("Blur behind decorations.");
o->type = CompOptionTypeBool;
o->value.b = BLURFX_SCREEN_OPTION_BLUR_DECORATION_DEFAULT;
o = &bs->opt[BLURFX_SCREEN_OPTION_BLUR_WINDOWS];
o->advanced = False;
o->name = "blur_windows";
o->group = N_("Blur");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Blur Windows");
o->longDesc = N_("Blur behind windows.");
o->type = CompOptionTypeBool;
o->value.b = BLURFX_SCREEN_OPTION_BLUR_WINDOWS_DEFAULT;
o = &bs->opt[BLURFX_SCREEN_OPTION_REFLECTION_DECORATION];
o->advanced = False;
o->name = "reflection_decoration";
o->group = N_("Reflection");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Reflection for Decorations");
o->longDesc = N_("Draw Reflection for decorations.");
o->type = CompOptionTypeBool;
o->value.b = BLURFX_SCREEN_OPTION_REFLECTION_DECORATION_DEFAULT;
o = &bs->opt[BLURFX_SCREEN_OPTION_REFLECTION_WINDOWS];
o->advanced = False;
o->name = "reflection_windows";
o->group = N_("Reflection");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Reflection for Windows");
o->longDesc = N_("Draw Reflection for windows.");
o->type = CompOptionTypeBool;
o->value.b = BLURFX_SCREEN_OPTION_REFLECTION_WINDOWS_DEFAULT;
o = &bs->opt[BLURFX_SCREEN_OPTION_BLUR_ON_TRANSFORMED_SCREEN];
o->advanced = False;
o->name = "blur_transformed_screen";
o->group = N_("Blur");
o->subGroup = N_("Special cases");
o->displayHints = "";
o->shortDesc = N_("Blur on Transformed Screen");
o->longDesc = N_("Draw Blur if the screen is transformed.");
o->type = CompOptionTypeBool;
o->value.b = BLURFX_SCREEN_OPTION_BLUR_ON_TRANSFORMED_SCREEN_DEFAULT;
o = &bs->opt[BLURFX_SCREEN_OPTION_BLUR_TRANSFORMED_WINDOW];
o->advanced = False;
o->name = "blur_transformed_window";
o->group = N_("Blur");
o->subGroup = N_("Special cases");
o->displayHints = "";
o->shortDesc = N_("Blur Transformed Windows");
o->longDesc = N_("Draw Blur if window is transformed.");
o->type = CompOptionTypeBool;
o->value.b = BLURFX_SCREEN_OPTION_BLUR_TRANSFORMED_WINDOW_DEFAULT;
o = &bs->opt[BLURFX_SCREEN_OPTION_BLUR_SHADER];
o->advanced = False;
o->name = "blur_shader";
o->group = N_("Blur");
o->subGroup = N_("Visibility/Performance");
o->displayHints = "";
o->shortDesc = N_("Blur Shader");
o->longDesc = N_("Blur shader.");
o->type = CompOptionTypeString;
o->value.s = strdup(BLURFX_SCREEN_OPTION_BLUR_SHADER_DEFAULT);
o->rest.s.string = blurShaderNames;
o->rest.s.nString = LIST_SIZE(blurShaderNames);
o = &bs->opt[BLURFX_SCREEN_OPTION_FORCE_NON_FBO_BLUR];
o->advanced = False;
o->name = "force_non_fbo_blur";
o->group = N_("Blur");
o->subGroup = N_("Visibility/Performance");
o->displayHints = "";
o->shortDesc = N_("Force non FBO Blur");
o->longDesc = N_("Force non FBO Blur.");
o->type = CompOptionTypeBool;
o->value.b = BLURFX_SCREEN_OPTION_FORCE_NON_FBO_BLUR_DEFAULT;
o = &bs->opt[BLURFX_SCREEN_OPTION_NON_FBO_BLUR_STRENGTH];
o->advanced = False;
o->name = "non_fbo_blur_strength";
o->group = N_("Blur");
o->subGroup = N_("Visibility/Performance");
o->displayHints = "";
o->shortDesc = N_("Non FBO Blur Strength");
o->longDesc = N_("Non FBO mode Blur strength.");
o->type = CompOptionTypeInt;
o->value.i = BLURFX_SCREEN_OPTION_NON_FBO_BLUR_STRENGTH_DEFAULT;
o->rest.i.min = 2;
o->rest.i.max = 12;
o = &bs->opt[BLURFX_SCREEN_OPTION_BLUR_CACHE_TEXTURES];
o->advanced = False;
o->name = "blur_cache";
o->group = N_("Blur");
o->subGroup = N_("Visibility/Performance");
o->displayHints = "";
o->shortDesc = N_("Use Blur Cache");
o->longDesc = N_("Enables Blur cache texture system.");
o->type = CompOptionTypeBool;
o->value.b = BLURFX_SCREEN_OPTION_BLUR_CACHE_TEXTURES_DEFAULT;
o = &bs->opt[BLURFX_SCREEN_OPTION_NO_BLUR_CACHE_ON_TRANSFORMED_SCREEN];
o->advanced = False;
o->name = "no_cache_when_transformed";
o->group = N_("Blur");
o->subGroup = N_("Visibility/Performance");
o->displayHints = "";
o->shortDesc = N_("Disable Blur Cache on Transformed Screen");
o->longDesc = N_("Disables Blur cache on transformed screen.");
o->type = CompOptionTypeBool;
o->value.b =
BLURFX_SCREEN_OPTION_NO_BLUR_CACHE_ON_TRANSFORMED_SCREEN_DEFAULT;
o = &bs->opt[BLURFX_SCREEN_OPTION_DISABLE_DECORATION_ALPHADEP];
o->advanced = False;
o->name = "disable_deco_alpha_dep";
o->group = N_("Blur");
o->subGroup = N_("Special cases");
o->displayHints = "";
o->shortDesc = N_("Disable Decoration Alpha Dependency");
o->longDesc = N_("Disable decoration alpha dependency.");
o->type = CompOptionTypeBool;
o->value.b = BLURFX_SCREEN_OPTION_DISABLE_DECORATION_ALPHADEP_DEFAULT;
o = &bs->opt[BLURFX_SCREEN_OPTION_DISABLE_BLUR_ON_SCREENGRAB_OF];
o->advanced = False;
o->name = "disable_blur_on_screengrab_of";
o->group = N_("Blur");
o->subGroup = N_("Special cases");
o->displayHints = "";
o->shortDesc = N_("Disable Blur on ScreenGrab");
o->longDesc =
N_
("Disable drawing of Blur when an other plugin grabs the input.");
o->type = CompOptionTypeList;
o->value.list.type = CompOptionTypeString;
o->value.list.nValue = LIST_SIZE(blurDisable);
o->value.list.value =
malloc(sizeof(CompOptionValue) * LIST_SIZE(blurDisable));
for (i = 0; i < LIST_SIZE(blurDisable); i++)
o->value.list.value[i].s = strdup(blurDisable[i]);
o = &bs->opt[BLURFX_SCREEN_OPTION_REFLECTION_ON_TRANSFORMED_SCREEN];
o->advanced = False;
o->name = "reflection_transformed_screen";
o->group = N_("Reflection");
o->subGroup = N_("Special cases");
o->displayHints = "";
o->shortDesc = N_("Reflection on Transformed Screen");
o->longDesc = N_("Draw Reflection if the screen is transformed.");
o->type = CompOptionTypeBool;
o->value.b =
BLURFX_SCREEN_OPTION_REFLECTION_ON_TRANSFORMED_SCREEN_DEFAULT;
o = &bs->opt[BLURFX_SCREEN_OPTION_REFLECTION_TRANSFORMED_WINDOW];
o->advanced = False;
o->name = "reflection_transformed_window";
o->group = N_("Reflection");
o->subGroup = N_("Special cases");
o->displayHints = "";
o->shortDesc = N_("Reflection Transformed Windows");
o->longDesc = N_("Draw Reflection if the window is transformed.");
o->type = CompOptionTypeBool;
o->value.b = BLURFX_SCREEN_OPTION_REFLECTION_TRANSFORMED_WINDOW_DEFAULT;
o = &bs->opt[BLURFX_SCREEN_OPTION_DISABLE_REFLECTION_ON_SCREENGRAB_OF];
o->advanced = False;
o->name = "disable_reflection_on_screengrab_of";
o->group = N_("Reflection");
o->subGroup = N_("Special cases");
o->displayHints = "";
o->shortDesc = N_("Disable Reflection on ScreenGrab");
o->longDesc =
N_
("Disable drawing of Reflection when an other plugin grabs the input.");
o->type = CompOptionTypeList;
o->value.list.type = CompOptionTypeString;
o->value.list.nValue = 0;
o->value.list.value = NULL;
o = &bs->opt[BLURFX_SCREEN_OPTION_REFLECTION_FILE];
o->advanced = False;
o->name = "reflection_file";
o->group = N_("Reflection");
o->subGroup = N_("Image");
o->displayHints = "file;image;pngonly;";
o->shortDesc = N_("Reflection Image File");
o->longDesc = N_("Reflection image file.");
o->type = CompOptionTypeString;
o->value.s = strdup(BLURFX_SCREEN_OPTION_REFLECTION_FILE_DEFAULT);
o->rest.s.string = 0;
o->rest.s.nString = 0;
o = &bs->opt[BLURFX_SCREEN_OPTION_REFLECTION_SCALE];
o->advanced = False;
o->name = "reflection_scale";
o->group = N_("Reflection");
o->subGroup = N_("Image");
o->displayHints = "";
o->shortDesc = N_("Scale Reflection");
o->longDesc = N_("Scale Reflection image.");
o->type = CompOptionTypeBool;
o->value.b = BLURFX_SCREEN_OPTION_REFLECTION_SCALE_DEFAULT;
o = &bs->opt[BLURFX_SCREEN_OPTION_REFLECTION_PROPORTIONAL];
o->advanced = False;
o->name = "reflection_proportional";
o->group = N_("Reflection");
o->subGroup = N_("Image");
o->displayHints = "";
o->shortDesc = N_("Scale Proportionally");
o->longDesc = N_("Scale Reflection proportionally.");
o->type = CompOptionTypeBool;
o->value.b = BLURFX_SCREEN_OPTION_REFLECTION_PROPORTIONAL_DEFAULT;
o = &bs->opt[BLURFX_SCREEN_OPTION_REFLECTION_USE_IMAGE_COLOR];
o->advanced = False;
o->name = "reflection_use_image_colors";
o->group = N_("Reflection");
o->subGroup = N_("Image");
o->displayHints = "";
o->shortDesc = N_("Use Image Colors");
o->longDesc = N_("Do not generate grayscale Reflection.");
o->type = CompOptionTypeBool;
o->value.b = BLURFX_SCREEN_OPTION_REFLECTION_USE_IMAGE_COLOR_DEFAULT;
o = &bs->opt[BLURFX_SCREEN_OPTION_REFLECTION_USE_IMAGE_ALPHA];
o->advanced = False;
o->name = "reflection_use_image_alpha";
o->group = N_("Reflection");
o->subGroup = N_("Image");
o->displayHints = "";
o->shortDesc = N_("Use Image Alpha");
o->longDesc = N_("Use image alpha channel.");
o->type = CompOptionTypeBool;
o->value.b = BLURFX_SCREEN_OPTION_REFLECTION_USE_IMAGE_ALPHA_DEFAULT;
o = &bs->opt[BLURFX_SCREEN_OPTION_MOTION_BLUR_MODE];
o->advanced = False;
o->name = "motion_blur_mode";
o->group = N_("Motion Blur");
o->subGroup = N_("Visibility/Performance");
o->displayHints = "";
o->shortDesc = N_("Motion Blur Mode");
o->longDesc =
N_
("Motion Blur mode: simple = uses texture copy and blending; accum = "
"uses gl accumulation buffer; fbo = uses framebuffer objects and float texture.");
o->type = CompOptionTypeString;
o->value.s = strdup(BLURFX_SCREEN_OPTION_MOTION_BLUR_MODE_DEFAULT);
o->rest.s.string = mBlurModes;
o->rest.s.nString = LIST_SIZE(mBlurModes);
o = &bs->opt[BLURFX_SCREEN_OPTION_MOTION_BLUR_ON_SCREENGRAB_OF];
o->advanced = False;
o->name = "motion_blur_on_screengrab_of";
o->group = N_("Motion Blur");
o->subGroup = N_("Activate");
o->displayHints = "";
o->shortDesc = N_("Blur on ScreenGrab");
o->longDesc = N_("Activate Motion Blur on screengrab.");
o->type = CompOptionTypeList;
o->value.list.type = CompOptionTypeString;
o->value.list.nValue = 0;
o->value.list.value = NULL;
o = &bs->opt[BLURFX_SCREEN_OPTION_MOTION_BLUR_ON_TRANSFORMED_SCREEN];
o->advanced = False;
o->name = "motion_blur_on_transformed_screen";
o->group = N_("Motion Blur");
o->subGroup = N_("Activate");
o->displayHints = "";
o->shortDesc = N_("Motion Blur on Transformed Screen");
o->longDesc = N_("Execute Motion Blur if the screen is transformed.");
o->type = CompOptionTypeBool;
o->value.b =
BLURFX_SCREEN_OPTION_MOTION_BLUR_ON_TRANSFORMED_SCREEN_DEFAULT;
o = &bs->opt[BLURFX_SCREEN_OPTION_MOTION_BLUR_STRENGTH];
o->advanced = False;
o->name = "motion_blur_strength";
o->group = N_("Motion Blur");
o->subGroup = N_("Visibility/Performance");
o->displayHints = "";
o->shortDesc = N_("Motion Blur Strength");
o->longDesc = N_("Motion Blur strength.");
o->type = CompOptionTypeFloat;
o->value.f = BLURFX_SCREEN_OPTION_MOTION_BLUR_STRENGTH_DEFAULT;
o->rest.f.min = 0.0;
o->rest.f.max = 100.0;
o->rest.f.precision = 0.01;
o = &bs->opt[BLURFX_SCREEN_OPTION_DISABLE_BLUR_WINDOW_TYPE];
o->advanced = False;
o->name = "disable_blur_window_types";
o->group = N_("Blur");
o->subGroup = N_("Special cases");
o->displayHints = "";
o->shortDesc = N_("Disable Blur Window Types");
o->longDesc = N_("Window types that Blur shouldn't affect.");
o->type = CompOptionTypeList;
o->value.list.type = CompOptionTypeString;
o->value.list.nValue = 0;
o->value.list.value = NULL;
o->rest.s.string = (char **)windowTypeString;
o->rest.s.nString = nWindowTypeString;
o = &bs->opt[BLURFX_SCREEN_OPTION_DISABLE_REFLECTION_WINDOW_TYPE];
o->advanced = False;
o->name = "disable_reflection_window_types";
o->group = N_("Reflection");
o->subGroup = N_("Special cases");
o->displayHints = "";
o->shortDesc = N_("Disable Reflection Window Types");
o->longDesc = N_("Window types that Reflection shouldn't affect.");
o->type = CompOptionTypeList;
o->value.list.type = CompOptionTypeString;
o->value.list.nValue = 0;
o->value.list.value = NULL;
o->rest.s.string = (char **)windowTypeString;
o->rest.s.nString = nWindowTypeString;
o = &bs->opt[BLURFX_SCREEN_OPTION_BLUR_SATURATION];
o->advanced = False;
o->name = "blur_saturation";
o->group = N_("Blur");
o->subGroup = N_("Visibility/Performance");
o->displayHints = "";
o->shortDesc = N_("Blur Saturation");
o->longDesc = N_("Blur saturation.");
o->type = CompOptionTypeFloat;
o->value.f = BLURFX_SCREEN_OPTION_BLUR_SATURATION_DEFAULT;
o->rest.f.min = 0.0;
o->rest.f.max = 100.0;
o->rest.f.precision = 0.1;
o = &bs->opt[BLURFX_SCREEN_OPTION_WARNING];
o->advanced = False;
o->name = "warning";
o->group = N_("Warning");
o->subGroup = N_("");
o->displayHints = "";
o->shortDesc = N_("Warning: NVidia users experiencing the black window bug should disable Blur");
o->longDesc = N_("Warning: NVidia users experiencing the black window bug should disable Blur.");
o->type = CompOptionTypeBool;
o->value.f = TRUE;
}
static void blurfxPreparePaintScreen(CompScreen * s, int ms)
{
BLURFX_SCREEN(s);
Bool mba = FALSE;
int i;
// activate motion blur on desired screen grab
for (i = 0;
i <
bs->opt[BLURFX_SCREEN_OPTION_MOTION_BLUR_ON_SCREENGRAB_OF].
value.list.nValue; i++)
{
mba |= screenGrabExist(s,
bs->
opt
[BLURFX_SCREEN_OPTION_MOTION_BLUR_ON_SCREENGRAB_OF].
value.list.value[i].s, 0);
}
bs->motion_blur_active |= bs->mb_activated;
bs->motion_blur_active |= mba;
bs->motion_blur_active &= bs->mblur_supported;
// fade motion blur out if no longer active
if (mba || bs->mb_activated)
{
bs->mb_timer = 500;
}
else
{
bs->mb_timer -= ms;
}
// calculate motion blur strength dependent on framerate
float val = 101 - MIN(100, MAX(1, ms));
float a_val =
(bs->opt[BLURFX_SCREEN_OPTION_MOTION_BLUR_STRENGTH].value.f /
20.0);
a_val = a_val * a_val;
a_val /= 100.0;
bs->mb_alpha = 1.0 - pow(a_val, 1.0 / val);
if (bs->motion_blur_active && bs->mb_timer <= 0)
damageScreen(s);
if (bs->mb_timer <= 0)
{
bs->motion_blur_active = FALSE;
}
if (bs->mb_update && bs->motion_blur_active)
damageScreen(s);
UNWRAP(bs, s, preparePaintScreen);
(*s->preparePaintScreen) (s, ms);
WRAP(bs, s, preparePaintScreen, blurfxPreparePaintScreen);
}
static Bool
blurfxPaintScreen(CompScreen * s, const ScreenPaintAttrib * sa,
Region region, int output, unsigned int mask)
{
Bool status, blur_fbo;
BLURFX_SCREEN(s);
int i;
Region bigregion = XCreateRegion();
XRectangle rect;
bs->fboActive = FALSE;
bs->realPaintRegion = region;
bs->output = output;
// blur needs bigger repaint regions
for (i = 0; i < region->numRects; i++)
{
rect.x = region->rects[i].x1 - 7;
rect.y = region->rects[i].y1 - 7;
rect.width = region->rects[i].x2 - rect.x + 14;
rect.height = region->rects[i].y2 - rect.y + 14;
XUnionRectWithRegion(&rect, bigregion, bigregion);
}
//Initiliaze the screen if ith hasnt beens
if (bs->hasInit != 1)
{
initBlurfxScreen(bs, s->width, s->height, s);
}
// clear screen damage region
XUnionRegion(getEmptyRegion(), getEmptyRegion(), bs->screenDamage);
// enable blur if needed
blur_fbo = bs->blur_supported && bs->fboBlur_supported
&& !bs->opt[BLURFX_SCREEN_OPTION_FORCE_NON_FBO_BLUR].value.b;
blur_fbo &= bs->opt[BLURFX_SCREEN_OPTION_BLUR_DECORATION].value.b
|| bs->opt[BLURFX_SCREEN_OPTION_BLUR_WINDOWS].value.b;
if (!bs->opt[BLURFX_SCREEN_OPTION_BLUR_ON_TRANSFORMED_SCREEN].value.b)
blur_fbo &= !(mask & PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK);
for (i = 0;
i <
bs->opt[BLURFX_SCREEN_OPTION_DISABLE_BLUR_ON_SCREENGRAB_OF].
value.list.nValue; i++)
{
blur_fbo &=
!screenGrabExist(s,
bs->
opt
[BLURFX_SCREEN_OPTION_DISABLE_BLUR_ON_SCREENGRAB_OF].
value.list.value[i].s, 0);
}
bs->od_active = FALSE;
// calculate occluted regions
if (bs->opt[BLURFX_SCREEN_OPTION_BLUR_DECORATION].value.b
|| bs->opt[BLURFX_SCREEN_OPTION_BLUR_WINDOWS].value.b
|| bs->opt[BLURFX_SCREEN_OPTION_REFLECTION_WINDOWS].value.b)
{
bs->mode = MODE_OCCLUSION;
bs->od_active = TRUE;
XUnionRegion(getEmptyRegion(), getEmptyRegion(), bs->occlusion);
CompWindow *w;
for (w = s->reverseWindows; w; w = w->prev)
{
BLURFX_WINDOW(w);
if (w->destroyed)
continue;
if (w->state & CompWindowStateOffscreenMask)
continue;
if (!w->shaded)
{
if (w->attrib.map_state != IsViewable || !w->damaged)
continue;
}
XUnionRegion(bs->occlusion, getEmptyRegion(), bw->clip);
(*s->drawWindow) (w, &w->paint, &s->region,
PAINT_WINDOW_SOLID_MASK);
}
}
bs->mode = MODE_NORMAL;
Bool splash = IPCS_GetBoolND(IPCS_OBJECT(s), "SPLASH_IS_ACTIVE", FALSE);
blur_fbo &= !DISABLE_FEATURE(s, bs->ipcs_disable_blur);
blur_fbo &= !splash;
bs->motion_blur_active &= !DISABLE_FEATURE(s, bs->ipcs_disable_mblur);
bs->motion_blur_active &= !splash;
if (!bs->motion_blur_active)
bs->mb_update = TRUE;
Bool enable_scissor = FALSE;
// store the projection matrix
glGetFloatv(GL_PROJECTION_MATRIX, bs->pm);
if ((blur_fbo || (bs->motion_blur_active && bs->mb_mode == 2)) && s->fbo)
{
float ModelView[16];
glGetFloatv(GL_MODELVIEW_MATRIX, ModelView);
// redirect all drawing operations into background texture
Bool fbo_ok = bindFbo(s, bs->backTex);
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(bs->pm);
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(ModelView);
// paint the screen into fbo
UNWRAP(bs, s, paintScreen);
status = (*s->paintScreen) (s, sa, bigregion, output, mask);
WRAP(bs, s, paintScreen, blurfxPaintScreen);
unbindFbo(s);
if (fbo_ok)
{
if (bs->motion_blur_active && bs->mb_mode == 2
&& output + 1 == s->nOutputDev)
{
// blend actual screen into motion blur texture
if (glIsEnabled(GL_SCISSOR_TEST))
{
glDisable(GL_SCISSOR_TEST);
enable_scissor = TRUE;
}
glPushAttrib(GL_COLOR_BUFFER_BIT | GL_TEXTURE_BIT);
GLERR;
bindFbo(s, bs->motionTex);
glPushMatrix();
glLoadIdentity();
glViewport(0, 0, s->width, s->height);
glTranslatef(-0.5f, -0.5f, -DEFAULT_Z_CAMERA);
glScalef(1.0f / s->width, -1.0f / s->height, 1.0f);
glTranslatef(0.0f, -s->height, 0.0f);
if (bs->mb_update)
{
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_BLEND);
}
else
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
bs->mb_alpha =
(bs->mb_timer / 500.0) * bs->mb_alpha + (1.0 -
(bs->
mb_timer
/ 500.0)) *
0.5;
bs->mb_alpha = MIN(1.0, bs->mb_alpha);
glColor4f(1, 1, 1, (bs->mb_update) ? 1.0 : bs->mb_alpha);
enableBlurfxTexture(&bs->backTex, COMP_TEXTURE_FILTER_FAST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PRIMARY_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
glBegin(GL_QUADS);
glTexCoord2f(0, bs->backTex.height);
glVertex2f(0, 0);
glTexCoord2f(0, 0);
glVertex2f(0, bs->backTex.height);
glTexCoord2f(bs->backTex.width, 0);
glVertex2f(bs->backTex.width, bs->backTex.height);
glTexCoord2f(bs->backTex.width, bs->backTex.height);
glVertex2f(bs->backTex.width, 0);
glEnd();
glDisable(GL_BLEND);
glPopMatrix();
unbindFbo(s);
// paint motion blur texture
glPushMatrix();
glLoadIdentity();
glViewport(0, 0, s->width, s->height);
glTranslatef(-0.5f, -0.5f, -DEFAULT_Z_CAMERA);
glScalef(1.0f / s->width, -1.0f / s->height, 1.0f);
glTranslatef(0.0f, -s->height, 0.0f);
glColor4f(1.0, 1.0, 1.0, 1.0);
switchBlurfxTexture(&bs->backTex, &bs->motionTex,
COMP_TEXTURE_FILTER_FAST);
glBegin(GL_QUADS);
glTexCoord2f(0, bs->backTex.height);
glVertex2f(0, 0);
glTexCoord2f(0, 0);
glVertex2f(0, bs->backTex.height);
glTexCoord2f(bs->backTex.width, 0);
glVertex2f(bs->backTex.width, bs->backTex.height);
glTexCoord2f(bs->backTex.width, bs->backTex.height);
glVertex2f(bs->backTex.width, 0);
glEnd();
disableBlurfxTexture(&bs->motionTex);
glPopMatrix();
glViewport(s->outputDev[bs->output].region.extents.
x1,
s->height -
s->outputDev[bs->output].region.extents.
y2, s->outputDev[bs->output].width,
s->outputDev[bs->output].height);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PREVIOUS);
glPopAttrib();
GLERR;
bs->mb_update = FALSE;
damageScreen(s);
}
else
{
glPushMatrix();
glLoadIdentity();
prepareXCoords(s, output, -DEFAULT_Z_CAMERA);
// draw background texture
int stride;
CompMatrix mat;
mat.xx = 1.0;
mat.yx = 0.0;
mat.xy = 0.0;
mat.yy = -1.0;
mat.x0 = 0;
mat.y0 = s->height;
stride = 4 * sizeof(GLfloat);
genGeometry(&bs->vertArray, mat, 0,
&s->outputDev[bs->output].region);
glVertexPointer(2, GL_FLOAT, stride,
bs->vertArray.vertices + 2);
glTexCoordPointer(2, GL_FLOAT, stride,
bs->vertArray.vertices);
glColor4f(1.0, 1.0, 1.0, 1.0);
enableBlurfxTexture(&bs->backTex, COMP_TEXTURE_FILTER_FAST);
glDrawArrays(GL_QUADS, 0, bs->vertArray.vCount);
disableBlurfxTexture(&bs->backTex);
glPopMatrix();
}
}
}
else
{
UNWRAP(bs, s, paintScreen);
status = (*s->paintScreen) (s, sa, bigregion, output, mask);
WRAP(bs, s, paintScreen, blurfxPaintScreen);
}
if (bs->motion_blur_active && glIsEnabled(GL_SCISSOR_TEST))
{
glDisable(GL_SCISSOR_TEST);
enable_scissor = TRUE;
}
if (bs->motion_blur_active && bs->mb_mode == 0
&& output + 1 == s->nOutputDev)
{
// blend motion blur texture to screen
glPushAttrib(GL_COLOR_BUFFER_BIT | GL_TEXTURE_BIT);
GLERR;
glPushMatrix();
glLoadIdentity();
glViewport(0, 0, s->width, s->height);
glTranslatef(-0.5f, -0.5f, -DEFAULT_Z_CAMERA);
glScalef(1.0f / s->width, -1.0f / s->height, 1.0f);
glTranslatef(0.0f, -s->height, 0.0f);
enableBlurfxTexture(&bs->motionTex, COMP_TEXTURE_FILTER_FAST);
if (!bs->mb_update)
{
glEnable(GL_BLEND);
glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
bs->mb_alpha =
(bs->mb_timer / 500.0) * bs->mb_alpha + (1.0 -
(bs->
mb_timer
/ 500.0)) * 0.5;
glColor4f(1, 1, 1, bs->mb_alpha);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glBegin(GL_QUADS);
glTexCoord2f(0, bs->motionTex.height);
glVertex2f(0, 0);
glTexCoord2f(0, 0);
glVertex2f(0, bs->motionTex.height);
glTexCoord2f(bs->motionTex.width, 0);
glVertex2f(bs->motionTex.width, bs->motionTex.height);
glTexCoord2f(bs->motionTex.width, bs->motionTex.height);
glVertex2f(bs->motionTex.width, 0);
glEnd();
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
GLERR;
glDisable(GL_BLEND);
}
// copy new screen to motion blur texture
glCopyTexSubImage2D(bs->motionTex.target, 0, 0, 0, 0, 0,
s->width, s->height);
GLERR;
disableBlurfxTexture(&bs->motionTex);
glViewport(s->outputDev[bs->output].region.extents.x1,
s->height -
s->outputDev[bs->output].region.extents.y2,
s->outputDev[bs->output].width,
s->outputDev[bs->output].height);
glPopMatrix();
glPopAttrib();
GLERR;
bs->mb_update = FALSE;
damageScreen(s);
}
if (bs->motion_blur_active && bs->mb_mode == 1
&& output + 1 == s->nOutputDev)
{
// create motion blur effect using accumulation buffer
bs->mb_alpha =
(bs->mb_timer / 500.0) * bs->mb_alpha + (1.0 -
(bs->
mb_timer /
500.0)) * 0.5;
if (bs->mb_update)
{
glAccum(GL_LOAD, 1.0);
}
else
{
glAccum(GL_MULT, 1.0 - bs->mb_alpha);
glAccum(GL_ACCUM, bs->mb_alpha);
glAccum(GL_RETURN, 1.0);
}
bs->mb_update = FALSE;
damageScreen(s);
}
if (enable_scissor)
glEnable(GL_SCISSOR_TEST);
XDestroyRegion(bigregion);
return status;
}
static void
blurfxPaintTransformedScreen(CompScreen * s, const ScreenPaintAttrib * sa,
Region region, int output, unsigned int mask)
{
BLURFX_SCREEN(s);
bs->realPaintRegion = &s->region;
// calculate occluted regions
if (bs->opt[BLURFX_SCREEN_OPTION_BLUR_DECORATION].value.b
|| bs->opt[BLURFX_SCREEN_OPTION_BLUR_WINDOWS].value.b
|| bs->opt[BLURFX_SCREEN_OPTION_REFLECTION_WINDOWS].value.b)
{
bs->mode = MODE_OCCLUSION;
bs->od_active = TRUE;
XUnionRegion(getEmptyRegion(), getEmptyRegion(), bs->occlusion);
CompWindow *w;
for (w = s->reverseWindows; w; w = w->prev)
{
BLURFX_WINDOW(w);
if (w->destroyed)
continue;
if (!w->shaded)
{
if (w->attrib.map_state != IsViewable || !w->damaged)
continue;
}
XUnionRegion(bs->occlusion, getEmptyRegion(), bw->clip);
(*s->drawWindow) (w, &w->paint, &s->region,
PAINT_WINDOW_SOLID_MASK);
}
}
bs->mode = MODE_NORMAL;
UNWRAP(bs, s, paintTransformedScreen);
(*s->paintTransformedScreen) (s, sa, region, output, mask);
WRAP(bs, s, paintTransformedScreen, blurfxPaintTransformedScreen);
}
static Bool
blurfxDrawWindow(CompWindow * w, const WindowPaintAttrib * attrib,
Region region, unsigned int mask)
{
Bool status;
int i;
BLURFX_SCREEN(w->screen);
BLURFX_WINDOW(w);
CompScreen *s = w->screen;
Bool blur_enabled, reflection_enabled;
if (bs->mode == MODE_OCCLUSION)
{
UNWRAP(bs, s, drawWindow);
status = (*s->drawWindow) (w, attrib, region, mask);
WRAP(bs, s, drawWindow, blurfxDrawWindow);
return status;
}
// enable blur and/or reflection
blur_enabled = bs->blur_supported;
reflection_enabled = bs->reflection_supported;
blur_enabled &=
bs->opt[BLURFX_SCREEN_OPTION_BLUR_DECORATION].value.b
|| bs->opt[BLURFX_SCREEN_OPTION_BLUR_WINDOWS].value.b;
reflection_enabled &=
bs->opt[BLURFX_SCREEN_OPTION_REFLECTION_DECORATION].value.b
|| bs->opt[BLURFX_SCREEN_OPTION_REFLECTION_WINDOWS].value.b;
blur_enabled &= !(mask & PAINT_WINDOW_SOLID_MASK);
reflection_enabled &= !(mask & PAINT_WINDOW_SOLID_MASK);
reflection_enabled &= bs->modTex.handle > 0;
if (bs->
opt[BLURFX_SCREEN_OPTION_MOTION_BLUR_ON_TRANSFORMED_SCREEN].
value.b && (mask & PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK))
{
bs->motion_blur_active = bs->mblur_supported;
bs->mb_timer = 500;
}
if (!bs->opt[BLURFX_SCREEN_OPTION_BLUR_ON_TRANSFORMED_SCREEN].value.b)
blur_enabled &= !(mask & PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK);
if (!bs->
opt[BLURFX_SCREEN_OPTION_REFLECTION_ON_TRANSFORMED_SCREEN].value.b)
reflection_enabled &=
!(mask & PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK);
if (!bs->opt[BLURFX_SCREEN_OPTION_BLUR_TRANSFORMED_WINDOW].value.b)
blur_enabled &= !(mask & PAINT_WINDOW_TRANSFORMED_MASK);
if (!bs->opt[BLURFX_SCREEN_OPTION_REFLECTION_TRANSFORMED_WINDOW].value.b)
reflection_enabled &= !(mask & PAINT_WINDOW_TRANSFORMED_MASK);
for (i = 0;
i <
bs->opt[BLURFX_SCREEN_OPTION_DISABLE_BLUR_ON_SCREENGRAB_OF].
value.list.nValue; i++)
{
blur_enabled &=
!screenGrabExist(s,
bs->
opt
[BLURFX_SCREEN_OPTION_DISABLE_BLUR_ON_SCREENGRAB_OF].
value.list.value[i].s, 0);
}
for (i = 0;
i <
bs->
opt[BLURFX_SCREEN_OPTION_DISABLE_REFLECTION_ON_SCREENGRAB_OF].
value.list.nValue; i++)
{
reflection_enabled &=
!screenGrabExist(s,
bs->
opt
[BLURFX_SCREEN_OPTION_DISABLE_REFLECTION_ON_SCREENGRAB_OF].
value.list.value[i].s, 0);
}
Bool splash = IPCS_GetBoolND(IPCS_OBJECT(s), "SPLASH_IS_ACTIVE", FALSE);
blur_enabled &= !DISABLE_FEATURE(s, bs->ipcs_disable_blur);
blur_enabled &= !DISABLE_FEATURE(w, bw->ipcs_disable_blur);
blur_enabled &= !splash;
reflection_enabled &= !DISABLE_FEATURE(s, bs->ipcs_disable_reflection);
reflection_enabled &= !DISABLE_FEATURE(w, bw->ipcs_disable_reflection);
reflection_enabled &= !splash;
// check for restacking and update damage if needed
if (w->next != bw->my_next)
{
XRectangle rect;
rect.x = WIN_X(w) - 7;
rect.y = WIN_Y(w) - 7;
rect.width = WIN_W(w) + 14;
rect.height = WIN_H(w) + 14;
XUnionRectWithRegion(&rect, bs->screenDamage, bs->screenDamage);
bw->my_next = w->next;
}
if (bs->opt[BLURFX_SCREEN_OPTION_BLUR_CACHE_TEXTURES].value.b)
XUnionRegion(bw->texDamage, bs->screenDamage, bw->texDamage);
bw->mvm_updated = FALSE;
if (blur_enabled || reflection_enabled)
{
// clear our decoration vertex array
bw->decoArray.vCount = 0;
bw->decoArray.indexSize = 0;
bw->decoArray.indexCount = 0;
// store region we need to paint
XUnionRegion(getEmptyRegion(), getEmptyRegion(), bw->paintRegion);
XIntersectRegion(bs->realPaintRegion, region, bw->paintRegion);
bw->texUpdated = FALSE;
XUnionRegion(getEmptyRegion(), getEmptyRegion(), bs->blurredRegion);
// paint blur and reflection
bs->mode = MODE_BLURREFLECTION;
bs->paintingSwitcher = bw->isSwitcher;
UNWRAP(bs, s, drawWindow);
status = (*s->drawWindow) (w, attrib, region, mask);
WRAP(bs, s, drawWindow, blurfxDrawWindow);
glColor4usv(defaultColor);
screenTexEnvMode(w->screen, GL_REPLACE);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
GLERR;
// paint window
bs->mode = MODE_NORMAL;
bs->was_transformed = FALSE;
UNWRAP(bs, s, drawWindow);
status = (*s->drawWindow) (w, attrib, region, mask);
WRAP(bs, s, drawWindow, blurfxDrawWindow);
}
else
{
// paint window
bs->mode = MODE_NORMAL;
bs->was_transformed = FALSE;
UNWRAP(bs, s, drawWindow);
status = (*s->drawWindow) (w, attrib, region, mask);
WRAP(bs, s, drawWindow, blurfxDrawWindow);
}
if (bs->was_transformed)
XUnionRegion(&s->outputDev[bs->output].region,
bs->screenDamage, bs->screenDamage);
if (!(mask & PAINT_WINDOW_SOLID_MASK) && !WINDOW_INPUT_INVISIBLE(w))
{
// not all plugins send damage events on move or scale
XRectangle rect;
if (bw->lastX != w->attrib.x || bw->lastY != w->attrib.y
|| w->lastPaint.xScale != attrib->xScale
|| w->lastPaint.yScale != attrib->yScale)
{
rect.x = bw->lastPAttrib.xTranslate +
(-w->output.left * bw->lastPAttrib.xScale) + bw->lastX;
rect.y = bw->lastPAttrib.yTranslate +
(-w->output.top * bw->lastPAttrib.yScale) + bw->lastY;
rect.width = WIN_W(w) * bw->lastPAttrib.xScale;
rect.height = WIN_H(w) * bw->lastPAttrib.yScale;
XUnionRectWithRegion(&rect, bs->screenDamage, bs->screenDamage);
rect.x = attrib->xTranslate +
(-w->output.left * attrib->xScale) + w->attrib.x;
rect.y = attrib->yTranslate +
(-w->output.top * attrib->yScale) + w->attrib.x;
rect.width = WIN_W(w) * attrib->xScale;
rect.height = WIN_H(w) * attrib->yScale;
XUnionRectWithRegion(&rect, bs->screenDamage, bs->screenDamage);
}
bw->lastX = w->attrib.x;
bw->lastY = w->attrib.y;
if (bw->lastPAttrib.xScale != 1.0 || bw->lastPAttrib.yScale != 1.0)
{
for (i = 0; i < bw->damageRegion->numRects; i++)
{
BOX box = bw->damageRegion->rects[i];
rect.x = bw->lastPAttrib.xTranslate +
(box.x1 - w->attrib.x) * bw->lastPAttrib.xScale;
rect.y = bw->lastPAttrib.yTranslate + (box.y1 -
w->
attrib.
y) *
bw->lastPAttrib.yScale;
rect.width = (box.x2 - box.x1) * bw->lastPAttrib.xScale;
rect.height = (box.y2 - box.y1) * bw->lastPAttrib.yScale;
XUnionRectWithRegion(&rect,
bs->screenDamage, bs->screenDamage);
}
}
else
{
XUnionRegion(bw->damageRegion, bs->screenDamage,
bs->screenDamage);
}
bw->lastPAttrib = *attrib;
XUnionRegion(getEmptyRegion(), getEmptyRegion(), bw->damageRegion);
}
return status;
}
static void
blurfxDrawWindowTexture(CompWindow * w, CompTexture * texture,
const WindowPaintAttrib * attrib, unsigned int mask)
{
CompScreen *s = w->screen;
Bool blur_enabled, reflection_enabled;
int i;
BLURFX_SCREEN(w->screen);
BLURFX_WINDOW(w);
// enable blur and/or reflection
blur_enabled = bs->blur_supported;
reflection_enabled = bs->reflection_supported;
blur_enabled &=
(mask & PAINT_WINDOW_DECORATION_MASK) ? bs->
opt[BLURFX_SCREEN_OPTION_BLUR_DECORATION].value.b : bs->
opt[BLURFX_SCREEN_OPTION_BLUR_WINDOWS].value.b;
reflection_enabled &=
(mask & PAINT_WINDOW_DECORATION_MASK) ? bs->
opt[BLURFX_SCREEN_OPTION_REFLECTION_DECORATION].value.b : bs->
opt[BLURFX_SCREEN_OPTION_REFLECTION_WINDOWS].value.b;
if ((mask & PAINT_WINDOW_DECORATION_MASK) && w->input.top == 0
&& w->input.bottom == 0 && w->input.left == 0 && w->input.right == 0)
{
if (!bw->isSwitcher)
{
blur_enabled = FALSE;
reflection_enabled = FALSE;
}
}
if (!(mask & PAINT_WINDOW_DECORATION_MASK))
{
blur_enabled &= !(bs->noBlurWMask & w->type);
reflection_enabled &= !(bs->noReflectionWMask & w->type);
blur_enabled &= w->alpha || attrib->opacity < OPAQUE;
reflection_enabled &= w->alpha || attrib->opacity < OPAQUE;
}
reflection_enabled &= bs->modTex.handle > 0;
if (!bs->opt[BLURFX_SCREEN_OPTION_BLUR_ON_TRANSFORMED_SCREEN].value.b)
blur_enabled &= !(mask & PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK);
if (!bs->
opt[BLURFX_SCREEN_OPTION_REFLECTION_ON_TRANSFORMED_SCREEN].value.b)
reflection_enabled &=
!(mask & PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK);
if (!bs->opt[BLURFX_SCREEN_OPTION_BLUR_TRANSFORMED_WINDOW].value.b)
blur_enabled &= !(mask & PAINT_WINDOW_TRANSFORMED_MASK);
if (!bs->opt[BLURFX_SCREEN_OPTION_REFLECTION_TRANSFORMED_WINDOW].value.b)
reflection_enabled &= !(mask & PAINT_WINDOW_TRANSFORMED_MASK);
for (i = 0;
i <
bs->opt[BLURFX_SCREEN_OPTION_DISABLE_BLUR_ON_SCREENGRAB_OF].
value.list.nValue; i++)
{
blur_enabled &=
!screenGrabExist(s,
bs->
opt
[BLURFX_SCREEN_OPTION_DISABLE_BLUR_ON_SCREENGRAB_OF].
value.list.value[i].s, 0);
}
for (i = 0;
i <
bs->
opt[BLURFX_SCREEN_OPTION_DISABLE_REFLECTION_ON_SCREENGRAB_OF].
value.list.nValue; i++)
{
reflection_enabled &=
!screenGrabExist(s,
bs->
opt
[BLURFX_SCREEN_OPTION_DISABLE_REFLECTION_ON_SCREENGRAB_OF].
value.list.value[i].s, 0);
}
Bool splash = IPCS_GetBoolND(IPCS_OBJECT(s), "SPLASH_IS_ACTIVE", FALSE);
blur_enabled &= !DISABLE_FEATURE(s, bs->ipcs_disable_blur);
blur_enabled &= !DISABLE_FEATURE(w, bw->ipcs_disable_blur);
blur_enabled &= !splash;
reflection_enabled &= !DISABLE_FEATURE(s, bs->ipcs_disable_reflection);
reflection_enabled &= !DISABLE_FEATURE(w, bw->ipcs_disable_reflection);
reflection_enabled &= !splash;
// add window region to occlusion region
if (bs->mode == MODE_OCCLUSION)
{
if (!(mask & PAINT_WINDOW_TRANSFORMED_MASK))
return;
if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
return;
if (mask & PAINT_WINDOW_DECORATION_MASK)
return;
if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
return;
if (WINDOW_INPUT_INVISIBLE(w))
return;
XUnionRegion(w->region, bs->occlusion, bs->occlusion);
return;
}
// draw normal window
if (bs->mode == MODE_NORMAL)
{
GLERR;
UNWRAP(bs, w->screen, drawWindowTexture);
(*w->screen->drawWindowTexture) (w, texture, attrib, mask);
WRAP(bs, w->screen, drawWindowTexture, blurfxDrawWindowTexture);
#ifdef GL_DEBUG
glGetError();
#endif
bs->was_transformed |= (mask & PAINT_WINDOW_TRANSFORMED_MASK);
return;
}
if (!(mask & PAINT_WINDOW_TRANSLUCENT_MASK)
|| bs->mode != MODE_BLURREFLECTION
|| (mask & PAINT_WINDOW_SHADOW_MASK))
return;
if (WINDOW_INPUT_INVISIBLE(w)
&& !(w->shaded && (mask & PAINT_WINDOW_DECORATION_MASK)))
return;
if (bs->paintingSwitcher && !bw->isSwitcher)
return;
int filter;
Bool useFbo = bs->fboActive
&& !bs->opt[BLURFX_SCREEN_OPTION_FORCE_NON_FBO_BLUR].value.b;
// select texture filter
if (mask &
(PAINT_WINDOW_TRANSFORMED_MASK |
PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK) && useFbo)
filter = COMP_TEXTURE_FILTER_FAST;
else
filter = COMP_TEXTURE_FILTER_GOOD;
// draw blur
if (blur_enabled)
{
Bool enable_scissor = FALSE;
Bool enable_clipPlanes = FALSE;
if (useFbo)
{
if (glIsEnabled(GL_CLIP_PLANE0))
{
glDisable (GL_CLIP_PLANE0);
glDisable (GL_CLIP_PLANE1);
glDisable (GL_CLIP_PLANE2);
glDisable (GL_CLIP_PLANE3);
enable_clipPlanes = TRUE;
}
if (glIsEnabled(GL_SCISSOR_TEST))
{
glDisable(GL_SCISSOR_TEST);
enable_scissor = TRUE;
}
bs->downSample = 1.0;
}
else
{
bs->downSample =
bs->opt[BLURFX_SCREEN_OPTION_NON_FBO_BLUR_STRENGTH].value.
i;
}
if (bs->opt[BLURFX_SCREEN_OPTION_BLUR_CACHE_TEXTURES].value.b)
{
// update blur cache texture
bw->texUpdated = TRUE;
updateBlurTextureSize(w, s, attrib, mask);
GLERR;
if (useFbo)
{
updateBlurTexture(w, s, attrib, mask, filter);
GLERR;
}
else
{
updateBlurTextureNoFBO(w, s, attrib, mask);
GLERR;
}
}
if (useFbo)
{
updateBlur(w, s, attrib, mask, filter);
GLERR;
if (enable_clipPlanes)
{
glEnable (GL_CLIP_PLANE0);
glEnable (GL_CLIP_PLANE1);
glEnable (GL_CLIP_PLANE2);
glEnable (GL_CLIP_PLANE3);
}
if (enable_scissor)
glEnable(GL_SCISSOR_TEST);
}
else
{
updateBlurNoFBO(w, s, attrib, mask);
GLERR;
}
drawBlur(w, s, texture, attrib, mask, filter);
}
// draw reflection
if (reflection_enabled)
drawReflection(w, s, texture, attrib, mask, COMP_TEXTURE_FILTER_GOOD);
}
static void
blurfxAddWindowGeometry(CompWindow * w, CompMatrix * m, int nM,
Region region, Region clip)
{
BLURFX_SCREEN(w->screen);
BLURFX_WINDOW(w);
REGION box;
if (bs->mode == MODE_OCCLUSION)
return;
// try to detect decorations
if (bs->mode == MODE_BLURREFLECTION && region->numRects == 1
&&
((region->extents.x1 < w->attrib.x
&& region->extents.x2 <= w->attrib.x)
|| (region->extents.y1 < w->attrib.y
&& region->extents.y2 <= w->attrib.y)
|| (region->extents.x1 >= w->attrib.x + w->width
&& region->extents.x2 > w->attrib.x + w->width)
|| (region->extents.y1 >= w->attrib.y + w->height
&& region->extents.y2 > w->attrib.y + w->height)))
{
box.numRects = 1;
// create vertex array without shadow
box.rects = &box.extents;
box.extents.x1 = MAX(region->extents.x1, WIN_XO(w));
box.extents.y1 = MAX(region->extents.y1, WIN_YO(w));
box.extents.x2 = MIN(region->extents.x2, WIN_XO(w) + WIN_WO(w));
box.extents.y2 = MIN(region->extents.y2, WIN_YO(w) + WIN_HO(w));
if (box.extents.x1 < box.extents.x2
&& box.extents.y1 < box.extents.y2)
{
CompWindow *cw = malloc(sizeof(CompWindow));
memcpy(cw, w, sizeof(CompWindow));
cw->vertexSize = bw->decoArray.vertexSize;
cw->indexSize = bw->decoArray.indexSize;
cw->vertices = bw->decoArray.vertices;
cw->indices = bw->decoArray.indices;
cw->vCount = bw->decoArray.vCount;
cw->indexCount = bw->decoArray.indexCount;
UNWRAP(bs, w->screen, addWindowGeometry);
(*w->screen->addWindowGeometry) (cw, m, nM, &box, clip);
WRAP(bs, w->screen, addWindowGeometry, blurfxAddWindowGeometry);
bw->decoArray.vertexSize = cw->vertexSize;
bw->decoArray.indexSize = cw->indexSize;
bw->decoArray.vertices = cw->vertices;
bw->decoArray.indices = cw->indices;
bw->decoArray.vCount = cw->vCount;
bw->decoArray.indexCount = cw->indexCount;
free(cw);
}
}
UNWRAP(bs, w->screen, addWindowGeometry);
(*w->screen->addWindowGeometry) (w, m, nM, region, clip);
WRAP(bs, w->screen, addWindowGeometry, blurfxAddWindowGeometry);
}
static Bool blurfxDamageWindowRect(CompWindow * w, Bool initial, BoxPtr box)
{
Bool status;
BLURFX_SCREEN(w->screen);
BLURFX_WINDOW(w);
XRectangle rect;
// a bigger damage region is needed to have correct blur
box->x1 -= 7;
box->x2 += 7;
box->y1 -= 7;
box->y2 += 7;
rect.x = w->serverX + box->x1;
rect.y = w->serverY + box->y1;
rect.width = box->x2 - box->x1;
rect.height = box->y2 - box->y1;
// store window damage
if (bs->opt[BLURFX_SCREEN_OPTION_BLUR_CACHE_TEXTURES].value.b)
XUnionRectWithRegion(&rect, bw->damageRegion, bw->damageRegion);
UNWRAP(bs, w->screen, damageWindowRect);
status = (*w->screen->damageWindowRect) (w, initial, box);
WRAP(bs, w->screen, damageWindowRect, blurfxDamageWindowRect);
return status;
}
static void
updateBlurTexture(CompWindow * w, CompScreen * s,
const WindowPaintAttrib * attrib, unsigned int mask,
CompTextureFilter filter)
{
Region reblurRegion;
Region blurPaintRegion;
int stride, count, stop, vCount, iCount;
CompMatrix mat;
GLfloat *vertices, x1, x2, x3, x4, y1, y2, y3, y4, bx1, bx2, by1, by2;
GLushort *indices;
XRectangle rect;
BLURFX_SCREEN(s);
BLURFX_WINDOW(w);
if (bw->bc_x != s->x || bw->bc_y != s->y)
{
bw->texUpdated = FALSE;
return;
}
if (bs->
opt[BLURFX_SCREEN_OPTION_NO_BLUR_CACHE_ON_TRANSFORMED_SCREEN].
value.b && mask & PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK)
{
bw->texUpdated = FALSE;
return;
}
// Do we have an decoration vertex array thet does not contain shadows?
if (mask & PAINT_WINDOW_DECORATION_MASK && bw->decoArray.vCount)
{
vertices = bw->decoArray.vertices + (w->texUnits * w->texCoordSize);
indices = bw->decoArray.indices;
vCount = bw->decoArray.vCount;
iCount = bw->decoArray.indexCount;
}
else
{
vertices = w->vertices + (w->texUnits * w->texCoordSize);
indices = w->indices;
vCount = w->vCount;
iCount = w->indexCount;
}
if (vCount <= 0)
return;
stride = (w->texUnits * w->texCoordSize) + 2;
// get regions we need not to update
reblurRegion = XCreateRegion();
blurPaintRegion = XCreateRegion();
count = 0;
stop = (iCount) ? iCount : vCount;
bx1 = 65535;
bx2 = 0.0;
by1 = 65535;
by2 = 0.0;
// generate region that needs blur
while (count < stop)
{
if (iCount)
{
x1 = vertices[indices[count] * stride];
y1 = vertices[(indices[count] * stride) + 1];
count++;
x2 = vertices[indices[count] * stride];
y2 = vertices[(indices[count] * stride) + 1];
count++;
x3 = vertices[indices[count] * stride];
y3 = vertices[(indices[count] * stride) + 1];
count++;
x4 = vertices[indices[count] * stride];
y4 = vertices[(indices[count] * stride) + 1];
count++;
}
else
{
x1 = vertices[0];
y1 = vertices[1];
vertices += stride;
x2 = vertices[0];
y2 = vertices[1];
vertices += stride;
x3 = vertices[0];
y3 = vertices[1];
vertices += stride;
x4 = vertices[0];
y4 = vertices[1];
vertices += stride;
count += 4;
}
if (!(mask & PAINT_WINDOW_TRANSFORMED_MASK))
{
bx1 = 65535;
bx2 = 0.0;
by1 = 65535;
by2 = 0.0;
}
bx1 = MIN(bx1, x1);
bx2 = MAX(bx2, x1);
bx1 = MIN(bx1, x2);
bx2 = MAX(bx2, x2);
bx1 = MIN(bx1, x3);
bx2 = MAX(bx2, x3);
bx1 = MIN(bx1, x4);
bx2 = MAX(bx2, x4);
by1 = MIN(by1, y1);
by2 = MAX(by2, y1);
by1 = MIN(by1, y2);
by2 = MAX(by2, y2);
by1 = MIN(by1, y3);
by2 = MAX(by2, y3);
by1 = MIN(by1, y4);
by2 = MAX(by2, y4);
if (bx2 - bx1 > 0 && by2 - by1 > 0
&& !(mask & PAINT_WINDOW_TRANSFORMED_MASK))
{
rect.x = attrib->xTranslate +
(((bx1 - 7) - w->attrib.x) * attrib->xScale) +
w->attrib.x;
rect.y = attrib->yTranslate +
(((by1 - 1) - w->attrib.y) * attrib->yScale) +
w->attrib.y;
rect.width = (bx2 - bx1 + 14) * attrib->xScale;
rect.height = (by2 - by1 + 2) * attrib->yScale;
XUnionRectWithRegion(&rect, reblurRegion, reblurRegion);
}
}
if (bx2 - bx1 > 0 && by2 - by1 > 0
&& (mask & PAINT_WINDOW_TRANSFORMED_MASK))
{
rect.x = attrib->xTranslate +
(((bx1 - 7) - w->attrib.x) * attrib->xScale) + w->attrib.x;
rect.y = attrib->yTranslate +
(((by1 - 1) - w->attrib.y) * attrib->yScale) + w->attrib.y;
rect.width = (bx2 - bx1 + 14) * attrib->xScale;
rect.height = (by2 - by1 + 2) * attrib->yScale;
XUnionRectWithRegion(&rect, reblurRegion, reblurRegion);
}
XIntersectRegion(reblurRegion, bw->bTexRegion, blurPaintRegion);
// get regions we need to update
XIntersectRegion(reblurRegion, bw->paintRegion, reblurRegion);
XIntersectRegion(reblurRegion, bw->texDamage, reblurRegion);
XIntersectRegion(reblurRegion, bw->bTexRegion, reblurRegion);
XIntersectRegion(reblurRegion, &s->outputDev[bs->output].region,
reblurRegion);
// subtract occluded region
if (bs->od_active)
XSubtractRegion(reblurRegion, bw->clip, reblurRegion);
stride = 4 * sizeof(GLfloat);
if (screenGrabExist(s, "switcher", 0) || bw->isSwitcher)
{
bw->texUpdated = FALSE;
XDestroyRegion(reblurRegion);
XDestroyRegion(blurPaintRegion);
return;
}
if (reblurRegion->numRects)
{
if (mask & PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK)
{
float bm[16] = { s->outputDev[bs->output].width / 2.0, 0, 0,
0,
0, s->outputDev[bs->output].height / 2.0,
0, 0,
0, 0, 1, 0,
s->outputDev[bs->output].width / 2.0 +
s->outputDev[bs->output].region.extents.x1,
s->outputDev[bs->output].height / 2.0 +
s->height -
s->outputDev[bs->output].region.extents.y2, 1, 1
};
float bpm[16];
float tm[16];
if (!bw->mvm_updated)
{
bw->mvm_updated = TRUE;
glGetFloatv(GL_MODELVIEW_MATRIX, bw->mvm);
}
MULTM(bm, bs->pm, bpm);
MULTM(bpm, bw->mvm, tm);
XRectangle rect, outputRect;
XClipBox(reblurRegion, &rect);
// check region for visibility
float bbProj[4][2];
bbProj[0][0] = rect.x * tm[0] + rect.y * tm[4] + tm[12];
bbProj[0][0] /= rect.x * tm[3] + rect.y * tm[7] + tm[15];
bbProj[0][1] = rect.x * tm[1] + rect.y * tm[5] + tm[13];
bbProj[0][1] /= rect.x * tm[3] + rect.y * tm[7] + tm[15];
bbProj[1][0] =
(rect.x + rect.width) * tm[0] + rect.y * tm[4] + tm[12];
bbProj[1][0] /= (rect.x + rect.width) * tm[3] +
rect.y * tm[7] + tm[15];
bbProj[1][1] =
(rect.x + rect.width) * tm[1] + rect.y * tm[5] + tm[13];
bbProj[1][1] /= (rect.x + rect.width) * tm[3] +
rect.y * tm[7] + tm[15];
bbProj[2][0] =
rect.x * tm[0] + (rect.y + rect.height) * tm[4] + tm[12];
bbProj[2][0] /= rect.x * tm[3] + (rect.y +
rect.height) * tm[7] + tm[15];
bbProj[2][1] =
rect.x * tm[1] + (rect.y + rect.height) * tm[5] + tm[13];
bbProj[2][1] /= rect.x * tm[3] + (rect.y +
rect.height) * tm[7] + tm[15];
bbProj[3][0] =
(rect.x + rect.width) * tm[0] + (rect.y +
rect.height) *
tm[4] + tm[12];
bbProj[3][0] /= (rect.x + rect.width) * tm[3] +
(rect.y + rect.height) * tm[7] + tm[15];
bbProj[3][1] =
(rect.x + rect.width) * tm[1] + (rect.y +
rect.height) *
tm[5] + tm[13];
bbProj[3][1] /= (rect.x + rect.width) * tm[3] +
(rect.y + rect.height) * tm[7] + tm[15];
screenGetOutputDevRect(s, bs->output, &outputRect);
int s_x1 = outputRect.x;
int s_y1 = outputRect.y;
int s_x2 = s_x1 + outputRect.width;
int s_y2 = s_y1 + outputRect.height;
if (bbProj[0][0] >= bbProj[1][0]
|| bbProj[2][0] >= bbProj[3][0]
|| bbProj[2][1] >= bbProj[0][1]
|| bbProj[3][1] >= bbProj[1][1]
|| bbProj[1][0] - bbProj[0][0] <
rect.width * 0.5
|| bbProj[3][0] - bbProj[2][0] <
rect.width * 0.5
|| bbProj[0][1] - bbProj[2][1] <
rect.height * 0.5
|| bbProj[1][1] - bbProj[3][1] <
rect.height * 0.5 || bbProj[0][0] < s_x1
|| bbProj[1][0] > s_x2 || bbProj[2][0] < s_x1
|| bbProj[3][0] > s_x2 || bbProj[0][1] < s_y1
|| bbProj[2][1] > s_y2 || bbProj[1][1] < s_y1
|| bbProj[3][1] > s_y2)
{
XDestroyRegion(reblurRegion);
XDestroyRegion(blurPaintRegion);
bw->texUpdated = FALSE;
return;
}
// enable projective texture coordinate generation
float s_gen[4] = { tm[0], tm[4], tm[8], tm[12] };
float t_gen[4] = { tm[1], tm[5], tm[9], tm[13] };
float r_gen[4] = { tm[2], tm[6], tm[10], tm[14] };
float q_gen[4] = { tm[3], tm[7], tm[11], tm[15] };
glTexGenfv(GL_T, GL_OBJECT_PLANE, t_gen);
glTexGenfv(GL_S, GL_OBJECT_PLANE, s_gen);
glTexGenfv(GL_R, GL_OBJECT_PLANE, r_gen);
glTexGenfv(GL_Q, GL_OBJECT_PLANE, q_gen);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
glEnable(GL_TEXTURE_GEN_Q);
}
else
{
// enable texture coordinate generation
float s_gen[4] = { 1.0, 0.0, 0.0, 0.0 };
float t_gen[4] = { 0.0, -1.0, 0.0, s->height };
glTexGenfv(GL_T, GL_OBJECT_PLANE, t_gen);
glTexGenfv(GL_S, GL_OBJECT_PLANE, s_gen);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
}
// draw vertically blured region into temprorary texture
(*s->framebufferTexture2D) (GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_RECTANGLE_ARB,
bs->blurTempTexV.handle, 0);
GLERR;
// bind vertival blur shader
glEnable(GL_FRAGMENT_PROGRAM_ARB);
(*s->bindProgram) (GL_FRAGMENT_PROGRAM_ARB, bs->blurShaderV);
// bind unblurred background
enableBlurfxTexture(&bs->backTex, filter);
mat.xx = 1.0;
mat.yx = 0.0;
mat.xy = 0.0;
mat.yy = -1.0;
mat.x0 = 0.0;
mat.y0 = bs->backTex.height;
genGeometry(&bw->vertArray, mat, 7, reblurRegion);
glVertexPointer(2, GL_FLOAT, stride, bw->vertArray.vertices + 2);
glTexCoordPointer(2, GL_FLOAT, stride, bw->vertArray.vertices);
glDrawArrays(GL_QUADS, 0, bw->vertArray.vCount);
// draw vertically blured region into blur cache texture
(*s->framebufferTexture2D) (GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_RECTANGLE_ARB,
bw->blurTex.handle, 0);
GLERR;
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glDepthRange(0, 1);
glViewport(-1, -1, 2, 2);
glRasterPos2f(0, 0);
glViewport(0, 0, bw->blurTex.width, bw->blurTex.height);
glTranslatef(-0.5f, -0.5f, -DEFAULT_Z_CAMERA);
glScalef(1.0f / bw->blurTex.width, -1.0f / bw->blurTex.height, 1.0f);
glTranslatef(0.0f, -bw->blurTex.height, 0.0f);
// bind horizontal blur shader
(*s->bindProgram) (GL_FRAGMENT_PROGRAM_ARB, bs->blurShaderH);
// bind temprorary texture
switchBlurfxTexture(&bs->backTex, &bs->blurTempTexV, filter);
glTranslated(-bw->blurTex.x, -bw->blurTex.y, 0);
genGeometry(&bw->vertArray, mat, 0, reblurRegion);
glVertexPointer(2, GL_FLOAT, stride, bw->vertArray.vertices + 2);
glTexCoordPointer(2, GL_FLOAT, stride, bw->vertArray.vertices);
glDrawArrays(GL_QUADS, 0, bw->vertArray.vCount);
GLERR;
(*s->framebufferTexture2D) (GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_RECTANGLE_ARB,
bs->backTex.handle, 0);
GLERR;
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDepthRange(0, 1);
glViewport(-1, -1, 2, 2);
glRasterPos2f(0, 0);
s->rasterX = s->rasterY = 0;
glViewport(s->outputDev[bs->output].region.extents.x1,
s->height -
s->outputDev[bs->output].region.extents.y2,
s->outputDev[bs->output].width,
s->outputDev[bs->output].height);
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glDisable(GL_FRAGMENT_PROGRAM_ARB);
disableBlurfxTexture(&bs->blurTempTexV);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glDisable(GL_TEXTURE_GEN_R);
glDisable(GL_TEXTURE_GEN_Q);
// remove reblurred regions from blur cache texture damage
XSubtractRegion(bw->texDamage, reblurRegion, bw->texDamage);
}
// if the screen is transformed draw blur cache texture into temporary blur texture because there could be some regions we still need a blur for
if (blurPaintRegion->numRects && (mask & PAINT_WINDOW_TRANSFORMED_MASK))
{
(*s->framebufferTexture2D) (GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_RECTANGLE_ARB,
bs->blurTempTexH.handle, 0);
GLERR;
mat.xx = 1.0;
mat.yx = 0.0;
mat.xy = 0.0;
mat.yy = -1.0;
mat.x0 = -bw->blurTex.x;
mat.y0 = bw->blurTex.height + bw->blurTex.y;
genGeometry(&bw->vertArray, mat, 0, blurPaintRegion);
glVertexPointer(2, GL_FLOAT, stride, bw->vertArray.vertices + 2);
glTexCoordPointer(2, GL_FLOAT, stride, bw->vertArray.vertices);
enableBlurfxTexture(&bw->blurTex, filter);
glDrawArrays(GL_QUADS, 0, bw->vertArray.vCount);
GLERR;
disableBlurfxTexture(&bw->blurTex);
(*s->framebufferTexture2D) (GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_RECTANGLE_ARB,
bs->backTex.handle, 0);
GLERR;
}
// cleanup
XDestroyRegion(reblurRegion);
XDestroyRegion(blurPaintRegion);
}
static void
updateBlur(CompWindow * w, CompScreen * s,
const WindowPaintAttrib * attrib, unsigned int mask,
CompTextureFilter filter)
{
Region reblurRegion;
int stride, count, stop, vCount, iCount;
CompMatrix mat;
GLfloat *vertices, x1, x2, x3, x4, y1, y2, y3, y4, bx1, bx2, by1, by2;
GLushort *indices;
XRectangle rect;
BLURFX_SCREEN(s);
BLURFX_WINDOW(w);
// Do we have an decoration vertex array thet does not contain shadows?
if (mask & PAINT_WINDOW_DECORATION_MASK && bw->decoArray.vCount)
{
vertices = bw->decoArray.vertices + (w->texUnits * w->texCoordSize);
indices = bw->decoArray.indices;
vCount = bw->decoArray.vCount;
iCount = bw->decoArray.indexCount;
}
else
{
vertices = w->vertices + (w->texUnits * w->texCoordSize);
indices = w->indices;
vCount = w->vCount;
iCount = w->indexCount;
}
if (vCount <= 0)
return;
// get regions we need not to update
reblurRegion = XCreateRegion();
stride = (w->texUnits * w->texCoordSize) + 2;
count = 0;
stop = (iCount) ? iCount : vCount;
bx1 = 65535;
bx2 = 0.0;
by1 = 65535;
by2 = 0.0;
// generate region that needs blur
while (count < stop)
{
if (iCount)
{
x1 = vertices[indices[count] * stride];
y1 = vertices[(indices[count] * stride) + 1];
count++;
x2 = vertices[indices[count] * stride];
y2 = vertices[(indices[count] * stride) + 1];
count++;
x3 = vertices[indices[count] * stride];
y3 = vertices[(indices[count] * stride) + 1];
count++;
x4 = vertices[indices[count] * stride];
y4 = vertices[(indices[count] * stride) + 1];
count++;
}
else
{
x1 = vertices[0];
y1 = vertices[1];
vertices += stride;
x2 = vertices[0];
y2 = vertices[1];
vertices += stride;
x3 = vertices[0];
y3 = vertices[1];
vertices += stride;
x4 = vertices[0];
y4 = vertices[1];
vertices += stride;
count += 4;
}
if (!(mask & PAINT_WINDOW_TRANSFORMED_MASK))
{
bx1 = 65535;
bx2 = 0.0;
by1 = 65535;
by2 = 0.0;
}
bx1 = MIN(bx1, x1);
bx2 = MAX(bx2, x1);
bx1 = MIN(bx1, x2);
bx2 = MAX(bx2, x2);
bx1 = MIN(bx1, x3);
bx2 = MAX(bx2, x3);
bx1 = MIN(bx1, x4);
bx2 = MAX(bx2, x4);
by1 = MIN(by1, y1);
by2 = MAX(by2, y1);
by1 = MIN(by1, y2);
by2 = MAX(by2, y2);
by1 = MIN(by1, y3);
by2 = MAX(by2, y3);
by1 = MIN(by1, y4);
by2 = MAX(by2, y4);
if (bx2 - bx1 > 0 && by2 - by1 > 0
&& !(mask & PAINT_WINDOW_TRANSFORMED_MASK))
{
rect.x = -attrib->xTranslate +
(((bx1 - 7) - w->attrib.x) * attrib->xScale) +
w->attrib.x;
rect.y = -attrib->yTranslate +
(((by1 - 1) - w->attrib.y) * attrib->yScale) +
w->attrib.y;
rect.width = (bx2 - bx1 + 14) * attrib->xScale;
rect.height = (by2 - by1 + 2) * attrib->yScale;
XUnionRectWithRegion(&rect, reblurRegion, reblurRegion);
}
}
if (bx2 - bx1 > 0 && by2 - by1 > 0
&& (mask & PAINT_WINDOW_TRANSFORMED_MASK))
{
rect.x = attrib->xTranslate +
(((bx1 - 7) - w->attrib.x) * attrib->xScale) + w->attrib.x;
rect.y = attrib->yTranslate +
(((by1 - 1) - w->attrib.y) * attrib->yScale) + w->attrib.y;
rect.width = (bx2 - bx1 + 14) * attrib->xScale;
rect.height = (by2 - by1 + 2) * attrib->yScale;
XUnionRectWithRegion(&rect, reblurRegion, reblurRegion);
}
if (!(mask & PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK))
XIntersectRegion(reblurRegion,
&s->outputDev[bs->output].region, reblurRegion);
XSubtractRegion(reblurRegion, bs->blurredRegion, reblurRegion);
// subtract occluded region
if (bs->od_active)
XSubtractRegion(reblurRegion, bw->clip, reblurRegion);
// subtract blur cache texture region
if (bw->texUpdated)
XSubtractRegion(reblurRegion, bw->bTexRegion, reblurRegion);
if (!reblurRegion->numRects)
{
XDestroyRegion(reblurRegion);
return;
}
XUnionRegion(reblurRegion, bs->blurredRegion, bs->blurredRegion);
mat.xx = 1.0;
mat.yx = 0.0;
mat.xy = 0.0;
mat.yy = -1.0;
mat.x0 = 0.0;
mat.y0 = bs->backTex.height;
stride = 4 * sizeof(GLfloat);
// draw vertically blured region into temprorary texture
(*s->framebufferTexture2D) (GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_RECTANGLE_ARB,
bs->blurTempTexV.handle, 0);
GLERR;
glPushMatrix();
// enable projective texture cooridinate generation
float bm[16] = { s->outputDev[bs->output].width / 2.0, 0, 0, 0,
0, s->outputDev[bs->output].height / 2.0, 0, 0,
0, 0, 1, 0,
s->outputDev[bs->output].width / 2.0 +
s->outputDev[bs->output].region.extents.x1,
s->outputDev[bs->output].height / 2.0 + s->height -
s->outputDev[bs->output].region.extents.y2, 1, 1
};
float bpm[16];
float tm[16];
bw->mvm_updated = FALSE;
glGetFloatv(GL_MODELVIEW_MATRIX, bw->mvm);
MULTM(bm, bs->pm, bpm);
MULTM(bpm, bw->mvm, tm);
float s_gen[4] = { tm[0], tm[4], tm[8], tm[12] };
float t_gen[4] = { tm[1], tm[5], tm[9], tm[13] };
float r_gen[4] = { tm[2], tm[6], tm[10], tm[14] };
float q_gen[4] = { tm[3], tm[7], tm[11], tm[15] };
glTexGenfv(GL_T, GL_OBJECT_PLANE, t_gen);
glTexGenfv(GL_S, GL_OBJECT_PLANE, s_gen);
glTexGenfv(GL_R, GL_OBJECT_PLANE, r_gen);
glTexGenfv(GL_Q, GL_OBJECT_PLANE, q_gen);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
glEnable(GL_TEXTURE_GEN_Q);
// bind vertival blur shader
glEnable(GL_FRAGMENT_PROGRAM_ARB);
GLERR;
(*s->bindProgram) (GL_FRAGMENT_PROGRAM_ARB, bs->blurShaderV);
GLERR;
// bind unblurred background
enableBlurfxTexture(&bs->backTex, filter);
genGeometry(&bs->vertArray, mat, 0, reblurRegion);
glVertexPointer(2, GL_FLOAT, stride, bs->vertArray.vertices + 2);
GLERR;
glTexCoordPointer(2, GL_FLOAT, stride, bs->vertArray.vertices);
GLERR;
glDrawArrays(GL_QUADS, 0, bs->vertArray.vCount);
GLERR;
// draw vertically blured region into temprorary texture
(*s->framebufferTexture2D) (GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_RECTANGLE_ARB,
bs->blurTempTexH.handle, 0);
GLERR;
// bind horizontal blur shader
(*s->bindProgram) (GL_FRAGMENT_PROGRAM_ARB, bs->blurShaderH);
GLERR;
// bind temprorary texture
switchBlurfxTexture(&bs->backTex, &bs->blurTempTexV, filter);
glDrawArrays(GL_QUADS, 0, bs->vertArray.vCount);
GLERR;
glPopMatrix();
GLERR;
(*s->framebufferTexture2D) (GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_RECTANGLE_ARB,
bs->backTex.handle, 0);
GLERR;
(*s->bindProgram) (GL_FRAGMENT_PROGRAM_ARB, 0);
GLERR;
glDisable(GL_FRAGMENT_PROGRAM_ARB);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glDisable(GL_TEXTURE_GEN_R);
glDisable(GL_TEXTURE_GEN_Q);
disableBlurfxTexture(&bs->blurTempTexV);
XDestroyRegion(reblurRegion);
}
static void
updateBlurTextureSize(CompWindow * w, CompScreen * s,
const WindowPaintAttrib * attrib, unsigned int mask)
{
XRectangle box;
int texCheck = 0;
float div_w, div_h;
BLURFX_SCREEN(s);
BLURFX_WINDOW(w);
// if the window does not have a blur cache texture create it
if (!bw->hasTexture && !WINDOW_INPUT_INVISIBLE(w))
{
bw->hasTexture = TRUE;
genBlurTexture(bs, &bw->blurTex,
ceil((WIN_W(w) + 80) / bs->downSample),
ceil((WIN_H(w) + 80) / bs->downSample), 0);
bw->blurTex.x =
floor((WIN_X(w) - 40) / bs->downSample) * bs->downSample;
bw->blurTex.y =
floor((WIN_Y(w) - 40) / bs->downSample) * bs->downSample;
bw->blurTex.downSample = bs->downSample;
box.x = bw->blurTex.x;
box.y = bw->blurTex.y;
box.width = bw->blurTex.width;
box.height = bw->blurTex.height;
bw->bc_x = s->x;
bw->bc_y = s->y;
XUnionRegion(getEmptyRegion(), getEmptyRegion(), bw->texDamage);
XUnionRegion(getEmptyRegion(), getEmptyRegion(), bw->bTexRegion);
XUnionRectWithRegion(&box, bw->texDamage, bw->texDamage);
XUnionRectWithRegion(&box, bw->bTexRegion, bw->bTexRegion);
}
// if the window has moved out of his blur cache texture then update the blur cache texture
if (bw->blurTex.x > WIN_X(w)
|| WIN_X(w) + WIN_W(w) > bw->blurTex.x + bw->blurTex.width)
texCheck = 1;
if (bw->blurTex.y > WIN_Y(w)
|| WIN_Y(w) + WIN_H(w) > bw->blurTex.y + bw->blurTex.height)
texCheck = 1;
// do not update if the window is still moving
if ((mask & PAINT_WINDOW_TRANSFORMED_MASK) && texCheck
&& !(w->attrib.x == bw->lastX && w->attrib.y == bw->lastY))
texCheck = 0;
// do we need to resize the blur cache texture
if (bw->blurTex.width < WIN_W(w) || bw->blurTex.height < WIN_H(w))
texCheck = 2;
if (bw->blurTex.width - WIN_W(w) > 160
|| bw->blurTex.height - WIN_H(w) > 160)
texCheck = 2;
if ((bw->bc_x != s->x || bw->bc_y != s->y)
&& !(mask & PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK))
{
texCheck = 1;
}
// do not update blur cache texture size if window is transformed
if ((mask & PAINT_WINDOW_TRANSFORMED_MASK) && texCheck == 2)
texCheck = 0;
if (bw->blurTex.downSample != bs->downSample)
texCheck = 2;
if (texCheck && (!WINDOW_INPUT_INVISIBLE(w) || w->shaded))
{
if (texCheck == 2)
{
// update blur cache texture size
enableBlurfxTexture(&bw->blurTex, COMP_TEXTURE_FILTER_FAST);
glTexImage2D(bw->blurTex.target, 0, 3,
ceil((WIN_W(w) +
80) / bs->downSample),
ceil((WIN_H(w) +
80) / bs->downSample), 0,
GL_RGB, GL_UNSIGNED_BYTE, NULL);
disableBlurfxTexture(&bw->blurTex);
bw->blurTex.width = WIN_W(w) + 80;
bw->blurTex.height = WIN_H(w) + 80;
}
// update blur cache texture position
div_w = (bw->blurTex.width - WIN_W(w)) / 2;
div_h = (bw->blurTex.height - WIN_H(w)) / 2;
bw->blurTex.x =
floor((WIN_X(w) - div_w) / bs->downSample) * bs->downSample;
bw->blurTex.y =
floor((WIN_Y(w) - div_h) / bs->downSample) * bs->downSample;
bw->blurTex.downSample = bs->downSample;
box.x = bw->blurTex.x;
box.y = bw->blurTex.y;
box.width = bw->blurTex.width;
box.height = bw->blurTex.height;
bw->bc_x = s->x;
bw->bc_y = s->y;
// update to new regions and add damage
XUnionRegion(getEmptyRegion(), getEmptyRegion(), bw->texDamage);
XUnionRegion(getEmptyRegion(), getEmptyRegion(), bw->bTexRegion);
XUnionRectWithRegion(&box, bw->texDamage, bw->texDamage);
XUnionRectWithRegion(&box, bw->bTexRegion, bw->bTexRegion);
}
}
static void
updateBlurTextureNoFBO(CompWindow * w, CompScreen * s,
const WindowPaintAttrib * attrib, unsigned int mask)
{
Region reblurRegion;
Region blurPaintRegion;
int stride, count, stop, vCount, iCount;
GLfloat *vertices, x1, x2, x3, x4, y1, y2, y3, y4, bx1, bx2, by1, by2;
GLushort *indices;
XRectangle rect;
BLURFX_SCREEN(s);
BLURFX_WINDOW(w);
if (bw->bc_x != s->x || bw->bc_y != s->y)
{
bw->texUpdated = FALSE;
return;
}
if (screenGrabExist(s, "switcher", 0)
|| mask & PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK
|| mask & PAINT_WINDOW_TRANSFORMED_MASK || bw->isSwitcher)
{
bw->texUpdated = FALSE;
return;
}
// Do we have an decoration vertex array thet does not contain shadows?
if (mask & PAINT_WINDOW_DECORATION_MASK && bw->decoArray.vCount)
{
vertices = bw->decoArray.vertices + (w->texUnits * w->texCoordSize);
indices = bw->decoArray.indices;
vCount = bw->decoArray.vCount;
iCount = bw->decoArray.indexCount;
}
else
{
vertices = w->vertices + (w->texUnits * w->texCoordSize);
indices = w->indices;
vCount = w->vCount;
iCount = w->indexCount;
}
if (vCount <= 0)
return;
stride = (w->texUnits * w->texCoordSize) + 2;
// get regions we need not to update
reblurRegion = XCreateRegion();
blurPaintRegion = XCreateRegion();
count = 0;
stop = (iCount) ? iCount : vCount;
bx1 = 65535;
bx2 = 0.0;
by1 = 65535;
by2 = 0.0;
// generate region that needs blur
while (count < stop)
{
if (iCount)
{
x1 = vertices[indices[count] * stride];
y1 = vertices[(indices[count] * stride) + 1];
count++;
x2 = vertices[indices[count] * stride];
y2 = vertices[(indices[count] * stride) + 1];
count++;
x3 = vertices[indices[count] * stride];
y3 = vertices[(indices[count] * stride) + 1];
count++;
x4 = vertices[indices[count] * stride];
y4 = vertices[(indices[count] * stride) + 1];
count++;
}
else
{
x1 = vertices[0];
y1 = vertices[1];
vertices += stride;
x2 = vertices[0];
y2 = vertices[1];
vertices += stride;
x3 = vertices[0];
y3 = vertices[1];
vertices += stride;
x4 = vertices[0];
y4 = vertices[1];
vertices += stride;
count += 4;
}
bx1 = 65535;
bx2 = 0.0;
by1 = 65535;
by2 = 0.0;
bx1 = MIN(bx1, x1);
bx2 = MAX(bx2, x1);
bx1 = MIN(bx1, x2);
bx2 = MAX(bx2, x2);
bx1 = MIN(bx1, x3);
bx2 = MAX(bx2, x3);
bx1 = MIN(bx1, x4);
bx2 = MAX(bx2, x4);
by1 = MIN(by1, y1);
by2 = MAX(by2, y1);
by1 = MIN(by1, y2);
by2 = MAX(by2, y2);
by1 = MIN(by1, y3);
by2 = MAX(by2, y3);
by1 = MIN(by1, y4);
by2 = MAX(by2, y4);
if (bx2 - bx1 > 0 && by2 - by1 > 0)
{
rect.x = attrib->xTranslate +
(((bx1 - 7) - w->attrib.x) * attrib->xScale) +
w->attrib.x;
rect.y = attrib->yTranslate +
(((by1 - 1) - w->attrib.y) * attrib->yScale) +
w->attrib.y;
rect.width = (bx2 - bx1 + 14) * attrib->xScale;
rect.height = (by2 - by1 + 2) * attrib->yScale;
XUnionRectWithRegion(&rect, reblurRegion, reblurRegion);
}
}
XIntersectRegion(reblurRegion, bw->bTexRegion, blurPaintRegion);
// get regions we need to update
XIntersectRegion(reblurRegion, bw->paintRegion, reblurRegion);
XIntersectRegion(reblurRegion, bw->texDamage, reblurRegion);
XIntersectRegion(reblurRegion, bw->bTexRegion, reblurRegion);
XIntersectRegion(reblurRegion, &s->outputDev[bs->output].region,
reblurRegion);
// subtract occluded region
if (bs->od_active)
XSubtractRegion(reblurRegion, bw->clip, reblurRegion);
if (reblurRegion->numRects)
{
// enable projective texture cooridinate generation
float bm[16] = { s->outputDev[bs->output].width / 2.0, 0, 0, 0,
0, s->outputDev[bs->output].height / -2.0, 0, 0,
0, 0, 1, 0,
s->outputDev[bs->output].width / 2.0 +
s->outputDev[bs->output].region.extents.x1,
s->outputDev[bs->output].height / 2.0 +
s->outputDev[bs->output].region.extents.y1, 1,
1
};
float bpm[16];
float tm[16];
if (!bw->mvm_updated)
{
bw->mvm_updated = TRUE;
glGetFloatv(GL_MODELVIEW_MATRIX, bw->mvm);
}
MULTM(bm, bs->pm, bpm);
MULTM(bpm, bw->mvm, tm);
int i;
XRectangle sRect, bRect;
for (i = 0; i < reblurRegion->numRects; i++)
{
sRect.x = floor(reblurRegion->rects[i].x1 / bs->downSample);
sRect.y = floor(reblurRegion->rects[i].y1 / bs->downSample);
sRect.width =
MAX(1.0,
ceil(reblurRegion->rects[i].x2 /
bs->downSample) - sRect.x);
sRect.height =
MAX(1.0,
ceil(reblurRegion->rects[i].y2 /
bs->downSample) - sRect.y);
bRect.x = sRect.x * bs->downSample;
bRect.y = sRect.y * bs->downSample;
bRect.width = sRect.width * bs->downSample;
bRect.height = sRect.height * bs->downSample;
// copy background into temporary texture
enableBlurfxTexture(&bs->blurTempTexV, COMP_TEXTURE_FILTER_GOOD);
glCopyTexSubImage2D(bs->blurTempTexV.target, 0, 0,
0, bRect.x,
s->height - bRect.y -
bRect.height, bRect.width, bRect.height);
// draw downsampled texture
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2f(bRect.x, bRect.y);
glTexCoord2f(0, bRect.height);
glVertex2f(bRect.x, bRect.y + sRect.height);
glTexCoord2f(bRect.width, bRect.height);
glVertex2f(bRect.x + sRect.width, bRect.y + sRect.height);
glTexCoord2f(bRect.width, 0);
glVertex2f(bRect.x + sRect.width, bRect.y);
glEnd();
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
float shift = bs->downSample / 2.0;
glColor4f(1.0, 1.0, 1.0, 0.5);
glBegin(GL_QUADS);
glTexCoord2f(0 + shift, 0);
glVertex2f(bRect.x, bRect.y);
glTexCoord2f(0 + shift, bRect.height);
glVertex2f(bRect.x, bRect.y + sRect.height);
glTexCoord2f(bRect.width + shift, bRect.height);
glVertex2f(bRect.x + sRect.width, bRect.y + sRect.height);
glTexCoord2f(bRect.width + shift, 0);
glVertex2f(bRect.x + sRect.width, bRect.y);
glEnd();
glColor4f(1.0, 1.0, 1.0, 0.333);
glBegin(GL_QUADS);
glTexCoord2f(0 - shift, 0);
glVertex2f(bRect.x, bRect.y);
glTexCoord2f(0 - shift, bRect.height);
glVertex2f(bRect.x, bRect.y + sRect.height);
glTexCoord2f(bRect.width - shift, bRect.height);
glVertex2f(bRect.x + sRect.width, bRect.y + sRect.height);
glTexCoord2f(bRect.width - shift, 0);
glVertex2f(bRect.x + sRect.width, bRect.y);
glEnd();
glColor4f(1.0, 1.0, 1.0, 0.25);
glBegin(GL_QUADS);
glTexCoord2f(0, 0 - shift);
glVertex2f(bRect.x, bRect.y);
glTexCoord2f(0, bRect.height - shift);
glVertex2f(bRect.x, bRect.y + sRect.height);
glTexCoord2f(bRect.width, bRect.height - shift);
glVertex2f(bRect.x + sRect.width, bRect.y + sRect.height);
glTexCoord2f(bRect.width, 0 - shift);
glVertex2f(bRect.x + sRect.width, bRect.y);
glEnd();
glColor4f(1.0, 1.0, 1.0, 0.2);
glBegin(GL_QUADS);
glTexCoord2f(0, 0 + shift);
glVertex2f(bRect.x, bRect.y);
glTexCoord2f(0, bRect.height + shift);
glVertex2f(bRect.x, bRect.y + sRect.height);
glTexCoord2f(bRect.width, bRect.height + shift);
glVertex2f(bRect.x + sRect.width, bRect.y + sRect.height);
glTexCoord2f(bRect.width, 0 + shift);
glVertex2f(bRect.x + sRect.width, bRect.y);
glEnd();
glDisable(GL_BLEND);
// copy downsampled background into temporary texture
switchBlurfxTexture(&bs->blurTempTexV,
&bw->blurTex, COMP_TEXTURE_FILTER_GOOD);
glCopyTexSubImage2D(bw->blurTex.target, 0,
sRect.x -
(bw->blurTex.x /
bs->downSample),
sRect.y -
(bw->blurTex.y /
bs->downSample), bRect.x,
s->height - bRect.y -
sRect.height, sRect.width, sRect.height);
// copy normal background back to screen
switchBlurfxTexture(&bw->blurTex,
&bs->blurTempTexV, COMP_TEXTURE_FILTER_GOOD);
glBegin(GL_QUADS);
glTexCoord2f(0, bRect.height);
glVertex2f(bRect.x, bRect.y);
glTexCoord2f(0, 0);
glVertex2f(bRect.x, bRect.y + bRect.height);
glTexCoord2f(bRect.width, 0);
glVertex2f(bRect.x + bRect.width, bRect.y + bRect.height);
glTexCoord2f(bRect.width, bRect.height);
glVertex2f(bRect.x + bRect.width, bRect.y);
glEnd();
disableBlurfxTexture(&bs->blurTempTexV);
}
// remove reblurred regions from blur cache texture damage
XSubtractRegion(bw->texDamage, reblurRegion, bw->texDamage);
}
// cleanup
XDestroyRegion(reblurRegion);
XDestroyRegion(blurPaintRegion);
}
static void
updateBlurNoFBO(CompWindow * w, CompScreen * s,
const WindowPaintAttrib * attrib, unsigned int mask)
{
Region reblurRegion;
int stride, count, stop, vCount, iCount;
GLfloat *vertices, x1, x2, x3, x4, y1, y2, y3, y4, bx1, bx2, by1, by2;
GLushort *indices;
XRectangle rect;
BLURFX_SCREEN(s);
BLURFX_WINDOW(w);
// Do we have an decoration vertex array thet does not contain shadows?
if (mask & PAINT_WINDOW_DECORATION_MASK && bw->decoArray.vCount)
{
vertices = bw->decoArray.vertices + (w->texUnits * w->texCoordSize);
indices = bw->decoArray.indices;
vCount = bw->decoArray.vCount;
iCount = bw->decoArray.indexCount;
}
else
{
vertices = w->vertices + (w->texUnits * w->texCoordSize);
indices = w->indices;
vCount = w->vCount;
iCount = w->indexCount;
}
if (vCount <= 0)
return;
// get regions we need not to update
reblurRegion = XCreateRegion();
stride = (w->texUnits * w->texCoordSize) + 2;
count = 0;
stop = (iCount) ? iCount : vCount;
bx1 = 65535;
bx2 = 0.0;
by1 = 65535;
by2 = 0.0;
// generate region that needs blur
while (count < stop)
{
if (iCount)
{
x1 = vertices[indices[count] * stride];
y1 = vertices[(indices[count] * stride) + 1];
count++;
x2 = vertices[indices[count] * stride];
y2 = vertices[(indices[count] * stride) + 1];
count++;
x3 = vertices[indices[count] * stride];
y3 = vertices[(indices[count] * stride) + 1];
count++;
x4 = vertices[indices[count] * stride];
y4 = vertices[(indices[count] * stride) + 1];
count++;
}
else
{
x1 = vertices[0];
y1 = vertices[1];
vertices += stride;
x2 = vertices[0];
y2 = vertices[1];
vertices += stride;
x3 = vertices[0];
y3 = vertices[1];
vertices += stride;
x4 = vertices[0];
y4 = vertices[1];
vertices += stride;
count += 4;
}
if (!(mask & PAINT_WINDOW_TRANSFORMED_MASK))
{
bx1 = 65535;
bx2 = 0.0;
by1 = 65535;
by2 = 0.0;
}
bx1 = MIN(bx1, x1);
bx2 = MAX(bx2, x1);
bx1 = MIN(bx1, x2);
bx2 = MAX(bx2, x2);
bx1 = MIN(bx1, x3);
bx2 = MAX(bx2, x3);
bx1 = MIN(bx1, x4);
bx2 = MAX(bx2, x4);
by1 = MIN(by1, y1);
by2 = MAX(by2, y1);
by1 = MIN(by1, y2);
by2 = MAX(by2, y2);
by1 = MIN(by1, y3);
by2 = MAX(by2, y3);
by1 = MIN(by1, y4);
by2 = MAX(by2, y4);
if (bx2 - bx1 > 0 && by2 - by1 > 0
&& !(mask & PAINT_WINDOW_TRANSFORMED_MASK))
{
rect.x = attrib->xTranslate +
(((bx1 - 7) - w->attrib.x) * attrib->xScale) +
w->attrib.x;
rect.y = attrib->yTranslate +
(((by1 - 1) - w->attrib.y) * attrib->yScale) +
w->attrib.y;
rect.width = (bx2 - bx1 + 14) * attrib->xScale;
rect.height = (by2 - by1 + 2) * attrib->yScale;
XUnionRectWithRegion(&rect, reblurRegion, reblurRegion);
}
}
if (bx2 - bx1 > 0 && by2 - by1 > 0
&& (mask & PAINT_WINDOW_TRANSFORMED_MASK))
{
rect.x = attrib->xTranslate +
(((bx1 - 7) - w->attrib.x) * attrib->xScale) + w->attrib.x;
rect.y = attrib->yTranslate +
(((by1 - 1) - w->attrib.y) * attrib->yScale) + w->attrib.y;
rect.width = (bx2 - bx1 + 14) * attrib->xScale;
rect.height = (by2 - by1 + 2) * attrib->yScale;
XUnionRectWithRegion(&rect, reblurRegion, reblurRegion);
}
XIntersectRegion(reblurRegion, &s->region, reblurRegion);
XSubtractRegion(reblurRegion, bs->blurredRegion, reblurRegion);
// subtract occluded region
if (bs->od_active)
XSubtractRegion(reblurRegion, bw->clip, reblurRegion);
// subtract blur cache texture region
if (bw->texUpdated)
XSubtractRegion(reblurRegion, bw->bTexRegion, reblurRegion);
if (!reblurRegion->numRects)
{
XDestroyRegion(reblurRegion);
return;
}
XUnionRegion(reblurRegion, bs->blurredRegion, bs->blurredRegion);
glPushMatrix();
// enable projective texture cooridinate generation
float bm[16] = { s->outputDev[bs->output].width / 2.0, 0, 0, 0,
0, s->outputDev[bs->output].height / -2.0, 0, 0,
0, 0, 1, 0,
s->outputDev[bs->output].width / 2.0 +
s->outputDev[bs->output].region.extents.x1,
s->outputDev[bs->output].height / 2.0 +
s->outputDev[bs->output].region.extents.y1, 1, 1
};
float bpm[16];
float tm[16];
bw->mvm_updated = FALSE;
glGetFloatv(GL_MODELVIEW_MATRIX, bw->mvm);
MULTM(bm, bs->pm, bpm);
MULTM(bpm, bw->mvm, tm);
Bool enable_light = FALSE;
if (glIsEnabled(GL_LIGHTING))
{
glDisable(GL_LIGHTING);
enable_light = TRUE;
}
Bool enable_clipPlanes = FALSE;
if (glIsEnabled(GL_CLIP_PLANE0))
{
glDisable (GL_CLIP_PLANE0);
glDisable (GL_CLIP_PLANE1);
glDisable (GL_CLIP_PLANE2);
glDisable (GL_CLIP_PLANE3);
enable_clipPlanes = TRUE;
}
int i;
XRectangle sRect, bRect;
for (i = 0; i < reblurRegion->numRects; i++)
{
rect.x = reblurRegion->rects[i].x1;
rect.y = reblurRegion->rects[i].y1;
rect.width = reblurRegion->rects[i].x2 - rect.x;
rect.height = reblurRegion->rects[i].y2 - rect.y;
// check region for visibility and project it to screen
float bbProj[4][2];
float bBox[4];
bbProj[0][0] = rect.x * tm[0] + rect.y * tm[4] + tm[12];
bbProj[0][0] /= rect.x * tm[3] + rect.y * tm[7] + tm[15];
bbProj[0][1] = rect.x * tm[1] + rect.y * tm[5] + tm[13];
bbProj[0][1] /= rect.x * tm[3] + rect.y * tm[7] + tm[15];
bbProj[1][0] =
(rect.x + rect.width) * tm[0] + rect.y * tm[4] + tm[12];
bbProj[1][0] /= (rect.x + rect.width) * tm[3] +
rect.y * tm[7] + tm[15];
bbProj[1][1] =
(rect.x + rect.width) * tm[1] + rect.y * tm[5] + tm[13];
bbProj[1][1] /= (rect.x + rect.width) * tm[3] +
rect.y * tm[7] + tm[15];
bbProj[2][0] =
rect.x * tm[0] + (rect.y + rect.height) * tm[4] + tm[12];
bbProj[2][0] /= rect.x * tm[3] + (rect.y +
rect.height) * tm[7] + tm[15];
bbProj[2][1] =
rect.x * tm[1] + (rect.y + rect.height) * tm[5] + tm[13];
bbProj[2][1] /= rect.x * tm[3] + (rect.y +
rect.height) * tm[7] + tm[15];
bbProj[3][0] =
(rect.x + rect.width) * tm[0] + (rect.y +
rect.height) * tm[4] +
tm[12];
bbProj[3][0] /= (rect.x + rect.width) * tm[3] + (rect.y +
rect.height) *
tm[7] + tm[15];
bbProj[3][1] =
(rect.x + rect.width) * tm[1] + (rect.y +
rect.height) * tm[5] +
tm[13];
bbProj[3][1] /= (rect.x + rect.width) * tm[3] + (rect.y +
rect.height) *
tm[7] + tm[15];
// calculate a bounding box of the projected rectangle
bBox[0] =
MIN(s->outputDev[bs->output].region.extents.x2, bbProj[0][0]);
bBox[0] = MIN(bBox[0], bbProj[1][0]);
bBox[0] = MIN(bBox[0], bbProj[2][0]);
bBox[0] = MIN(bBox[0], bbProj[3][0]);
bBox[0] = MAX(bBox[0], s->outputDev[bs->output].region.extents.x1);
bBox[1] =
MIN(s->outputDev[bs->output].region.extents.y2, bbProj[0][1]);
bBox[1] = MIN(bBox[1], bbProj[1][1]);
bBox[1] = MIN(bBox[1], bbProj[2][1]);
bBox[1] = MIN(bBox[1], bbProj[3][1]);
bBox[1] = MAX(bBox[1], s->outputDev[bs->output].region.extents.y1);
bBox[2] =
MAX(s->outputDev[bs->output].region.extents.x1, bbProj[0][0]);
bBox[2] = MAX(bBox[2], bbProj[1][0]);
bBox[2] = MAX(bBox[2], bbProj[2][0]);
bBox[2] = MAX(bBox[2], bbProj[3][0]);
bBox[2] = MIN(bBox[2], s->outputDev[bs->output].region.extents.x2);
bBox[3] =
MAX(s->outputDev[bs->output].region.extents.y1, bbProj[0][1]);
bBox[3] = MAX(bBox[3], bbProj[1][1]);
bBox[3] = MAX(bBox[3], bbProj[2][1]);
bBox[3] = MAX(bBox[3], bbProj[3][1]);
bBox[3] = MIN(bBox[3], s->outputDev[bs->output].region.extents.y2);
if (bBox[2] - bBox[0] <= 0 || bBox[3] - bBox[1] <= 0)
continue;
sRect.x = floor(bBox[0] / bs->downSample);
sRect.y = floor(bBox[1] / bs->downSample);
sRect.width = MAX(1.0, ceil(bBox[2] / bs->downSample) - sRect.x);
sRect.height = MAX(1.0, ceil(bBox[3] / bs->downSample) - sRect.y);
bRect.x = sRect.x * bs->downSample;
bRect.y = sRect.y * bs->downSample;
bRect.width = sRect.width * bs->downSample;
bRect.height = sRect.height * bs->downSample;
glLoadIdentity();
prepareXCoords(s, bs->output, -DEFAULT_Z_CAMERA);
// copy background into temporary texture
enableBlurfxTexture(&bs->blurTempTexV, COMP_TEXTURE_FILTER_GOOD);
glCopyTexSubImage2D(bs->blurTempTexV.target, 0, 0, 0,
bRect.x,
s->height - bRect.y - bRect.height,
bRect.width, bRect.height);
// draw downsampled texture
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2f(bRect.x, bRect.y);
glTexCoord2f(0, bRect.height);
glVertex2f(bRect.x, bRect.y + sRect.height);
glTexCoord2f(bRect.width, bRect.height);
glVertex2f(bRect.x + sRect.width, bRect.y + sRect.height);
glTexCoord2f(bRect.width, 0);
glVertex2f(bRect.x + sRect.width, bRect.y);
glEnd();
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
float shift = bs->downSample / 2.0;
glColor4f(1.0, 1.0, 1.0, 0.5);
glBegin(GL_QUADS);
glTexCoord2f(0 + shift, 0);
glVertex2f(bRect.x, bRect.y);
glTexCoord2f(0 + shift, bRect.height);
glVertex2f(bRect.x, bRect.y + sRect.height);
glTexCoord2f(bRect.width + shift, bRect.height);
glVertex2f(bRect.x + sRect.width, bRect.y + sRect.height);
glTexCoord2f(bRect.width + shift, 0);
glVertex2f(bRect.x + sRect.width, bRect.y);
glEnd();
glColor4f(1.0, 1.0, 1.0, 0.333);
glBegin(GL_QUADS);
glTexCoord2f(0 - shift, 0);
glVertex2f(bRect.x, bRect.y);
glTexCoord2f(0 - shift, bRect.height);
glVertex2f(bRect.x, bRect.y + sRect.height);
glTexCoord2f(bRect.width - shift, bRect.height);
glVertex2f(bRect.x + sRect.width, bRect.y + sRect.height);
glTexCoord2f(bRect.width - shift, 0);
glVertex2f(bRect.x + sRect.width, bRect.y);
glEnd();
glColor4f(1.0, 1.0, 1.0, 0.25);
glBegin(GL_QUADS);
glTexCoord2f(0, 0 - shift);
glVertex2f(bRect.x, bRect.y);
glTexCoord2f(0, bRect.height - shift);
glVertex2f(bRect.x, bRect.y + sRect.height);
glTexCoord2f(bRect.width, bRect.height - shift);
glVertex2f(bRect.x + sRect.width, bRect.y + sRect.height);
glTexCoord2f(bRect.width, 0 - shift);
glVertex2f(bRect.x + sRect.width, bRect.y);
glEnd();
glColor4f(1.0, 1.0, 1.0, 0.2);
glBegin(GL_QUADS);
glTexCoord2f(0, 0 + shift);
glVertex2f(bRect.x, bRect.y);
glTexCoord2f(0, bRect.height + shift);
glVertex2f(bRect.x, bRect.y + sRect.height);
glTexCoord2f(bRect.width, bRect.height + shift);
glVertex2f(bRect.x + sRect.width, bRect.y + sRect.height);
glTexCoord2f(bRect.width, 0 + shift);
glVertex2f(bRect.x + sRect.width, bRect.y);
glEnd();
glDisable(GL_BLEND);
// copy downsampled background into temporary texture
switchBlurfxTexture(&bs->blurTempTexV, &bs->blurTempTexH,
COMP_TEXTURE_FILTER_GOOD);
glCopyTexSubImage2D(bs->blurTempTexV.target, 0, sRect.x,
sRect.y +
((s->height -
s->outputDev[bs->output].region.
extents.y2) / bs->downSample),
bRect.x,
s->height - bRect.y - sRect.height,
sRect.width, sRect.height);
// copy normal background back to screen
switchBlurfxTexture(&bs->blurTempTexH, &bs->blurTempTexV,
COMP_TEXTURE_FILTER_GOOD);
glBegin(GL_QUADS);
glTexCoord2f(0, bRect.height);
glVertex2f(bRect.x, bRect.y);
glTexCoord2f(0, 0);
glVertex2f(bRect.x, bRect.y + bRect.height);
glTexCoord2f(bRect.width, 0);
glVertex2f(bRect.x + bRect.width, bRect.y + bRect.height);
glTexCoord2f(bRect.width, bRect.height);
glVertex2f(bRect.x + bRect.width, bRect.y);
glEnd();
disableBlurfxTexture(&bs->blurTempTexV);
}
glPopMatrix();
if (enable_light)
glEnable(GL_LIGHTING);
if (enable_clipPlanes)
{
glEnable (GL_CLIP_PLANE0);
glEnable (GL_CLIP_PLANE1);
glEnable (GL_CLIP_PLANE2);
glEnable (GL_CLIP_PLANE3);
}
XDestroyRegion(reblurRegion);
}
static void
drawBlur(CompWindow * w, CompScreen * s, CompTexture * texture,
const WindowPaintAttrib * attrib, int mask, CompTextureFilter filter)
{
int i, count, vCount, iCount, stride;
GLfloat *vertices;
GLushort *indices;
GLfloat constant[4];
unsigned int actTex = 0;
BLURFX_SCREEN(s);
BLURFX_WINDOW(w);
glPushMatrix();
if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
{
glTranslatef(w->attrib.x, w->attrib.y, 0.0f);
glScalef(attrib->xScale, attrib->yScale, 0.0f);
glTranslatef(attrib->xTranslate / attrib->xScale -
w->attrib.x,
attrib->yTranslate / attrib->yScale - w->attrib.y, 0.0f);
}
// Do we have an decoration vertex array thet does not contain shadows?
if (mask & PAINT_WINDOW_DECORATION_MASK && bw->decoArray.vCount)
{
vertices = bw->decoArray.vertices + (w->texUnits * w->texCoordSize);
indices = bw->decoArray.indices;
vCount = bw->decoArray.vCount;
iCount = bw->decoArray.indexCount;
}
else
{
vertices = w->vertices + (w->texUnits * w->texCoordSize);
indices = w->indices;
vCount = w->vCount;
iCount = w->indexCount;
}
if (vCount <= 0)
return;
i = 0;
count = 0;
stride = (w->texUnits * w->texCoordSize + 2) * sizeof(GLfloat);
// draw blur only for visible regions
if (!(mask & PAINT_WINDOW_DECORATION_MASK) && !w->alpha
&& !(mask & PAINT_WINDOW_TRANSFORMED_MASK) && !w->shaded
&& bs->od_active)
{
Region drawBlurRegion = XCreateRegion();
XIntersectRegion(w->region, bw->paintRegion, drawBlurRegion);
if (bw->texUpdated)
XIntersectRegion(drawBlurRegion, bw->bTexRegion, drawBlurRegion);
XSubtractRegion(drawBlurRegion, bw->clip, drawBlurRegion);
CompMatrix mat;
mat.xx = 0.0;
mat.yx = 0.0;
mat.xy = 0.0;
mat.yy = 0.0;
mat.x0 = 0.0;
mat.y0 = 0.0;
genGeometry(&bs->vertArray, mat, 0, drawBlurRegion);
stride = 4 * sizeof(GLfloat);
vCount = bs->vertArray.vCount;
iCount = 0;
vertices = bs->vertArray.vertices + 2;
XDestroyRegion(drawBlurRegion);
}
glVertexPointer(2, GL_FLOAT, stride, vertices);
GLERR;
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
(*s->activeTexture) (GL_TEXTURE0_ARB);
float tm[16];
if ((mask & PAINT_WINDOW_TRANSFORMED_MASK) || !bw->texUpdated)
{
// enable projective texture cooridinate generation
float bm[16] =
{ s->outputDev[bs->output].width / (2.0 * bs->downSample), 0,
0, 0, 0,
s->outputDev[bs->output].height / (2.0 * bs->downSample),
0, 0, 0, 0, 1, 0,
s->outputDev[bs->output].width / (2.0 *
bs->downSample) +
(s->outputDev[bs->output].region.extents.x1 /
bs->downSample),
s->outputDev[bs->output].height / (2.0 * bs->downSample) +
((s->height -
s->outputDev[bs->output].region.extents.y2) /
bs->downSample), 1,
1
};
if (bs->downSample != 1.0)
bm[5] *= -1;
float bpm[16];
//if (!bw->mvm_updated)
{
bw->mvm_updated = TRUE;
glGetFloatv(GL_MODELVIEW_MATRIX, bw->mvm);
}
MULTM(bm, bs->pm, bpm);
MULTM(bpm, bw->mvm, tm);
float s_gen[4] = { tm[0], tm[4], tm[8], tm[12] };
float t_gen[4] = { tm[1], tm[5], tm[9], tm[13] };
float r_gen[4] = { tm[2], tm[6], tm[10], tm[14] };
float q_gen[4] = { tm[3], tm[7], tm[11], tm[15] };
glTexGenfv(GL_T, GL_OBJECT_PLANE, t_gen);
glTexGenfv(GL_S, GL_OBJECT_PLANE, s_gen);
glTexGenfv(GL_R, GL_OBJECT_PLANE, r_gen);
glTexGenfv(GL_Q, GL_OBJECT_PLANE, q_gen);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
glEnable(GL_TEXTURE_GEN_Q);
enableBlurfxTexture(&bs->blurTempTexH, filter);
}
else
{
// enable texture cooridinate generation
float s_gen[4] = { 1.0 / bs->downSample, 0.0, 0.0,
-bw->blurTex.x / bs->downSample
};
if (bs->downSample != 1.0)
{
float t_gen[4] = { 0.0, 1.0 / bs->downSample, 0.0,
-bw->blurTex.y / bs->downSample
};
glTexGenfv(GL_T, GL_OBJECT_PLANE, t_gen);
}
else
{
float t_gen[4] = { 0.0, -1.0, 0.0,
bw->blurTex.height + bw->blurTex.y
};
glTexGenfv(GL_T, GL_OBJECT_PLANE, t_gen);
}
glTexGenfv(GL_S, GL_OBJECT_PLANE, s_gen);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
enableBlurfxTexture(&bw->blurTex, filter);
}
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
// simple switcher detection hack
Bool switcher = FALSE;
if (w->resName == 0 && w->resClass == 0
&& (mask & PAINT_WINDOW_DECORATION_MASK)
&& screenGrabExist(s, "switcher", 0))
switcher = TRUE;
// we need alpha dependend blur if window has alpha channel
if (((mask & PAINT_WINDOW_DECORATION_MASK)
&& !bs->opt[BLURFX_SCREEN_OPTION_DISABLE_DECORATION_ALPHADEP].
value.b) || switcher
|| (!(mask & PAINT_WINDOW_DECORATION_MASK) && w->alpha))
{
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
actTex++;
(*s->activeTexture) (GL_TEXTURE0_ARB + actTex);
glDisable(GL_TEXTURE_GEN_T);
glDisable(GL_TEXTURE_GEN_S);
enableTexture(s, texture, filter);
GLERR;
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_CONSTANT);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
glTexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 4.0);
constant[3] = attrib->opacity / 65535.0f;
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
(*s->clientActiveTexture) (GL_TEXTURE1_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, stride,
vertices - (w->texUnits * w->texCoordSize));
GLERR;
}
else
{
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_CONSTANT);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
constant[3] = MIN(1.0, (attrib->opacity / 65535.0f) * 4.0);
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
}
if (s->canDoSlightlySaturated
&& bs->opt[BLURFX_SCREEN_OPTION_BLUR_SATURATION].value.f < 100.0)
{
actTex++;
(*s->activeTexture) (GL_TEXTURE0_ARB + actTex);
enableBlurfxTexture(&bs->blurTempTexH, filter);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PRIMARY_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
glColor4f(1.0f, 1.0f, 1.0f, 0.5f);
actTex++;
(*s->activeTexture) (GL_TEXTURE0_ARB + actTex);
enableBlurfxTexture(&bs->blurTempTexH, filter);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
constant[0] = 0.5f + 0.5f * RED_SATURATION_WEIGHT;
constant[1] = 0.5f + 0.5f * GREEN_SATURATION_WEIGHT;
constant[2] = 0.5f + 0.5f * BLUE_SATURATION_WEIGHT;
constant[3] = 1.0;
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
actTex++;
(*s->activeTexture) (GL_TEXTURE0_ARB + actTex);
enableBlurfxTexture(&bs->blurTempTexH, filter);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE0);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_CONSTANT);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
constant[3] =
bs->opt[BLURFX_SCREEN_OPTION_BLUR_SATURATION].value.f / 100.0;
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
}
// draw blur
if (iCount)
{
glDrawElements(GL_QUADS, iCount, GL_UNSIGNED_SHORT, indices);
GLERR;
}
else
{
glDrawArrays(GL_QUADS, 0, vCount);
GLERR;
}
// set all back to normal
if (s->canDoSlightlySaturated
&& bs->opt[BLURFX_SCREEN_OPTION_BLUR_SATURATION].value.f < 100.0)
{
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
disableBlurfxTexture(&bs->blurTempTexH);
actTex--;
(*s->activeTexture) (GL_TEXTURE0_ARB + actTex);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glDisable(GL_TEXTURE_GEN_R);
glDisable(GL_TEXTURE_GEN_Q);
disableBlurfxTexture(&bs->blurTempTexH);
actTex--;
(*s->activeTexture) (GL_TEXTURE0_ARB + actTex);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
disableBlurfxTexture(&bs->blurTempTexH);
actTex--;
(*s->activeTexture) (GL_TEXTURE0_ARB + actTex);
}
if (((mask & PAINT_WINDOW_DECORATION_MASK)
&& !bs->opt[BLURFX_SCREEN_OPTION_DISABLE_DECORATION_ALPHADEP].
value.b) || switcher
|| (!(mask & PAINT_WINDOW_DECORATION_MASK) && w->alpha))
{
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
disableTexture(s, texture);
GLERR;
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PREVIOUS);
glTexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1.0);
(*s->clientActiveTexture) (GL_TEXTURE0_ARB);
actTex--;
(*s->activeTexture) (GL_TEXTURE0_ARB + actTex);
}
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
glDisable(GL_TEXTURE_RECTANGLE_ARB);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glDisable(GL_TEXTURE_GEN_R);
glDisable(GL_TEXTURE_GEN_Q);
glDisable(GL_BLEND);
glPopMatrix();
GLERR;
}
static void
drawReflection(CompWindow * w, CompScreen * s, CompTexture * texture,
const WindowPaintAttrib * attrib, int mask,
CompTextureFilter filter)
{
int vCount, iCount;
GLfloat *vertices;
GLushort *indices;
float dx, dy;
BLURFX_SCREEN(w->screen);
BLURFX_WINDOW(w);
glPushMatrix();
if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
{
glTranslatef(w->attrib.x, w->attrib.y, 0.0f);
glScalef(attrib->xScale, attrib->yScale, 0.0f);
glTranslatef(attrib->xTranslate / attrib->xScale -
w->attrib.x,
attrib->yTranslate / attrib->yScale - w->attrib.y, 0.0f);
}
// setup reflection texture scaling
if (bs->opt[BLURFX_SCREEN_OPTION_REFLECTION_SCALE].value.b)
{
if (bs->opt[BLURFX_SCREEN_OPTION_REFLECTION_PROPORTIONAL].value.b)
{
dx = 1.0 /
(((s->width / bs->modTex.width) *
bs->modTex.height >
s->height) ? (s->height /
bs->modTex.height) *
bs->modTex.width : s->width);
dy = 1.0 /
(((s->width / bs->modTex.width) *
bs->modTex.height >
s->height) ? s->height : (s->width /
bs->modTex.width) *
bs->modTex.height);
}
else
{
dx = 1.0 / s->width;
dy = 1.0 / s->height;
}
}
else
{
dx = 1.0 / bs->modTex.width;
dy = 1.0 / bs->modTex.height;
}
// Do we have an decoration vertex array thet does not contain shadows?
if (mask & PAINT_WINDOW_DECORATION_MASK && bw->decoArray.vCount)
{
vertices = bw->decoArray.vertices + (w->texUnits * w->texCoordSize);
indices = bw->decoArray.indices;
vCount = bw->decoArray.vCount;
iCount = bw->decoArray.indexCount;
}
else
{
vertices = w->vertices + (w->texUnits * w->texCoordSize);
indices = w->indices;
vCount = w->vCount;
iCount = w->indexCount;
}
if (vCount <= 0)
return;
int stride = (w->texUnits * w->texCoordSize + 2) * sizeof(GLfloat);
// draw reflection only for visible regions
if (!(mask & PAINT_WINDOW_DECORATION_MASK) && !w->alpha
&& !(mask & PAINT_WINDOW_TRANSFORMED_MASK) && !w->shaded)
{
Region drawBlurRegion = XCreateRegion();
XIntersectRegion(w->region, bw->paintRegion, drawBlurRegion);
XSubtractRegion(drawBlurRegion, bw->clip, drawBlurRegion);
CompMatrix mat;
mat.xx = 0.0;
mat.yx = 0.0;
mat.xy = 0.0;
mat.yy = 0.0;
mat.x0 = 0.0;
mat.y0 = 0.0;
genGeometry(&bs->vertArray, mat, 0, drawBlurRegion);
stride = 4 * sizeof(GLfloat);
vCount = bs->vertArray.vCount;
iCount = 0;
vertices = bs->vertArray.vertices + 2;
XDestroyRegion(drawBlurRegion);
}
glVertexPointer(2, GL_FLOAT, stride, vertices);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
(*s->activeTexture) (GL_TEXTURE0_ARB);
enableBlurfxTexture(&bs->modTex, filter);
if (mask &
(PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK |
PAINT_WINDOW_TRANSFORMED_MASK))
{
// enable projective texture cooridinate generation
float bm[16] = { (s->width * dx) / 2.0, 0, 0, 0, 0,
(s->height * dy) / -2.0, 0,
0, 0, 0, 1, 0, (s->width * dx) / 2.0,
(s->height * dy) / 2.0, 1, 1
};
float bpm[16];
float tm[16];
float mvm[16];
glPushMatrix();
glLoadIdentity();
glTranslatef(-0.5f, -0.5f, -DEFAULT_Z_CAMERA);
glScalef(1.0f / s->width, -1.0f / s->height, 1.0f);
glTranslatef(0.0f, -s->height, 0.0f);
if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
{
glTranslatef(w->attrib.x, w->attrib.y, 0.0f);
glScalef(attrib->xScale, attrib->yScale, 0.0f);
glTranslatef(attrib->xTranslate / attrib->xScale -
w->attrib.x,
attrib->yTranslate / attrib->yScale -
w->attrib.y, 0.0f);
}
glGetFloatv(GL_MODELVIEW_MATRIX, mvm);
glPopMatrix();
MULTM(bm, bs->pm, bpm);
MULTM(bpm, mvm, tm);
float s_gen[4] = { tm[0], tm[4], tm[8], tm[12] };
float t_gen[4] = { tm[1], tm[5], tm[9], tm[13] };
float r_gen[4] = { tm[2], tm[6], tm[10], tm[14] };
float q_gen[4] = { tm[3], tm[7], tm[11], tm[15] };
glTexGenfv(GL_T, GL_OBJECT_PLANE, t_gen);
glTexGenfv(GL_S, GL_OBJECT_PLANE, s_gen);
glTexGenfv(GL_R, GL_OBJECT_PLANE, r_gen);
glTexGenfv(GL_Q, GL_OBJECT_PLANE, q_gen);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
glEnable(GL_TEXTURE_GEN_Q);
}
else
{
// enable texture cooridinate generation
float s_gen[4] = { dx, 0.0, 0.0, 0.0 };
float t_gen[4] = { 0.0, dy, 0.0, 0.0 };
glTexGenfv(GL_T, GL_OBJECT_PLANE, t_gen);
glTexGenfv(GL_S, GL_OBJECT_PLANE, s_gen);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
}
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glColor4f(1.0, 1.0, 1.0, attrib->opacity / 65535.0f);
// simple switcher detection hack
Bool switcher = FALSE;
if (w->resName == 0 && w->resClass == 0
&& (mask & PAINT_WINDOW_DECORATION_MASK)
&& screenGrabExist(s, "switcher", 0))
switcher = TRUE;
// we need alpha dependend reflection if window has alpha channel
if (((mask & PAINT_WINDOW_DECORATION_MASK)
&& !bs->opt[BLURFX_SCREEN_OPTION_DISABLE_DECORATION_ALPHADEP].
value.b) || switcher
|| (!(mask & PAINT_WINDOW_DECORATION_MASK) && w->alpha))
{
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PRIMARY_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
(*s->activeTexture) (GL_TEXTURE1_ARB);
enableTexture(s, texture, filter);
GLERR;
glDisable(GL_TEXTURE_GEN_T);
glDisable(GL_TEXTURE_GEN_S);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
(*s->clientActiveTexture) (GL_TEXTURE1_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, stride,
vertices - (w->texUnits * w->texCoordSize));
}
else
{
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PRIMARY_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
}
// draw reflection
if (iCount)
{
glDrawElements(GL_QUADS, iCount, GL_UNSIGNED_SHORT, indices);
GLERR;
}
else
{
glDrawArrays(GL_QUADS, 0, vCount);
GLERR;
}
// set all back to normal
if (((mask & PAINT_WINDOW_DECORATION_MASK)
&& !bs->opt[BLURFX_SCREEN_OPTION_DISABLE_DECORATION_ALPHADEP].
value.b) || switcher
|| (!(mask & PAINT_WINDOW_DECORATION_MASK) && w->alpha))
{
disableTexture(s, texture);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PREVIOUS);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
(*s->clientActiveTexture) (GL_TEXTURE0_ARB);
(*s->activeTexture) (GL_TEXTURE0_ARB);
}
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PREVIOUS);
disableBlurfxTexture(&bs->modTex);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glDisable(GL_TEXTURE_GEN_R);
glDisable(GL_TEXTURE_GEN_Q);
glPopMatrix();
glDisable(GL_BLEND);
}
// activate/deactivate motion blur
static Bool
blurfxToggleMotionBlur(CompDisplay * d, CompAction * ac,
CompActionState state, CompOption * option,
int nOption)
{
CompScreen *s;
s = findScreenAtDisplay(d, getIntOptionNamed(option, nOption, "root", 0));
if (s)
{
BLURFX_SCREEN(s);
bs->mb_activated = !bs->mb_activated;
bs->mb_activated &= bs->mblur_supported;
}
return FALSE;
}
// bind our fbo and bind the texture to it
static Bool bindFbo(CompScreen * s, BlurTexture tex)
{
BLURFX_SCREEN(s);
GLERR;
(*s->bindFramebuffer) (GL_FRAMEBUFFER_EXT, bs->fbo);
(*s->framebufferTexture2D) (GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_RECTANGLE_ARB, tex.handle, 0);
if (!bs->fboStatus)
{
bs->fboStatus = (*s->checkFramebufferStatus) (GL_FRAMEBUFFER_EXT);
if (bs->fboStatus != GL_FRAMEBUFFER_COMPLETE_EXT)
{
(*s->bindFramebuffer) (GL_FRAMEBUFFER_EXT, 0);
s->bindRenderbuffer(GL_RENDERBUFFER_EXT, 0);
printf("Framebuffer attach failed\n");
bs->fboStatus = 0;
bs->fboActive = FALSE;
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glDepthRange(0, 1);
glViewport(-1, -1, 2, 2);
glRasterPos2f(0, 0);
s->rasterX = s->rasterY = 0;
glViewport(s->outputDev[bs->output].region.extents.x1,
s->height - s->outputDev[bs->output].region.extents.y2,
s->outputDev[bs->output].width,
s->outputDev[bs->output].height);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glDrawBuffer(GL_BACK);
glReadBuffer(GL_BACK);
return FALSE;
}
}
//Set the draw buffer
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glDepthRange(0, 1);
glViewport(-1, -1, 2, 2);
glRasterPos2f(0, 0);
glViewport(s->outputDev[bs->output].region.extents.x1,
s->height - s->outputDev[bs->output].region.extents.y2,
s->outputDev[bs->output].width,
s->outputDev[bs->output].height);
prepareXCoords(s, bs->output, -DEFAULT_Z_CAMERA);
bs->fboActive = TRUE;
GLERR;
return TRUE;
}
// unbind the fbo and set everything back to normal
static void unbindFbo(CompScreen * s)
{
BLURFX_SCREEN(s);
if (!bs->fboActive)
return;
GLERR;
// unbind fbo
(*s->bindFramebuffer) (GL_FRAMEBUFFER_EXT, 0);
// set alles back to normal
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDepthRange(0, 1);
glViewport(-1, -1, 2, 2);
glRasterPos2f(0, 0);
s->rasterX = s->rasterY = 0;
glViewport(s->outputDev[bs->output].region.extents.x1,
s->height - s->outputDev[bs->output].region.extents.y2,
s->outputDev[bs->output].width,
s->outputDev[bs->output].height);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glDrawBuffer(GL_BACK);
glReadBuffer(GL_BACK);
bs->fboActive = FALSE;
GLERR;
}
// generate a vertex and coordinate aray for the given region
static void
genGeometry(BlurfxVertArray * vA, CompMatrix matrix, int xextend,
Region region)
{
BoxPtr pBox;
int nBox;
int vSize;
int n, x1, y1, x2, y2;
GLfloat *d;
pBox = region->rects;
nBox = region->numRects;
vSize = 4;
n = 0;
if (nBox * vSize * 4 > vA->vertexSize)
{
if (!moreVertices(vA, nBox * vSize * 4))
return;
}
d = vA->vertices;
while (nBox--)
{
x1 = pBox->x1 - xextend;
y1 = pBox->y1;
x2 = pBox->x2 + xextend;
y2 = pBox->y2;
pBox++;
if (x1 < x2 && y1 < y2)
{
BFX_ADD_RECT(d, matrix, x1, y1, x2, y2);
n++;
}
}
vA->vCount = n * 4;
}
// helper function for genGeometry
static Bool moreVertices(BlurfxVertArray * vA, int newSize)
{
if (newSize > vA->vertexSize)
{
GLfloat *vertices;
vertices = realloc(vA->vertices, sizeof(GLfloat) * newSize);
if (!vertices)
return FALSE;
vA->vertices = vertices;
vA->vertexSize = newSize;
}
return TRUE;
}
// does opengl level iniliazation of the screen
static void
initBlurfxScreen(BlurfxScreen * bs, int Screenwidth, int Screenheight,
CompScreen * s)
{
bs->blurShaderV = 0;
bs->blurShaderH = 0;
bs->backTex.handle = 0;
bs->blurTempTexV.handle = 0;
bs->blurTempTexH.handle = 0;
bs->motionTex.handle = 0;
bs->fbo = 0;
if (bs->fboBlur_supported
&& !bs->opt[BLURFX_SCREEN_OPTION_FORCE_NON_FBO_BLUR].value.b)
{
// load shaders
loadShader(GL_FRAGMENT_PROGRAM_ARB, s, &bs->blurShaderV,
blurShader[bs->blur_shader][0]);
loadShader(GL_FRAGMENT_PROGRAM_ARB, s, &bs->blurShaderH,
blurShader[bs->blur_shader][1]);
bs->downSample = 1.0;
}
if (bs->blur_supported)
{
genBlurTexture(bs, &bs->blurTempTexV, Screenwidth, Screenheight, 0);
genBlurTexture(bs, &bs->blurTempTexH, Screenwidth, Screenheight, 0);
}
//Generate a fbo
if (s->fbo)
{
(*s->genFramebuffers) (1, &bs->fbo);
GLERR;
bs->fboStatus = 0;
// generate textures
genBlurTexture(bs, &bs->backTex, Screenwidth, Screenheight, 1);
}
if (bs->mblur_supported && bs->mb_mode != 1)
{
// generate morion blur texture
genBlurTexture(bs, &bs->motionTex, Screenwidth,
Screenheight, bs->mb_mode);
}
bs->modTex.handle = 0;
if (bs->reflection_supported)
{
// load reflection map
loadPngToTexture2D(s, &bs->modTex,
bs->
opt[BLURFX_SCREEN_OPTION_REFLECTION_FILE].value.s);
}
bs->hasInit = 1;
}
// generate texture
static void
genBlurTexture(BlurfxScreen * bs, BlurTexture * tex, int width, int height,
int type)
{
GLERR;
//Enable texturing
glEnable(GL_TEXTURE_RECTANGLE_ARB);
//Generate the OpenGL textures
if (!tex->handle)
glGenTextures(1, &tex->handle);
//Write important info into the structure
tex->width = width;
tex->height = height;
//Bind the texture
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex->handle);
//Load the parameters
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
GL_LINEAR);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
GL_LINEAR);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
tex->target = GL_TEXTURE_RECTANGLE_ARB;
tex->active_filter = GL_LINEAR;
//Generate a large image
switch (type)
{
case 1:
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, width,
height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
break;
case 2:
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB16F_ARB,
width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
break;
case 0:
default:
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, width,
height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
break;
}
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
glDisable(GL_TEXTURE_RECTANGLE_ARB);
GLERR;
}
// load shader
static void
loadShader(GLenum type, CompScreen * s, GLuint * shader, const char *prog)
{
//Switch a bunch of strings
char buffer[4096];
sprintf(buffer, prog);
int errorPos, errorNum;
glGetError();
//Load the fragment program
if (*shader == 0)
(*s->genPrograms) (1, shader);
(*s->bindProgram) (type, *shader);
(*s->programString) (type, GL_PROGRAM_FORMAT_ASCII_ARB,
strlen(buffer), buffer);
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);
errorNum = glGetError();
if (errorNum != GL_NO_ERROR || errorPos != -1)
{
fprintf(stderr,
"%s: (0x%X) error loading fragment program at line: %d\n",
getProgramName(), errorNum, errorPos);
fprintf(stderr, "%s\n", glGetString(GL_PROGRAM_ERROR_STRING_ARB));
glGetIntegerv(GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &errorPos);
if (*shader)
(*s->deletePrograms) (1, shader);
*shader = 0;
}
(*s->bindProgram) (type, 0);
}
// load png
static void
loadPngToTexture2D(CompScreen * s, BlurTexture * tex, char *filename)
{
int img_w = 0, img_h = 0, stride = 0;
char *img_data;
char *img_mod;
struct stat fInfo;
int i = 0;
float Y, R, G, B;
int pix;
BLURFX_SCREEN(s);
if (strlen(filename) == 0)
return;
GLERR;
if (stat(filename, &fInfo) ||
!S_ISREG(fInfo.st_mode) ||
S_ISDIR(fInfo.st_mode) || access(filename, F_OK) != 0)
{
fprintf(stderr, "Unable to read image \"%s\" \n", filename);
return;
}
fprintf(stderr, "Loading image \"%s\" \n", filename);
// Was: readPng(filename, &img_data, &img_w, &img_h);
if (!(*s->display->fileToImage)
(s->display, NULL, filename, &img_w, &img_h, &stride,
(void *)&img_data))
{
printf("Unable to load image \"%s\" \n", filename);
return;
}
printf("%s loaded. w: %i; h: %i\n", filename, img_w, img_h);
//Generate the OpenGL textures
if (tex->handle == 0)
glGenTextures(1, &tex->handle);
glEnable(GL_TEXTURE_2D);
//Bind the texture
glBindTexture(GL_TEXTURE_2D, tex->handle);
//Load the parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
tex->target = GL_TEXTURE_2D;
tex->active_filter = GL_LINEAR;
tex->width = img_w;
tex->height = img_h;
// merge all colors to an alpha texture if not disabled
img_mod = malloc(img_w * img_h * 4);
for (i = 0; i < img_w * img_h; i++)
{
R = img_data[(i * 4) + 2];
G = img_data[(i * 4) + 1];
B = img_data[i * 4];
Y = (R * 0.299) + (G * 0.587) + (B * 0.114);
pix = Y;
img_mod[i * 4] =
(bs->
opt[BLURFX_SCREEN_OPTION_REFLECTION_USE_IMAGE_COLOR].
value.b) ? img_data[(i * 4) + 2] : (char)pix;
img_mod[(i * 4) + 1] =
(bs->
opt[BLURFX_SCREEN_OPTION_REFLECTION_USE_IMAGE_COLOR].
value.b) ? img_data[(i * 4) + 1] : (char)pix;
img_mod[(i * 4) + 2] =
(bs->
opt[BLURFX_SCREEN_OPTION_REFLECTION_USE_IMAGE_COLOR].
value.b) ? img_data[i * 4] : (char)pix;
img_mod[(i * 4) + 3] =
(bs->
opt[BLURFX_SCREEN_OPTION_REFLECTION_USE_IMAGE_ALPHA].
value.b) ? img_data[(i * 4) + 3] : (char)pix;
}
glTexImage2D(GL_TEXTURE_2D, 0, 4, img_w, img_h, 0, GL_RGBA,
GL_UNSIGNED_BYTE, img_mod);
GLERR;
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
free(img_mod);
free(img_data);
}
// enable texture and set filter
static void enableBlurfxTexture(BlurTexture * tex, CompTextureFilter filter)
{
glEnable(tex->target);
glBindTexture(tex->target, tex->handle);
GLERR;
switch (filter)
{
case COMP_TEXTURE_FILTER_FAST:
if (tex->active_filter != GL_NEAREST)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
tex->active_filter = GL_NEAREST;
}
break;
case COMP_TEXTURE_FILTER_GOOD:
default:
if (tex->active_filter != GL_LINEAR)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
tex->active_filter = GL_LINEAR;
}
break;
}
}
// disable texture
static void disableBlurfxTexture(BlurTexture * tex)
{
glBindTexture(tex->target, 0);
GLERR;
glDisable(tex->target);
}
// switch to another texture and set filter
static void
switchBlurfxTexture(BlurTexture * from, BlurTexture * to,
CompTextureFilter filter)
{
if (from->target != to->target)
{
disableBlurfxTexture(from);
enableBlurfxTexture(to, filter);
}
glBindTexture(to->target, to->handle);
GLERR;
switch (filter)
{
case COMP_TEXTURE_FILTER_FAST:
if (to->active_filter != GL_NEAREST)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
to->active_filter = GL_NEAREST;
}
break;
case COMP_TEXTURE_FILTER_GOOD:
default:
if (to->active_filter != GL_LINEAR)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
to->active_filter = GL_LINEAR;
}
break;
}
}
syntax highlighted by Code2HTML, v. 0.9.1