1 /*
2 * Copyright © 2005 Novell, Inc.
3 *
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without
6 * fee, provided that the above copyright notice appear in all copies
7 * and that both that copyright notice and this permission notice
8 * appear in supporting documentation, and that the name of
9 * Novell, Inc. not be used in advertising or publicity pertaining to
10 * distribution of the software without specific, written prior permission.
11 * Novell, Inc. makes no representations about the suitability of this
12 * software for any purpose. It is provided "as is" without express or
13 * implied warranty.
14 *
15 * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17 * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 * Author: David Reveman <davidr@novell.com>
24 * Mirco Müller <macslow@bangang.de> (Skydome support)
25 */
26
27 #include <string.h>
28 #include <math.h>
29
30 #include <X11/Xatom.h>
31 #include <X11/Xproto.h>
32
33 #include <compiz-cube.h>
34
35 static CompMetadata cubeMetadata;
36
37 static int cubeCorePrivateIndex;
38 static int cubeDisplayPrivateIndex;
39
40 #define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))
41
42 static void
cubeLoadImg(CompScreen * s,int n)43 cubeLoadImg (CompScreen *s,
44 int n)
45 {
46 unsigned int width, height;
47 int pw, ph;
48 CompOptionValue *imgFiles;
49 int imgNFile;
50
51 CUBE_SCREEN (s);
52
53 imgFiles = cs->opt[CUBE_SCREEN_OPTION_IMAGES].value.list.value;
54 imgNFile = cs->opt[CUBE_SCREEN_OPTION_IMAGES].value.list.nValue;
55
56 if (!cs->fullscreenOutput)
57 {
58 pw = s->width;
59 ph = s->height;
60 }
61 else
62 {
63 pw = s->outputDev[0].width;
64 ph = s->outputDev[0].height;
65 }
66
67 if (!imgNFile || cs->pw != pw || cs->ph != ph)
68 {
69 finiTexture (s, &cs->texture);
70 initTexture (s, &cs->texture);
71
72 if (!imgNFile)
73 return;
74 }
75
76 cs->imgCurFile = n % imgNFile;
77
78 if (!readImageToTexture (s, &cs->texture,
79 imgFiles[cs->imgCurFile].s,
80 &width, &height))
81 {
82 compLogMessage ("cube", CompLogLevelWarn,
83 "Failed to load slide: %s",
84 imgFiles[cs->imgCurFile].s);
85
86 finiTexture (s, &cs->texture);
87 initTexture (s, &cs->texture);
88
89 return;
90 }
91
92 cs->tc[0] = COMP_TEX_COORD_X (&cs->texture.matrix, width / 2.0f);
93 cs->tc[1] = COMP_TEX_COORD_Y (&cs->texture.matrix, height / 2.0f);
94
95 if (cs->opt[CUBE_SCREEN_OPTION_SCALE_IMAGE].value.b)
96 {
97 cs->tc[2] = COMP_TEX_COORD_X (&cs->texture.matrix, width);
98 cs->tc[3] = COMP_TEX_COORD_Y (&cs->texture.matrix, 0.0f);
99
100 cs->tc[4] = COMP_TEX_COORD_X (&cs->texture.matrix, 0.0f);
101 cs->tc[5] = COMP_TEX_COORD_Y (&cs->texture.matrix, 0.0f);
102
103 cs->tc[6] = COMP_TEX_COORD_X (&cs->texture.matrix, 0.0f);
104 cs->tc[7] = COMP_TEX_COORD_Y (&cs->texture.matrix, height);
105
106 cs->tc[8] = COMP_TEX_COORD_X (&cs->texture.matrix, width);
107 cs->tc[9] = COMP_TEX_COORD_Y (&cs->texture.matrix, height);
108
109 cs->tc[10] = COMP_TEX_COORD_X (&cs->texture.matrix, width);
110 cs->tc[11] = COMP_TEX_COORD_Y (&cs->texture.matrix, 0.0f);
111 }
112 else
113 {
114 float x1 = width / 2.0f - pw / 2.0f;
115 float y1 = height / 2.0f - ph / 2.0f;
116 float x2 = width / 2.0f + pw / 2.0f;
117 float y2 = height / 2.0f + ph / 2.0f;
118
119 cs->tc[2] = COMP_TEX_COORD_X (&cs->texture.matrix, x2);
120 cs->tc[3] = COMP_TEX_COORD_Y (&cs->texture.matrix, y1);
121
122 cs->tc[4] = COMP_TEX_COORD_X (&cs->texture.matrix, x1);
123 cs->tc[5] = COMP_TEX_COORD_Y (&cs->texture.matrix, y1);
124
125 cs->tc[6] = COMP_TEX_COORD_X (&cs->texture.matrix, x1);
126 cs->tc[7] = COMP_TEX_COORD_Y (&cs->texture.matrix, y2);
127
128 cs->tc[8] = COMP_TEX_COORD_X (&cs->texture.matrix, x2);
129 cs->tc[9] = COMP_TEX_COORD_Y (&cs->texture.matrix, y2);
130
131 cs->tc[10] = COMP_TEX_COORD_X (&cs->texture.matrix, x2);
132 cs->tc[11] = COMP_TEX_COORD_Y (&cs->texture.matrix, y1);
133 }
134 }
135
136 static Bool
cubeUpdateGeometry(CompScreen * s,int sides,Bool invert)137 cubeUpdateGeometry (CompScreen *s,
138 int sides,
139 Bool invert)
140 {
141 GLfloat radius, distance;
142 GLfloat *v;
143 int i, n;
144
145 CUBE_SCREEN (s);
146
147 sides *= cs->nOutput;
148
149 distance = 0.5f / tanf (M_PI / sides);
150 radius = 0.5f / sinf (M_PI / sides);
151
152 n = (sides + 2) * 2;
153
154 if (cs->nVertices != n)
155 {
156 v = realloc (cs->vertices, sizeof (GLfloat) * n * 3);
157 if (!v)
158 return FALSE;
159
160 cs->nVertices = n;
161 cs->vertices = v;
162 }
163 else
164 v = cs->vertices;
165
166 *v++ = 0.0f;
167 *v++ = 0.5 * invert;
168 *v++ = 0.0f;
169
170 for (i = 0; i <= sides; i++)
171 {
172 *v++ = radius * sinf (i * 2 * M_PI / sides + M_PI / sides);
173 *v++ = 0.5 * invert;
174 *v++ = radius * cosf (i * 2 * M_PI / sides + M_PI / sides);
175 }
176
177 *v++ = 0.0f;
178 *v++ = -0.5 * invert;
179 *v++ = 0.0f;
180
181 for (i = sides; i >= 0; i--)
182 {
183 *v++ = radius * sinf (i * 2 * M_PI / sides + M_PI / sides);
184 *v++ = -0.5 * invert;
185 *v++ = radius * cosf (i * 2 * M_PI / sides + M_PI / sides);
186 }
187
188 cs->invert = invert;
189 cs->distance = distance;
190
191 return TRUE;
192 }
193
194 static void
cubeUpdateOutputs(CompScreen * s)195 cubeUpdateOutputs (CompScreen *s)
196 {
197 BoxPtr pBox0, pBox1;
198 int i, j, k, x;
199
200 CUBE_SCREEN (s);
201
202 k = 0;
203
204 cs->fullscreenOutput = TRUE;
205
206 for (i = 0; i < s->nOutputDev; i++)
207 {
208 cs->outputMask[i] = -1;
209
210 /* dimensions must match first output */
211 if (s->outputDev[i].width != s->outputDev[0].width ||
212 s->outputDev[i].height != s->outputDev[0].height)
213 continue;
214
215 pBox0 = &s->outputDev[0].region.extents;
216 pBox1 = &s->outputDev[i].region.extents;
217
218 /* top and bottom line must match first output */
219 if (pBox0->y1 != pBox1->y1 || pBox0->y2 != pBox1->y2)
220 continue;
221
222 k++;
223
224 for (j = 0; j < s->nOutputDev; j++)
225 {
226 pBox0 = &s->outputDev[j].region.extents;
227
228 /* must not intersect other output region */
229 if (i != j && pBox0->x2 > pBox1->x1 && pBox0->x1 < pBox1->x2)
230 {
231 k--;
232 break;
233 }
234 }
235 }
236
237 if (cs->moMode == CUBE_MOMODE_ONE)
238 {
239 cs->fullscreenOutput = FALSE;
240 cs->nOutput = 1;
241 return;
242 }
243
244 if (cs->moMode == CUBE_MOMODE_MULTI)
245 {
246 cs->fullscreenOutput = TRUE;
247 cs->nOutput = 1;
248 return;
249 }
250
251 if (k != s->nOutputDev)
252 {
253 cs->fullscreenOutput = FALSE;
254 cs->nOutput = 1;
255 return;
256 }
257
258 /* add output indices from left to right */
259 j = 0;
260 for (;;)
261 {
262 x = MAXSHORT;
263 k = -1;
264
265 for (i = 0; i < s->nOutputDev; i++)
266 {
267 if (cs->outputMask[i] != -1)
268 continue;
269
270 if (s->outputDev[i].region.extents.x1 < x)
271 {
272 x = s->outputDev[i].region.extents.x1;
273 k = i;
274 }
275 }
276
277 if (k < 0)
278 break;
279
280 cs->outputMask[k] = j;
281 cs->output[j] = k;
282
283 j++;
284 }
285
286 cs->nOutput = j;
287
288 if (cs->nOutput == 1)
289 {
290 if (s->outputDev[0].width != s->width ||
291 s->outputDev[0].height != s->height)
292 cs->fullscreenOutput = FALSE;
293 }
294 }
295
296 static CompOption *
cubeGetScreenOptions(CompPlugin * plugin,CompScreen * screen,int * count)297 cubeGetScreenOptions (CompPlugin *plugin,
298 CompScreen *screen,
299 int *count)
300 {
301 CUBE_SCREEN (screen);
302
303 *count = NUM_OPTIONS (cs);
304 return cs->opt;
305 }
306
307 static void
cubeUpdateSkyDomeTexture(CompScreen * screen)308 cubeUpdateSkyDomeTexture (CompScreen *screen)
309 {
310 CUBE_SCREEN (screen);
311
312 finiTexture (screen, &cs->sky);
313 initTexture (screen, &cs->sky);
314
315 if (!cs->opt[CUBE_SCREEN_OPTION_SKYDOME].value.b)
316 return;
317
318 if (strlen (cs->opt[CUBE_SCREEN_OPTION_SKYDOME_IMG].value.s) == 0 ||
319 !readImageToTexture (screen,
320 &cs->sky,
321 cs->opt[CUBE_SCREEN_OPTION_SKYDOME_IMG].value.s,
322 &cs->skyW,
323 &cs->skyH))
324 {
325 GLfloat aaafTextureData[128][128][3];
326 GLfloat fRStart = (GLfloat)
327 cs->opt[CUBE_SCREEN_OPTION_SKYDOME_GRAD_START].value.c[0] / 0xffff;
328 GLfloat fGStart = (GLfloat)
329 cs->opt[CUBE_SCREEN_OPTION_SKYDOME_GRAD_START].value.c[1] / 0xffff;
330 GLfloat fBStart = (GLfloat)
331 cs->opt[CUBE_SCREEN_OPTION_SKYDOME_GRAD_START].value.c[2] / 0xffff;
332 GLfloat fREnd = (GLfloat)
333 cs->opt[CUBE_SCREEN_OPTION_SKYDOME_GRAD_END].value.c[0] / 0xffff;
334 GLfloat fGEnd = (GLfloat)
335 cs->opt[CUBE_SCREEN_OPTION_SKYDOME_GRAD_END].value.c[1] / 0xffff;
336 GLfloat fBEnd = (GLfloat)
337 cs->opt[CUBE_SCREEN_OPTION_SKYDOME_GRAD_END].value.c[2] / 0xffff;
338 GLfloat fRStep = (fREnd - fRStart) / 128.0f;
339 GLfloat fGStep = (fGEnd - fGStart) / 128.0f;
340 GLfloat fBStep = (fBStart - fBEnd) / 128.0f;
341 GLfloat fR = fRStart;
342 GLfloat fG = fGStart;
343 GLfloat fB = fBStart;
344
345 int iX, iY;
346
347 for (iX = 127; iX >= 0; iX--)
348 {
349 fR += fRStep;
350 fG += fGStep;
351 fB -= fBStep;
352
353 for (iY = 0; iY < 128; iY++)
354 {
355 aaafTextureData[iX][iY][0] = fR;
356 aaafTextureData[iX][iY][1] = fG;
357 aaafTextureData[iX][iY][2] = fB;
358 }
359 }
360
361 cs->sky.target = GL_TEXTURE_2D;
362 cs->sky.filter = GL_LINEAR;
363 cs->sky.wrap = GL_CLAMP_TO_EDGE;
364
365 cs->sky.matrix.xx = 1.0 / 128.0;
366 cs->sky.matrix.yy = -1.0 / 128.0;
367 cs->sky.matrix.xy = 0;
368 cs->sky.matrix.yx = 0;
369 cs->sky.matrix.x0 = 0;
370 cs->sky.matrix.y0 = 1.0;
371
372 cs->skyW = 128;
373 cs->skyH = 128;
374
375 glGenTextures (1, &cs->sky.name);
376 glBindTexture (cs->sky.target, cs->sky.name);
377
378 glTexParameteri (cs->sky.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
379 glTexParameteri (cs->sky.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
380
381 glTexParameteri (cs->sky.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
382 glTexParameteri (cs->sky.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
383
384 glTexImage2D (cs->sky.target,
385 0,
386 GL_RGB,
387 128,
388 128,
389 0,
390 GL_RGB,
391 GL_FLOAT,
392 aaafTextureData);
393
394 glBindTexture (cs->sky.target, 0);
395 }
396 }
397
398 static Bool
fillCircleTable(GLfloat ** ppSint,GLfloat ** ppCost,const int n)399 fillCircleTable (GLfloat **ppSint,
400 GLfloat **ppCost,
401 const int n)
402 {
403 const GLfloat angle = 2 * M_PI / (GLfloat) ((n == 0) ? 1 : n);
404 const int size = abs (n);
405 int i;
406
407 *ppSint = (GLfloat *) calloc (sizeof (GLfloat), size + 1);
408 *ppCost = (GLfloat *) calloc (sizeof (GLfloat), size + 1);
409
410 if (!(*ppSint) || !(*ppCost))
411 {
412 free (*ppSint);
413 free (*ppCost);
414
415 return FALSE;
416 }
417
418 (*ppSint)[0] = 0.0;
419 (*ppCost)[0] = 1.0;
420
421 for (i = 1; i < size; i++)
422 {
423 (*ppSint)[i] = sin (angle * i);
424 (*ppCost)[i] = cos (angle * i);
425 }
426
427 (*ppSint)[size] = (*ppSint)[0];
428 (*ppCost)[size] = (*ppCost)[0];
429
430 return TRUE;
431 }
432
433 static void
cubeUpdateSkyDomeList(CompScreen * s,GLfloat fRadius)434 cubeUpdateSkyDomeList (CompScreen *s,
435 GLfloat fRadius)
436 {
437 GLint iSlices = 128;
438 GLint iStacks = 64;
439 GLfloat afTexCoordX[4];
440 GLfloat afTexCoordY[4];
441 GLfloat *sint1;
442 GLfloat *cost1;
443 GLfloat *sint2;
444 GLfloat *cost2;
445 GLfloat r;
446 GLfloat x;
447 GLfloat y;
448 GLfloat z;
449 int i;
450 int j;
451 int iStacksStart;
452 int iStacksEnd;
453 int iSlicesStart;
454 int iSlicesEnd;
455 GLfloat fStepX;
456 GLfloat fStepY;
457
458 CUBE_SCREEN (s);
459
460 if (cs->opt[CUBE_SCREEN_OPTION_SKYDOME_ANIM].value.b)
461 {
462 iStacksStart = 11; /* min. 0 */
463 iStacksEnd = 53; /* max. 64 */
464 iSlicesStart = 0; /* min. 0 */
465 iSlicesEnd = 128; /* max. 128 */
466 }
467 else
468 {
469 iStacksStart = 21; /* min. 0 */
470 iStacksEnd = 43; /* max. 64 */
471 iSlicesStart = 21; /* min. 0 */
472 iSlicesEnd = 44; /* max. 128 */
473 }
474
475 fStepX = 1.0 / (GLfloat) (iSlicesEnd - iSlicesStart);
476 fStepY = 1.0 / (GLfloat) (iStacksEnd - iStacksStart);
477
478 if (!fillCircleTable (&sint1, &cost1, -iSlices))
479 return;
480
481 if (!fillCircleTable (&sint2, &cost2, iStacks * 2))
482 {
483 free (sint1);
484 free (cost1);
485 return;
486 }
487
488 afTexCoordX[0] = 1.0f;
489 afTexCoordY[0] = 1.0f - fStepY;
490 afTexCoordX[1] = 1.0f - fStepX;
491 afTexCoordY[1] = 1.0f - fStepY;
492 afTexCoordX[2] = 1.0f - fStepX;
493 afTexCoordY[2] = 1.0f;
494 afTexCoordX[3] = 1.0f;
495 afTexCoordY[3] = 1.0f;
496
497 if (!cs->skyListId)
498 cs->skyListId = glGenLists (1);
499
500 glNewList (cs->skyListId, GL_COMPILE);
501
502 enableTexture (s, &cs->sky, COMP_TEXTURE_FILTER_GOOD);
503
504 glBegin (GL_QUADS);
505
506 for (i = iStacksStart; i < iStacksEnd; i++)
507 {
508 afTexCoordX[0] = 1.0f;
509 afTexCoordX[1] = 1.0f - fStepX;
510 afTexCoordX[2] = 1.0f - fStepX;
511 afTexCoordX[3] = 1.0f;
512
513 for (j = iSlicesStart; j < iSlicesEnd; j++)
514 {
515 /* bottom-right */
516 z = cost2[i];
517 r = sint2[i];
518 x = cost1[j];
519 y = sint1[j];
520
521 glTexCoord2f (
522 COMP_TEX_COORD_X (&cs->sky.matrix, afTexCoordX[3] * cs->skyW),
523 COMP_TEX_COORD_Y (&cs->sky.matrix, afTexCoordY[3] * cs->skyH));
524 glVertex3f (x * r * fRadius, y * r * fRadius, z * fRadius);
525
526 /* top-right */
527 z = cost2[i + 1];
528 r = sint2[i + 1];
529 x = cost1[j];
530 y = sint1[j];
531
532 glTexCoord2f (
533 COMP_TEX_COORD_X (&cs->sky.matrix, afTexCoordX[0] * cs->skyW),
534 COMP_TEX_COORD_Y (&cs->sky.matrix, afTexCoordY[0] * cs->skyH));
535 glVertex3f (x * r * fRadius, y * r * fRadius, z * fRadius);
536
537 /* top-left */
538 z = cost2[i + 1];
539 r = sint2[i + 1];
540 x = cost1[j + 1];
541 y = sint1[j + 1];
542
543 glTexCoord2f (
544 COMP_TEX_COORD_X (&cs->sky.matrix, afTexCoordX[1] * cs->skyW),
545 COMP_TEX_COORD_Y (&cs->sky.matrix, afTexCoordY[1] * cs->skyH));
546 glVertex3f (x * r * fRadius, y * r * fRadius, z * fRadius);
547
548 /* bottom-left */
549 z = cost2[i];
550 r = sint2[i];
551 x = cost1[j + 1];
552 y = sint1[j + 1];
553
554 glTexCoord2f (
555 COMP_TEX_COORD_X (&cs->sky.matrix, afTexCoordX[2] * cs->skyW),
556 COMP_TEX_COORD_Y (&cs->sky.matrix, afTexCoordY[2] * cs->skyH));
557 glVertex3f (x * r * fRadius, y * r * fRadius, z * fRadius);
558
559 afTexCoordX[0] -= fStepX;
560 afTexCoordX[1] -= fStepX;
561 afTexCoordX[2] -= fStepX;
562 afTexCoordX[3] -= fStepX;
563 }
564
565 afTexCoordY[0] -= fStepY;
566 afTexCoordY[1] -= fStepY;
567 afTexCoordY[2] -= fStepY;
568 afTexCoordY[3] -= fStepY;
569 }
570
571 glEnd ();
572
573 disableTexture (s, &cs->sky);
574
575 glEndList ();
576
577 free (sint1);
578 free (cost1);
579 free (sint2);
580 free (cost2);
581 }
582
583 static Bool
cubeSetScreenOption(CompPlugin * plugin,CompScreen * screen,const char * name,CompOptionValue * value)584 cubeSetScreenOption (CompPlugin *plugin,
585 CompScreen *screen,
586 const char *name,
587 CompOptionValue *value)
588 {
589 CompOption *o;
590 int index;
591
592 CUBE_SCREEN (screen);
593
594 o = compFindOption (cs->opt, NUM_OPTIONS (cs), name, &index);
595 if (!o)
596 return FALSE;
597
598 switch (index) {
599 case CUBE_SCREEN_OPTION_COLOR:
600 if (compSetColorOption (o, value))
601 {
602 memcpy (cs->color, o->value.c, sizeof (cs->color));
603 damageScreen (screen);
604 return TRUE;
605 }
606 break;
607 case CUBE_SCREEN_OPTION_IN:
608 if (compSetBoolOption (o, value))
609 {
610 if (cubeUpdateGeometry (screen, screen->hsize, o->value.b ? -1 : 1))
611 return TRUE;
612 }
613 break;
614 case CUBE_SCREEN_OPTION_SCALE_IMAGE:
615 if (compSetBoolOption (o, value))
616 {
617 cubeLoadImg (screen, cs->imgCurFile);
618 damageScreen (screen);
619
620 return TRUE;
621 }
622 break;
623 case CUBE_SCREEN_OPTION_IMAGES:
624 if (compSetOptionList (o, value))
625 {
626 cubeLoadImg (screen, cs->imgCurFile);
627 damageScreen (screen);
628
629 return TRUE;
630 }
631 break;
632 case CUBE_SCREEN_OPTION_SKYDOME:
633 if (compSetBoolOption (o, value))
634 {
635 cubeUpdateSkyDomeTexture (screen);
636 cubeUpdateSkyDomeList (screen, 1.0f);
637 damageScreen (screen);
638 return TRUE;
639 }
640 break;
641 case CUBE_SCREEN_OPTION_SKYDOME_IMG:
642 if (compSetStringOption (o, value))
643 {
644 cubeUpdateSkyDomeTexture (screen);
645 cubeUpdateSkyDomeList (screen, 1.0f);
646 damageScreen (screen);
647 return TRUE;
648 }
649 break;
650 case CUBE_SCREEN_OPTION_SKYDOME_ANIM:
651 if (compSetBoolOption (o, value))
652 {
653 cubeUpdateSkyDomeTexture (screen);
654 cubeUpdateSkyDomeList (screen, 1.0f);
655 damageScreen (screen);
656 return TRUE;
657 }
658 break;
659 case CUBE_SCREEN_OPTION_SKYDOME_GRAD_START:
660 if (compSetColorOption (o, value))
661 {
662 cubeUpdateSkyDomeTexture (screen);
663 cubeUpdateSkyDomeList (screen, 1.0f);
664 damageScreen (screen);
665 return TRUE;
666 }
667 break;
668 case CUBE_SCREEN_OPTION_SKYDOME_GRAD_END:
669 if (compSetColorOption (o, value))
670 {
671 cubeUpdateSkyDomeTexture (screen);
672 cubeUpdateSkyDomeList (screen, 1.0f);
673 damageScreen (screen);
674 return TRUE;
675 }
676 break;
677 case CUBE_SCREEN_OPTION_MULTIOUTPUT_MODE:
678 if (compSetIntOption (o, value))
679 {
680 cs->moMode = o->value.i;
681 cubeUpdateOutputs (screen);
682 cubeUpdateGeometry (screen, screen->hsize, cs->invert);
683 damageScreen (screen);
684 return TRUE;
685 }
686 break;
687 default:
688 return compSetScreenOption (screen, o, value);
689 }
690
691 return FALSE;
692 }
693
694 static int
adjustVelocity(CubeScreen * cs)695 adjustVelocity (CubeScreen *cs)
696 {
697 float unfold, adjust, amount;
698
699 if (cs->unfolded)
700 unfold = 1.0f - cs->unfold;
701 else
702 unfold = 0.0f - cs->unfold;
703
704 adjust = unfold * 0.02f * cs->opt[CUBE_SCREEN_OPTION_ACCELERATION].value.f;
705 amount = fabs (unfold);
706 if (amount < 1.0f)
707 amount = 1.0f;
708 else if (amount > 3.0f)
709 amount = 3.0f;
710
711 cs->unfoldVelocity = (amount * cs->unfoldVelocity + adjust) /
712 (amount + 2.0f);
713
714 return (fabs (unfold) < 0.002f && fabs (cs->unfoldVelocity) < 0.01f);
715 }
716
717 static void
cubePreparePaintScreen(CompScreen * s,int msSinceLastPaint)718 cubePreparePaintScreen (CompScreen *s,
719 int msSinceLastPaint)
720 {
721 int opt;
722 float x, progress;
723
724 CUBE_SCREEN (s);
725
726 if (cs->grabIndex)
727 {
728 int steps;
729 float amount, chunk;
730
731 amount = msSinceLastPaint * 0.2f *
732 cs->opt[CUBE_SCREEN_OPTION_SPEED].value.f;
733 steps = amount / (0.5f * cs->opt[CUBE_SCREEN_OPTION_TIMESTEP].value.f);
734 if (!steps) steps = 1;
735 chunk = amount / (float) steps;
736
737 while (steps--)
738 {
739 cs->unfold += cs->unfoldVelocity * chunk;
740 if (cs->unfold > 1.0f)
741 cs->unfold = 1.0f;
742
743 if (adjustVelocity (cs))
744 {
745 if (cs->unfold < 0.5f)
746 {
747 if (cs->grabIndex)
748 {
749 removeScreenGrab (s, cs->grabIndex, NULL);
750 cs->grabIndex = 0;
751 }
752
753 cs->unfold = 0.0f;
754 }
755 break;
756 }
757 }
758 }
759
760 memset (cs->cleared, 0, sizeof (Bool) * s->nOutputDev);
761 memset (cs->capsPainted, 0, sizeof (Bool) * s->nOutputDev);
762
763 /* Transparency handling */
764 if (cs->rotationState == RotationManual ||
765 (cs->rotationState == RotationChange &&
766 !cs->opt[CUBE_SCREEN_OPTION_TRANSPARENT_MANUAL_ONLY].value.b))
767 {
768 opt = cs->lastOpacityIndex = CUBE_SCREEN_OPTION_ACTIVE_OPACITY;
769 }
770 else if (cs->rotationState == RotationChange)
771 {
772 opt = cs->lastOpacityIndex = CUBE_SCREEN_OPTION_INACTIVE_OPACITY;
773 }
774 else
775 {
776 opt = CUBE_SCREEN_OPTION_INACTIVE_OPACITY;
777 }
778
779 cs->toOpacity = (cs->opt[opt].value.f / 100.0f) * OPAQUE;
780
781 (*cs->getRotation) (s, &x, &x, &progress);
782
783 if (cs->desktopOpacity != cs->toOpacity ||
784 (progress > 0.0 && progress < 1.0))
785 {
786 cs->desktopOpacity =
787 (cs->opt[CUBE_SCREEN_OPTION_INACTIVE_OPACITY].value.f -
788 ((cs->opt[CUBE_SCREEN_OPTION_INACTIVE_OPACITY].value.f -
789 cs->opt[cs->lastOpacityIndex].value.f) * progress))
790 / 100.0f * OPAQUE;
791
792 }
793
794 cs->paintAllViewports = (cs->desktopOpacity != OPAQUE);
795
796 UNWRAP (cs, s, preparePaintScreen);
797 (*s->preparePaintScreen) (s, msSinceLastPaint);
798 WRAP (cs, s, preparePaintScreen, cubePreparePaintScreen);
799 }
800
801 static void
cubePaintScreen(CompScreen * s,CompOutput * outputs,int numOutputs,unsigned int mask)802 cubePaintScreen (CompScreen *s,
803 CompOutput *outputs,
804 int numOutputs,
805 unsigned int mask)
806 {
807 float x, progress;
808
809 CUBE_SCREEN (s);
810
811 (*cs->getRotation) (s, &x, &x, &progress);
812
813 UNWRAP (cs, s, paintScreen);
814 if (cs->moMode == CUBE_MOMODE_ONE && s->nOutputDev &&
815 (progress > 0.0f || cs->desktopOpacity != OPAQUE))
816 (*s->paintScreen) (s, &s->fullscreenOutput, 1, mask);
817 else
818 (*s->paintScreen) (s, outputs, numOutputs, mask);
819 WRAP (cs, s, paintScreen, cubePaintScreen);
820 }
821
822 static Bool
cubePaintOutput(CompScreen * s,const ScreenPaintAttrib * sAttrib,const CompTransform * transform,Region region,CompOutput * output,unsigned int mask)823 cubePaintOutput (CompScreen *s,
824 const ScreenPaintAttrib *sAttrib,
825 const CompTransform *transform,
826 Region region,
827 CompOutput *output,
828 unsigned int mask)
829 {
830 Bool status;
831
832 CUBE_SCREEN (s);
833
834 if (cs->grabIndex || cs->desktopOpacity != OPAQUE)
835 {
836 mask &= ~PAINT_SCREEN_REGION_MASK;
837 mask |= PAINT_SCREEN_TRANSFORMED_MASK;
838 }
839
840 cs->srcOutput = (output->id != ~0) ? output->id : 0;
841 /* Always use BTF painting on non-transformed screen */
842 cs->paintOrder = BTF;
843
844 UNWRAP (cs, s, paintOutput);
845 status = (*s->paintOutput) (s, sAttrib, transform, region, output, mask);
846 WRAP (cs, s, paintOutput, cubePaintOutput);
847
848 return status;
849 }
850
851 static void
cubeDonePaintScreen(CompScreen * s)852 cubeDonePaintScreen (CompScreen *s)
853 {
854 CUBE_SCREEN (s);
855
856 if (cs->grabIndex || cs->desktopOpacity != cs->toOpacity)
857 damageScreen (s);
858
859 UNWRAP (cs, s, donePaintScreen);
860 (*s->donePaintScreen) (s);
861 WRAP (cs, s, donePaintScreen, cubeDonePaintScreen);
862 }
863
864 static Bool
cubeCheckOrientation(CompScreen * s,const ScreenPaintAttrib * sAttrib,const CompTransform * transform,CompOutput * outputPtr,CompVector * points)865 cubeCheckOrientation (CompScreen *s,
866 const ScreenPaintAttrib *sAttrib,
867 const CompTransform *transform,
868 CompOutput *outputPtr,
869 CompVector *points)
870 {
871 CompTransform sTransform = *transform;
872 CompTransform mvp, pm;
873 CompVector pntA, pntB, pntC;
874 CompVector vecA, vecB, ortho;
875 Bool rv = FALSE;
876
877 CUBE_SCREEN (s);
878
879 (*s->applyScreenTransform) (s, sAttrib, outputPtr, &sTransform);
880 matrixTranslate (&sTransform, cs->outputXOffset, -cs->outputYOffset, 0.0f);
881 matrixScale (&sTransform, cs->outputXScale, cs->outputYScale, 1.0f);
882
883 memcpy (pm.m, s->projection, sizeof (pm.m));
884 matrixMultiply (&mvp, &pm, &sTransform);
885
886 matrixMultiplyVector (&pntA, &points[0], &mvp);
887
888 if (pntA.w < 0.0f)
889 rv = !rv;
890
891 matrixVectorDiv (&pntA);
892
893 matrixMultiplyVector (&pntB, &points[1], &mvp);
894
895 if (pntB.w < 0.0f)
896 rv = !rv;
897
898 matrixVectorDiv (&pntB);
899 matrixMultiplyVector (&pntC, &points[2], &mvp);
900 matrixVectorDiv (&pntC);
901
902 vecA.x = pntC.x - pntA.x;
903 vecA.y = pntC.y - pntA.y;
904 vecA.z = pntC.z - pntA.z;
905
906 vecB.x = pntC.x - pntB.x;
907 vecB.y = pntC.y - pntB.y;
908 vecB.z = pntC.z - pntB.z;
909
910 ortho.x = vecA.y * vecB.z - vecA.z * vecB.y;
911 ortho.y = vecA.z * vecB.x - vecA.x * vecB.z;
912 ortho.z = vecA.x * vecB.y - vecA.y * vecB.x;
913
914 if (ortho.z > 0.0f)
915 rv = !rv;
916
917 return rv;
918 }
919
920 static Bool
cubeShouldPaintViewport(CompScreen * s,const ScreenPaintAttrib * sAttrib,const CompTransform * transform,CompOutput * outputPtr,PaintOrder order)921 cubeShouldPaintViewport (CompScreen *s,
922 const ScreenPaintAttrib *sAttrib,
923 const CompTransform *transform,
924 CompOutput *outputPtr,
925 PaintOrder order)
926 {
927 Bool ftb;
928 float pointZ;
929
930 CUBE_SCREEN (s);
931
932 pointZ = cs->invert * cs->distance;
933 CompVector vPoints[3] = { {.v = { -0.5, 0.0, pointZ, 1.0 } },
934 {.v = { 0.0, 0.5, pointZ, 1.0 } },
935 {.v = { 0.0, 0.0, pointZ, 1.0 } } };
936
937 ftb = (*cs->checkOrientation) (s, sAttrib, transform, outputPtr, vPoints);
938
939 return (order == FTB && ftb) || (order == BTF && !ftb);
940 }
941
942 static void
cubeMoveViewportAndPaint(CompScreen * s,const ScreenPaintAttrib * sAttrib,const CompTransform * transform,CompOutput * outputPtr,unsigned int mask,PaintOrder paintOrder,int dx)943 cubeMoveViewportAndPaint (CompScreen *s,
944 const ScreenPaintAttrib *sAttrib,
945 const CompTransform *transform,
946 CompOutput *outputPtr,
947 unsigned int mask,
948 PaintOrder paintOrder,
949 int dx)
950 {
951 int output;
952
953 CUBE_SCREEN (s);
954
955 if (!(*cs->shouldPaintViewport) (s,
956 sAttrib,
957 transform,
958 outputPtr,
959 paintOrder))
960 return;
961
962 output = (outputPtr->id != ~0) ? outputPtr->id : 0;
963
964 cs->paintOrder = paintOrder;
965
966 if (cs->nOutput > 1)
967 {
968 int cubeOutput, dView;
969
970 /* translate to cube output */
971 cubeOutput = cs->outputMask[output];
972
973 /* convert from window movement to viewport movement */
974 dView = -dx;
975
976 cubeOutput += dView;
977
978 dView = cubeOutput / cs->nOutput;
979 cubeOutput = cubeOutput % cs->nOutput;
980
981 if (cubeOutput < 0)
982 {
983 cubeOutput += cs->nOutput;
984 dView--;
985 }
986
987 /* translate back to compiz output */
988 output = cs->srcOutput = cs->output[cubeOutput];
989
990 setWindowPaintOffset (s, -dView * s->width, 0);
991 (*cs->paintViewport) (s, sAttrib, transform,
992 &s->outputDev[output].region,
993 &s->outputDev[output], mask);
994 setWindowPaintOffset (s, 0, 0);
995 }
996 else
997 {
998 Region region;
999
1000 setWindowPaintOffset (s, dx * s->width, 0);
1001
1002 if (cs->moMode == CUBE_MOMODE_MULTI)
1003 region = &outputPtr->region;
1004 else
1005 region = &s->region;
1006
1007 (*cs->paintViewport) (s, sAttrib, transform, region, outputPtr, mask);
1008
1009 setWindowPaintOffset (s, 0, 0);
1010 }
1011 }
1012
1013 static void
cubePaintAllViewports(CompScreen * s,ScreenPaintAttrib * sAttrib,const CompTransform * transform,Region region,CompOutput * outputPtr,unsigned int mask,int xMove,float size,int hsize,PaintOrder paintOrder)1014 cubePaintAllViewports (CompScreen *s,
1015 ScreenPaintAttrib *sAttrib,
1016 const CompTransform *transform,
1017 Region region,
1018 CompOutput *outputPtr,
1019 unsigned int mask,
1020 int xMove,
1021 float size,
1022 int hsize,
1023 PaintOrder paintOrder)
1024 {
1025 ScreenPaintAttrib sa = *sAttrib;
1026
1027 int i;
1028 int xMoveAdd;
1029 int origXMoveAdd = 0; /* dx for the viewport we start
1030 painting with (back-most). */
1031 int iFirstSign; /* 1 if we do xMove += i first and
1032 -1 if we do xMove -= i first. */
1033
1034 CUBE_SCREEN (s);
1035
1036 if (cs->invert == 1)
1037 {
1038 /* xMove ==> dx for the viewport which is the
1039 nearest to the viewer in z axis.
1040 xMove +/- hsize / 2 ==> dx for the viewport
1041 which is the farthest to the viewer in z axis. */
1042
1043 if ((sa.xRotate < 0.0f && hsize % 2 == 1) ||
1044 (sa.xRotate > 0.0f && hsize % 2 == 0))
1045 {
1046 origXMoveAdd = hsize / 2;
1047 iFirstSign = 1;
1048 }
1049 else
1050 {
1051 origXMoveAdd = -hsize / 2;
1052 iFirstSign = -1;
1053 }
1054 }
1055 else
1056 {
1057 /* xMove is already the dx for farthest viewport. */
1058 if (sa.xRotate > 0.0f)
1059 iFirstSign = -1;
1060 else
1061 iFirstSign = 1;
1062 }
1063
1064 for (i = 0; i <= hsize / 2; i++)
1065 {
1066 /* move to the correct viewport (back to front). */
1067 xMoveAdd = origXMoveAdd; /* move to farthest viewport. */
1068 xMoveAdd += iFirstSign * i; /* move i more viewports to
1069 the right / left. */
1070
1071 /* Needed especially for unfold.
1072 We paint the viewports around xMove viewport.
1073 Adding or subtracting hsize from xMove has no effect on
1074 what viewport we paint, but can make shorter paths. */
1075 if (xMoveAdd < -hsize / 2)
1076 xMoveAdd += hsize;
1077 else if (xMoveAdd > hsize / 2)
1078 xMoveAdd -= hsize;
1079
1080 /* Paint the viewport. */
1081 xMove += xMoveAdd;
1082
1083 sa.yRotate -= cs->invert * xMoveAdd * 360.0f / size;
1084 cubeMoveViewportAndPaint (s, &sa, transform, outputPtr, mask,
1085 paintOrder, xMove);
1086 sa.yRotate += cs->invert * xMoveAdd * 360.0f / size;
1087
1088 xMove -= xMoveAdd;
1089
1090 /* do the same for an equally far viewport. */
1091 if (i == 0 || i * 2 == hsize)
1092 continue;
1093
1094 xMoveAdd = origXMoveAdd; /* move to farthest viewport. */
1095 xMoveAdd -= iFirstSign * i; /* move i more viewports to the
1096 left / right (opposite side
1097 from the one chosen first) */
1098
1099 if (xMoveAdd < -hsize / 2)
1100 xMoveAdd += hsize;
1101 else if (xMoveAdd > hsize / 2)
1102 xMoveAdd -= hsize;
1103
1104 xMove += xMoveAdd;
1105
1106 sa.yRotate -= cs->invert * xMoveAdd * 360.0f / size;
1107 cubeMoveViewportAndPaint (s, &sa, transform, outputPtr, mask,
1108 paintOrder, xMove);
1109 sa.yRotate += cs->invert * xMoveAdd * 360.0f / size;
1110
1111 xMove -= xMoveAdd;
1112 }
1113 }
1114
1115 static void
cubeGetRotation(CompScreen * s,float * x,float * v,float * progress)1116 cubeGetRotation (CompScreen *s,
1117 float *x,
1118 float *v,
1119 float *progress)
1120 {
1121 *x = 0.0f;
1122 *v = 0.0f;
1123 *progress = 0.0f;
1124 }
1125
1126 static void
cubeClearTargetOutput(CompScreen * s,float xRotate,float vRotate)1127 cubeClearTargetOutput (CompScreen *s,
1128 float xRotate,
1129 float vRotate)
1130 {
1131 CUBE_SCREEN (s);
1132
1133 if (cs->sky.name)
1134 {
1135 screenLighting (s, FALSE);
1136
1137 glPushMatrix ();
1138
1139 if (cs->opt[CUBE_SCREEN_OPTION_SKYDOME_ANIM].value.b &&
1140 cs->grabIndex == 0)
1141 {
1142 glRotatef (vRotate / 5.0f + 90.0f, 1.0f, 0.0f, 0.0f);
1143 glRotatef (xRotate, 0.0f, 0.0f, -1.0f);
1144 }
1145 else
1146 {
1147 glRotatef (90.0f, 1.0f, 0.0f, 0.0f);
1148 }
1149
1150 glCallList (cs->skyListId);
1151 glPopMatrix ();
1152 }
1153 else
1154 {
1155 clearTargetOutput (s->display, GL_COLOR_BUFFER_BIT);
1156 }
1157 }
1158
1159 static void
cubePaintTop(CompScreen * s,const ScreenPaintAttrib * sAttrib,const CompTransform * transform,CompOutput * output,int size)1160 cubePaintTop (CompScreen *s,
1161 const ScreenPaintAttrib *sAttrib,
1162 const CompTransform *transform,
1163 CompOutput *output,
1164 int size)
1165 {
1166 ScreenPaintAttrib sa = *sAttrib;
1167 CompTransform sTransform = *transform;
1168
1169 CUBE_SCREEN (s);
1170
1171 screenLighting (s, TRUE);
1172
1173 glColor4us (cs->color[0], cs->color[1], cs->color[2], cs->desktopOpacity);
1174
1175 glPushMatrix ();
1176
1177 sa.yRotate += (360.0f / size) * (cs->xRotations + 1);
1178 if (!cs->opt[CUBE_SCREEN_OPTION_ADJUST_IMAGE].value.b)
1179 sa.yRotate -= (360.0f / size) * s->x;
1180
1181 (*s->applyScreenTransform) (s, &sa, output, &sTransform);
1182
1183 glLoadMatrixf (sTransform.m);
1184 glTranslatef (cs->outputXOffset, -cs->outputYOffset, 0.0f);
1185 glScalef (cs->outputXScale, cs->outputYScale, 1.0f);
1186
1187 if (cs->desktopOpacity != OPAQUE)
1188 {
1189 screenTexEnvMode (s, GL_MODULATE);
1190 glEnable (GL_BLEND);
1191 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1192 }
1193
1194 glVertexPointer (3, GL_FLOAT, 0, cs->vertices);
1195
1196 if (cs->invert == 1 && size == 4 && cs->texture.name)
1197 {
1198 enableTexture (s, &cs->texture, COMP_TEXTURE_FILTER_GOOD);
1199 glTexCoordPointer (2, GL_FLOAT, 0, cs->tc);
1200 glDrawArrays (GL_TRIANGLE_FAN, 0, cs->nVertices >> 1);
1201 disableTexture (s, &cs->texture);
1202 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
1203 }
1204 else
1205 {
1206 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
1207 glDrawArrays (GL_TRIANGLE_FAN, 0, cs->nVertices >> 1);
1208 }
1209
1210 glPopMatrix ();
1211
1212 glColor4usv (defaultColor);
1213 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
1214
1215 screenTexEnvMode (s, GL_REPLACE);
1216 glDisable (GL_BLEND);
1217 glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1218 }
1219
1220 static void
cubePaintBottom(CompScreen * s,const ScreenPaintAttrib * sAttrib,const CompTransform * transform,CompOutput * output,int size)1221 cubePaintBottom (CompScreen *s,
1222 const ScreenPaintAttrib *sAttrib,
1223 const CompTransform *transform,
1224 CompOutput *output,
1225 int size)
1226 {
1227 ScreenPaintAttrib sa = *sAttrib;
1228 CompTransform sTransform = *transform;
1229
1230 CUBE_SCREEN (s);
1231
1232 screenLighting (s, TRUE);
1233
1234 glColor4us (cs->color[0], cs->color[1], cs->color[2], cs->desktopOpacity);
1235
1236 glPushMatrix ();
1237
1238 sa.yRotate += (360.0f / size) * (cs->xRotations + 1);
1239 if (!cs->opt[CUBE_SCREEN_OPTION_ADJUST_IMAGE].value.b)
1240 sa.yRotate -= (360.0f / size) * s->x;
1241
1242 (*s->applyScreenTransform) (s, &sa, output, &sTransform);
1243
1244 glLoadMatrixf (sTransform.m);
1245 glTranslatef (cs->outputXOffset, -cs->outputYOffset, 0.0f);
1246 glScalef (cs->outputXScale, cs->outputYScale, 1.0f);
1247
1248 if (cs->desktopOpacity != OPAQUE)
1249 {
1250 screenTexEnvMode (s, GL_MODULATE);
1251 glEnable (GL_BLEND);
1252 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1253 }
1254
1255 glVertexPointer (3, GL_FLOAT, 0, cs->vertices);
1256
1257 glDrawArrays (GL_TRIANGLE_FAN, cs->nVertices >> 1,
1258 cs->nVertices >> 1);
1259
1260 glPopMatrix ();
1261
1262 glColor4usv (defaultColor);
1263 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
1264
1265 screenTexEnvMode (s, GL_REPLACE);
1266 glDisable (GL_BLEND);
1267 glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1268 }
1269
1270 static void
cubePaintInside(CompScreen * s,const ScreenPaintAttrib * sAttrib,const CompTransform * transform,CompOutput * output,int size)1271 cubePaintInside (CompScreen *s,
1272 const ScreenPaintAttrib *sAttrib,
1273 const CompTransform *transform,
1274 CompOutput *output,
1275 int size)
1276 {
1277 }
1278
1279 static void
cubeEnableOutputClipping(CompScreen * s,const CompTransform * transform,Region region,CompOutput * output)1280 cubeEnableOutputClipping (CompScreen *s,
1281 const CompTransform *transform,
1282 Region region,
1283 CompOutput *output)
1284 {
1285 CUBE_SCREEN (s);
1286
1287 if (cs->rotationState != RotationNone)
1288 {
1289 glPushMatrix ();
1290 glLoadMatrixf (transform->m);
1291 glTranslatef (cs->outputXOffset, -cs->outputYOffset, 0.0f);
1292 glScalef (cs->outputXScale, cs->outputYScale, 1.0f);
1293
1294 if (cs->invert == 1)
1295 {
1296 GLdouble clipPlane0[] = { 1.0, 0.0, 0.5 / cs->distance, 0.0 };
1297 GLdouble clipPlane1[] = { -1.0, 0.0, 0.5 / cs->distance, 0.0 };
1298 GLdouble clipPlane2[] = { 0.0, -1.0, 0.5 / cs->distance, 0.0 };
1299 GLdouble clipPlane3[] = { 0.0, 1.0, 0.5 / cs->distance, 0.0 };
1300 glClipPlane (GL_CLIP_PLANE0, clipPlane0);
1301 glClipPlane (GL_CLIP_PLANE1, clipPlane1);
1302 glClipPlane (GL_CLIP_PLANE2, clipPlane2);
1303 glClipPlane (GL_CLIP_PLANE3, clipPlane3);
1304 }
1305 else
1306 {
1307 GLdouble clipPlane0[] = { -1.0, 0.0, -0.5 / cs->distance, 0.0 };
1308 GLdouble clipPlane1[] = { 1.0, 0.0, -0.5 / cs->distance, 0.0 };
1309 GLdouble clipPlane2[] = { 0.0, 1.0, -0.5 / cs->distance, 0.0 };
1310 GLdouble clipPlane3[] = { 0.0, -1.0, -0.5 / cs->distance, 0.0 };
1311 glClipPlane (GL_CLIP_PLANE0, clipPlane0);
1312 glClipPlane (GL_CLIP_PLANE1, clipPlane1);
1313 glClipPlane (GL_CLIP_PLANE2, clipPlane2);
1314 glClipPlane (GL_CLIP_PLANE3, clipPlane3);
1315 }
1316
1317 glEnable (GL_CLIP_PLANE0);
1318 glEnable (GL_CLIP_PLANE1);
1319 glEnable (GL_CLIP_PLANE2);
1320 glEnable (GL_CLIP_PLANE3);
1321
1322 glPopMatrix ();
1323 }
1324 else
1325 {
1326 UNWRAP (cs, s, enableOutputClipping);
1327 (*s->enableOutputClipping) (s, transform, region, output);
1328 WRAP (cs, s, enableOutputClipping, cubeEnableOutputClipping);
1329 }
1330 }
1331
1332 static void
cubePaintViewport(CompScreen * s,const ScreenPaintAttrib * sAttrib,const CompTransform * transform,Region region,CompOutput * output,unsigned int mask)1333 cubePaintViewport (CompScreen *s,
1334 const ScreenPaintAttrib *sAttrib,
1335 const CompTransform *transform,
1336 Region region,
1337 CompOutput *output,
1338 unsigned int mask)
1339 {
1340 (*s->paintTransformedOutput) (s, sAttrib, transform, region, output, mask);
1341 }
1342
1343 static void
cubePaintTransformedOutput(CompScreen * s,const ScreenPaintAttrib * sAttrib,const CompTransform * transform,Region region,CompOutput * outputPtr,unsigned int mask)1344 cubePaintTransformedOutput (CompScreen *s,
1345 const ScreenPaintAttrib *sAttrib,
1346 const CompTransform *transform,
1347 Region region,
1348 CompOutput *outputPtr,
1349 unsigned int mask)
1350 {
1351 ScreenPaintAttrib sa = *sAttrib;
1352 float xRotate, vRotate, progress;
1353 int hsize;
1354 float size;
1355 GLenum filter = s->display->textureFilter;
1356 PaintOrder paintOrder;
1357 Bool wasCulled = FALSE;
1358 Bool paintCaps;
1359 int cullNorm, cullInv;
1360 int output = 0;
1361
1362 CUBE_SCREEN (s);
1363
1364 output = (outputPtr->id != ~0) ? outputPtr->id : 0;
1365
1366 if (((outputPtr->id != ~0) && cs->recalcOutput) ||
1367 ((outputPtr->id == ~0) && !cs->recalcOutput && cs->nOutput > 1))
1368 {
1369 cs->recalcOutput = (outputPtr->id == ~0);
1370 cs->nOutput = 1;
1371 cubeUpdateGeometry (s, s->hsize, cs->invert);
1372 }
1373
1374 hsize = s->hsize * cs->nOutput;
1375 size = hsize;
1376
1377 glGetIntegerv (GL_CULL_FACE_MODE, &cullNorm);
1378 cullInv = (cullNorm == GL_BACK)? GL_FRONT : GL_BACK;
1379 wasCulled = glIsEnabled (GL_CULL_FACE);
1380
1381 if (!cs->fullscreenOutput)
1382 {
1383 cs->outputXScale = (float) s->width / outputPtr->width;
1384 cs->outputYScale = (float) s->height / outputPtr->height;
1385
1386 cs->outputXOffset =
1387 (s->width / 2.0f -
1388 (outputPtr->region.extents.x1 +
1389 outputPtr->region.extents.x2) / 2.0f) /
1390 (float) outputPtr->width;
1391
1392 cs->outputYOffset =
1393 (s->height / 2.0f -
1394 (outputPtr->region.extents.y1 +
1395 outputPtr->region.extents.y2) / 2.0f) /
1396 (float) outputPtr->height;
1397 }
1398 else
1399 {
1400 cs->outputXScale = 1.0f;
1401 cs->outputYScale = 1.0f;
1402 cs->outputXOffset = 0.0f;
1403 cs->outputYOffset = 0.0f;
1404 }
1405
1406 (*cs->getRotation) (s, &xRotate, &vRotate, &progress);
1407
1408 sa.xRotate += xRotate;
1409 sa.vRotate += vRotate;
1410
1411 if (!cs->cleared[output])
1412 {
1413 float rRotate;
1414
1415 rRotate = xRotate - ((s->x *360.0f) / s->hsize);
1416
1417 (*cs->clearTargetOutput) (s, rRotate, vRotate);
1418 cs->cleared[output] = TRUE;
1419 }
1420
1421 mask &= ~PAINT_SCREEN_CLEAR_MASK;
1422
1423 UNWRAP (cs, s, paintTransformedOutput);
1424
1425 if (cs->grabIndex)
1426 {
1427 sa.vRotate = 0.0f;
1428
1429 size += cs->unfold * 8.0f;
1430 size += powf (cs->unfold, 6) * 64.0;
1431 size += powf (cs->unfold, 16) * 8192.0;
1432
1433 sa.zTranslate = -cs->invert * (0.5f / tanf (M_PI / size));
1434
1435 /* distance we move the camera back when unfolding the cube.
1436 currently hardcoded to 1.5 but it should probably be optional. */
1437 sa.zCamera -= cs->unfold * 1.5f;
1438 }
1439 else
1440 {
1441 if (vRotate > 100.0f)
1442 sa.vRotate = 100.0f;
1443 else if (vRotate < -100.0f)
1444 sa.vRotate = -100.0f;
1445 else
1446 sa.vRotate = vRotate;
1447
1448 sa.zTranslate = -cs->invert * cs->distance;
1449 }
1450
1451 if (sa.xRotate > 0.0f)
1452 cs->xRotations = (int) (hsize * sa.xRotate + 180.0f) / 360.0f;
1453 else
1454 cs->xRotations = (int) (hsize * sa.xRotate - 180.0f) / 360.0f;
1455
1456 sa.xRotate -= (360.0f * cs->xRotations) / hsize;
1457 sa.xRotate *= cs->invert;
1458
1459 sa.xRotate = sa.xRotate / size * hsize;
1460
1461 if (cs->grabIndex && cs->opt[CUBE_SCREEN_OPTION_MIPMAP].value.b)
1462 s->display->textureFilter = GL_LINEAR_MIPMAP_LINEAR;
1463
1464 if (cs->invert == 1)
1465 {
1466 /* Outside cube - start with FTB faces */
1467 paintOrder = FTB;
1468 glCullFace (cullInv);
1469 }
1470 else
1471 {
1472 /* Inside cube - start with BTF faces */
1473 paintOrder = BTF;
1474 }
1475
1476 if (cs->invert == -1 || cs->paintAllViewports)
1477 cubePaintAllViewports (s, &sa, transform, region, outputPtr,
1478 mask, cs->xRotations, size, hsize, paintOrder);
1479
1480 glCullFace (cullNorm);
1481
1482 if (wasCulled && cs->paintAllViewports)
1483 glDisable (GL_CULL_FACE);
1484
1485 paintCaps = !cs->grabIndex && (hsize > 2) && !cs->capsPainted[output] &&
1486 (cs->invert != 1 || cs->desktopOpacity != OPAQUE ||
1487 cs->paintAllViewports || sa.vRotate != 0.0f ||
1488 sa.yTranslate != 0.0f);
1489
1490 if (paintCaps)
1491 {
1492 Bool topDir, bottomDir, allCaps;
1493
1494 static CompVector top[3] = { { .v = { 0.5, 0.5, 0.0, 1.0} },
1495 { .v = { 0.0, 0.5, -0.5, 1.0} },
1496 { .v = { 0.0, 0.5, 0.0, 1.0} } };
1497 static CompVector bottom[3] = { { .v = { 0.5, -0.5, 0.0, 1.0} },
1498 { .v = { 0.0, -0.5, -0.5, 1.0} },
1499 { .v = { 0.0, -0.5, 0.0, 1.0} } };
1500
1501 topDir = (*cs->checkOrientation) (s, &sa, transform, outputPtr, top);
1502 bottomDir = (*cs->checkOrientation) (s, &sa, transform,
1503 outputPtr, bottom);
1504
1505 cs->capsPainted[output] = TRUE;
1506
1507 allCaps = cs->paintAllViewports || cs->invert != 1;
1508
1509 if (topDir && bottomDir)
1510 {
1511 glNormal3f (0.0f, -1.0f, 0.0f);
1512 if (allCaps)
1513 {
1514 (*cs->paintBottom) (s, &sa, transform, outputPtr, hsize);
1515 glNormal3f (0.0f, 0.0f, -1.0f);
1516 (*cs->paintInside) (s, &sa, transform, outputPtr, hsize);
1517 glNormal3f (0.0f, -1.0f, 0.0f);
1518 }
1519 (*cs->paintTop) (s, &sa, transform, outputPtr, hsize);
1520 }
1521 else if (!topDir && !bottomDir)
1522 {
1523 glNormal3f (0.0f, 1.0f, 0.0f);
1524 if (allCaps)
1525 {
1526 (*cs->paintTop) (s, &sa, transform, outputPtr, hsize);
1527 glNormal3f (0.0f, 0.0f, -1.0f);
1528 (*cs->paintInside) (s, &sa, transform, outputPtr, hsize);
1529 glNormal3f (0.0f, 1.0f, 0.0f);
1530 }
1531 (*cs->paintBottom) (s, &sa, transform, outputPtr, hsize);
1532 }
1533 else if (allCaps)
1534 {
1535 glNormal3f (0.0f, 1.0f, 0.0f);
1536 (*cs->paintTop) (s, &sa, transform, outputPtr, hsize);
1537 glNormal3f (0.0f, -1.0f, 0.0f);
1538 (*cs->paintBottom) (s, &sa, transform, outputPtr, hsize);
1539 glNormal3f (0.0f, 0.0f, -1.0f);
1540 (*cs->paintInside) (s, &sa, transform, outputPtr, hsize);
1541 }
1542 glNormal3f (0.0f, 0.0f, -1.0f);
1543 }
1544
1545 if (wasCulled)
1546 glEnable (GL_CULL_FACE);
1547
1548 if (cs->invert == 1)
1549 {
1550 /* Outside cube - continue with BTF faces */
1551 paintOrder = BTF;
1552 }
1553 else
1554 {
1555 /* Inside cube - continue with FTB faces */
1556 paintOrder = FTB;
1557 glCullFace (cullInv);
1558 }
1559
1560 if (cs->invert == 1 || cs->paintAllViewports)
1561 cubePaintAllViewports (s, &sa, transform, region,
1562 outputPtr, mask, cs->xRotations,
1563 size, hsize, paintOrder);
1564
1565 glCullFace (cullNorm);
1566
1567 s->display->textureFilter = filter;
1568
1569 WRAP (cs, s, paintTransformedOutput, cubePaintTransformedOutput);
1570 }
1571
1572 static Bool
cubePaintWindow(CompWindow * w,const WindowPaintAttrib * attrib,const CompTransform * transform,Region region,unsigned int mask)1573 cubePaintWindow (CompWindow *w,
1574 const WindowPaintAttrib *attrib,
1575 const CompTransform *transform,
1576 Region region,
1577 unsigned int mask)
1578 {
1579 Bool status;
1580 CompScreen *s = w->screen;
1581 CUBE_SCREEN (s);
1582
1583 if ((w->type & CompWindowTypeDesktopMask) &&
1584 (attrib->opacity != cs->desktopOpacity))
1585 {
1586 WindowPaintAttrib wAttrib = *attrib;
1587
1588 wAttrib.opacity = cs->desktopOpacity;
1589
1590 UNWRAP (cs, s, paintWindow);
1591 status = (*s->paintWindow) (w, &wAttrib, transform, region, mask);
1592 WRAP (cs, s, paintWindow, cubePaintWindow);
1593 }
1594 else
1595 {
1596 UNWRAP (cs, s, paintWindow);
1597 status = (*s->paintWindow) (w, attrib, transform, region, mask);
1598 WRAP (cs, s, paintWindow, cubePaintWindow);
1599 }
1600
1601 return status;
1602 }
1603
1604 static void
cubeInitWindowWalker(CompScreen * s,CompWalker * walker)1605 cubeInitWindowWalker (CompScreen *s, CompWalker* walker)
1606 {
1607 CUBE_SCREEN (s);
1608
1609 UNWRAP (cs, s, initWindowWalker);
1610 (*s->initWindowWalker) (s, walker);
1611 WRAP (cs, s, initWindowWalker, cubeInitWindowWalker);
1612
1613 if (cs->paintOrder == FTB)
1614 {
1615 WalkInitProc tmpInit = walker->first;
1616 WalkStepProc tmpStep = walker->next;
1617
1618 walker->first = walker->last;
1619 walker->last = tmpInit;
1620
1621 walker->next = walker->prev;
1622 walker->prev = tmpStep;
1623 }
1624 }
1625
1626 static void
cubeApplyScreenTransform(CompScreen * s,const ScreenPaintAttrib * sAttrib,CompOutput * output,CompTransform * transform)1627 cubeApplyScreenTransform (CompScreen *s,
1628 const ScreenPaintAttrib *sAttrib,
1629 CompOutput *output,
1630 CompTransform *transform)
1631 {
1632 CUBE_SCREEN (s);
1633
1634 matrixTranslate (transform, cs->outputXOffset, -cs->outputYOffset, 0.0f);
1635 matrixScale (transform, cs->outputXScale, cs->outputYScale, 1.0f);
1636
1637 UNWRAP (cs, s, applyScreenTransform);
1638 (*s->applyScreenTransform) (s, sAttrib, output, transform);
1639 WRAP (cs, s, applyScreenTransform, cubeApplyScreenTransform);
1640
1641 matrixScale (transform, 1.0f / cs->outputXScale,
1642 1.0f / cs->outputYScale, 1.0f);
1643 matrixTranslate (transform, -cs->outputXOffset, cs->outputYOffset, 0.0f);
1644 }
1645
1646 static Bool
cubeUnfold(CompDisplay * d,CompAction * action,CompActionState state,CompOption * option,int nOption)1647 cubeUnfold (CompDisplay *d,
1648 CompAction *action,
1649 CompActionState state,
1650 CompOption *option,
1651 int nOption)
1652 {
1653 CompScreen *s;
1654 Window xid;
1655
1656 xid = getIntOptionNamed (option, nOption, "root", 0);
1657
1658 s = findScreenAtDisplay (d, xid);
1659 if (s)
1660 {
1661 CUBE_SCREEN (s);
1662
1663 if (s->hsize * cs->nOutput < 4)
1664 return FALSE;
1665
1666 if (otherScreenGrabExist (s, "rotate", "switcher", "cube", NULL))
1667 return FALSE;
1668
1669 if (!cs->grabIndex)
1670 cs->grabIndex = pushScreenGrab (s, s->invisibleCursor, "cube");
1671
1672 if (cs->grabIndex)
1673 {
1674 cs->unfolded = TRUE;
1675 damageScreen (s);
1676 }
1677
1678 if (state & CompActionStateInitButton)
1679 action->state |= CompActionStateTermButton;
1680
1681 if (state & CompActionStateInitKey)
1682 action->state |= CompActionStateTermKey;
1683 }
1684
1685 return FALSE;
1686 }
1687
1688 static Bool
cubeFold(CompDisplay * d,CompAction * action,CompActionState state,CompOption * option,int nOption)1689 cubeFold (CompDisplay *d,
1690 CompAction *action,
1691 CompActionState state,
1692 CompOption *option,
1693 int nOption)
1694 {
1695 CompScreen *s;
1696 Window xid;
1697
1698 xid = getIntOptionNamed (option, nOption, "root", 0);
1699
1700 for (s = d->screens; s; s = s->next)
1701 {
1702 CUBE_SCREEN (s);
1703
1704 if (xid && s->root != xid)
1705 continue;
1706
1707 if (cs->grabIndex)
1708 {
1709 cs->unfolded = FALSE;
1710 damageScreen (s);
1711 }
1712 }
1713
1714 action->state &= ~(CompActionStateTermButton | CompActionStateTermKey);
1715
1716 return FALSE;
1717 }
1718
1719 static Bool
cubeNextImage(CompDisplay * d,CompAction * action,CompActionState state,CompOption * option,int nOption)1720 cubeNextImage (CompDisplay *d,
1721 CompAction *action,
1722 CompActionState state,
1723 CompOption *option,
1724 int nOption)
1725 {
1726 CompScreen *s;
1727 Window xid;
1728
1729 xid = getIntOptionNamed (option, nOption, "root", 0);
1730
1731 s = findScreenAtDisplay (d, xid);
1732 if (s)
1733 {
1734 int imgNFile;
1735
1736 CUBE_SCREEN (s);
1737
1738 imgNFile = cs->opt[CUBE_SCREEN_OPTION_IMAGES].value.list.nValue;
1739 if (imgNFile)
1740 {
1741 cubeLoadImg (s, (cs->imgCurFile + 1) % imgNFile);
1742 damageScreen (s);
1743 }
1744 }
1745
1746 return FALSE;
1747 }
1748
1749 static Bool
cubePrevImage(CompDisplay * d,CompAction * action,CompActionState state,CompOption * option,int nOption)1750 cubePrevImage (CompDisplay *d,
1751 CompAction *action,
1752 CompActionState state,
1753 CompOption *option,
1754 int nOption)
1755 {
1756 CompScreen *s;
1757 Window xid;
1758
1759 xid = getIntOptionNamed (option, nOption, "root", 0);
1760
1761 s = findScreenAtDisplay (d, xid);
1762 if (s)
1763 {
1764 int imgNFile;
1765
1766 CUBE_SCREEN (s);
1767
1768 imgNFile = cs->opt[CUBE_SCREEN_OPTION_IMAGES].value.list.nValue;
1769 if (imgNFile)
1770 {
1771 cubeLoadImg (s, (cs->imgCurFile - 1 + imgNFile) % imgNFile);
1772 damageScreen (s);
1773 }
1774 }
1775
1776 return FALSE;
1777 }
1778
1779 static void
cubeOutputChangeNotify(CompScreen * s)1780 cubeOutputChangeNotify (CompScreen *s)
1781 {
1782 CUBE_SCREEN (s);
1783
1784 cubeUpdateOutputs (s);
1785 cubeUpdateGeometry (s, s->hsize, cs->invert);
1786
1787 if (cs->opt[CUBE_SCREEN_OPTION_IMAGES].value.list.nValue)
1788 cubeLoadImg (s, cs->imgCurFile);
1789
1790 UNWRAP (cs, s, outputChangeNotify);
1791 (*s->outputChangeNotify) (s);
1792 WRAP (cs, s, outputChangeNotify, cubeOutputChangeNotify);
1793 }
1794
1795 static Bool
cubeSetOptionForPlugin(CompObject * o,const char * plugin,const char * name,CompOptionValue * value)1796 cubeSetOptionForPlugin (CompObject *o,
1797 const char *plugin,
1798 const char *name,
1799 CompOptionValue *value)
1800 {
1801 Bool status;
1802
1803 CUBE_CORE (&core);
1804
1805 UNWRAP (cc, &core, setOptionForPlugin);
1806 status = (*core.setOptionForPlugin) (o, plugin, name, value);
1807 WRAP (cc, &core, setOptionForPlugin, cubeSetOptionForPlugin);
1808
1809 if (status && o->type == COMP_OBJECT_TYPE_SCREEN)
1810 {
1811 if (strcmp (plugin, "core") == 0 && strcmp (name, "hsize") == 0)
1812 {
1813 CompScreen *s = (CompScreen *) o;
1814
1815 CUBE_SCREEN (s);
1816
1817 cubeUpdateGeometry (s, s->hsize, cs->invert);
1818 }
1819 }
1820
1821 return status;
1822 }
1823
1824 static CompOption *
cubeGetDisplayOptions(CompPlugin * plugin,CompDisplay * display,int * count)1825 cubeGetDisplayOptions (CompPlugin *plugin,
1826 CompDisplay *display,
1827 int *count)
1828 {
1829 CUBE_DISPLAY (display);
1830
1831 *count = NUM_OPTIONS (cd);
1832 return cd->opt;
1833 }
1834
1835 static Bool
cubeSetDisplayOption(CompPlugin * plugin,CompDisplay * display,const char * name,CompOptionValue * value)1836 cubeSetDisplayOption (CompPlugin *plugin,
1837 CompDisplay *display,
1838 const char *name,
1839 CompOptionValue *value)
1840 {
1841 CompOption *o;
1842 int index;
1843
1844 CUBE_DISPLAY (display);
1845
1846 o = compFindOption (cd->opt, NUM_OPTIONS (cd), name, &index);
1847 if (!o)
1848 return FALSE;
1849
1850 switch (index) {
1851 case CUBE_DISPLAY_OPTION_ABI:
1852 case CUBE_DISPLAY_OPTION_INDEX:
1853 break;
1854 default:
1855 return compSetDisplayOption (display, o, value);
1856 }
1857
1858 return FALSE;
1859 }
1860
1861 static Bool
cubeInitCore(CompPlugin * p,CompCore * c)1862 cubeInitCore (CompPlugin *p,
1863 CompCore *c)
1864 {
1865 CubeCore *cc;
1866
1867 if (!checkPluginABI ("core", CORE_ABIVERSION))
1868 return FALSE;
1869
1870 cc = malloc (sizeof (CubeCore));
1871 if (!cc)
1872 return FALSE;
1873
1874 cubeDisplayPrivateIndex = allocateDisplayPrivateIndex ();
1875 if (cubeDisplayPrivateIndex < 0)
1876 {
1877 free (cc);
1878 return FALSE;
1879 }
1880
1881 WRAP (cc, &core, setOptionForPlugin, cubeSetOptionForPlugin);
1882
1883 c->base.privates[cubeCorePrivateIndex].ptr = cc;
1884
1885 return TRUE;
1886 }
1887
1888 static void
cubeFiniCore(CompPlugin * p,CompCore * c)1889 cubeFiniCore (CompPlugin *p,
1890 CompCore *c)
1891 {
1892 CUBE_CORE (c);
1893
1894 UNWRAP (cc, &core, setOptionForPlugin);
1895
1896 freeDisplayPrivateIndex (cubeDisplayPrivateIndex);
1897
1898 free (cc);
1899 }
1900
1901 static const CompMetadataOptionInfo cubeDisplayOptionInfo[] = {
1902 { "abi", "int", 0, 0, 0 },
1903 { "index", "int", 0, 0, 0 },
1904 { "unfold_key", "key", 0, cubeUnfold, cubeFold },
1905 { "next_slide_key", "key", "<passive_grab>false</passive_grab>",
1906 cubeNextImage, 0 },
1907 { "prev_slide_key", "key", "<passive_grab>false</passive_grab>",
1908 cubePrevImage, 0 }
1909 };
1910
1911 static Bool
cubeInitDisplay(CompPlugin * p,CompDisplay * d)1912 cubeInitDisplay (CompPlugin *p,
1913 CompDisplay *d)
1914 {
1915 CubeDisplay *cd;
1916
1917 cd = malloc (sizeof (CubeDisplay));
1918 if (!cd)
1919 return FALSE;
1920
1921 if (!compInitDisplayOptionsFromMetadata (d,
1922 &cubeMetadata,
1923 cubeDisplayOptionInfo,
1924 cd->opt,
1925 CUBE_DISPLAY_OPTION_NUM))
1926 {
1927 free (cd);
1928 return FALSE;
1929 }
1930
1931 cd->opt[CUBE_DISPLAY_OPTION_ABI].value.i = CUBE_ABIVERSION;
1932 cd->opt[CUBE_DISPLAY_OPTION_INDEX].value.i = cubeDisplayPrivateIndex;
1933
1934 cd->screenPrivateIndex = allocateScreenPrivateIndex (d);
1935 if (cd->screenPrivateIndex < 0)
1936 {
1937 compFiniDisplayOptions (d, cd->opt, CUBE_DISPLAY_OPTION_NUM);
1938 free (cd);
1939 return FALSE;
1940 }
1941
1942 d->base.privates[cubeDisplayPrivateIndex].ptr = cd;
1943
1944 return TRUE;
1945 }
1946
1947 static void
cubeFiniDisplay(CompPlugin * p,CompDisplay * d)1948 cubeFiniDisplay (CompPlugin *p,
1949 CompDisplay *d)
1950 {
1951 CUBE_DISPLAY (d);
1952
1953 freeScreenPrivateIndex (d, cd->screenPrivateIndex);
1954
1955 compFiniDisplayOptions (d, cd->opt, CUBE_DISPLAY_OPTION_NUM);
1956
1957 free (cd);
1958 }
1959
1960 static const CompMetadataOptionInfo cubeScreenOptionInfo[] = {
1961 { "color", "color", 0, 0, 0 },
1962 { "in", "bool", 0, 0, 0 },
1963 { "scale_image", "bool", 0, 0, 0 },
1964 { "images", "list", "<type>string</type>", 0, 0 },
1965 { "skydome", "bool", 0, 0, 0 },
1966 { "skydome_image", "string", 0, 0, 0 },
1967 { "skydome_animated", "bool", 0, 0, 0 },
1968 { "skydome_gradient_start_color", "color", 0, 0, 0 },
1969 { "skydome_gradient_end_color", "color", 0, 0, 0 },
1970 { "acceleration", "float", "<min>1.0</min>", 0, 0 },
1971 { "speed", "float", "<min>0.1</min>", 0, 0 },
1972 { "timestep", "float", "<min>0.1</min>", 0, 0 },
1973 { "mipmap", "bool", 0, 0, 0 },
1974 { "adjust_image", "bool", 0, 0, 0 },
1975 { "active_opacity", "float", "<min>0.0</min><max>100.0</max>", 0, 0 },
1976 { "inactive_opacity", "float", "<min>0.0</min><max>100.0</max>", 0, 0 },
1977 { "transparent_manual_only", "bool", 0, 0, 0 },
1978 { "multioutput_mode", "int", "<min>0</min><max>2</max>", 0, 0 }
1979 };
1980
1981 static Bool
cubeInitScreen(CompPlugin * p,CompScreen * s)1982 cubeInitScreen (CompPlugin *p,
1983 CompScreen *s)
1984 {
1985 CubeScreen *cs;
1986
1987 CUBE_DISPLAY (s->display);
1988
1989 cs = malloc (sizeof (CubeScreen));
1990 if (!cs)
1991 return FALSE;
1992
1993 if (!compInitScreenOptionsFromMetadata (s,
1994 &cubeMetadata,
1995 cubeScreenOptionInfo,
1996 cs->opt,
1997 CUBE_SCREEN_OPTION_NUM))
1998 {
1999 free (cs);
2000 return FALSE;
2001 }
2002
2003 cs->pw = 0;
2004 cs->ph = 0;
2005
2006 cs->invert = 1;
2007
2008 cs->tc[0] = cs->tc[1] = cs->tc[2] = cs->tc[3] = 0.0f;
2009 cs->tc[4] = cs->tc[5] = cs->tc[6] = cs->tc[7] = 0.0f;
2010
2011 memcpy (cs->color, cs->opt[CUBE_SCREEN_OPTION_COLOR].value.c,
2012 sizeof (cs->color));
2013
2014 cs->nVertices = 0;
2015 cs->vertices = NULL;
2016
2017 cs->grabIndex = 0;
2018
2019 cs->srcOutput = 0;
2020
2021 cs->skyListId = 0;
2022
2023 cs->getRotation = cubeGetRotation;
2024 cs->clearTargetOutput = cubeClearTargetOutput;
2025 cs->paintTop = cubePaintTop;
2026 cs->paintBottom = cubePaintBottom;
2027 cs->paintInside = cubePaintInside;
2028 cs->checkOrientation = cubeCheckOrientation;
2029 cs->paintViewport = cubePaintViewport;
2030 cs->shouldPaintViewport = cubeShouldPaintViewport;
2031
2032 s->base.privates[cd->screenPrivateIndex].ptr = cs;
2033
2034 initTexture (s, &cs->texture);
2035 initTexture (s, &cs->sky);
2036
2037 cs->imgCurFile = 0;
2038
2039 cs->unfolded = FALSE;
2040 cs->unfold = 0.0f;
2041
2042 cs->unfoldVelocity = 0.0f;
2043
2044 cs->paintAllViewports = FALSE;
2045 cs->fullscreenOutput = TRUE;
2046
2047 cs->outputXScale = 1.0f;
2048 cs->outputYScale = 1.0f;
2049 cs->outputXOffset = 0.0f;
2050 cs->outputYOffset = 0.0f;
2051
2052 cs->rotationState = RotationNone;
2053
2054 cs->desktopOpacity = OPAQUE;
2055
2056 cs->lastOpacityIndex = CUBE_SCREEN_OPTION_INACTIVE_OPACITY;
2057
2058 cs->moMode = cs->opt[CUBE_SCREEN_OPTION_MULTIOUTPUT_MODE].value.i;
2059
2060 cs->recalcOutput = FALSE;
2061
2062 memset (cs->cleared, 0, sizeof (cs->cleared));
2063
2064 cubeUpdateOutputs (s);
2065
2066 if (!cubeUpdateGeometry (s, s->hsize, cs->invert))
2067 {
2068 compFiniScreenOptions (s, cs->opt, CUBE_SCREEN_OPTION_NUM);
2069 free (cs);
2070 return FALSE;
2071 }
2072
2073 if (cs->opt[CUBE_SCREEN_OPTION_IMAGES].value.list.nValue)
2074 {
2075 cubeLoadImg (s, cs->imgCurFile);
2076 damageScreen (s);
2077 }
2078
2079 WRAP (cs, s, preparePaintScreen, cubePreparePaintScreen);
2080 WRAP (cs, s, donePaintScreen, cubeDonePaintScreen);
2081 WRAP (cs, s, paintScreen, cubePaintScreen);
2082 WRAP (cs, s, paintOutput, cubePaintOutput);
2083 WRAP (cs, s, paintTransformedOutput, cubePaintTransformedOutput);
2084 WRAP (cs, s, enableOutputClipping, cubeEnableOutputClipping);
2085 WRAP (cs, s, paintWindow, cubePaintWindow);
2086 WRAP (cs, s, applyScreenTransform, cubeApplyScreenTransform);
2087 WRAP (cs, s, outputChangeNotify, cubeOutputChangeNotify);
2088 WRAP (cs, s, initWindowWalker, cubeInitWindowWalker);
2089
2090 return TRUE;
2091 }
2092
2093 static void
cubeFiniScreen(CompPlugin * p,CompScreen * s)2094 cubeFiniScreen (CompPlugin *p,
2095 CompScreen *s)
2096 {
2097 CUBE_SCREEN (s);
2098
2099 if (cs->vertices)
2100 free (cs->vertices);
2101
2102 if (cs->skyListId)
2103 glDeleteLists (cs->skyListId, 1);
2104
2105 UNWRAP (cs, s, preparePaintScreen);
2106 UNWRAP (cs, s, donePaintScreen);
2107 UNWRAP (cs, s, paintScreen);
2108 UNWRAP (cs, s, paintOutput);
2109 UNWRAP (cs, s, paintTransformedOutput);
2110 UNWRAP (cs, s, enableOutputClipping);
2111 UNWRAP (cs, s, paintWindow);
2112 UNWRAP (cs, s, applyScreenTransform);
2113 UNWRAP (cs, s, outputChangeNotify);
2114 UNWRAP (cs, s, initWindowWalker);
2115
2116 finiTexture (s, &cs->texture);
2117 finiTexture (s, &cs->sky);
2118
2119 compFiniScreenOptions (s, cs->opt, CUBE_SCREEN_OPTION_NUM);
2120
2121 free (cs);
2122 }
2123
2124 static CompBool
cubeInitObject(CompPlugin * p,CompObject * o)2125 cubeInitObject (CompPlugin *p,
2126 CompObject *o)
2127 {
2128 static InitPluginObjectProc dispTab[] = {
2129 (InitPluginObjectProc) cubeInitCore,
2130 (InitPluginObjectProc) cubeInitDisplay,
2131 (InitPluginObjectProc) cubeInitScreen
2132 };
2133
2134 RETURN_DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), TRUE, (p, o));
2135 }
2136
2137 static void
cubeFiniObject(CompPlugin * p,CompObject * o)2138 cubeFiniObject (CompPlugin *p,
2139 CompObject *o)
2140 {
2141 static FiniPluginObjectProc dispTab[] = {
2142 (FiniPluginObjectProc) cubeFiniCore,
2143 (FiniPluginObjectProc) cubeFiniDisplay,
2144 (FiniPluginObjectProc) cubeFiniScreen
2145 };
2146
2147 DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), (p, o));
2148 }
2149
2150 static CompOption *
cubeGetObjectOptions(CompPlugin * plugin,CompObject * object,int * count)2151 cubeGetObjectOptions (CompPlugin *plugin,
2152 CompObject *object,
2153 int *count)
2154 {
2155 static GetPluginObjectOptionsProc dispTab[] = {
2156 (GetPluginObjectOptionsProc) 0, /* GetCoreOptions */
2157 (GetPluginObjectOptionsProc) cubeGetDisplayOptions,
2158 (GetPluginObjectOptionsProc) cubeGetScreenOptions
2159 };
2160
2161 *count = 0;
2162 RETURN_DISPATCH (object, dispTab, ARRAY_SIZE (dispTab),
2163 (void *) count, (plugin, object, count));
2164 }
2165
2166 static CompBool
cubeSetObjectOption(CompPlugin * plugin,CompObject * object,const char * name,CompOptionValue * value)2167 cubeSetObjectOption (CompPlugin *plugin,
2168 CompObject *object,
2169 const char *name,
2170 CompOptionValue *value)
2171 {
2172 static SetPluginObjectOptionProc dispTab[] = {
2173 (SetPluginObjectOptionProc) 0, /* SetCoreOption */
2174 (SetPluginObjectOptionProc) cubeSetDisplayOption,
2175 (SetPluginObjectOptionProc) cubeSetScreenOption
2176 };
2177
2178 RETURN_DISPATCH (object, dispTab, ARRAY_SIZE (dispTab), FALSE,
2179 (plugin, object, name, value));
2180 }
2181
2182 static Bool
cubeInit(CompPlugin * p)2183 cubeInit (CompPlugin *p)
2184 {
2185 if (!compInitPluginMetadataFromInfo (&cubeMetadata,
2186 p->vTable->name,
2187 cubeDisplayOptionInfo,
2188 CUBE_DISPLAY_OPTION_NUM,
2189 cubeScreenOptionInfo,
2190 CUBE_SCREEN_OPTION_NUM))
2191 return FALSE;
2192
2193 cubeCorePrivateIndex = allocateCorePrivateIndex ();
2194 if (cubeCorePrivateIndex < 0)
2195 {
2196 compFiniMetadata (&cubeMetadata);
2197 return FALSE;
2198 }
2199
2200 compAddMetadataFromFile (&cubeMetadata, p->vTable->name);
2201
2202 return TRUE;
2203 }
2204
2205 static void
cubeFini(CompPlugin * p)2206 cubeFini (CompPlugin *p)
2207 {
2208 freeCorePrivateIndex (cubeCorePrivateIndex);
2209 compFiniMetadata (&cubeMetadata);
2210 }
2211
2212 static CompMetadata *
cubeGetMetadata(CompPlugin * plugin)2213 cubeGetMetadata (CompPlugin *plugin)
2214 {
2215 return &cubeMetadata;
2216 }
2217
2218 CompPluginVTable cubeVTable = {
2219 "cube",
2220 cubeGetMetadata,
2221 cubeInit,
2222 cubeFini,
2223 cubeInitObject,
2224 cubeFiniObject,
2225 cubeGetObjectOptions,
2226 cubeSetObjectOption
2227 };
2228
2229 CompPluginVTable *
getCompPluginInfo20070830(void)2230 getCompPluginInfo20070830 (void)
2231 {
2232 return &cubeVTable;
2233 }
2234