2
* Compiz Cube Caps plugin
6
* Copyright : (C) 2007 Guillaume Seguin
7
* E-mail : guillaume@segu.in
9
* Modifications for proper handling of opacity added by:
10
* Kevin Lange <klange@ogunderground.com>
12
* This program is free software; you can redistribute it and/or
13
* modify it under the terms of the GNU General Public License
14
* as published by the Free Software Foundation; either version 2
15
* of the License, or (at your option) any later version.
17
* This program is distributed in the hope that it will be useful,
18
* but WITHOUT ANY WARRANTY; without even the implied warranty of
19
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
* GNU General Public License for more details.
29
#include <compiz-core.h>
30
#include <compiz-cube.h>
31
#include "cubecaps_options.h"
33
static int displayPrivateIndex;
35
static int cubeDisplayPrivateIndex;
37
typedef struct _CubeCapsDisplay
39
int screenPrivateIndex;
42
typedef struct _CubeCap
55
typedef struct _CubeCapsScreen
57
PreparePaintScreenProc preparePaintScreen;
58
CubePaintTopProc paintTop;
59
CubePaintBottomProc paintBottom;
65
#define GET_CUBECAPS_DISPLAY(d) \
66
((CubeCapsDisplay *) (d)->base.privates[displayPrivateIndex].ptr)
67
#define CUBECAPS_DISPLAY(d) \
68
CubeCapsDisplay *ccd = GET_CUBECAPS_DISPLAY (d);
70
#define GET_CUBECAPS_SCREEN(s, ccd) \
71
((CubeCapsScreen *) (s)->base.privates[(ccd)->screenPrivateIndex].ptr)
72
#define CUBECAPS_SCREEN(s) \
73
CubeCapsScreen *ccs = GET_CUBECAPS_SCREEN (s, \
74
GET_CUBECAPS_DISPLAY (s->display))
76
/* Actual caps handling ----------------------------------------------------- */
82
cubecapsInitCap (CompScreen *s, CubeCap *cap)
84
memset (cap->tc, 0, sizeof (cap->tc));
86
initTexture (s, &cap->texture);
97
* Prepare cap texture coordinates
100
cubecapsInitTextureCoords (CompScreen * s, CubeCap * cap,
101
unsigned int width, unsigned int height)
103
float x1, x2, y1, y2;
109
matrix = &cap->texture.matrix;
121
int bigWidth, bigHeight;
125
bigHeight = s->height;
127
/* Scale the texture in a sane way for multi head too */
128
if (s->nOutputDev > 1 && cs->moMode != CUBE_MOMODE_ONE)
130
for (i = bigscr = 0; i < s->nOutputDev; i++)
131
if (s->outputDev[i].width > s->outputDev[bigscr].width)
133
bigWidth = s->outputDev[bigscr].width;
134
bigHeight = s->outputDev[bigscr].height;
137
x1 = width / 2.0f - bigWidth / 2.0f;
138
y1 = height / 2.0f - bigHeight / 2.0f;
139
x2 = width / 2.0f + bigWidth / 2.0f;
140
y2 = height / 2.0f + bigHeight / 2.0f;
143
cap->tc[0] = COMP_TEX_COORD_X (matrix, width / 2.0f);
144
cap->tc[1] = COMP_TEX_COORD_Y (matrix, height / 2.0f);
146
cap->tc[2] = COMP_TEX_COORD_X (matrix, x2);
147
cap->tc[3] = COMP_TEX_COORD_Y (matrix, y1);
149
cap->tc[4] = COMP_TEX_COORD_X (matrix, x1);
150
cap->tc[5] = COMP_TEX_COORD_Y (matrix, y1);
152
cap->tc[6] = COMP_TEX_COORD_X (matrix, x1);
153
cap->tc[7] = COMP_TEX_COORD_Y (matrix, y2);
155
cap->tc[8] = COMP_TEX_COORD_X (matrix, x2);
156
cap->tc[9] = COMP_TEX_COORD_Y (matrix, y2);
158
cap->tc[10] = COMP_TEX_COORD_X (matrix, x2);
159
cap->tc[11] = COMP_TEX_COORD_Y (matrix, y1);
163
* Attempt to load current cap image (if any)
166
cubecapsLoadCap (CompScreen *s,
169
unsigned int width, height;
174
if (!cs->fullscreenOutput)
181
pw = s->outputDev[0].width;
182
ph = s->outputDev[0].height;
185
if (!cap->files || !cap->files->nValue || cap->pw != pw || cap->ph != ph)
187
finiTexture (s, &cap->texture);
188
initTexture (s, &cap->texture);
190
if (!cap->files || !cap->files->nValue)
194
cap->current = cap->current % cap->files->nValue;
196
if (!readImageToTexture (s, &cap->texture,
197
cap->files->value[cap->current].s,
200
compLogMessage (s->display, "cubecaps", CompLogLevelWarn,
201
"Failed to load image: %s",
202
cap->files->value[cap->current].s);
204
finiTexture (s, &cap->texture);
205
initTexture (s, &cap->texture);
210
cubecapsInitTextureCoords (s, cap, width, height);
217
cubecapsPaintCap (CompScreen *s,
221
unsigned short *colorOutside,
222
unsigned short *colorInside,
223
Bool clampToBorderOutside,
224
Bool clampToBorderInside)
227
unsigned short opacity;
232
opacity = cs->desktopOpacity;
237
clampToBorder = clampToBorderOutside;
238
// Honor selected opacity AND cube opacity
239
opacity = (opacity * colorOutside[3]) / 0xffff;
240
glColor4us (colorOutside[0],
245
else if (cs->invert != 1)
248
clampToBorder = clampToBorderInside;
249
opacity = (opacity * colorInside[3]) / 0xffff;
250
glColor4us (colorInside[0],
256
glTranslatef (cs->outputXOffset, -cs->outputYOffset, 0.0f);
257
glScalef (cs->outputXScale, cs->outputYScale, 1.0f);
259
glVertexPointer (3, GL_FLOAT, 0, cs->vertices);
262
/* Draw cap once and reset color so that image will get correctly
263
* blended, and for non-4-horizontal-viewports setups */
264
if (opacity != OPAQUE)
266
screenTexEnvMode (s, GL_MODULATE);
267
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
268
glDrawArrays (GL_TRIANGLE_FAN, offset, cs->nVertices >> 1);
269
glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
272
glDrawArrays (GL_TRIANGLE_FAN, offset, cs->nVertices >> 1);
274
glColor4usv (defaultColor);
276
/* It is not really a good idea to draw the cap texture when there are
277
* only three viewports */
278
if (cap && cap->texture.name && s->hsize >= 4)
280
/* Apply blend strategy to blend correctly color and image */
282
glColor4us (cs->desktopOpacity, cs->desktopOpacity,
283
cs->desktopOpacity, cs->desktopOpacity);
284
enableTexture (s, &cap->texture, COMP_TEXTURE_FILTER_GOOD);
286
/* Use CLAMP_TO_BORDER if available to avoid weird looking clamping
287
* of non-scaled images (it also improves scaled images a bit but
288
* that's much less obvious) */
289
if (clampToBorder && s->textureBorderClamp)
291
glTexParameteri (cap->texture.target, GL_TEXTURE_WRAP_S,
293
glTexParameteri (cap->texture.target, GL_TEXTURE_WRAP_T,
298
glTexParameteri (cap->texture.target, GL_TEXTURE_WRAP_S,
300
glTexParameteri (cap->texture.target, GL_TEXTURE_WRAP_T,
306
/* 4 viewports is pretty much straight forward ... */
307
glTexCoordPointer (2, GL_FLOAT, 0, cap->tc - (offset << 1));
308
glDrawArrays (GL_TRIANGLE_FAN, offset, cs->nVertices >> 1);
310
else if (s->hsize > 4)
312
/* Paint image using custom vertexes */
313
int centerx = *cs->vertices;
314
int centery = *(cs->vertices + 1);
315
int centerz = *(cs->vertices + 2);
316
GLfloat x1, y1, x2, y2;
329
glTexCoord2f (x1, y1);
330
glVertex3f (centerx - 0.5, centery + 0.5, centerz + 0.5);
331
glTexCoord2f (x1, y2);
332
glVertex3f (centerx - 0.5, centery + 0.5, centerz - 0.5);
333
glTexCoord2f (x2, y2);
334
glVertex3f (centerx + 0.5, centery + 0.5, centerz - 0.5);
335
glTexCoord2f (x2, y1);
336
glVertex3f (centerx + 0.5, centery + 0.5, centerz + 0.5);
340
glTexCoord2f (x2,y2);
341
glVertex3f (centerx + 0.5, centery + 0.5, centerz + 0.5);
342
glTexCoord2f (x2, y1);
343
glVertex3f (centerx + 0.5, centery + 0.5, centerz - 0.5);
344
glTexCoord2f (x1, y1);
345
glVertex3f (centerx - 0.5, centery + 0.5, centerz - 0.5);
346
glTexCoord2f (x1, y2);
347
glVertex3f (centerx - 0.5, centery + 0.5, centerz + 0.5);
352
disableTexture (s, &cap->texture);
355
if (opacity != OPAQUE)
356
screenTexEnvMode (s, GL_REPLACE);
358
glDisable (GL_BLEND);
361
/* Core painting hooks ------------------------------------------------------ */
364
* Force cube to paint all viewports if not drawing top or bottom cap(s)
367
cubecapsPreparePaintScreen (CompScreen *s,
368
int msSinceLastPaint)
373
UNWRAP (ccs, s, preparePaintScreen);
374
(*s->preparePaintScreen) (s, msSinceLastPaint);
375
WRAP (ccs, s, preparePaintScreen, cubecapsPreparePaintScreen);
377
if (cs->rotationState == RotationNone ||
378
cs->rotationState != RotationManual)
381
cs->paintAllViewports |= !cubecapsGetDrawTop (s) |
382
!cubecapsGetDrawBottom (s) |
383
(cubecapsGetTopColorAlpha (s) != OPAQUE) |
384
(cubecapsGetBottomColorAlpha (s) != OPAQUE);
387
/* Cube hooks --------------------------------------------------------------- */
390
* Paint top cube face
393
cubecapsPaintTop (CompScreen *s,
394
const ScreenPaintAttrib *sAttrib,
395
const CompTransform *transform,
399
ScreenPaintAttrib sa = *sAttrib;
400
CompTransform sTransform = *transform;
405
/* Only paint if required */
406
if (!cubecapsGetDrawTop (s))
409
screenLighting (s, TRUE);
413
/* Readjust cap orientation ... */
416
sa.yRotate += (360.0f / size) * (cs->xRotations + 1);
417
if (!cubecapsGetAdjustTop (s)) /* ... Or not */
418
sa.yRotate -= (360.0f / size) * s->x;
422
sa.yRotate -= (360.0f / size) * (cs->xRotations - 1);
423
if (!cubecapsGetAdjustTop (s)) /* ... Or not */
424
sa.yRotate += (360.0f / size) * s->x;
427
(*s->applyScreenTransform) (s, &sa, output, &sTransform);
429
glLoadMatrixf (sTransform.m);
431
/* Actually paint the cap */
432
cubecapsPaintCap (s, 0, &ccs->topCap, &ccs->bottomCap,
433
cubecapsGetTopColor (s), cubecapsGetBottomColor (s),
434
cubecapsGetClampTopToBorder (s),
435
cubecapsGetClampBottomToBorder (s));
439
glColor4usv (defaultColor);
443
* Paint bottom cube face
446
cubecapsPaintBottom (CompScreen *s,
447
const ScreenPaintAttrib *sAttrib,
448
const CompTransform *transform,
452
ScreenPaintAttrib sa = *sAttrib;
453
CompTransform sTransform = *transform;
458
/* Only paint if required */
459
if (!cubecapsGetDrawBottom (s))
462
screenLighting (s, TRUE);
466
/* Readjust cap orientation ... */
469
sa.yRotate += (360.0f / size) * cs->xRotations;
470
if (!cubecapsGetAdjustBottom (s)) /* ... Or not */
471
sa.yRotate -= (360.0f / size) * s->x;
475
sa.yRotate -= (360.0f / size) * cs->xRotations;
476
if (!cubecapsGetAdjustBottom (s)) /* ... Or not */
477
sa.yRotate += (360.0f / size) * s->x;
480
(*s->applyScreenTransform) (s, &sa, output, &sTransform);
482
glLoadMatrixf (sTransform.m);
484
/* Actually paint the cap */
485
cubecapsPaintCap (s, cs->nVertices >> 1, &ccs->bottomCap, &ccs->topCap,
486
cubecapsGetBottomColor (s), cubecapsGetTopColor (s),
487
cubecapsGetClampBottomToBorder (s),
488
cubecapsGetClampTopToBorder (s));
492
glColor4usv (defaultColor);
495
/* Settings handling -------------------------------------------------------- */
498
* Switch cap, load it and damage screen if possible
501
cubecapsChangeCap (CompScreen *s,
505
if (cap->files && cap->files->nValue)
507
int count = cap->files->nValue;
508
cap->current = (cap->current + change + count) % count;
509
cubecapsLoadCap (s, cap);
515
* Top images list changed, reload top cap if any
518
cubecapsTopImagesChanged (CompScreen *s,
520
CubecapsScreenOptions num)
524
ccs->topCap.files = cubecapsGetTopImages (s);
525
cubecapsChangeCap (s, &ccs->topCap, 0);
529
* Bottom images list changed, reload bottom cap if any
532
cubecapsBottomImagesChanged (CompScreen *s,
534
CubecapsScreenOptions num)
538
ccs->bottomCap.files = cubecapsGetBottomImages (s);
539
cubecapsChangeCap (s, &ccs->bottomCap, 0);
543
* scale_top_image setting changed, reload top cap if any to update texture
547
cubecapsScaleTopImageChanged (CompScreen *s,
549
CubecapsScreenOptions num)
553
ccs->topCap.scale = cubecapsGetScaleTopImage (s);
554
cubecapsChangeCap (s, &ccs->topCap, 0);
558
* scale_bottom_image setting changed, reload bottom cap if any to update
559
* texture coordinates
562
cubecapsScaleBottomImageChanged (CompScreen *s,
564
CubecapsScreenOptions num)
568
ccs->bottomCap.scale = cubecapsGetScaleBottomImage (s);
569
cubecapsChangeCap (s, &ccs->bottomCap, 0);
572
/* Actions handling --------------------------------------------------------- */
575
* Switch to next top image
578
cubecapsTopNext (CompDisplay *d,
580
CompActionState state,
587
xid = getIntOptionNamed (option, nOption, "root", 0);
589
s = findScreenAtDisplay (d, xid);
594
cubecapsChangeCap (s, &ccs->topCap, 1);
601
* Switch to previous top image
604
cubecapsTopPrev (CompDisplay *d,
606
CompActionState state,
613
xid = getIntOptionNamed (option, nOption, "root", 0);
615
s = findScreenAtDisplay (d, xid);
619
cubecapsChangeCap (s, &ccs->topCap, -1);
626
* Switch to next bottom image
629
cubecapsBottomNext (CompDisplay *d,
631
CompActionState state,
638
xid = getIntOptionNamed (option, nOption, "root", 0);
640
s = findScreenAtDisplay (d, xid);
645
cubecapsChangeCap (s, &ccs->bottomCap, 1);
652
* Switch to previous bottom image
655
cubecapsBottomPrev (CompDisplay *d,
657
CompActionState state,
664
xid = getIntOptionNamed (option, nOption, "root", 0);
666
s = findScreenAtDisplay (d, xid);
670
cubecapsChangeCap (s, &ccs->bottomCap, -1);
676
/* Internal stuff ----------------------------------------------------------- */
679
cubecapsInitDisplay (CompPlugin *p,
682
CubeCapsDisplay *ccd;
684
if (!checkPluginABI ("core", CORE_ABIVERSION))
687
if (!checkPluginABI ("cube", CUBE_ABIVERSION))
690
if (!getPluginDisplayIndex (d, "cube", &cubeDisplayPrivateIndex))
693
ccd = malloc (sizeof (CubeCapsDisplay));
698
ccd->screenPrivateIndex = allocateScreenPrivateIndex (d);
700
if (ccd->screenPrivateIndex < 0)
706
cubecapsSetTopNextKeyInitiate (d, cubecapsTopNext);
707
cubecapsSetTopPrevKeyInitiate (d, cubecapsTopPrev);
708
cubecapsSetBottomNextKeyInitiate (d, cubecapsBottomNext);
709
cubecapsSetBottomPrevKeyInitiate (d, cubecapsBottomPrev);
711
cubecapsSetTopNextButtonInitiate (d, cubecapsTopNext);
712
cubecapsSetTopPrevButtonInitiate (d, cubecapsTopPrev);
713
cubecapsSetBottomNextButtonInitiate (d, cubecapsBottomNext);
714
cubecapsSetBottomPrevButtonInitiate (d, cubecapsBottomPrev);
716
d->base.privates[displayPrivateIndex].ptr = ccd;
722
cubecapsFiniDisplay (CompPlugin *p,
725
CUBECAPS_DISPLAY (d);
727
freeScreenPrivateIndex (d, ccd->screenPrivateIndex);
732
cubecapsInitScreen (CompPlugin *p,
736
CUBECAPS_DISPLAY (s->display);
739
ccs = malloc (sizeof (CubeCapsScreen));
744
cubecapsInitCap (s, &ccs->topCap);
745
cubecapsInitCap (s, &ccs->bottomCap);
747
ccs->topCap.files = cubecapsGetTopImages (s);
748
ccs->bottomCap.files = cubecapsGetBottomImages (s);
750
cubecapsSetTopImagesNotify (s, cubecapsTopImagesChanged);
751
cubecapsSetBottomImagesNotify (s, cubecapsBottomImagesChanged);
753
cubecapsSetScaleTopImageNotify (s, cubecapsScaleTopImageChanged);
754
cubecapsSetScaleBottomImageNotify (s, cubecapsScaleBottomImageChanged);
756
WRAP (ccs, s, preparePaintScreen, cubecapsPreparePaintScreen);
757
WRAP (ccs, cs, paintTop, cubecapsPaintTop);
758
WRAP (ccs, cs, paintBottom, cubecapsPaintBottom);
760
s->base.privates[ccd->screenPrivateIndex].ptr = ccs;
762
cubecapsChangeCap (s, &ccs->topCap, 0);
763
cubecapsChangeCap (s, &ccs->bottomCap, 0);
769
cubecapsFiniScreen (CompPlugin *p,
775
UNWRAP (ccs, cs, paintTop);
776
UNWRAP (ccs, cs, paintBottom);
777
UNWRAP (ccs, s, preparePaintScreen);
783
cubecapsInitObject (CompPlugin *p,
786
static InitPluginObjectProc dispTab[] = {
787
(InitPluginObjectProc) 0, /* InitCore */
788
(InitPluginObjectProc) cubecapsInitDisplay,
789
(InitPluginObjectProc) cubecapsInitScreen
792
RETURN_DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), TRUE, (p, o));
796
cubecapsFiniObject (CompPlugin *p,
799
static FiniPluginObjectProc dispTab[] = {
800
(FiniPluginObjectProc) 0, /* FiniCore */
801
(FiniPluginObjectProc) cubecapsFiniDisplay,
802
(FiniPluginObjectProc) cubecapsFiniScreen
805
DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), (p, o));
809
cubecapsInit (CompPlugin * p)
811
displayPrivateIndex = allocateDisplayPrivateIndex();
813
if (displayPrivateIndex < 0)
820
cubecapsFini (CompPlugin * p)
822
if (displayPrivateIndex >= 0)
823
freeDisplayPrivateIndex (displayPrivateIndex);
826
CompPluginVTable cubecapsVTable =
839
getCompPluginInfo (void)
841
return &cubecapsVTable;