diff --git a/include/compiz.h b/include/compiz.h index 5e52c8c..03d6005 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 #include @@ -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 @@ -1274,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); @@ -1308,6 +1317,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, @@ -1362,6 +1383,10 @@ paintBackground (CompScreen *screen, Region region, unsigned int mask); +void setClipPlanes (CompScreen *screen, + Region region, + int output); + /* texture.c */ @@ -1941,6 +1966,7 @@ struct _CompScreen { PaintTransformedScreenProc paintTransformedScreen; ApplyScreenTransformProc applyScreenTransform; PaintBackgroundProc paintBackground; + SetClipPlanesProc setClipPlanes; PaintWindowProc paintWindow; DrawWindowProc drawWindow; AddWindowGeometryProc addWindowGeometry; @@ -1965,6 +1991,12 @@ struct _CompScreen { WindowStateChangeNotifyProc windowStateChangeNotify; OutputChangeNotifyProc outputChangeNotify; + + StackFirstProc stackFirst; + StackLastProc stackLast; + + StackNextProc stackNext; + StackPrevProc stackPrev; CompPrivate *privates; }; diff --git a/plugins/cube.c b/plugins/cube.c index 833d33e..356955f 100644 --- a/plugins/cube.c +++ b/plugins/cube.c @@ -46,6 +46,13 @@ #include +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 @@ -78,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; @@ -87,15 +133,20 @@ typedef struct _CubeScreen { ApplyScreenTransformProc applyScreenTransform; 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; @@ -120,11 +171,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; @@ -1061,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); @@ -1081,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; @@ -1131,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) @@ -1200,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 = 0.0f; screenLighting (s, TRUE); @@ -1279,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; - } + yRotate = 360.0f / size; - 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 @@ -1526,6 +1714,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, @@ -1546,6 +1769,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, @@ -1575,6 +1877,7 @@ cubeUnfold (CompDisplay *d, if (cs->grabIndex) { cs->unfolded = TRUE; + cubeFoldEvent (s, TRUE); damageScreen (s); } @@ -1610,6 +1913,7 @@ cubeFold (CompDisplay *d, if (cs->grabIndex) { cs->unfolded = FALSE; + cubeFoldEvent (s, FALSE); damageScreen (s); } } @@ -1783,6 +2087,8 @@ cubeInitDisplay (CompPlugin *p, } d->privates[displayPrivateIndex].ptr = cd; + + WRAP (cd, d, handleCompizEvent, cubeHandleCompizEvent); return TRUE; } @@ -1794,6 +2100,8 @@ cubeFiniDisplay (CompPlugin *p, CUBE_DISPLAY (d); freeScreenPrivateIndex (d, cd->screenPrivateIndex); + + UNWRAP (cd, d, handleCompizEvent); compFiniDisplayOptions (d, cd->opt, CUBE_DISPLAY_OPTION_NUM); @@ -1857,8 +2165,6 @@ cubeInitScreen (CompPlugin *p, s->privates[cd->screenPrivateIndex].ptr = cs; - cs->paintTopBottom = FALSE; - initTexture (s, &cs->texture); initTexture (s, &cs->sky); @@ -1875,6 +2181,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)); @@ -1901,6 +2211,11 @@ cubeInitScreen (CompPlugin *p, WRAP (cs, s, applyScreenTransform, cubeApplyScreenTransform); 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; } @@ -1922,6 +2237,11 @@ cubeFiniScreen (CompPlugin *p, UNWRAP (cs, s, applyScreenTransform); 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); 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) { diff --git a/src/paint.c b/src/paint.c index 39bcacc..a4679e0 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; @@ -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); @@ -378,6 +359,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++) \ { \ @@ -1161,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 d73ceb4..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; @@ -1540,6 +1541,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;