[compiz] Re: [PATCH] Transparent cube

Roi Cohen roico.beryl at gmail.com
Mon May 7 11:24:20 PDT 2007


Hi.

I re-created my patches to work on latest git, and use the order system.
David, what do you think of these patches now?

Regards,
Roi.

On 5/4/07, David Reveman <davidr at novell.com> wrote:
> On Tue, 2007-05-01 at 23:06 +0200, Dennis Kasprzyk wrote:
> > Am Dienstag, 1. Mai 2007 22:54 schrieben Sie:
> > > On Tue, 2007-05-01 at 23:29 +0300, Roi Cohen wrote:
> > > > Hi David.
> > > >
> > > > I thought about your suggestion a bit more, and i think it has a
> > > > problem, although it's a bit hard to explain it.
> > > > How will plugins exactly wrap this function? I mean, obviously they
> > > > will just call the WRAP / UNWRAP macros, but what i'm asking is, what
> > > > will they actually do inside this function?
> > > > I guess it needs to be something like this:
> > > >
> > > > nextInStack(w)
> > > > {
> > > >   if (Plugin makes an effect and needs to change order)
> > > >           return next;
> > > >
> > > >   UNWRAP;
> > > >   call;
> > > >   WRAP;
> > > > }
> > > >
> > > > If one plugin needs to change painting order, plugins loaded before it
> > > > won't get the chance to change their painting order.
> > > >
> > > > 3D and cube will still work together, but only because of "luck" - 3d
> > > > needs to be loaded before cube (it needs the openGL matrices of the
> > > > cube's transformations to know how to reorder the painting) which
> > > > means that theoretically, 3d's paint order won't be executed. However,
> > > > it will work because 3d doesn't need to change painting order for ftb
> > > > faces, and cube doesn't need to change painting order for btf faces.
> > > > Again, I consider this as a "lucky coincidence", both 3d and cube will
> > > > work, but it shows why I think wrapping this function is somewhat
> > > > problematic.
> > > >
> > > > Dennis Kasprzyk suggested another approach to this problem - instead
> > > > of wrapping this function, we will pass another argument to
> > > > paintTransformedScreen which is:
> > > > struct CompWindowListSort {
> > > >   // Function pointers
> > > >   FirstInStackProc* first;
> > > >   LastInStackProc* last;
> > > >
> > > >   NextInStackProc* next;
> > > >   PrevInStackProc* prev;
> > > > }
> > > > This way, plugins won't wrap this function, and the plugin which is
> > > > loaded first gets the call on painting order, instead of the last
> > > > plugin which is loaded last.
> > > > It fixes the problem with 3d and transcube - 3d's paint order will
> > > > always be prefered over cube's one.
> > > > I'm not really sure this is the best solution - there isn't really a
> > > > reason to prefer the first loaded plugin over the last loaded one.
> > > >
> > > > Do you think we should stay with your original idea, ignoring the
> > > > problems that will occur when 2 different plugins want to change
> > > > painting order (after all, similar problems occur with window
> > > > transformations etc), or do you have another idea?
> > >
> > > Yes, maybe it's better to just require a depth buffer and destination
> > > alpha for these kind of effects and construct an proper interface for
> > > that instead.
> > >
> > > - David
> >
> > But this could also cause problems with something like skydome. I think that
> > every solution can cause problems with other plugins, but I think it is
> > better to add a solution that will not add additional dependencies. And I
> > think that the order change system is more flexible so that we could use it
> > for another effects later.
>
> I fail to see how it could cause problems with the skydome but using
> destination alpha is definitely not going to work with the blur plugin.
> We're going to have to address the problem with drawing intersecting
> translucent objects at some point but as we don't have a perfect
> solution for that yet, the order system seem like a good idea to start
> with.
>
> - David
>
> _______________________________________________
> compiz mailing list
> compiz at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/compiz
>
-------------- next part --------------
From 811af5fbc5da120d8c2c9a944d4b6f6ca207ae94 Mon Sep 17 00:00:00 2001
From: Roi Cohen <roico at roico-desktop.(none)>
Date: Mon, 7 May 2007 19:32:38 +0300
Subject: [PATCH] painting order interface

---
 include/compiz.h |   25 ++++++++++++++++++++++++-
 src/paint.c      |   28 ++++++++++++++++++++++++++--
 src/screen.c     |    6 ++++++
 3 files changed, 56 insertions(+), 3 deletions(-)

diff --git a/include/compiz.h b/include/compiz.h
index 5e52c8c..22a8bed 100644
--- a/include/compiz.h
+++ b/include/compiz.h
@@ -26,7 +26,7 @@
 #ifndef _COMPIZ_H
 #define _COMPIZ_H
 
-#define ABIVERSION 20070506
+#define ABIVERSION 20070507
 
 #include <stdio.h>
 #include <sys/time.h>
@@ -1193,6 +1193,11 @@ typedef void (*ApplyScreenTransformProc) (CompScreen		  *screen,
 					  int			  output,
 					  CompTransform	          *transform);
 
+typedef CompWindow* (*StackFirstProc) (CompScreen *screen);
+typedef CompWindow* (*StackLastProc) (CompScreen *screen);
+
+typedef CompWindow* (*StackNextProc) (CompWindow *window);
+typedef CompWindow* (*StackPrevProc) (CompWindow *window);
 /*
   window paint flags
 
@@ -1308,6 +1313,18 @@ applyScreenTransform (CompScreen	      *screen,
 		      int		      output,
 		      CompTransform	      *transform);
 
+CompWindow*
+stackFirst (CompScreen* screen);
+
+CompWindow*
+stackLast (CompScreen* screen);
+
+CompWindow*
+stackNext (CompWindow* window);
+
+CompWindow*
+stackPrev (CompWindow* window);
+
 Bool
 paintScreen (CompScreen		     *screen,
 	     const ScreenPaintAttrib *sAttrib,
@@ -1965,6 +1982,12 @@ struct _CompScreen {
     WindowStateChangeNotifyProc windowStateChangeNotify;
 
     OutputChangeNotifyProc outputChangeNotify;
+    
+    StackFirstProc stackFirst;
+    StackLastProc  stackLast;
+
+    StackNextProc  stackNext;
+    StackPrevProc  stackPrev;
 
     CompPrivate *privates;
 };
diff --git a/src/paint.c b/src/paint.c
index 39bcacc..b736cdf 100644
--- a/src/paint.c
+++ b/src/paint.c
@@ -185,7 +185,7 @@ paintScreenRegion (CompScreen	       *screen,
     XSubtractRegion (region, &emptyRegion, tmpRegion);
 
     /* detect occlusions */
-    for (w = screen->reverseWindows; w; w = w->prev)
+    for (w = (*screen->stackLast) (screen); w; w = (*screen->stackPrev) (w))
     {
 	if (w->destroyed)
 	    continue;
@@ -221,7 +221,7 @@ paintScreenRegion (CompScreen	       *screen,
     (*screen->paintBackground) (screen, tmpRegion, backgroundMask);
 
     /* paint all windows from bottom to top */
-    for (w = screen->windows; w; w = w->next)
+    for (w = (*screen->stackFirst) (screen); w; w = (*screen->stackNext) (w))
     {
 	if (w->destroyed)
 	    continue;
@@ -378,6 +378,30 @@ paintScreen (CompScreen		     *screen,
     return TRUE;
 }
 
+CompWindow*
+stackFirst (CompScreen* screen)
+{
+    return screen->windows;
+}
+
+CompWindow*
+stackLast (CompScreen* screen)
+{
+    return screen->reverseWindows;
+}
+
+CompWindow*
+stackNext (CompWindow* window)
+{
+    return window->next;
+}
+
+CompWindow*
+stackPrev (CompWindow* window)
+{
+    return window->prev;
+}
+
 #define ADD_RECT(data, m, n, x1, y1, x2, y2)	   \
     for (it = 0; it < n; it++)			   \
     {						   \
diff --git a/src/screen.c b/src/screen.c
index d73ceb4..469e437 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -1540,6 +1540,12 @@ addScreen (CompDisplay *display,
     s->windowStateChangeNotify = windowStateChangeNotify;
 
     s->outputChangeNotify = outputChangeNotify;
+    
+    s->stackFirst = stackFirst;
+    s->stackLast = stackLast;
+    
+    s->stackNext = stackNext;
+    s->stackPrev = stackPrev;
 
     s->getProcAddress = 0;
 
-- 
1.4.4.2
-------------- next part --------------
From 79860acf804a17bd826b13b3436ed63308d3146b Mon Sep 17 00:00:00 2001
From: Roi Cohen <roico at roico-desktop.(none)>
Date: Mon, 7 May 2007 19:32:59 +0300
Subject: [PATCH] set clip planes

---
 include/compiz.h |   11 ++++++++++-
 plugins/cube.c   |   38 ++++++++++++++++++++++++++++++++++++++
 src/paint.c      |   45 +++++++++++++++++++++++++--------------------
 src/screen.c     |    1 +
 4 files changed, 74 insertions(+), 21 deletions(-)

diff --git a/include/compiz.h b/include/compiz.h
index 22a8bed..8e29d93 100644
--- a/include/compiz.h
+++ b/include/compiz.h
@@ -26,7 +26,7 @@
 #ifndef _COMPIZ_H
 #define _COMPIZ_H
 
-#define ABIVERSION 20070507
+#define ABIVERSION 20070508
 
 #include <stdio.h>
 #include <sys/time.h>
@@ -1279,6 +1279,10 @@ typedef void (*PaintBackgroundProc) (CompScreen   *screen,
 				     Region	  region,
 				     unsigned int mask);
 
+typedef void (*SetClipPlanesProc) (CompScreen *screen,
+                                   Region region,
+                                   int output);
+
 void
 preparePaintScreen (CompScreen *screen,
 		    int	       msSinceLastPaint);
@@ -1379,6 +1383,10 @@ paintBackground (CompScreen   *screen,
 		 Region	      region,
 		 unsigned int mask);
 
+void setClipPlanes (CompScreen *screen, 
+                    Region region,
+                    int output);
+
 
 /* texture.c */
 
@@ -1958,6 +1966,7 @@ struct _CompScreen {
     PaintTransformedScreenProc	   paintTransformedScreen;
     ApplyScreenTransformProc	   applyScreenTransform;
     PaintBackgroundProc		   paintBackground;
+    SetClipPlanesProc              setClipPlanes;
     PaintWindowProc		   paintWindow;
     DrawWindowProc		   drawWindow;
     AddWindowGeometryProc	   addWindowGeometry;
diff --git a/plugins/cube.c b/plugins/cube.c
index 833d33e..a4767ac 100644
--- a/plugins/cube.c
+++ b/plugins/cube.c
@@ -87,6 +87,7 @@ typedef struct _CubeScreen {
     ApplyScreenTransformProc   applyScreenTransform;
     SetScreenOptionProc	       setScreenOption;
     OutputChangeNotifyProc     outputChangeNotify;
+    SetClipPlanesProc          setClipPlanes;
 
     CompOption opt[CUBE_SCREEN_OPTION_NUM];
 
@@ -1526,6 +1527,41 @@ cubePaintBackground (CompScreen   *s,
     }
 }
 
+static void cubeSetClipPlanes (CompScreen *s, Region region, int output)
+{
+    CUBE_SCREEN(s);
+
+    glTranslatef(cs->outputXOffset, -cs->outputYOffset, 0.0f);
+    glScalef( cs->outputXScale, cs->outputYScale, 1.0f);
+
+    UNWRAP(cs, s, setClipPlanes);
+    (*s->setClipPlanes) (s, region, output);
+    WRAP(cs, s, setClipPlanes, cubeSetClipPlanes);
+
+    if (cs->invert == 1)
+    {
+	GLdouble clipPlane0[] = { 1.0, 0.0, 0.5 / cs->distance, 0.0 };
+	GLdouble clipPlane1[] = { -1.0,  0.0, 0.5 / cs->distance, 0.0 };
+	GLdouble clipPlane2[] = { 0.0,  -1.0, 0.5 / cs->distance, 0.0 };
+	GLdouble clipPlane3[] = { 0.0,  1.0, 0.5 / cs->distance, 0.0 };
+	glClipPlane (GL_CLIP_PLANE0, clipPlane0);
+	glClipPlane (GL_CLIP_PLANE1, clipPlane1);
+	glClipPlane (GL_CLIP_PLANE2, clipPlane2);
+	glClipPlane (GL_CLIP_PLANE3, clipPlane3);
+    }
+    else
+    {
+	GLdouble clipPlane0[] = { -1.0, 0.0, -0.5 / cs->distance, 0.0 };
+	GLdouble clipPlane1[] = { 1.0,  0.0, -0.5 / cs->distance, 0.0 };
+	GLdouble clipPlane2[] = { 0.0,  1.0, -0.5 / cs->distance, 0.0 };
+	GLdouble clipPlane3[] = { 0.0,  -1.0, -0.5 / cs->distance, 0.0 };
+	glClipPlane (GL_CLIP_PLANE0, clipPlane0);
+	glClipPlane (GL_CLIP_PLANE1, clipPlane1);
+	glClipPlane (GL_CLIP_PLANE2, clipPlane2);
+	glClipPlane (GL_CLIP_PLANE3, clipPlane3);
+    }
+}
+
 static void
 cubeApplyScreenTransform (CompScreen		  *s,
 			  const ScreenPaintAttrib *sAttrib,
@@ -1901,6 +1937,7 @@ cubeInitScreen (CompPlugin *p,
     WRAP (cs, s, applyScreenTransform, cubeApplyScreenTransform);
     WRAP (cs, s, setScreenOption, cubeSetGlobalScreenOption);
     WRAP (cs, s, outputChangeNotify, cubeOutputChangeNotify);
+    WRAP (cs, s, setClipPlanes, cubeSetClipPlanes);
 
     return TRUE;
 }
@@ -1922,6 +1959,7 @@ cubeFiniScreen (CompPlugin *p,
     UNWRAP (cs, s, applyScreenTransform);
     UNWRAP (cs, s, setScreenOption);
     UNWRAP (cs, s, outputChangeNotify);
+    UNWRAP (cs, s, setClipPlanes);
 
     finiTexture (s, &cs->texture);
     finiTexture (s, &cs->sky);
diff --git a/src/paint.c b/src/paint.c
index b736cdf..a4679e0 100644
--- a/src/paint.c
+++ b/src/paint.c
@@ -266,29 +266,10 @@ paintTransformedScreen (CompScreen		*screen,
 
     if ((mask & CLIP_PLANE_MASK) == CLIP_PLANE_MASK)
     {
-	GLdouble h = screen->height;
-
-	GLdouble p1[2] = { region->extents.x1, h - region->extents.y2 };
-	GLdouble p2[2] = { region->extents.x2, h - region->extents.y1 };
-
-	GLdouble halfW = screen->outputDev[output].width / 2.0;
-	GLdouble halfH = screen->outputDev[output].height / 2.0;
-
-	GLdouble cx = screen->outputDev[output].region.extents.x1 + halfW;
-	GLdouble cy = (h - screen->outputDev[output].region.extents.y2) + halfH;
-
-	GLdouble top[4]    = { 0.0, halfH / (cy - p1[1]), 0.0, 0.5 };
-	GLdouble bottom[4] = { 0.0, halfH / (cy - p2[1]), 0.0, 0.5 };
-	GLdouble left[4]   = { halfW / (cx - p1[0]), 0.0, 0.0, 0.5 };
-	GLdouble right[4]  = { halfW / (cx - p2[0]), 0.0, 0.0, 0.5 };
-
 	glPushMatrix ();
 	glLoadMatrixf (sTransform.m);
 
-	glClipPlane (GL_CLIP_PLANE0, top);
-	glClipPlane (GL_CLIP_PLANE1, bottom);
-	glClipPlane (GL_CLIP_PLANE2, left);
-	glClipPlane (GL_CLIP_PLANE3, right);
+	(*screen->setClipPlanes) (screen, region, output);
 
 	glEnable (GL_CLIP_PLANE0);
 	glEnable (GL_CLIP_PLANE1);
@@ -1185,3 +1166,27 @@ paintBackground (CompScreen   *s,
 
     free (data);
 }
+
+void setClipPlanes (CompScreen *screen, Region region, int output)
+{
+    GLdouble h = screen->height;
+
+    GLdouble p1[2] = { region->extents.x1, h - region->extents.y2 };
+    GLdouble p2[2] = { region->extents.x2, h - region->extents.y1 };
+
+    GLdouble halfW = screen->outputDev[output].width / 2.0;
+    GLdouble halfH = screen->outputDev[output].height / 2.0;
+
+    GLdouble cx = screen->outputDev[output].region.extents.x1 + halfW;
+    GLdouble cy = (h - screen->outputDev[output].region.extents.y2) + halfH;
+
+    GLdouble top[4]    = { 0.0, halfH / (cy - p1[1]), 0.0, 0.5 };
+    GLdouble bottom[4] = { 0.0, halfH / (cy - p2[1]), 0.0, 0.5 };
+    GLdouble left[4]   = { halfW / (cx - p1[0]), 0.0, 0.0, 0.5 };
+    GLdouble right[4]  = { halfW / (cx - p2[0]), 0.0, 0.0, 0.5 };
+
+    glClipPlane (GL_CLIP_PLANE0, top);
+    glClipPlane (GL_CLIP_PLANE1, bottom);
+    glClipPlane (GL_CLIP_PLANE2, left);
+    glClipPlane (GL_CLIP_PLANE3, right);
+}
diff --git a/src/screen.c b/src/screen.c
index 469e437..0155bad 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -1516,6 +1516,7 @@ addScreen (CompDisplay *display,
     s->paintTransformedScreen	  = paintTransformedScreen;
     s->applyScreenTransform	  = applyScreenTransform;
     s->paintBackground		  = paintBackground;
+    s->setClipPlanes		  = setClipPlanes;
     s->paintWindow		  = paintWindow;
     s->drawWindow		  = drawWindow;
     s->addWindowGeometry	  = addWindowGeometry;
-- 
1.4.4.2
-------------- next part --------------
From 9d48207f553f39287e0f083ad2e3e6c8940f6ad8 Mon Sep 17 00:00:00 2001
From: Roi Cohen <roico at roico-desktop.(none)>
Date: Mon, 7 May 2007 19:33:33 +0300
Subject: [PATCH] plugin events

---
 plugins/cube.c   |  102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 plugins/rotate.c |   30 ++++++++++++++++
 2 files changed, 132 insertions(+), 0 deletions(-)

diff --git a/plugins/cube.c b/plugins/cube.c
index a4767ac..9ba05e1 100644
--- a/plugins/cube.c
+++ b/plugins/cube.c
@@ -46,6 +46,13 @@
 
 #include <compiz.h>
 
+typedef enum _RotationMode
+{
+    NoRotation = 0,
+    RotationChange,
+    RotationManual
+} RotationMode;
+
 static CompMetadata cubeMetadata;
 
 #define CUBE_DISPLAY_OPTION_UNFOLD 0
@@ -59,6 +66,8 @@ typedef struct _CubeDisplay {
     int	screenPrivateIndex;
 
     CompOption opt[CUBE_DISPLAY_OPTION_NUM];
+    
+    HandleCompizEventProc handleCompizEvent;
 } CubeDisplay;
 
 #define CUBE_SCREEN_OPTION_COLOR	      0
@@ -121,11 +130,15 @@ typedef struct _CubeScreen {
     Bool cleared[64];
 
     Bool fullscreenOutput;
+    RotationMode rotationMode;
 
     float outputXScale;
     float outputYScale;
     float outputXOffset;
     float outputYOffset;
+    
+    Bool disableCaps;
+    Bool paintAllViewports;
 
     CompTexture *bg;
     int		nBg;
@@ -1582,6 +1595,85 @@ cubeApplyScreenTransform (CompScreen		  *s,
     matrixTranslate (transform, -cs->outputXOffset, cs->outputYOffset, 0.0f);
 }
 
+static void cubeHandleCompizEvent(CompDisplay * d, char *pluginName,
+				  char *eventName, CompOption * option, int nOption)
+{
+    CUBE_DISPLAY(d);
+
+    UNWRAP (cd, d, handleCompizEvent);
+    (*d->handleCompizEvent) (d, pluginName, eventName, option, nOption);
+    WRAP (cd, d, handleCompizEvent, cubeHandleCompizEvent);
+	
+    if (strcmp(pluginName, "3d") == 0)
+    {
+	if (strcmp(eventName, "disableCapsEvent") == 0)
+	{
+	    Window xid = getIntOptionNamed(option, nOption, "root", 0);
+	    CompScreen *s = findScreenAtDisplay(d, xid);
+
+	    if (s)
+	    {
+		CUBE_SCREEN(s);
+		cs->disableCaps = getBoolOptionNamed(option, nOption, "disableCaps", FALSE);
+	    }
+	}
+	
+	else if (strcmp(eventName, "paintAllViewportsEvent") == 0)
+	{
+	    Window xid = getIntOptionNamed(option, nOption, "root", 0);
+	    CompScreen *s = findScreenAtDisplay(d, xid);
+
+	    if (s)
+	    {
+		CUBE_SCREEN(s);
+		cs->paintAllViewports = getBoolOptionNamed(option, nOption, "paintAllViewports", FALSE);
+	    }
+	}
+    }
+    if (strcmp(pluginName, "rotate") == 0)
+    {
+	if (strcmp(eventName, "rotateEvent") == 0)
+	{
+	    Window xid = getIntOptionNamed(option, nOption, "root", 0);
+	    CompScreen *s = findScreenAtDisplay(d, xid);
+
+	    if (s)
+	    {
+		CUBE_SCREEN(s);
+		Bool rotate = getBoolOptionNamed(option, nOption, "rotating", FALSE);
+		Bool manual = getBoolOptionNamed(option, nOption, "manual", FALSE);
+
+		if (rotate && manual)
+		    cs->rotationMode = RotationManual;
+		else if (rotate)
+		    cs->rotationMode = RotationChange;
+		else
+		    cs->rotationMode = NoRotation;
+		damageScreen(s);
+	    }
+	}
+    }
+}
+
+static void
+cubeFoldEvent(CompScreen *s, Bool unfolded)
+{
+    CompOption o[2];
+    
+    o[0].type = CompOptionTypeInt;
+    o[0].name = "root";
+    o[0].value.i = s->root;
+
+    o[1].type = CompOptionTypeBool;
+    o[1].name = "unfolded";
+    o[1].value.b = unfolded;
+
+    (*s->display->handleCompizEvent) (s->display, 
+                                      "cube", 
+                                      "unfoldEvent", 
+                                      o, 2);
+}
+
 static Bool
 cubeUnfold (CompDisplay     *d,
 	    CompAction      *action,
@@ -1611,6 +1703,7 @@ cubeUnfold (CompDisplay     *d,
 	if (cs->grabIndex)
 	{
 	    cs->unfolded = TRUE;
+	    cubeFoldEvent (s, TRUE);
 	    damageScreen (s);
 	}
 
@@ -1646,6 +1739,7 @@ cubeFold (CompDisplay     *d,
 	if (cs->grabIndex)
 	{
 	    cs->unfolded = FALSE;
+	    cubeFoldEvent (s, FALSE);
 	    damageScreen (s);
 	}
     }
@@ -1819,6 +1913,8 @@ cubeInitDisplay (CompPlugin  *p,
     }
 
     d->privates[displayPrivateIndex].ptr = cd;
+    
+    WRAP (cd, d, handleCompizEvent, cubeHandleCompizEvent);
 
     return TRUE;
 }
@@ -1830,6 +1926,8 @@ cubeFiniDisplay (CompPlugin  *p,
     CUBE_DISPLAY (d);
 
     freeScreenPrivateIndex (d, cd->screenPrivateIndex);
+    
+    UNWRAP (cd, d, handleCompizEvent);
 
     compFiniDisplayOptions (d, cd->opt, CUBE_DISPLAY_OPTION_NUM);
 
@@ -1911,6 +2009,10 @@ cubeInitScreen (CompPlugin *p,
 
     cs->bg  = NULL;
     cs->nBg = 0;
+    
+    cs->disableCaps = FALSE;
+    cs->paintAllViewports = FALSE;
+    cs->rotationMode = NoRotation;
 
     memset (cs->cleared, 0, sizeof (cs->cleared));
 
diff --git a/plugins/rotate.c b/plugins/rotate.c
index eb337ca..c257790 100644
--- a/plugins/rotate.c
+++ b/plugins/rotate.c
@@ -251,6 +251,30 @@ rotateReleaseMoveWindow (CompScreen *s)
     rs->moveWindow = None;
 }
 
+static void rotateEvent(CompScreen *s, 
+			Bool       rotating, 
+			Bool       manual)
+{
+    CompOption o[3];
+
+    o[0].type = CompOptionTypeInt;
+    o[0].name = "root";
+    o[0].value.i = s->root;
+
+    o[1].type = CompOptionTypeBool;
+    o[1].name = "rotating";
+    o[1].value.b = rotating;
+
+    o[2].type = CompOptionTypeBool;
+    o[2].name = "manual";
+    o[2].value.b = manual;
+
+    (*s->display->handleCompizEvent)(s->display, 
+				     "rotate", 
+				     "rotateEvent", 
+				     o, 3);
+}
+
 static void
 rotatePreparePaintScreen (CompScreen *s,
 			  int	     msSinceLastPaint)
@@ -337,6 +361,8 @@ rotatePreparePaintScreen (CompScreen *s,
 			tx = (s->hsize * xrot / 360.0f) - 0.5f;
 		    else
 			tx = (s->hsize * xrot / 360.0f) + 0.5f;
+			
+		    rotateEvent (s, FALSE, FALSE);
 
 		    moveScreenViewport (s, tx, 0, TRUE);
 
@@ -491,6 +517,10 @@ rotateInitiate (CompDisplay     *d,
 
 	rs->moving = FALSE;
 	rs->slow   = FALSE;
+	
+	/* notify other plugins that rotation starts - if action is
+	   non-NULL, we are called from the 'Initiate rotate' binding */
+	rotateEvent (s, TRUE, (action != NULL));
 
 	if (!rs->grabIndex)
 	{
-- 
1.4.4.2

-------------- next part --------------
From 720a602d099e937d2512013f8531a4e22c64786f Mon Sep 17 00:00:00 2001
From: Roi Cohen <roico at roico-desktop.(none)>
Date: Mon, 7 May 2007 19:56:42 +0300
Subject: [PATCH] cube painting order

---
 plugins/cube.c |  618 ++++++++++++++++++++++++++++++++++++--------------------
 1 files changed, 399 insertions(+), 219 deletions(-)

diff --git a/plugins/cube.c b/plugins/cube.c
index 9ba05e1..fe146f3 100644
--- a/plugins/cube.c
+++ b/plugins/cube.c
@@ -87,6 +87,43 @@ typedef struct _CubeDisplay {
 #define CUBE_SCREEN_OPTION_ADJUST_IMAGE	      14
 #define CUBE_SCREEN_OPTION_NUM                15
 
+#define MULTM(x, y, z) \
+z[0] = x[0] * y[0] + x[4] * y[1] + x[8] * y[2] + x[12] * y[3]; \
+z[1] = x[1] * y[0] + x[5] * y[1] + x[9] * y[2] + x[13] * y[3]; \
+z[2] = x[2] * y[0] + x[6] * y[1] + x[10] * y[2] + x[14] * y[3]; \
+z[3] = x[3] * y[0] + x[7] * y[1] + x[11] * y[2] + x[15] * y[3]; \
+z[4] = x[0] * y[4] + x[4] * y[5] + x[8] * y[6] + x[12] * y[7]; \
+z[5] = x[1] * y[4] + x[5] * y[5] + x[9] * y[6] + x[13] * y[7]; \
+z[6] = x[2] * y[4] + x[6] * y[5] + x[10] * y[6] + x[14] * y[7]; \
+z[7] = x[3] * y[4] + x[7] * y[5] + x[11] * y[6] + x[15] * y[7]; \
+z[8] = x[0] * y[8] + x[4] * y[9] + x[8] * y[10] + x[12] * y[11]; \
+z[9] = x[1] * y[8] + x[5] * y[9] + x[9] * y[10] + x[13] * y[11]; \
+z[10] = x[2] * y[8] + x[6] * y[9] + x[10] * y[10] + x[14] * y[11]; \
+z[11] = x[3] * y[8] + x[7] * y[9] + x[11] * y[10] + x[15] * y[11]; \
+z[12] = x[0] * y[12] + x[4] * y[13] + x[8] * y[14] + x[12] * y[15]; \
+z[13] = x[1] * y[12] + x[5] * y[13] + x[9] * y[14] + x[13] * y[15]; \
+z[14] = x[2] * y[12] + x[6] * y[13] + x[10] * y[14] + x[14] * y[15]; \
+z[15] = x[3] * y[12] + x[7] * y[13] + x[11] * y[14] + x[15] * y[15];
+
+#define MULTMV(m, v) { \
+float v0 = m[0]*v[0] + m[4]*v[1] + m[8]*v[2] + m[12]*v[3]; \
+float v1 = m[1]*v[0] + m[5]*v[1] + m[9]*v[2] + m[13]*v[3]; \
+float v2 = m[2]*v[0] + m[6]*v[1] + m[10]*v[2] + m[14]*v[3]; \
+float v3 = m[3]*v[0] + m[7]*v[1] + m[11]*v[2] + m[15]*v[3]; \
+v[0] = v0; v[1] = v1; v[2] = v2; v[3] = v3; }
+
+#define DIVV(v) \
+v[0] /= v[3]; \
+v[1] /= v[3]; \
+v[2] /= v[3]; \
+v[3] /= v[3];
+
+typedef enum _PaintOrder
+{
+    BTF = 0,
+    FTB
+} PaintOrder;
+
 typedef struct _CubeScreen {
     PreparePaintScreenProc     preparePaintScreen;
     DonePaintScreenProc	       donePaintScreen;
@@ -97,15 +134,19 @@ typedef struct _CubeScreen {
     SetScreenOptionProc	       setScreenOption;
     OutputChangeNotifyProc     outputChangeNotify;
     SetClipPlanesProc          setClipPlanes;
+    StackFirstProc             stackFirst;
+    StackLastProc              stackLast;
+    StackNextProc              stackNext;
+    StackPrevProc              stackPrev;
 
     CompOption opt[CUBE_SCREEN_OPTION_NUM];
 
-    int      invert;
-    int      xrotations;
-    GLfloat  distance;
-    Bool     paintTopBottom;
-    GLushort color[3];
-    GLfloat  tc[12];
+    int        invert;
+    int        xrotations;
+    PaintOrder paintOrder;
+    GLfloat    distance;
+    GLushort   color[3];
+    GLfloat    tc[12];
 
     int grabIndex;
 
@@ -1075,6 +1116,8 @@ cubePaintScreen (CompScreen		 *s,
 	mask |= PAINT_SCREEN_TRANSFORMED_MASK;
     }
 
+    cs->paintOrder = BTF;	// Always use BTF painting on non-transformed screen.
+
     UNWRAP (cs, s, paintScreen);
     status = (*s->paintScreen) (s, sAttrib, transform, region, output, mask);
     WRAP (cs, s, paintScreen, cubePaintScreen);
@@ -1095,16 +1138,78 @@ cubeDonePaintScreen (CompScreen *s)
     WRAP (cs, s, donePaintScreen, cubeDonePaintScreen);
 }
 
+static Bool
+cubeCheckFTB (CompScreen *s, 
+              const ScreenPaintAttrib *sAttrib, 
+              const CompTransform  *transform,
+              int output)
+{
+    float mvp[16];
+    CompTransform sTransform = *transform;
+    
+    (*s->applyScreenTransform) (s, sAttrib, output, &sTransform);
+    transformToScreenSpace (s, output, -sAttrib->zTranslate, &sTransform);
+
+    MULTM(s->projection, sTransform.m, mvp);
+
+    float pntA[4] = { s->outputDev[output].region.extents.x1,
+                      s->outputDev[output].region.extents.y1,
+                      0, 1};
+
+    float pntB[4] = { s->outputDev[output].region.extents.x2,
+                      s->outputDev[output].region.extents.y1,
+                      0, 1};
+
+    float pntC[4] = { s->outputDev[output].region.extents.x1 + s->outputDev[output].width / 2.0f,
+                      s->outputDev[output].region.extents.y1 + s->outputDev[output].height / 2.0f,
+                      0, 1};
+
+    MULTMV(mvp, pntA);
+    DIVV(pntA);
+
+    MULTMV(mvp, pntB);
+    DIVV(pntB);
+
+    MULTMV(mvp, pntC);
+    DIVV(pntC);
+
+    float vecA[3] = { pntC[0] - pntA[0],
+                      pntC[1] - pntA[1],
+                      pntC[2] - pntA[2]};
+    
+    float vecB[3] = { pntC[0] - pntB[0], 
+                      pntC[1] - pntB[1],
+                      pntC[2] - pntB[2]};
+
+    float ortho[3] = { vecA[1] * vecB[2] - vecA[2] * vecB[1],
+	               vecA[2] * vecB[0] - vecA[0] * vecB[2],
+	               vecA[0] * vecB[1] - vecA[1] * vecB[0]};
+
+    if (ortho[2] > 0.0f)	//The viewport is reversed, should be painted front to back.
+	return TRUE;
+    
+    return FALSE;
+}
+
 static void
 cubeMoveViewportAndPaint (CompScreen		  *s,
 			  const ScreenPaintAttrib *sAttrib,
 			  const CompTransform	  *transform,
 			  int			  output,
 			  unsigned int		  mask,
+			  PaintOrder              paintOrder,
 			  int			  dx)
 {
     CUBE_SCREEN (s);
+    
+    Bool ftb = cubeCheckFTB(s, sAttrib, transform, output);
 
+    if ((paintOrder == FTB && !ftb) ||
+        (paintOrder == BTF && ftb))
+	return;
+    
+    cs->paintOrder = paintOrder;
+    
     if (cs->nOutput > 1)
     {
 	int cubeOutput, dView;
@@ -1145,49 +1250,83 @@ cubeMoveViewportAndPaint (CompScreen		  *s,
 }
 
 static void
-cubePaintTransformedScreen (CompScreen		    *s,
-			    const ScreenPaintAttrib *sAttrib,
-			    const CompTransform	    *transform,
-			    Region		    region,
-			    int			    output,
-			    unsigned int	    mask)
+cubePaintAllViewports (CompScreen              *s,
+                       ScreenPaintAttrib       *sAttrib,
+	               const CompTransform     *transform,
+                       Region		       region,
+                       int                     output,
+                       unsigned int            mask,
+                       int                     xMove,
+                       int                     size, 
+                       int                     hsize,
+                       PaintOrder              paintOrder)
 {
-    ScreenPaintAttrib sa = *sAttrib;
-    int		      hsize, xMove = 0;
-    float	      size;
-    Bool	      clear;
-
-    CUBE_SCREEN (s);
+    CUBE_SCREEN(s);
 
-    hsize = s->hsize * cs->nOutput;
-    size  = hsize;
+    ScreenPaintAttrib sa = *sAttrib;
 
-    if (!cs->fullscreenOutput)
+    int i;
+    int iFirstSign;	// 1 if we do xMove += i first and -1 if we do xMove -= i first.
+    
+    if (cs->invert == 1)
     {
-	cs->outputXScale = (float) s->width / s->outputDev[output].width;
-	cs->outputYScale = (float) s->height / s->outputDev[output].height;
-
-	cs->outputXOffset =
-	    (s->width / 2.0f -
-	     (s->outputDev[output].region.extents.x1 +
-	      s->outputDev[output].region.extents.x2) / 2.0f) /
-	    (float) s->outputDev[output].width;
-
-	cs->outputYOffset =
-	    (s->height / 2.0f -
-	     (s->outputDev[output].region.extents.y1 +
-	      s->outputDev[output].region.extents.y2) / 2.0f) /
-	    (float) s->outputDev[output].height;
+	// xMove ==> dx for the viewport which is the nearest to the viewer in z axis.
+	// xMove +/- hsize / 2 ==> dx for the viewport which is the farest to the viewer in z axis.
+    
+	if ((sa.xRotate < 0.0f && hsize % 2 == 1) ||
+	    (sa.xRotate > 0.0f && hsize % 2 == 0))
+	{
+	    xMove += hsize / 2;
+	    sa.yRotate -= (hsize / 2) * 360.0f / size;
+	    iFirstSign = 1;
+	}
+        
+	else
+	{
+	    xMove -= hsize / 2;
+	    sa.yRotate += (hsize / 2) * 360.0f / size;
+	    iFirstSign = -1;
+	}
     }
+    
     else
     {
-	cs->outputXScale  = 1.0f;
-	cs->outputYScale  = 1.0f;
-	cs->outputXOffset = 0.0f;
-	cs->outputYOffset = 0.0f;
+    	// xMove is already the dx for farest viewport.
+    
+	if (sa.xRotate > 0.0f)
+	    iFirstSign = -1;
+	else
+	    iFirstSign = 1;
     }
+    
+    for (i = 0; i <= hsize / 2; i++)
+    {
+	xMove += iFirstSign * i;
+	sa.yRotate -= cs->invert * iFirstSign * i * 360.0f / size;
+	cubeMoveViewportAndPaint (s, &sa, transform, output, mask,
+	                          paintOrder, xMove);
+	sa.yRotate += cs->invert * iFirstSign * i * 360.0f / size;
+	xMove -= iFirstSign * i;
+
+	if (i == 0 || i * 2 == hsize)	// same viewport.
+	    continue;
 
-    clear = cs->cleared[output];
+	xMove -= iFirstSign * i;
+	sa.yRotate += cs->invert * iFirstSign * i * 360.0f / size;
+	cubeMoveViewportAndPaint (s, &sa, transform, output, mask,
+	                          paintOrder, xMove);
+	sa.yRotate -= cs->invert * iFirstSign * i * 360.0f / size;
+	xMove += iFirstSign * i;
+    }
+}
+
+static void
+cubePaintSkydome (CompScreen        *s,
+                  ScreenPaintAttrib *sAttrib,
+                  Bool              clear)
+{
+    CUBE_SCREEN(s);
+    
     if (!clear)
     {
 	if (cs->sky.name)
@@ -1214,77 +1353,25 @@ cubePaintTransformedScreen (CompScreen		    *s,
 	{
 	    clearTargetOutput (s->display, GL_COLOR_BUFFER_BIT);
 	}
-
-	cs->cleared[output] = TRUE;
-    }
-
-    mask &= ~PAINT_SCREEN_CLEAR_MASK;
-
-    UNWRAP (cs, s, paintTransformedScreen);
-
-    sa.xTranslate = sAttrib->xTranslate;
-    sa.yTranslate = sAttrib->yTranslate;
-
-    if (cs->grabIndex)
-    {
-	sa.vRotate = 0.0f;
-
-	size += cs->unfold * 8.0f;
-	size += powf (cs->unfold, 6) * 64.0;
-	size += powf (cs->unfold, 16) * 8192.0;
-
-	sa.zTranslate = -cs->invert * (0.5f / tanf (M_PI / size));
-
-	/* distance we move the camera back when unfolding the cube.
-	   currently hardcoded to 1.5 but it should probably be optional. */
-	sa.zCamera -= cs->unfold * 1.5f;
-
-	sa.xRotate = sAttrib->xRotate * cs->invert;
-	if (sa.xRotate > 0.0f)
-	{
-	    cs->xrotations = (int) (hsize * sa.xRotate) / 360;
-	    sa.xRotate = sa.xRotate - (360.0f * cs->xrotations) / hsize;
-	}
-	else
-	{
-	    cs->xrotations = (int) (hsize * sa.xRotate) / 360;
-	    sa.xRotate = sa.xRotate -
-		(360.0f * cs->xrotations) / hsize + 360.0f / hsize;
-	    cs->xrotations--;
-	}
-
-	sa.xRotate = sa.xRotate / size * hsize;
     }
-    else
-    {
-	if (sAttrib->vRotate > 100.0f)
-	    sa.vRotate = 100.0f;
-	else if (sAttrib->vRotate < -100.0f)
-	    sa.vRotate = -100.0f;
-	else
-	    sa.vRotate = sAttrib->vRotate;
+}
 
-	sa.zTranslate = -cs->invert * cs->distance;
-	sa.xRotate = sAttrib->xRotate * cs->invert;
-	if (sa.xRotate > 0.0f)
-	{
-	    cs->xrotations = (int) (size * sa.xRotate) / 360;
-	    sa.xRotate = sa.xRotate - (360.0f * cs->xrotations) / size;
-	}
-	else
-	{
-	    cs->xrotations = (int) (size * sa.xRotate) / 360;
-	    sa.xRotate = sa.xRotate -
-		(360.0f * cs->xrotations) / size + 360.0f / size;
-	    cs->xrotations--;
-	}
-    }
+static void
+cubePaintCaps (CompScreen          *s,
+               ScreenPaintAttrib   *sAttrib,
+               const CompTransform *transform,
+               Bool                clear,
+               int                 output,
+               int                 hsize,
+               int                 size)
+{
+    CUBE_SCREEN(s);
 
     if (!clear && cs->grabIndex == 0 && hsize > 2 &&
-	(cs->invert != 1 || sa.vRotate != 0.0f || sa.yTranslate != 0.0f))
+	(cs->invert != 1 || sAttrib->vRotate != 0.0f || sAttrib->yTranslate != 0.0f))
     {
 	CompTransform sTransform = *transform;
-	float	      yRotate = (360.0f / size) * (cs->xrotations + 1);
+	float	      yRotate = (360.0f / size) * (cs->xrotations + 1);;
 
 	screenLighting (s, TRUE);
 
@@ -1293,155 +1380,242 @@ cubePaintTransformedScreen (CompScreen		    *s,
 	glPushMatrix ();
 
 	if (cs->opt[CUBE_SCREEN_OPTION_ADJUST_IMAGE].value.b)
-	{
-	    if (sAttrib->xRotate > 0.0f)
 		yRotate = 360.0f / size;
-	    else
-		yRotate = 0.0f;
-	}
 
-	sa.yRotate += yRotate;
+	sAttrib->yRotate += yRotate;
 
-	(*s->applyScreenTransform) (s, &sa, output, &sTransform);
+	(*s->applyScreenTransform) (s, sAttrib, output, &sTransform);
 	glLoadMatrixf (sTransform.m);
 	glTranslatef (cs->outputXOffset, -cs->outputYOffset, 0.0f);
 	glScalef (cs->outputXScale, cs->outputYScale, 1.0f);
 
-	sa.yRotate -= yRotate;
+	sAttrib->yRotate -= yRotate;
 
 	glVertexPointer (3, GL_FLOAT, 0, cs->vertices);
-
-	glNormal3f (0.0f, -1.0f, 0.0f);
-
-	if (cs->invert == 1 && hsize == 4 && cs->texture.name)
-	{
-	    enableTexture (s, &cs->texture, COMP_TEXTURE_FILTER_GOOD);
-	    glTexCoordPointer (2, GL_FLOAT, 0, cs->tc);
-	    glDrawArrays (GL_TRIANGLE_FAN, 0, cs->nvertices >> 1);
-	    disableTexture (s, &cs->texture);
-	    glDisableClientState (GL_TEXTURE_COORD_ARRAY);
-	}
-	else
+	
+	int i;
+	for (i = 0; i < 2; i++)
 	{
-	    glDisableClientState (GL_TEXTURE_COORD_ARRAY);
-	    glDrawArrays (GL_TRIANGLE_FAN, 0, cs->nvertices >> 1);
+	    if ((i == 0 && sAttrib->vRotate < 0.0f) ||
+	        (i == 1 && sAttrib->vRotate > 0.0f))
+	    {
+		glNormal3f (0.0f, -1.0f, 0.0f);
+		if (cs->invert == 1 && hsize == 4 && cs->texture.name)
+		{
+		    enableTexture (s, &cs->texture, COMP_TEXTURE_FILTER_GOOD);
+		    glTexCoordPointer (2, GL_FLOAT, 0, cs->tc);
+		    glDrawArrays (GL_TRIANGLE_FAN, 0, cs->nvertices >> 1);
+		    disableTexture (s, &cs->texture);
+		    glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+		}
+		else
+		{
+		    glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+		    glDrawArrays (GL_TRIANGLE_FAN, 0, cs->nvertices >> 1);
+		}
+	    }
+	    else
+	    {
+		glNormal3f (0.0f, 1.0f, 0.0f);
+	        glDrawArrays (GL_TRIANGLE_FAN, cs->nvertices >> 1,
+		              cs->nvertices >> 1);
+	    }
 	}
-
-	glNormal3f (0.0f, 1.0f, 0.0f);
-
-	glDrawArrays (GL_TRIANGLE_FAN, cs->nvertices >> 1,
-		      cs->nvertices >> 1);
-
+	
 	glNormal3f (0.0f, 0.0f, -1.0f);
-
+	
 	glPopMatrix ();
-
+	
 	glColor4usv (defaultColor);
 	glEnableClientState (GL_TEXTURE_COORD_ARRAY);
     }
+}
 
-    /* outside cube */
-    if (cs->invert == 1)
-    {
-	if (cs->grabIndex || hsize > 4)
-	{
-	    GLenum filter;
-	    int    i;
-
-	    xMove = cs->xrotations - ((hsize >> 1) - 1);
-	    sa.yRotate += (360.0f / size) * ((hsize >> 1) - 1);
-
-	    filter = s->display->textureFilter;
-	    if (cs->grabIndex && cs->opt[CUBE_SCREEN_OPTION_MIPMAP].value.b)
-		s->display->textureFilter = GL_LINEAR_MIPMAP_LINEAR;
-
-	    for (i = 0; i < hsize; i++)
-	    {
-		cubeMoveViewportAndPaint (s, &sa, transform, output, mask,
-					  xMove);
-
-		sa.yRotate -= 360.0f / size;
-		xMove++;
-	    }
-
-	    s->display->textureFilter = filter;
-	}
-	else
-	{
-	    if (sAttrib->xRotate != 0.0f)
-	    {
-		xMove = cs->xrotations;
+static void
+cubePaintTransformedScreen (CompScreen		    *s,
+			    const ScreenPaintAttrib *sAttrib,
+			    const CompTransform	    *transform,
+			    Region		    region,
+			    int			    output,
+			    unsigned int	    mask)
+{
+    ScreenPaintAttrib sa = *sAttrib;
+    int		      hsize, xMove = 0;
+    float	      size;
+    GLenum            filter = s->display->textureFilter;
+    PaintOrder        paintOrder;
+    Bool              clear;
+    
+    CUBE_SCREEN (s);
+    
+    clear = cs->cleared[output];
+    cs->cleared[output] = TRUE;
 
-		cubeMoveViewportAndPaint (s, &sa, transform, output, mask,
-					  xMove);
+    hsize = s->hsize * cs->nOutput;
+    size  = hsize;
 
-		xMove++;
-	    }
+    if (!cs->fullscreenOutput)
+    {
+	cs->outputXScale = (float) s->width / s->outputDev[output].width;
+	cs->outputYScale = (float) s->height / s->outputDev[output].height;
 
-	    sa.yRotate -= 360.0f / size;
+	cs->outputXOffset =
+	    (s->width / 2.0f -
+	     (s->outputDev[output].region.extents.x1 +
+	      s->outputDev[output].region.extents.x2) / 2.0f) /
+	    (float) s->outputDev[output].width;
 
-	    cubeMoveViewportAndPaint (s, &sa, transform, output, mask, xMove);
-	}
+	cs->outputYOffset =
+	    (s->height / 2.0f -
+	     (s->outputDev[output].region.extents.y1 +
+	      s->outputDev[output].region.extents.y2) / 2.0f) /
+	    (float) s->outputDev[output].height;
     }
     else
     {
-	if (sa.xRotate > 180.0f / size)
-	{
-	    sa.yRotate -= 360.0f / size;
-	    cs->xrotations++;
-	}
+	cs->outputXScale  = 1.0f;
+	cs->outputYScale  = 1.0f;
+	cs->outputXOffset = 0.0f;
+	cs->outputYOffset = 0.0f;
+    }
 
-	sa.yRotate -= 360.0f / size;
-	xMove = -1 - cs->xrotations;
+    cubePaintSkydome (s, &sa, clear);	// Paint skydome first.
 
-	if (cs->grabIndex)
-	{
-	    GLenum filter;
-	    int    i;
+    mask &= ~PAINT_SCREEN_CLEAR_MASK;
 
-	    filter = s->display->textureFilter;
-	    if (cs->opt[CUBE_SCREEN_OPTION_MIPMAP].value.b)
-		s->display->textureFilter = GL_LINEAR_MIPMAP_LINEAR;
+    UNWRAP (cs, s, paintTransformedScreen);
 
-	    if (sa.xRotate > 180.0f / size)
-	    {
-		xMove -= ((hsize >> 1) - 2);
-		sa.yRotate -= (360.0f / size) * ((hsize >> 1) - 2);
-	    }
-	    else
-	    {
-		xMove -= ((hsize >> 1) - 1);
-		sa.yRotate -= (360.0f / size) * ((hsize >> 1) - 1);
-	    }
+    sa.xTranslate = sAttrib->xTranslate;
+    sa.yTranslate = sAttrib->yTranslate;
 
-	    for (i = 0; i < hsize; i++)
-	    {
-		cubeMoveViewportAndPaint (s, &sa, transform, output, mask,
-					  xMove);
+    if (cs->grabIndex)
+    {
+	sa.vRotate = 0.0f;
 
-		sa.yRotate += 360.0f / size;
-		xMove++;
-	    }
+	size += cs->unfold * 8.0f;
+	size += powf (cs->unfold, 6) * 64.0;
+	size += powf (cs->unfold, 16) * 8192.0;
 
-	    s->display->textureFilter = filter;
-	}
+	sa.zTranslate = -cs->invert * (0.5f / tanf (M_PI / size));
+
+	/* distance we move the camera back when unfolding the cube.
+	   currently hardcoded to 1.5 but it should probably be optional. */
+	sa.zCamera -= cs->unfold * 1.5f;
+    }
+    else
+    {
+	if (sAttrib->vRotate > 100.0f)
+	    sa.vRotate = 100.0f;
+	else if (sAttrib->vRotate < -100.0f)
+	    sa.vRotate = -100.0f;
 	else
-	{
-	    cubeMoveViewportAndPaint (s, &sa, transform, output, mask, xMove);
+	    sa.vRotate = sAttrib->vRotate;
 
-	    sa.yRotate += 360.0f / size;
-	    xMove = -cs->xrotations;
+	sa.zTranslate = -cs->invert * cs->distance;
+    }
+    
+    sa.xRotate = sAttrib->xRotate;
 
-	    cubeMoveViewportAndPaint (s, &sa, transform, output, mask, xMove);
+    if (sa.xRotate > 0.0f)
+	cs->xrotations = (int) (hsize * sa.xRotate + 180) / 360;
+    else
+	cs->xrotations = (int) (hsize * sa.xRotate - 180) / 360;
+    
+    sa.xRotate -= (360.0f * cs->xrotations) / size;
+    sa.xRotate *= cs->invert;
+   
+    xMove = cs->xrotations;
+    
+    if (cs->grabIndex && cs->opt[CUBE_SCREEN_OPTION_MIPMAP].value.b)
+	s->display->textureFilter = GL_LINEAR_MIPMAP_LINEAR;
+    
+    if (cs->invert == 1)
+	paintOrder = FTB;	// Outside cube - start with FTB faces.
+    else
+	paintOrder = BTF;	// Inside cube -  start with BTF faces.
+    
+    if (cs->paintAllViewports || cs->invert == -1)
+	cubePaintAllViewports(s, &sa, transform, region, output, mask, xMove, size, hsize, paintOrder);
+    
+    cubePaintCaps (s, &sa, transform, clear, output, hsize, size);	// Paint caps between BTF faces and FTB faces.
+    
+    if (cs->invert == 1)
+	paintOrder = BTF;	// Outside cube - continue with BTF faces.
+    else
+	paintOrder = FTB;	// Inside cube -  continue with FTB faces.	
+    
+    if (cs->paintAllViewports || cs->invert == 1)
+	cubePaintAllViewports(s, &sa, transform, region, output, mask, xMove, size, hsize, paintOrder);
+    
+    s->display->textureFilter = filter;
 
-	    sa.yRotate += 360.0f / size;
-	    xMove = 1 - cs->xrotations;
+    WRAP (cs, s, paintTransformedScreen, cubePaintTransformedScreen);
+}
 
-	    cubeMoveViewportAndPaint (s, &sa, transform, output, mask, xMove);
-	}
-    }
+static CompWindow*
+cubeStackFirst (CompScreen* screen)
+{
+    CompWindow* status;
+    CUBE_SCREEN (screen);
+    
+    if (cs->paintOrder == FTB)
+	return screen->reverseWindows;
+    
+    UNWRAP (cs, screen, stackFirst);
+    status = (*screen->stackFirst) (screen);
+    WRAP (cs, screen, stackFirst, cubeStackFirst);
+    
+    return status;
+}
 
-    WRAP (cs, s, paintTransformedScreen, cubePaintTransformedScreen);
+static CompWindow*
+cubeStackLast (CompScreen* screen)
+{
+    CompWindow* status;
+    CUBE_SCREEN (screen);
+    
+    if (cs->paintOrder == FTB)
+	return screen->windows;
+    
+    UNWRAP (cs, screen, stackLast);
+    status = (*screen->stackLast) (screen);
+    WRAP (cs, screen, stackLast, cubeStackLast);
+    
+    return status;
+}
+
+static CompWindow*
+cubeStackNext (CompWindow* window)
+{
+    CompWindow* status;
+    CompScreen *screen = window->screen;
+    CUBE_SCREEN (screen);
+    
+    if (cs->paintOrder == FTB)
+	return window->prev;
+    
+    UNWRAP (cs, screen, stackNext);
+    status = (*screen->stackNext) (window);
+    WRAP (cs, screen, stackNext, cubeStackNext);
+    
+    return status;
+}
+
+static CompWindow*
+cubeStackPrev (CompWindow* window)
+{
+    CompWindow *status;
+    CompScreen *screen = window->screen;
+    CUBE_SCREEN (screen);
+    
+    if (cs->paintOrder == FTB)
+	return window->next;
+    
+    UNWRAP (cs, screen, stackPrev);
+    status = (*screen->stackPrev) (window);
+    WRAP (cs, screen, stackPrev, cubeStackPrev);
+    
+    return status;
 }
 
 static void
@@ -1991,8 +2165,6 @@ cubeInitScreen (CompPlugin *p,
 
     s->privates[cd->screenPrivateIndex].ptr = cs;
 
-    cs->paintTopBottom = FALSE;
-
     initTexture (s, &cs->texture);
     initTexture (s, &cs->sky);
 
@@ -2040,6 +2212,10 @@ cubeInitScreen (CompPlugin *p,
     WRAP (cs, s, setScreenOption, cubeSetGlobalScreenOption);
     WRAP (cs, s, outputChangeNotify, cubeOutputChangeNotify);
     WRAP (cs, s, setClipPlanes, cubeSetClipPlanes);
+    WRAP (cs, s, stackFirst, cubeStackFirst);
+    WRAP (cs, s, stackLast, cubeStackLast);
+    WRAP (cs, s, stackNext, cubeStackNext);
+    WRAP (cs, s, stackPrev, cubeStackPrev);
 
     return TRUE;
 }
@@ -2062,6 +2238,10 @@ cubeFiniScreen (CompPlugin *p,
     UNWRAP (cs, s, setScreenOption);
     UNWRAP (cs, s, outputChangeNotify);
     UNWRAP (cs, s, setClipPlanes);
+    UNWRAP (cs, s, stackFirst);
+    UNWRAP (cs, s, stackLast);
+    UNWRAP (cs, s, stackNext);
+    UNWRAP (cs, s, stackPrev);
 
     finiTexture (s, &cs->texture);
     finiTexture (s, &cs->sky);
-- 
1.4.4.2
-------------- next part --------------
From f6326ce232903a48253f68c14f205dc90c2a8b22 Mon Sep 17 00:00:00 2001
From: Roi Cohen <roico at roico-desktop.(none)>
Date: Mon, 7 May 2007 20:34:53 +0300
Subject: [PATCH] transparent cube

---
 metadata/cube.xml.in |   29 ++++++++
 plugins/cube.c       |  197 ++++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 202 insertions(+), 24 deletions(-)

diff --git a/metadata/cube.xml.in b/metadata/cube.xml.in
index f128f09..ea17ebd 100644
--- a/metadata/cube.xml.in
+++ b/metadata/cube.xml.in
@@ -123,6 +123,35 @@
 		<_long>Adjust top face image to rotation</_long>
 		<default>false</default>
 	    </option>
+	    <option name="active_opacity" type="float">
+		<_short>Opacity During Rotation</_short>
+		<_long>Opacity of desktop window during rotation.</_long>
+		<default>30.0</default>
+		<min>0.0</min>
+		<max>100.0</max>
+		<precision>1.0</precision>
+	    </option>
+	    <option name="inactive_opacity" type="float">
+		<_short>Opacity When Not Rotating</_short>
+		<_long>Opacity of desktop window when not rotating.</_long>
+		<default>100.0</default>
+		<min>0.0</min>
+		<max>100.0</max>
+		<precision>1.0</precision>
+	    </option>
+	    <option name="fade_time" type="float">
+		<_short>Fade Time</_short>
+		<_long>Desktop Window Opacity Fade Time.</_long>
+		<default>1.0</default>
+		<min>0.0</min>
+		<max>10.0</max>
+		<precision>0.1</precision>
+	    </option>
+	    <option name="transparent_manual_only" type="bool">
+		<_short>Transparency Only on Mouse Rotate</_short>
+		<_long>Initiates Cube transparency only if rotation is mouse driven.</_long>
+		<default>true</default>
+	    </option>
 	</screen>
     </plugin>
 </compiz>
diff --git a/plugins/cube.c b/plugins/cube.c
index fe146f3..f6c9924 100644
--- a/plugins/cube.c
+++ b/plugins/cube.c
@@ -70,22 +70,26 @@ typedef struct _CubeDisplay {
     HandleCompizEventProc handleCompizEvent;
 } CubeDisplay;
 
-#define CUBE_SCREEN_OPTION_COLOR	      0
-#define CUBE_SCREEN_OPTION_IN		      1
-#define CUBE_SCREEN_OPTION_SCALE_IMAGE	      2
-#define CUBE_SCREEN_OPTION_IMAGES	      3
-#define CUBE_SCREEN_OPTION_SKYDOME	      4
-#define CUBE_SCREEN_OPTION_SKYDOME_IMG	      5
-#define CUBE_SCREEN_OPTION_SKYDOME_ANIM	      6
-#define CUBE_SCREEN_OPTION_SKYDOME_GRAD_START 7
-#define CUBE_SCREEN_OPTION_SKYDOME_GRAD_END   8
-#define CUBE_SCREEN_OPTION_ACCELERATION	      9
-#define CUBE_SCREEN_OPTION_SPEED	      10
-#define CUBE_SCREEN_OPTION_TIMESTEP	      11
-#define CUBE_SCREEN_OPTION_MIPMAP	      12
-#define CUBE_SCREEN_OPTION_BACKGROUNDS	      13
-#define CUBE_SCREEN_OPTION_ADJUST_IMAGE	      14
-#define CUBE_SCREEN_OPTION_NUM                15
+#define CUBE_SCREEN_OPTION_COLOR	           0
+#define CUBE_SCREEN_OPTION_IN		           1
+#define CUBE_SCREEN_OPTION_SCALE_IMAGE	           2
+#define CUBE_SCREEN_OPTION_IMAGES	           3
+#define CUBE_SCREEN_OPTION_SKYDOME	           4
+#define CUBE_SCREEN_OPTION_SKYDOME_IMG	           5
+#define CUBE_SCREEN_OPTION_SKYDOME_ANIM	           6
+#define CUBE_SCREEN_OPTION_SKYDOME_GRAD_START      7
+#define CUBE_SCREEN_OPTION_SKYDOME_GRAD_END        8
+#define CUBE_SCREEN_OPTION_ACCELERATION	           9
+#define CUBE_SCREEN_OPTION_SPEED	           10
+#define CUBE_SCREEN_OPTION_TIMESTEP	           11
+#define CUBE_SCREEN_OPTION_MIPMAP	           12
+#define CUBE_SCREEN_OPTION_BACKGROUNDS	           13
+#define CUBE_SCREEN_OPTION_ADJUST_IMAGE	           14
+#define CUBE_SCREEN_OPTION_ACTIVE_OPACITY          15
+#define CUBE_SCREEN_OPTION_INACTIVE_OPACITY        16
+#define CUBE_SCREEN_OPTION_FADE_TIME               17
+#define CUBE_SCREEN_OPTION_TRANSPARENT_MANUAL_ONLY 18
+#define CUBE_SCREEN_OPTION_NUM                     19
 
 #define MULTM(x, y, z) \
 z[0] = x[0] * y[0] + x[4] * y[1] + x[8] * y[2] + x[12] * y[3]; \
@@ -130,6 +134,7 @@ typedef struct _CubeScreen {
     PaintScreenProc	       paintScreen;
     PaintTransformedScreenProc paintTransformedScreen;
     PaintBackgroundProc        paintBackground;
+    PaintWindowProc            paintWindow;
     ApplyScreenTransformProc   applyScreenTransform;
     SetScreenOptionProc	       setScreenOption;
     OutputChangeNotifyProc     outputChangeNotify;
@@ -180,6 +185,9 @@ typedef struct _CubeScreen {
     
     Bool disableCaps;
     Bool paintAllViewports;
+    
+    float desktopOpacity;
+    float toOpacity;
 
     CompTexture *bg;
     int		nBg;
@@ -1091,6 +1099,39 @@ cubePreparePaintScreen (CompScreen *s,
     }
 
     memset (cs->cleared, 0, sizeof (Bool) * s->nOutputDev);
+    
+    //transparency, mostly copied/ported from beryl's cube.c, orig. by onestone
+    if (cs->rotationMode != NoRotation && ((cs->rotationMode == RotationManual) || 
+		!(cs->opt[CUBE_SCREEN_OPTION_TRANSPARENT_MANUAL_ONLY].value.b)))
+    {
+	cs->toOpacity = 
+	      (cs->opt[CUBE_SCREEN_OPTION_ACTIVE_OPACITY].value.f / 100.0f) * OPAQUE;
+    }
+    else
+	cs->toOpacity =
+	    (cs->opt[CUBE_SCREEN_OPTION_INACTIVE_OPACITY].value.f / 100.0f) * OPAQUE;
+
+    if (cs->opt[CUBE_SCREEN_OPTION_FADE_TIME].value.f == 0.0f)
+	cs->desktopOpacity = cs->toOpacity;
+
+    else if (cs->desktopOpacity != cs->toOpacity)
+    {
+	float steps = (msSinceLastPaint * OPAQUE / 1000.0) /
+	    cs->opt[CUBE_SCREEN_OPTION_FADE_TIME].value.f;
+	if (steps < 12)
+	    steps = 12;
+
+	if (cs->toOpacity > cs->desktopOpacity)
+	{
+	    cs->desktopOpacity += steps;
+	    cs->desktopOpacity = MIN(cs->toOpacity, cs->desktopOpacity);
+	}
+	if (cs->toOpacity < cs->desktopOpacity)
+	{
+	    cs->desktopOpacity -= steps;
+	    cs->desktopOpacity = MAX(cs->toOpacity, cs->desktopOpacity);
+	}
+    }
 
     UNWRAP (cs, s, preparePaintScreen);
     (*s->preparePaintScreen) (s, msSinceLastPaint);
@@ -1110,7 +1151,7 @@ cubePaintScreen (CompScreen		 *s,
 
     CUBE_SCREEN (s);
 
-    if (cs->grabIndex)
+    if (cs->grabIndex || cs->desktopOpacity != OPAQUE)
     {
 	mask &= ~PAINT_SCREEN_REGION_MASK;
 	mask |= PAINT_SCREEN_TRANSFORMED_MASK;
@@ -1130,7 +1171,7 @@ cubeDonePaintScreen (CompScreen *s)
 {
     CUBE_SCREEN (s);
 
-    if (cs->grabIndex)
+    if (cs->grabIndex || cs->desktopOpacity != cs->toOpacity)
 	damageScreen (s);
 
     UNWRAP (cs, s, donePaintScreen);
@@ -1375,7 +1416,7 @@ cubePaintCaps (CompScreen          *s,
 
 	screenLighting (s, TRUE);
 
-	glColor3usv (cs->color);
+	glColor4us (cs->color[0], cs->color[1], cs->color[2], cs->desktopOpacity);
 
 	glPushMatrix ();
 
@@ -1390,6 +1431,13 @@ cubePaintCaps (CompScreen          *s,
 	glScalef (cs->outputXScale, cs->outputYScale, 1.0f);
 
 	sAttrib->yRotate -= yRotate;
+	
+	if (cs->desktopOpacity != OPAQUE)
+	{
+	    screenTexEnvMode (s, GL_MODULATE);
+	    glEnable(GL_BLEND);
+	    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+	}
 
 	glVertexPointer (3, GL_FLOAT, 0, cs->vertices);
 	
@@ -1428,6 +1476,10 @@ cubePaintCaps (CompScreen          *s,
 	
 	glColor4usv (defaultColor);
 	glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+	
+	screenTexEnvMode(s, GL_REPLACE);
+	glDisable(GL_BLEND);
+	glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
     }
 }
 
@@ -1445,6 +1497,7 @@ cubePaintTransformedScreen (CompScreen		    *s,
     GLenum            filter = s->display->textureFilter;
     PaintOrder        paintOrder;
     Bool              clear;
+    Bool              wasCulled = FALSE;
     
     CUBE_SCREEN (s);
     
@@ -1453,6 +1506,13 @@ cubePaintTransformedScreen (CompScreen		    *s,
 
     hsize = s->hsize * cs->nOutput;
     size  = hsize;
+    
+    if (cs->desktopOpacity != OPAQUE)
+    {
+	wasCulled = glIsEnabled(GL_CULL_FACE);
+	if (wasCulled)
+	    glDisable(GL_CULL_FACE);
+    }
 
     if (!cs->fullscreenOutput)
     {
@@ -1534,7 +1594,7 @@ cubePaintTransformedScreen (CompScreen		    *s,
     else
 	paintOrder = BTF;	// Inside cube -  start with BTF faces.
     
-    if (cs->paintAllViewports || cs->invert == -1)
+    if (cs->paintAllViewports || cs->desktopOpacity != OPAQUE || cs->invert == -1)
 	cubePaintAllViewports(s, &sa, transform, region, output, mask, xMove, size, hsize, paintOrder);
     
     cubePaintCaps (s, &sa, transform, clear, output, hsize, size);	// Paint caps between BTF faces and FTB faces.
@@ -1544,10 +1604,13 @@ cubePaintTransformedScreen (CompScreen		    *s,
     else
 	paintOrder = FTB;	// Inside cube -  continue with FTB faces.	
     
-    if (cs->paintAllViewports || cs->invert == 1)
+    if (cs->paintAllViewports || cs->desktopOpacity != OPAQUE || cs->invert == 1)
 	cubePaintAllViewports(s, &sa, transform, region, output, mask, xMove, size, hsize, paintOrder);
     
     s->display->textureFilter = filter;
+    
+    if (cs->desktopOpacity != OPAQUE && wasCulled)
+	glEnable(GL_CULL_FACE);
 
     WRAP (cs, s, paintTransformedScreen, cubePaintTransformedScreen);
 }
@@ -1619,6 +1682,50 @@ cubeStackPrev (CompWindow* window)
 }
 
 static void
+cubeSetBackgroundOpacity(CompScreen* s)
+{
+    CUBE_SCREEN(s);
+
+    if (cs->desktopOpacity != OPAQUE)
+    {
+	if (s->desktopWindowCount)
+	{
+	    glColor4us(0, 0, 0, 0);
+	    glEnable(GL_BLEND);
+	}
+	else
+	{
+	    glColor4us(0xffff, 0xffff, 0xffff, cs->desktopOpacity);
+	    glEnable(GL_BLEND);
+	    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+	    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+	}
+    }
+}
+
+static void
+cubeUnSetBackgroundOpacity(CompScreen* s)
+{
+    CUBE_SCREEN(s);
+
+    if (cs->desktopOpacity != OPAQUE)
+    {
+	if (s->desktopWindowCount)
+	{
+	    glColor3usv(defaultColor);
+	    glDisable(GL_BLEND);
+	}
+	else
+	{
+	    glColor3usv(defaultColor);
+	    glDisable(GL_BLEND);
+	    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+	    screenTexEnvMode(s, GL_REPLACE);
+	}
+    }
+}
+
+static void
 cubePaintBackground (CompScreen   *s,
 		     Region	  region,
 		     unsigned int mask)
@@ -1626,6 +1733,8 @@ cubePaintBackground (CompScreen   *s,
     int n;
 
     CUBE_SCREEN (s);
+    
+    cubeSetBackgroundOpacity(s);
 
     n = cs->opt[CUBE_SCREEN_OPTION_BACKGROUNDS].value.list.nValue;
     if (n)
@@ -1636,13 +1745,17 @@ cubePaintBackground (CompScreen   *s,
 	GLfloat     *d, *data;
 
 	if (!nBox)
-	    return;
+	{
+	    cubeUnSetBackgroundOpacity(s);
+ 	    return;
+	}
 
 	n = s->x % n;
 
 	if (s->desktopWindowCount)
 	{
 	    cubeUnloadBackgrounds (s);
+	    cubeUnSetBackgroundOpacity(s);
 	    return;
 	}
 	else
@@ -1655,7 +1768,10 @@ cubePaintBackground (CompScreen   *s,
 
 	data = malloc (sizeof (GLfloat) * nBox * 16);
 	if (!data)
-	    return;
+	{
+	    cubeUnSetBackgroundOpacity(s);
+ 	    return;
+	}
 
 	d = data;
 	n = nBox;
@@ -1712,6 +1828,31 @@ cubePaintBackground (CompScreen   *s,
 	(*s->paintBackground) (s, region, mask);
 	WRAP (cs, s, paintBackground, cubePaintBackground);
     }
+    
+    cubeUnSetBackgroundOpacity(s);
+}
+
+static Bool
+cubePaintWindow (CompWindow		  *w,
+		 const WindowPaintAttrib  *attrib,
+		 const CompTransform	  *transform,
+		 Region			  region,
+		 unsigned int		  mask)
+{
+    Bool status;
+    CompScreen* s = w->screen;
+    CUBE_SCREEN(s);
+    
+    WindowPaintAttrib wa = *attrib;
+
+    if (w->type & CompWindowTypeDesktopMask)
+	wa.opacity = cs->desktopOpacity;
+
+    UNWRAP (cs, s, paintWindow);
+    status = (*s->paintWindow) (w, &wa, transform, region, mask);
+    WRAP (cs, s, paintWindow, cubePaintWindow);
+    
+    return status;
 }
 
 static void cubeSetClipPlanes (CompScreen *s, Region region, int output)
@@ -2123,7 +2264,11 @@ static const CompMetadataOptionInfo cubeScreenOptionInfo[] = {
     { "timestep", "float", "<min>0.1</min>", 0, 0 },
     { "mipmap", "bool", 0, 0, 0 },
     { "backgrounds", "list", "<type>string</type>", 0, 0 },
-    { "adjust_image", "bool", 0, 0, 0 }
+    { "adjust_image", "bool", 0, 0, 0 },
+    { "active_opacity", "float", "<min>0.0</min><max>100.0</max>", 0, 0 },
+    { "inactive_opacity", "float", "<min>0.0</min><max>100.0</max>", 0, 0 },
+    { "fade_time", "float", "<min>0.0</min>", 0, 0 },
+    { "transparent_manual_only", "bool", 0, 0, 0 }
 };
 
 static Bool
@@ -2185,6 +2330,8 @@ cubeInitScreen (CompPlugin *p,
     cs->disableCaps = FALSE;
     cs->paintAllViewports = FALSE;
     cs->rotationMode = NoRotation;
+    
+    cs->desktopOpacity = OPAQUE;
 
     memset (cs->cleared, 0, sizeof (cs->cleared));
 
@@ -2208,6 +2355,7 @@ cubeInitScreen (CompPlugin *p,
     WRAP (cs, s, paintScreen, cubePaintScreen);
     WRAP (cs, s, paintTransformedScreen, cubePaintTransformedScreen);
     WRAP (cs, s, paintBackground, cubePaintBackground);
+    WRAP (cs, s, paintWindow, cubePaintWindow);
     WRAP (cs, s, applyScreenTransform, cubeApplyScreenTransform);
     WRAP (cs, s, setScreenOption, cubeSetGlobalScreenOption);
     WRAP (cs, s, outputChangeNotify, cubeOutputChangeNotify);
@@ -2234,6 +2382,7 @@ cubeFiniScreen (CompPlugin *p,
     UNWRAP (cs, s, paintScreen);
     UNWRAP (cs, s, paintTransformedScreen);
     UNWRAP (cs, s, paintBackground);
+    UNWRAP (cs, s, paintWindow);
     UNWRAP (cs, s, applyScreenTransform);
     UNWRAP (cs, s, setScreenOption);
     UNWRAP (cs, s, outputChangeNotify);
-- 
1.4.4.2


More information about the compiz mailing list