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 <privates.h>
34
35 class CubePluginVTable :
36 public CompPlugin::VTableForScreenAndWindow<CubeScreen, PrivateCubeWindow>
37 {
38 public:
39
40 bool init ();
41 void fini ();
42 };
43
44 COMPIZ_PLUGIN_20090315 (cube, CubePluginVTable)
45
46 void
47 CubeScreenInterface::cubeGetRotation (float &x, float &v, float &progress)
48 WRAPABLE_DEF (cubeGetRotation, x, v, progress);
49
50 void
51 CubeScreenInterface::cubeClearTargetOutput (float xRotate, float vRotate)
52 WRAPABLE_DEF (cubeClearTargetOutput, xRotate, vRotate);
53
54 void
55 CubeScreenInterface::cubePaintTop (const GLScreenPaintAttrib &sAttrib,
56 const GLMatrix &transform,
57 CompOutput *output,
58 int size,
59 const GLVector &normal)
60 WRAPABLE_DEF (cubePaintTop, sAttrib, transform, output, size, normal)
61
62 void
63 CubeScreenInterface::cubePaintBottom (const GLScreenPaintAttrib &sAttrib,
64 const GLMatrix &transform,
65 CompOutput *output,
66 int size,
67 const GLVector &normal)
68 WRAPABLE_DEF (cubePaintBottom, sAttrib, transform, output, size, normal)
69
70 void
71 CubeScreenInterface::cubePaintInside (const GLScreenPaintAttrib &sAttrib,
72 const GLMatrix &transform,
73 CompOutput *output,
74 int size,
75 const GLVector &normal)
76 WRAPABLE_DEF (cubePaintInside, sAttrib, transform, output, size, normal)
77
78 bool
79 CubeScreenInterface::cubeCheckOrientation (const GLScreenPaintAttrib &sAttrib,
80 const GLMatrix &transform,
81 CompOutput *output,
82 std::vector<GLVector> &points)
83 WRAPABLE_DEF (cubeCheckOrientation, sAttrib, transform, output, points)
84
85 void
86 CubeScreenInterface::cubePaintViewport (const GLScreenPaintAttrib &sAttrib,
87 const GLMatrix &transform,
88 const CompRegion ®ion,
89 CompOutput *output,
90 unsigned int mask)
91 WRAPABLE_DEF (cubePaintViewport, sAttrib, transform, region, output, mask)
92
93 bool
94 CubeScreenInterface::cubeShouldPaintViewport (const GLScreenPaintAttrib &sAttrib,
95 const GLMatrix &transform,
96 CompOutput *output,
97 PaintOrder order)
98 WRAPABLE_DEF (cubeShouldPaintViewport, sAttrib, transform, output, order)
99
100 bool
101 CubeScreenInterface::cubeShouldPaintAllViewports ()
102 WRAPABLE_DEF (cubeShouldPaintAllViewports);
103
104 int
105 CubeScreen::invert () const
106 {
107 return priv->mInvert;
108 }
109
110 unsigned short*
111 CubeScreen::topColor () const
112 {
113 return priv->optionGetTopColor ();
114 }
115
116 unsigned short*
117 CubeScreen::bottomColor () const
118 {
119 return priv->optionGetBottomColor ();
120 }
121
122 bool
123 CubeScreen::unfolded () const
124 {
125 return priv->mUnfolded;
126 }
127
128 CubeScreen::RotationState
129 CubeScreen::rotationState () const
130 {
131 return priv->mRotationState;
132 }
133
134 void
135 CubeScreen::rotationState (CubeScreen::RotationState state)
136 {
137 priv->mRotationState = state;
138 }
139
140 int
141 CubeScreen::xRotations () const
142 {
143 return priv->mXRotations;
144 }
145
146 int
147 CubeScreen::nOutput () const
148 {
149 return priv->mNOutput;
150 }
151
152 float
153 CubeScreen::outputXScale () const
154 {
155 return priv->mOutputXScale;
156 }
157
158 float
159 CubeScreen::outputYScale () const
160 {
161 return priv->mOutputYScale;
162 }
163
164 float
165 CubeScreen::outputXOffset () const
166 {
167 return priv->mOutputXOffset;
168 }
169
170 float
171 CubeScreen::outputYOffset () const
172 {
173 return priv->mOutputYOffset;
174 }
175
176 float
177 CubeScreen::distance () const
178 {
179 return priv->mDistance;
180 }
181
182 float
183 CubeScreen::desktopOpacity () const
184 {
185 return priv->mDesktopOpacity;
186 }
187
188 CubeScreen::MultioutputMode
189 CubeScreen::multioutputMode () const
190 {
191 switch (priv->optionGetMultioutputMode ())
192 {
193 case CubeOptions::MultioutputModeOneBigCube:
194 return OneBigCube;
195 case CubeOptions::MultioutputModeMultipleCubes:
196 return MultipleCubes;
197 default:
198 break;
199 }
200
201 return Automatic;
202 }
203
204 int
205 CubeScreen::sourceOutput () const
206 {
207 return priv->mSrcOutput;
208 }
209
210 PaintOrder
211 CubeScreen::paintOrder () const
212 {
213 return priv->mPaintOrder;
214 }
215
216 bool
217 CubeScreen::cubeShouldPaintAllViewports ()
218 {
219 WRAPABLE_HND_FUNCTN_RETURN (bool, cubeShouldPaintAllViewports);
220
221 return priv->mPaintAllViewports;
222 }
223
224 void
225 CubeScreen::repaintCaps ()
226 {
227 memset (priv->mCapsPainted, 0, sizeof (Bool) * screen->outputDevs ().size ());
228 }
229
230 bool
231 PrivateCubeScreen::updateGeometry (int sides, int invert)
232 {
233 GLfloat radius, distance;
234 GLfloat *v;
235 int i, n;
236
237 sides *= mNOutput;
238
239 distance = 0.5f / tanf (M_PI / sides);
240 radius = 0.5f / sinf (M_PI / sides);
241
242 n = (sides + 2) * 2;
243
Condition "this->mNVertices != n", taking true branch
Condition "this->mNVertices != n", taking true branch
Condition "this->mNVertices != n", taking true branch
Condition "this->mNVertices != n", taking true branch
244 if (mNVertices != n)
245 {
246 v = (GLfloat *) realloc (mVertices, sizeof (GLfloat) * n * 3);
Condition "!v", taking false branch
Condition "!v", taking false branch
Condition "!v", taking false branch
Condition "!v", taking false branch
247 if (!v)
248 return false;
249
250 mNVertices = n;
251 mVertices = v;
Falling through to end of if statement
Falling through to end of if statement
Falling through to end of if statement
Falling through to end of if statement
252 }
253 else
254 v = mVertices;
255
256 *v++ = 0.0f;
257 *v++ = 0.5 * invert;
258 *v++ = 0.0f;
259
Condition "i <= sides", taking true branch
Jumped back to beginning of loop
Condition "i <= sides", taking false branch
Condition "i <= sides", taking true branch
Jumped back to beginning of loop
Condition "i <= sides", taking false branch
Condition "i <= sides", taking true branch
Jumped back to beginning of loop
Condition "i <= sides", taking false branch
Condition "i <= sides", taking true branch
Jumped back to beginning of loop
Condition "i <= sides", taking false branch
260 for (i = 0; i <= sides; i++)
261 {
262 *v++ = radius * sinf (i * 2 * M_PI / sides + M_PI / sides);
263 *v++ = 0.5 * invert;
264 *v++ = radius * cosf (i * 2 * M_PI / sides + M_PI / sides);
Jumping back to the beginning of the loop
Reached end of loop
Jumping back to the beginning of the loop
Reached end of loop
Jumping back to the beginning of the loop
Reached end of loop
Jumping back to the beginning of the loop
Reached end of loop
265 }
266
267 *v++ = 0.0f;
268 *v++ = -0.5 * invert;
269 *v++ = 0.0f;
270
Condition "i >= 0", taking true branch
Condition "i >= 0", taking true branch
Condition "i >= 0", taking true branch
Condition "i >= 0", taking true branch
271 for (i = sides; i >= 0; i--)
272 {
CID 12435 - DIVIDE_BY_ZERO
In expression "3.14159 / sides", division by expression "sides" which may be zero has undefined behavior.
In expression "i * 2 * 3.14159 / sides", division by expression "sides" which may be zero has undefined behavior.
273 *v++ = radius * sinf (i * 2 * M_PI / sides + M_PI / sides);
274 *v++ = -0.5 * invert;
CID 12435 - DIVIDE_BY_ZERO
In expression "3.14159 / sides", division by expression "sides" which may be zero has undefined behavior.
In expression "i * 2 * 3.14159 / sides", division by expression "sides" which may be zero has undefined behavior.
275 *v++ = radius * cosf (i * 2 * M_PI / sides + M_PI / sides);
276 }
277
278 mInvert = invert;
279 mDistance = distance;
280
281 return true;
282 }
283
284 void
285 PrivateCubeScreen::updateOutputs ()
286 {
287 CompOutput *pBox0, *pBox1;
288 unsigned int i, j;
289 int k, x;
290
291 k = 0;
292
293 mFullscreenOutput = true;
294
295 for (i = 0; i < screen->outputDevs ().size (); i++)
296 {
297 mOutputMask[i] = -1;
298
299 /* dimensions must match first output */
300 if (screen->outputDevs ()[i].width () != screen->outputDevs ()[0].width () ||
301 screen->outputDevs ()[i].height () != screen->outputDevs ()[0].height ())
302 continue;
303
304 pBox0 = &screen->outputDevs ()[0];
305 pBox1 = &screen->outputDevs ()[i];
306
307 /* top and bottom line must match first output */
308 if (pBox0->y1 () != pBox1->y1 () || pBox0->y2 () != pBox1->y2 ())
309 continue;
310
311 k++;
312
313 for (j = 0; j < screen->outputDevs ().size (); j++)
314 {
315 pBox0 = &screen->outputDevs ()[j];
316
317 /* must not intersect other output region */
318 if (i != j && pBox0->x2 () > pBox1->x1 () && pBox0->x1 () < pBox1->x2 ())
319 {
320 k--;
321 break;
322 }
323 }
324 }
325
326 if (optionGetMultioutputMode () == CubeOptions::MultioutputModeOneBigCube)
327 {
328 mFullscreenOutput = false;
329 mNOutput = 1;
330 return;
331 }
332
333 if (optionGetMultioutputMode () == CubeOptions::MultioutputModeMultipleCubes)
334 {
335 mFullscreenOutput = true;
336 mNOutput = 1;
337 return;
338 }
339
340 if ((unsigned int) k != screen->outputDevs ().size ())
341 {
342 mFullscreenOutput = false;
343 mNOutput = 1;
344 return;
345 }
346
347 /* add output indices from left to right */
348 j = 0;
349 for (;;)
350 {
351 x = MAXSHORT;
352 k = -1;
353
354 for (i = 0; i < screen->outputDevs ().size (); i++)
355 {
356 if (mOutputMask[i] != -1)
357 continue;
358
359 if (screen->outputDevs ()[i].x1 () < x)
360 {
361 x = screen->outputDevs ()[i].x1 ();
362 k = i;
363 }
364 }
365
366 if (k < 0)
367 break;
368
369 mOutputMask[k] = j;
370 mOutput[j] = k;
371
372 j++;
373 }
374
375 mNOutput = j;
376
377 if (mNOutput == 1)
378 {
379 if (screen->outputDevs ()[0].width () != screen->width () ||
380 screen->outputDevs ()[0].height () != screen->height ())
381 mFullscreenOutput = true;
382 }
383 }
384
385 void
386 PrivateCubeScreen::updateSkydomeTexture ()
387 {
388 mSky.clear ();
389
390 if (!optionGetSkydome ())
391 return;
392
393 CompString imgName = optionGetSkydomeImage ();
394 CompString pname = "cube";
395
396 if (optionGetSkydomeImage ().empty () ||
397 (mSky = GLTexture::readImageToTexture (imgName, pname, mSkySize)).empty ())
398 {
399 GLfloat aaafTextureData[128][128][3];
400 GLfloat fRStart = (GLfloat) optionGetSkydomeGradientStartColorRed () / 0xffff;
401 GLfloat fGStart = (GLfloat) optionGetSkydomeGradientStartColorGreen () / 0xffff;
402 GLfloat fBStart = (GLfloat) optionGetSkydomeGradientStartColorBlue () / 0xffff;
403 GLfloat fREnd = (GLfloat) optionGetSkydomeGradientEndColorRed () / 0xffff;
404 GLfloat fGEnd = (GLfloat) optionGetSkydomeGradientEndColorGreen () / 0xffff;
405 GLfloat fBEnd = (GLfloat) optionGetSkydomeGradientEndColorBlue () / 0xffff;
406 GLfloat fRStep = (fREnd - fRStart) / 128.0f;
407 GLfloat fGStep = (fGEnd - fGStart) / 128.0f;
408 GLfloat fBStep = (fBStart - fBEnd) / 128.0f;
409 GLfloat fR = fRStart;
410 GLfloat fG = fGStart;
411 GLfloat fB = fBStart;
412
413 int iX, iY;
414
415 for (iX = 127; iX >= 0; iX--)
416 {
417 fR += fRStep;
418 fG += fGStep;
419 fB -= fBStep;
420
421 for (iY = 0; iY < 128; iY++)
422 {
423 aaafTextureData[iX][iY][0] = fR;
424 aaafTextureData[iX][iY][1] = fG;
425 aaafTextureData[iX][iY][2] = fB;
426 }
427 }
428
429 mSkySize = CompSize (128, 128);
430
431 mSky = GLTexture::imageDataToTexture ((char *) aaafTextureData,
432 mSkySize, GL_RGB, GL_FLOAT);
433
434 mSky[0]->setFilter (GL_LINEAR);
435 mSky[0]->setWrap (GL_CLAMP_TO_EDGE);
436 }
437 }
438
439 #ifndef USE_GLES
440 static bool
441 fillCircleTable (GLfloat **ppSint,
442 GLfloat **ppCost,
443 const int n)
444 {
445 const GLfloat angle = 2 * M_PI / (GLfloat) ((n == 0) ? 1 : n);
446 const int size = abs (n);
447
448 *ppSint = (GLfloat *) calloc (sizeof (GLfloat), size + 1);
449 *ppCost = (GLfloat *) calloc (sizeof (GLfloat), size + 1);
450
451 if (!(*ppSint) || !(*ppCost))
452 {
453 free (*ppSint);
454 free (*ppCost);
455
456 return false;
457 }
458
459 (*ppSint)[0] = 0.0;
460 (*ppCost)[0] = 1.0;
461
462 for (int i = 1; i < size; i++)
463 {
464 (*ppSint)[i] = sin (angle * i);
465 (*ppCost)[i] = cos (angle * i);
466 }
467
468 (*ppSint)[size] = (*ppSint)[0];
469 (*ppCost)[size] = (*ppCost)[0];
470
471 return true;
472 }
473 #endif
474
475 void
476 PrivateCubeScreen::updateSkydomeList (GLfloat fRadius)
477 {
478 #ifndef USE_GLES
479 GLint iSlices = 128;
480 GLint iStacks = 64;
481 GLfloat afTexCoordX[4];
482 GLfloat afTexCoordY[4];
483 GLfloat *sint1;
484 GLfloat *cost1;
485 GLfloat *sint2;
486 GLfloat *cost2;
487 GLfloat r;
488 GLfloat x;
489 GLfloat y;
490 GLfloat z;
491 int iStacksStart;
492 int iStacksEnd;
493 int iSlicesStart;
494 int iSlicesEnd;
495 GLfloat fStepX;
496 GLfloat fStepY;
497
498 if (optionGetSkydomeAnimated ())
499 {
500 iStacksStart = 11; /* min. 0 */
501 iStacksEnd = 53; /* max. 64 */
502 iSlicesStart = 0; /* min. 0 */
503 iSlicesEnd = 128; /* max. 128 */
504 }
505 else
506 {
507 iStacksStart = 21; /* min. 0 */
508 iStacksEnd = 43; /* max. 64 */
509 iSlicesStart = 21; /* min. 0 */
510 iSlicesEnd = 44; /* max. 128 */
511 }
512
513 fStepX = 1.0 / (GLfloat) (iSlicesEnd - iSlicesStart);
514 fStepY = 1.0 / (GLfloat) (iStacksEnd - iStacksStart);
515
516 if (!mSky.size ())
517 return;
518
519 if (!fillCircleTable (&sint1, &cost1, -iSlices))
520 return;
521
522 if (!fillCircleTable (&sint2, &cost2, iStacks * 2))
523 {
524 free (sint1);
525 free (cost1);
526 return;
527 }
528
529 afTexCoordX[0] = 1.0f;
530 afTexCoordY[0] = 1.0f - fStepY;
531 afTexCoordX[1] = 1.0f - fStepX;
532 afTexCoordY[1] = 1.0f - fStepY;
533 afTexCoordX[2] = 1.0f - fStepX;
534 afTexCoordY[2] = 1.0f;
535 afTexCoordX[3] = 1.0f;
536 afTexCoordY[3] = 1.0f;
537
538
539 if (!mSkyListId)
540 mSkyListId = glGenLists (1);
541
542 glNewList (mSkyListId, GL_COMPILE);
543
544 mSky[0]->enable (GLTexture::Good);
545
546 glBegin (GL_QUADS);
547
548 for (int i = iStacksStart; i < iStacksEnd; i++)
549 {
550 afTexCoordX[0] = 1.0f;
551 afTexCoordX[1] = 1.0f - fStepX;
552 afTexCoordX[2] = 1.0f - fStepX;
553 afTexCoordX[3] = 1.0f;
554
555 for (int j = iSlicesStart; j < iSlicesEnd; j++)
556 {
557 /* bottom-right */
558 z = cost2[i];
559 r = sint2[i];
560 x = cost1[j];
561 y = sint1[j];
562
563 glTexCoord2f (
564 COMP_TEX_COORD_X (mSky[0]->matrix (), afTexCoordX[3] * mSkySize.width ()),
565 COMP_TEX_COORD_Y (mSky[0]->matrix (), afTexCoordY[3] * mSkySize.height ()));
566 glVertex3f (x * r * fRadius, y * r * fRadius, z * fRadius);
567
568 /* top-right */
569 z = cost2[i + 1];
570 r = sint2[i + 1];
571 x = cost1[j];
572 y = sint1[j];
573
574 glTexCoord2f (
575 COMP_TEX_COORD_X (mSky[0]->matrix (), afTexCoordX[0] * mSkySize.width ()),
576 COMP_TEX_COORD_Y (mSky[0]->matrix (), afTexCoordY[0] * mSkySize.height ()));
577 glVertex3f (x * r * fRadius, y * r * fRadius, z * fRadius);
578
579 /* top-left */
580 z = cost2[i + 1];
581 r = sint2[i + 1];
582 x = cost1[j + 1];
583 y = sint1[j + 1];
584
585 glTexCoord2f (
586 COMP_TEX_COORD_X (mSky[0]->matrix (), afTexCoordX[1] * mSkySize.width ()),
587 COMP_TEX_COORD_Y (mSky[0]->matrix (), afTexCoordY[1] * mSkySize.height ()));
588 glVertex3f (x * r * fRadius, y * r * fRadius, z * fRadius);
589
590 /* bottom-left */
591 z = cost2[i];
592 r = sint2[i];
593 x = cost1[j + 1];
594 y = sint1[j + 1];
595
596 glTexCoord2f (
597 COMP_TEX_COORD_X (mSky[0]->matrix (), afTexCoordX[2] * mSkySize.width ()),
598 COMP_TEX_COORD_Y (mSky[0]->matrix (), afTexCoordY[2] * mSkySize.height ()));
599 glVertex3f (x * r * fRadius, y * r * fRadius, z * fRadius);
600
601 afTexCoordX[0] -= fStepX;
602 afTexCoordX[1] -= fStepX;
603 afTexCoordX[2] -= fStepX;
604 afTexCoordX[3] -= fStepX;
605 }
606
607 afTexCoordY[0] -= fStepY;
608 afTexCoordY[1] -= fStepY;
609 afTexCoordY[2] -= fStepY;
610 afTexCoordY[3] -= fStepY;
611 }
612
613 glEnd ();
614
615 mSky[0]->disable ();
616
617 glEndList ();
618
619 free (sint1);
620 free (cost1);
621 free (sint2);
622 free (cost2);
623
624 #endif
625 }
626
627 bool
628 PrivateCubeScreen::setOption (const CompString &name, CompOption::Value &value)
629 {
630
631 unsigned int index;
632
633 bool rv = CubeOptions::setOption (name, value);
634
635 if (!rv || !CompOption::findOption (getOptions (), name, &index))
636 return false;
637
638 switch (index) {
639 case CubeOptions::In:
640 rv = updateGeometry (screen->vpSize ().width (), value.b () ? -1 : 1);
641 break;
642 case CubeOptions::Skydome:
643 case CubeOptions::SkydomeImage:
644 case CubeOptions::SkydomeAnimated:
645 case CubeOptions::SkydomeGradientStartColor:
646 case CubeOptions::SkydomeGradientEndColor:
647 updateSkydomeTexture ();
648 updateSkydomeList (1.0f);
649 cScreen->damageScreen ();
650 break;
651 case CubeOptions::MultioutputMode:
652 updateOutputs ();
653 updateGeometry (screen->vpSize ().width (), mInvert);
654 cScreen->damageScreen ();
655 break;
656 default:
657 break;
658 }
659
660 return rv;
661 }
662
663 bool
664 PrivateCubeScreen::adjustVelocity ()
665 {
666 float unfold, adjust, amount;
667
668 if (mUnfolded)
669 unfold = 1.0f - mUnfold;
670 else
671 unfold = 0.0f - mUnfold;
672
673 adjust = unfold * 0.02f * optionGetAcceleration ();
674 amount = fabs (unfold);
675 if (amount < 1.0f)
676 amount = 1.0f;
677 else if (amount > 3.0f)
678 amount = 3.0f;
679
680 mUnfoldVelocity = (amount * mUnfoldVelocity + adjust) /
681 (amount + 2.0f);
682
683 return (fabs (unfold) < 0.002f && fabs (mUnfoldVelocity) < 0.01f);
684 }
685
686 void
687 PrivateCubeScreen::preparePaint (int msSinceLastPaint)
688 {
689 int opt;
690 float x, progress;
691 unsigned short *topColor, *bottomColor;
692
693 if (mGrabIndex)
694 {
695 int steps;
696 float amount, chunk;
697
698 amount = msSinceLastPaint * 0.2f *
699 optionGetSpeed ();
700 steps = amount / (0.5f * optionGetTimestep ());
701 if (!steps) steps = 1;
702 chunk = amount / (float) steps;
703
704 while (steps--)
705 {
706 mUnfold += mUnfoldVelocity * chunk;
707 if (mUnfold > 1.0f)
708 mUnfold = 1.0f;
709
710 if (adjustVelocity ())
711 {
712 if (mUnfold < 0.5f)
713 {
714 if (mGrabIndex)
715 {
716 screen->removeGrab (mGrabIndex, NULL);
717 mGrabIndex = 0;
718 }
719
720 mUnfold = 0.0f;
721 }
722 break;
723 }
724 }
725 }
726
727 memset (mCleared, 0, sizeof (Bool) * screen->outputDevs ().size ());
728 memset (mCapsPainted, 0, sizeof (Bool) * screen->outputDevs ().size ());
729
730 /* Transparency handling */
731 if (mRotationState == CubeScreen::RotationManual ||
732 (mRotationState == CubeScreen::RotationChange &&
733 !optionGetTransparentManualOnly ()))
734 {
735 opt = mLastOpacityIndex = CubeOptions::ActiveOpacity;
736 }
737 else if (mRotationState == CubeScreen::RotationChange)
738 {
739 opt = mLastOpacityIndex = CubeOptions::InactiveOpacity;
740 }
741 else
742 {
743 opt = CubeOptions::InactiveOpacity;
744 }
745
746 mToOpacity = (mOptions[opt].value ().f () / 100.0f) * OPAQUE;
747
748 cubeScreen->cubeGetRotation (x, x, progress);
749
750 if (mDesktopOpacity != mToOpacity ||
751 (progress > 0.0 && progress < 1.0))
752 {
753 mDesktopOpacity =
754 (optionGetInactiveOpacity () -
755 ((optionGetInactiveOpacity () -
756 mOptions[mLastOpacityIndex].value ().f ()) * progress))
757 / 100.0f * OPAQUE;
758
759 }
760
761 topColor = optionGetTopColor ();
762 bottomColor = optionGetBottomColor ();
763
764 mPaintAllViewports = (mDesktopOpacity != OPAQUE ||
765 topColor[3] != OPAQUE ||
766 bottomColor[3] != OPAQUE);
767
768 cScreen->preparePaint (msSinceLastPaint);
769 }
770
771 void
772 PrivateCubeScreen::paint (CompOutput::ptrList &outputs, unsigned int mask)
773 {
774 float x, progress;
775
776 cubeScreen->cubeGetRotation (x, x, progress);
777
778 if (optionGetMultioutputMode () == MultioutputModeOneBigCube &&
779 screen->outputDevs ().size () &&
780 (progress > 0.0f || mDesktopOpacity != OPAQUE))
781 {
782 outputs.clear ();
783 outputs.push_back (&screen->fullscreenOutput ());
784 }
785
786 cScreen->paint (outputs, mask);
787 }
788
789 bool
790 PrivateCubeScreen::glPaintOutput (const GLScreenPaintAttrib &sAttrib,
791 const GLMatrix &transform,
792 const CompRegion ®ion,
793 CompOutput *output,
794 unsigned int mask)
795 {
796 if (mGrabIndex || mDesktopOpacity != OPAQUE)
797 {
798 mask &= ~PAINT_SCREEN_REGION_MASK;
799 mask |= PAINT_SCREEN_TRANSFORMED_MASK;
800 }
801
802 mSrcOutput = ((unsigned int) output->id () != (unsigned int) ~0) ?
803 output->id () : 0;
804 /* Always use BTF painting on non-transformed screen */
805 mPaintOrder = BTF;
806
807 return gScreen->glPaintOutput (sAttrib, transform, region, output, mask);
808 }
809
810 void
811 PrivateCubeScreen::donePaint ()
812 {
813 if (mGrabIndex || mDesktopOpacity != mToOpacity)
814 cScreen->damageScreen ();
815
816 cScreen->donePaint ();
817 }
818
819 bool
820 CubeScreen::cubeCheckOrientation (const GLScreenPaintAttrib &sAttrib,
821 const GLMatrix &transform,
822 CompOutput *output,
823 std::vector<GLVector> &points)
824 {
825 WRAPABLE_HND_FUNCTN_RETURN (bool, cubeCheckOrientation, sAttrib, transform, output, points)
826 GLMatrix sTransform = transform;
827 GLMatrix mvp, pm (priv->gScreen->projectionMatrix ()->getMatrix ());
828 GLVector pntA, pntB, pntC;
829 GLVector vecA, vecB, ortho;
830 bool rv = false;
831
832 priv->gScreen->glApplyTransform (sAttrib, output, &sTransform);
833 sTransform.translate (priv->mOutputXOffset, -priv->mOutputYOffset, 0.0f);
834 sTransform.scale (priv->mOutputXScale, priv->mOutputYScale, 1.0f);
835
836 mvp = pm * sTransform;
837
838 pntA = mvp * points[0];
839
840 if (pntA[3] < 0.0f)
841 rv = !rv;
842
843 pntA.homogenize ();
844
845 pntB = mvp * points[1];
846
847 if (pntB[3] < 0.0f)
848 rv = !rv;
849
850 pntB.homogenize ();
851
852 pntC = mvp * points[2];
853 pntC.homogenize ();
854
855 vecA = pntC - pntA;
856 vecB = pntC - pntB;
857
858 ortho = vecA ^ vecB;
859
860 if (ortho[2] > 0.0f)
861 rv = !rv;
862
863 return rv;
864 }
865
866 bool
867 CubeScreen::cubeShouldPaintViewport (const GLScreenPaintAttrib &sAttrib,
868 const GLMatrix &transform,
869 CompOutput *output,
870 PaintOrder order)
871 {
872 WRAPABLE_HND_FUNCTN_RETURN (bool, cubeShouldPaintViewport, sAttrib, transform, output, order)
873
874 bool ftb;
875 float pointZ;
876
877 pointZ = priv->mInvert * priv->mDistance;
878 std::vector<GLVector> vPoints;
879 vPoints.push_back (GLVector (-0.5, 0.0, pointZ, 1.0));
880 vPoints.push_back (GLVector (0.0, 0.5, pointZ, 1.0));
881 vPoints.push_back (GLVector (0.0, 0.0, pointZ, 1.0));
882
883 ftb = cubeCheckOrientation (sAttrib, transform, output, vPoints);
884
885 return (order == FTB && ftb) || (order == BTF && !ftb);
886 }
887
888 void
889 PrivateCubeScreen::moveViewportAndPaint (const GLScreenPaintAttrib &sAttrib,
890 const GLMatrix &transform,
891 CompOutput *outputPtr,
892 unsigned int mask,
893 PaintOrder paintOrder,
894 int dx)
895 {
896 if (!cubeScreen->cubeShouldPaintViewport (sAttrib, transform, outputPtr,
897 paintOrder))
898 return;
899
900 int output = ((unsigned int) outputPtr->id () != (unsigned int) ~0)
901 ? outputPtr->id () : 0;
902
903 mPaintOrder = paintOrder;
904
905 if (mNOutput > 1)
906 {
907 int cubeOutput, dView;
908
909 /* translate to cube output */
910 cubeOutput = mOutputMask[output];
911
912 /* convert from window movement to viewport movement */
913 dView = -dx;
914
915 cubeOutput += dView;
916
917 dView = cubeOutput / mNOutput;
918 cubeOutput = cubeOutput % mNOutput;
919
920 if (cubeOutput < 0)
921 {
922 cubeOutput += mNOutput;
923 dView--;
924 }
925
926 /* translate back to compiz output */
927 output = mSrcOutput = mOutput[cubeOutput];
928
929 cScreen->setWindowPaintOffset (-dView * screen->width (), 0);
930
931 CompRegion reg (screen->outputDevs () [output]);
932 cubeScreen->cubePaintViewport (sAttrib, transform, reg,
933 &screen->outputDevs () [output], mask);
934 cScreen->setWindowPaintOffset (0, 0);
935 }
936 else
937 {
938 CompRegion region;
939
940 cScreen->setWindowPaintOffset (dx * screen->width (), 0);
941
942 if (optionGetMultioutputMode () == MultioutputModeMultipleCubes)
943 region = CompRegion (*outputPtr);
944 else
945 region = screen->region ();
946
947 cubeScreen->cubePaintViewport (sAttrib, transform, region, outputPtr, mask);
948
949 cScreen->setWindowPaintOffset (0, 0);
950 }
951 }
952
953 void
954 PrivateCubeScreen::paintAllViewports (const GLScreenPaintAttrib &sAttrib,
955 const GLMatrix &transform,
956 const CompRegion ®ion,
957 CompOutput *outputPtr,
958 unsigned int mask,
959 int xMove,
960 float size,
961 int hsize,
962 PaintOrder paintOrder)
963 {
964 GLScreenPaintAttrib sa = sAttrib;
965
966 int xMoveAdd;
967 int origXMoveAdd = 0; /* dx for the viewport we start
968 painting with (back-most). */
969 int iFirstSign; /* 1 if we do xMove += i first and
970 -1 if we do xMove -= i first. */
971
972 if (mInvert == 1)
973 {
974 /* xMove ==> dx for the viewport which is the
975 nearest to the viewer in z axis.
976 xMove +/- hsize / 2 ==> dx for the viewport
977 which is the farthest to the viewer in z axis. */
978
979 if ((sa.xRotate < 0.0f && hsize % 2 == 1) ||
980 (sa.xRotate > 0.0f && hsize % 2 == 0))
981 {
982 origXMoveAdd = hsize / 2;
983 iFirstSign = 1;
984 }
985 else
986 {
987 origXMoveAdd = -hsize / 2;
988 iFirstSign = -1;
989 }
990 }
991 else
992 {
993 /* xMove is already the dx for farthest viewport. */
994 if (sa.xRotate > 0.0f)
995 iFirstSign = -1;
996 else
997 iFirstSign = 1;
998 }
999
1000 for (int i = 0; i <= hsize / 2; i++)
1001 {
1002 /* move to the correct viewport (back to front). */
1003 xMoveAdd = origXMoveAdd; /* move to farthest viewport. */
1004 xMoveAdd += iFirstSign * i; /* move i more viewports to
1005 the right / left. */
1006
1007 /* Needed especially for unfold.
1008 We paint the viewports around xMove viewport.
1009 Adding or subtracting hsize from xMove has no effect on
1010 what viewport we paint, but can make shorter paths. */
1011 if (xMoveAdd < -hsize / 2)
1012 xMoveAdd += hsize;
1013 else if (xMoveAdd > hsize / 2)
1014 xMoveAdd -= hsize;
1015
1016 /* Paint the viewport. */
1017 xMove += xMoveAdd;
1018
1019 sa.yRotate -= mInvert * xMoveAdd * 360.0f / size;
1020 moveViewportAndPaint (sa, transform, outputPtr, mask,
1021 paintOrder, xMove);
1022 sa.yRotate += mInvert * xMoveAdd * 360.0f / size;
1023
1024 xMove -= xMoveAdd;
1025
1026 /* do the same for an equally far viewport. */
1027 if (i == 0 || i * 2 == hsize)
1028 continue;
1029
1030 xMoveAdd = origXMoveAdd; /* move to farthest viewport. */
1031 xMoveAdd -= iFirstSign * i; /* move i more viewports to the
1032 left / right (opposite side
1033 from the one chosen first) */
1034
1035 if (xMoveAdd < -hsize / 2)
1036 xMoveAdd += hsize;
1037 else if (xMoveAdd > hsize / 2)
1038 xMoveAdd -= hsize;
1039
1040 xMove += xMoveAdd;
1041
1042 sa.yRotate -= mInvert * xMoveAdd * 360.0f / size;
1043 moveViewportAndPaint (sa, transform, outputPtr, mask,
1044 paintOrder, xMove);
1045 sa.yRotate += mInvert * xMoveAdd * 360.0f / size;
1046
1047 xMove -= xMoveAdd;
1048 }
1049 }
1050
1051 void
1052 CubeScreen::cubeGetRotation (float &x, float &v, float &progress)
1053 {
1054 WRAPABLE_HND_FUNCTN (cubeGetRotation, x, v, progress)
1055
1056 x = 0.0f;
1057 v = 0.0f;
1058 progress = 0.0f;
1059 }
1060
1061 void
1062 CubeScreen::cubeClearTargetOutput (float xRotate, float vRotate)
1063 {
1064 WRAPABLE_HND_FUNCTN (cubeClearTargetOutput, xRotate, vRotate)
1065
1066 if (priv->mSky.size () > 0)
1067 {
1068 priv->gScreen->setLighting (false);
1069 #ifndef USE_GLES
1070 glPushMatrix ();
1071
1072 if (priv->optionGetSkydomeAnimated () &&
1073 priv->mGrabIndex == 0)
1074 {
1075 glRotatef (vRotate / 5.0f + 90.0f, 1.0f, 0.0f, 0.0f);
1076 glRotatef (xRotate, 0.0f, 0.0f, -1.0f);
1077 }
1078 else
1079 {
1080 glRotatef (90.0f, 1.0f, 0.0f, 0.0f);
1081 }
1082
1083 glCallList (priv->mSkyListId);
1084 glPopMatrix ();
1085 #endif
1086 }
1087 else
1088 {
1089 priv->gScreen->clearTargetOutput (GL_COLOR_BUFFER_BIT);
1090 }
1091 }
1092
1093 void
1094 CubeScreen::cubePaintTop (const GLScreenPaintAttrib &sAttrib,
1095 const GLMatrix &transform,
1096 CompOutput *output,
1097 int size,
1098 const GLVector &normal)
1099 {
1100 WRAPABLE_HND_FUNCTN (cubePaintTop, sAttrib, transform, output, size, normal)
1101
1102 GLScreenPaintAttrib sa = sAttrib;
1103 GLMatrix sTransform = transform;
1104
1105 unsigned short* color;
1106 int opacity;
1107
1108 priv->gScreen->setLighting (true);
1109
1110 color = priv->optionGetTopColor ();
1111 opacity = priv->mDesktopOpacity * color[3] / 0xffff;
1112
1113 GLVertexBuffer *streamingBuffer = GLVertexBuffer::streamingBuffer ();
1114 std::vector <GLushort> colorData;
1115
1116 colorData.push_back (color[0] * opacity / 0xffff);
1117 colorData.push_back (color[1] * opacity / 0xffff);
1118 colorData.push_back (color[2] * opacity / 0xffff);
1119 colorData.push_back (opacity);
1120
1121 sa.yRotate += (360.0f / size) * (priv->mXRotations + 1);
1122
1123 priv->gScreen->glApplyTransform (sa, output, &sTransform);
1124
1125 sTransform.translate (priv->mOutputXOffset, -priv->mOutputYOffset, 0.0f);
1126 sTransform.scale (priv->mOutputXScale, priv->mOutputYScale, 1.0f);
1127
1128 if ((priv->mDesktopOpacity != OPAQUE) || (color[3] != OPAQUE))
1129 {
1130 #ifndef USE_GLES
1131 priv->gScreen->setTexEnvMode (GL_MODULATE);
1132 #endif
1133 glEnable (GL_BLEND);
1134 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1135 }
1136
1137 bool withTexture = priv->mInvert == 1 && size == 4 && priv->mTexture.size ();
1138
1139 if (withTexture)
1140 priv->mTexture[0]->enable (GLTexture::Good);
1141
1142 streamingBuffer->begin (GL_TRIANGLE_FAN);
1143 streamingBuffer->addColors (1, &(colorData[0]));
1144 streamingBuffer->addVertices (priv->mNVertices >> 1, priv->mVertices);
1145 streamingBuffer->addNormals (1, const_cast <GLfloat *> (&normal[0]));
1146
1147 if (withTexture)
1148 streamingBuffer->addTexCoords (0, 2, priv->mTc);
1149
1150 streamingBuffer->end ();
1151 streamingBuffer->render (sTransform);
1152
1153 if (withTexture)
1154 priv->mTexture[0]->disable ();
1155
1156 priv->gScreen->setTexEnvMode (GL_REPLACE);
1157 glDisable (GL_BLEND);
1158 glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1159 }
1160
1161 void
1162 CubeScreen::cubePaintBottom (const GLScreenPaintAttrib &sAttrib,
1163 const GLMatrix &transform,
1164 CompOutput *output,
1165 int size,
1166 const GLVector &normal)
1167 {
1168 WRAPABLE_HND_FUNCTN (cubePaintBottom, sAttrib, transform, output, size, normal)
1169
1170 GLScreenPaintAttrib sa = sAttrib;
1171 GLMatrix sTransform = transform;
1172
1173 unsigned short* color;
1174 int opacity;
1175
1176 priv->gScreen->setLighting (true);
1177
1178 color = priv->optionGetBottomColor ();
1179 opacity = priv->mDesktopOpacity * color[3] / 0xffff;
1180
1181 GLVertexBuffer *streamingBuffer = GLVertexBuffer::streamingBuffer ();
1182 std::vector <GLushort> colorData;
1183
1184 colorData.push_back (color[0] * opacity / 0xffff);
1185 colorData.push_back (color[1] * opacity / 0xffff);
1186 colorData.push_back (color[2] * opacity / 0xffff);
1187 colorData.push_back (opacity);
1188
1189 sa.yRotate += (360.0f / size) * (priv->mXRotations + 1);
1190
1191 priv->gScreen->glApplyTransform (sa, output, &sTransform);
1192
1193 sTransform.translate (priv->mOutputXOffset, -priv->mOutputYOffset, 0.0f);
1194 sTransform.scale (priv->mOutputXScale, priv->mOutputYScale, 1.0f);
1195
1196 if ((priv->mDesktopOpacity != OPAQUE) || (color[3] != OPAQUE))
1197 {
1198 #ifndef USE_GLES
1199 priv->gScreen->setTexEnvMode (GL_MODULATE);
1200 #endif
1201 glEnable (GL_BLEND);
1202 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1203 }
1204
1205 streamingBuffer->begin (GL_TRIANGLE_FAN);
1206 streamingBuffer->addColors (1, &(colorData[0]));
1207 streamingBuffer->addVertices (priv->mNVertices, priv->mVertices);
1208 streamingBuffer->addNormals (1, const_cast <GLfloat *> (&normal[0]));
1209 streamingBuffer->setVertexOffset (priv->mNVertices >> 1);
1210 streamingBuffer->setMaxVertices (priv->mNVertices >> 1);
1211
1212 streamingBuffer->end ();
1213 streamingBuffer->render (sTransform);
1214
1215 priv->gScreen->setTexEnvMode (GL_REPLACE);
1216 glDisable (GL_BLEND);
1217 glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1218 }
1219
1220 void
1221 CubeScreen::cubePaintInside (const GLScreenPaintAttrib &sAttrib,
1222 const GLMatrix &transform,
1223 CompOutput *output,
1224 int size,
1225 const GLVector &normal)
1226 {
1227 WRAPABLE_HND_FUNCTN (cubePaintInside, sAttrib, transform, output, size, normal)
1228 }
1229
1230 void
1231 PrivateCubeScreen::glEnableOutputClipping (const GLMatrix &transform,
1232 const CompRegion ®ion,
1233 CompOutput *output)
1234 {
1235 if (mRotationState != CubeScreen::RotationNone)
1236 {
1237 /* FIXME: No output clipping in OpenGL|ES yet */
1238 #ifndef USE_GLES
1239 glPushMatrix ();
1240 glLoadMatrixf (transform.getMatrix ());
1241 glTranslatef (mOutputXOffset, -mOutputYOffset, 0.0f);
1242 glScalef (mOutputXScale, mOutputYScale, 1.0f);
1243
1244 if (mInvert == 1)
1245 {
1246 GLdouble clipPlane0[] = { 1.0, 0.0, 0.5 / mDistance, 0.0 };
1247 GLdouble clipPlane1[] = { -1.0, 0.0, 0.5 / mDistance, 0.0 };
1248 GLdouble clipPlane2[] = { 0.0, -1.0, 0.5 / mDistance, 0.0 };
1249 GLdouble clipPlane3[] = { 0.0, 1.0, 0.5 / mDistance, 0.0 };
1250 glClipPlane (GL_CLIP_PLANE0, clipPlane0);
1251 glClipPlane (GL_CLIP_PLANE1, clipPlane1);
1252 glClipPlane (GL_CLIP_PLANE2, clipPlane2);
1253 glClipPlane (GL_CLIP_PLANE3, clipPlane3);
1254 }
1255 else
1256 {
1257 GLdouble clipPlane0[] = { -1.0, 0.0, -0.5 / mDistance, 0.0 };
1258 GLdouble clipPlane1[] = { 1.0, 0.0, -0.5 / mDistance, 0.0 };
1259 GLdouble clipPlane2[] = { 0.0, 1.0, -0.5 / mDistance, 0.0 };
1260 GLdouble clipPlane3[] = { 0.0, -1.0, -0.5 / mDistance, 0.0 };
1261 glClipPlane (GL_CLIP_PLANE0, clipPlane0);
1262 glClipPlane (GL_CLIP_PLANE1, clipPlane1);
1263 glClipPlane (GL_CLIP_PLANE2, clipPlane2);
1264 glClipPlane (GL_CLIP_PLANE3, clipPlane3);
1265 }
1266
1267 glEnable (GL_CLIP_PLANE0);
1268 glEnable (GL_CLIP_PLANE1);
1269 glEnable (GL_CLIP_PLANE2);
1270 glEnable (GL_CLIP_PLANE3);
1271
1272 glPopMatrix ();
1273 #endif
1274 }
1275 else
1276 gScreen->glEnableOutputClipping (transform, region, output);
1277 }
1278
1279 void
1280 CubeScreen::cubePaintViewport (const GLScreenPaintAttrib &sAttrib,
1281 const GLMatrix &transform,
1282 const CompRegion ®ion,
1283 CompOutput *output,
1284 unsigned int mask)
1285 {
1286 WRAPABLE_HND_FUNCTN (cubePaintViewport, sAttrib, transform, region, output, mask)
1287
1288 priv->gScreen->glPaintTransformedOutput (sAttrib, transform, region,
1289 output, mask);
1290 }
1291
1292 void
1293 PrivateCubeScreen::glPaintTransformedOutput (const GLScreenPaintAttrib &sAttrib,
1294 const GLMatrix &transform,
1295 const CompRegion ®ion,
1296 CompOutput *outputPtr,
1297 unsigned int mask)
1298 {
1299 GLScreenPaintAttrib sa = sAttrib;
1300 float xRotate, vRotate, progress;
1301 int hsize;
1302 float size;
1303 GLenum filter = gScreen->textureFilter ();
1304 PaintOrder paintOrder;
1305 bool wasCulled = false;
1306 bool paintCaps;
1307 int cullNorm, cullInv;
1308 int output = 0;
1309
1310 output = ((unsigned int) outputPtr->id () != (unsigned int) ~0) ?
1311 outputPtr->id () : 0;
1312
1313 mReversedWindowList = cScreen->getWindowPaintList ();
1314 mReversedWindowList.reverse ();
1315
1316 if ((((unsigned int) outputPtr->id () != (unsigned int) ~0) && mRecalcOutput) ||
1317 (((unsigned int) outputPtr->id () == (unsigned int) ~0) && !mRecalcOutput &&
1318 mNOutput > 1))
1319 {
1320 mRecalcOutput = ((unsigned int) outputPtr->id () == (unsigned int) ~0);
1321 mNOutput = 1;
1322 updateGeometry (screen->vpSize ().width (), mInvert);
1323 }
1324
1325 hsize = screen->vpSize ().width () * mNOutput;
1326 size = hsize;
1327
1328 glGetIntegerv (GL_CULL_FACE_MODE, &cullNorm);
1329 cullInv = (cullNorm == GL_BACK)? GL_FRONT : GL_BACK;
1330 wasCulled = glIsEnabled (GL_CULL_FACE);
1331
1332 if (!mFullscreenOutput)
1333 {
1334 mOutputXScale = (float) screen->width () / outputPtr->width ();
1335 mOutputYScale = (float) screen->height () / outputPtr->height ();
1336
1337 mOutputXOffset =
1338 (screen->width () / 2.0f -
1339 (outputPtr->x1 () + outputPtr->x2 ()) / 2.0f) /
1340 (float) outputPtr->width ();
1341
1342 mOutputYOffset =
1343 (screen->height () / 2.0f -
1344 (outputPtr->y1 () +
1345 outputPtr->y2 ()) / 2.0f) /
1346 (float) outputPtr->height ();
1347 }
1348 else
1349 {
1350 mOutputXScale = 1.0f;
1351 mOutputYScale = 1.0f;
1352 mOutputXOffset = 0.0f;
1353 mOutputYOffset = 0.0f;
1354 }
1355
1356 cubeScreen->cubeGetRotation (xRotate, vRotate, progress);
1357
1358 sa.xRotate += xRotate;
1359 sa.vRotate += vRotate;
1360
1361 if (!mCleared[output])
1362 {
1363 float rRotate;
1364
1365 rRotate = xRotate - ((screen->vp ().x () *360.0f) / screen->vpSize ().width ());
1366
1367 cubeScreen->cubeClearTargetOutput (rRotate, vRotate);
1368 mCleared[output] = true;
1369 }
1370
1371 mask &= ~PAINT_SCREEN_CLEAR_MASK;
1372
1373 if (mGrabIndex)
1374 {
1375 sa.vRotate = 0.0f;
1376
1377 size += mUnfold * 8.0f;
1378 size += powf (mUnfold, 6) * 64.0;
1379 size += powf (mUnfold, 16) * 8192.0;
1380
1381 sa.zTranslate = -mInvert * (0.5f / tanf (M_PI / size));
1382
1383 /* distance we move the camera back when unfolding the cube.
1384 currently hardcoded to 1.5 but it should probably be optional. */
1385 sa.zCamera -= mUnfold * 1.5f;
1386 }
1387 else
1388 {
1389 if (vRotate > 100.0f)
1390 sa.vRotate = 100.0f;
1391 else if (vRotate < -100.0f)
1392 sa.vRotate = -100.0f;
1393 else
1394 sa.vRotate = vRotate;
1395
1396 sa.zTranslate = -mInvert * mDistance;
1397 }
1398
1399 if (sa.xRotate > 0.0f)
1400 mXRotations = (int) (hsize * sa.xRotate + 180.0f) / 360.0f;
1401 else
1402 mXRotations = (int) (hsize * sa.xRotate - 180.0f) / 360.0f;
1403
1404 sa.xRotate -= (360.0f * mXRotations) / hsize;
1405 sa.xRotate *= mInvert;
1406
1407 sa.xRotate = sa.xRotate / size * hsize;
1408
1409 if (mGrabIndex && optionGetMipmap ())
1410 gScreen->setTextureFilter (GL_LINEAR_MIPMAP_LINEAR);
1411
1412 if (mInvert == 1)
1413 {
1414 /* Outside cube - start with FTB faces */
1415 paintOrder = FTB;
1416 glCullFace (cullInv);
1417 }
1418 else
1419 {
1420 /* Inside cube - start with BTF faces */
1421 paintOrder = BTF;
1422 }
1423
1424 if (mInvert == -1 || cubeScreen->cubeShouldPaintAllViewports ())
1425 paintAllViewports (sa, transform, region, outputPtr,
1426 mask, mXRotations, size, hsize, paintOrder);
1427
1428 glCullFace (cullNorm);
1429
1430 if (wasCulled && cubeScreen->cubeShouldPaintAllViewports ())
1431 glDisable (GL_CULL_FACE);
1432
1433 paintCaps = !mGrabIndex && (hsize > 2) && !mCapsPainted[output] &&
1434 (mInvert != 1 || mDesktopOpacity != OPAQUE ||
1435 cubeScreen->cubeShouldPaintAllViewports () || sa.vRotate != 0.0f ||
1436 sa.yTranslate != 0.0f);
1437
1438 if (paintCaps)
1439 {
1440 Bool topDir, bottomDir, allCaps;
1441
1442 std::vector<GLVector> top;
1443 top.push_back (GLVector (0.5, 0.5, 0.0, 1.0));
1444 top.push_back (GLVector (0.0, 0.5, -0.5, 1.0));
1445 top.push_back (GLVector (0.0, 0.5, 0.0, 1.0));
1446
1447 std::vector<GLVector> bottom;
1448 bottom.push_back (GLVector (0.5, -0.5, 0.0, 1.0));
1449 bottom.push_back (GLVector (0.0, -0.5, -0.5, 1.0));
1450 bottom.push_back (GLVector (0.0, -0.5, 0.0, 1.0));
1451
1452 topDir = cubeScreen->cubeCheckOrientation (sa, transform, outputPtr, top);
1453 bottomDir = cubeScreen->cubeCheckOrientation (sa, transform, outputPtr, bottom);
1454
1455 mCapsPainted[output] = TRUE;
1456
1457 allCaps = cubeScreen->cubeShouldPaintAllViewports () || mInvert != 1;
1458
1459 if (topDir && bottomDir)
1460 {
1461 if (allCaps)
1462 {
1463 cubeScreen->cubePaintBottom (sa, transform, outputPtr, hsize, GLVector (0.0f, -1.0f, 0.0f, 1.0f));
1464 cubeScreen->cubePaintInside (sa, transform, outputPtr, hsize, GLVector (0.0f, 0.0f, -1.0f, 1.0f));
1465 }
1466 cubeScreen->cubePaintTop (sa, transform, outputPtr, hsize, GLVector (0.0f, -1.0f, 0.0f, 1.0f));
1467 }
1468 else if (!topDir && !bottomDir)
1469 {
1470 if (allCaps)
1471 {
1472 cubeScreen->cubePaintTop (sa, transform, outputPtr, hsize, GLVector (0.0f, 1.0f, 0.0f, 1.0f));
1473 cubeScreen->cubePaintInside (sa, transform, outputPtr, hsize, GLVector (0.0f, 0.0f, -1.0f, 1.0f));
1474 }
1475 cubeScreen->cubePaintBottom (sa, transform, outputPtr, hsize, GLVector (0.0f, -1.0f, 0.0f, 1.0f));
1476 }
1477 else if (allCaps)
1478 {
1479 cubeScreen->cubePaintTop (sa, transform, outputPtr, hsize, GLVector (0.0f, 1.0f, 0.0f, 1.0f));
1480 cubeScreen->cubePaintBottom (sa, transform, outputPtr, hsize, GLVector (0.0f, -1.0f, 0.0f, 1.0f));
1481 cubeScreen->cubePaintInside (sa, transform, outputPtr, hsize, GLVector (0.0f, 0.0f, -1.0f, 1.0f));
1482 }
1483 }
1484
1485 if (wasCulled)
1486 glEnable (GL_CULL_FACE);
1487
1488 if (mInvert == 1)
1489 {
1490 /* Outside cube - continue with BTF faces */
1491 paintOrder = BTF;
1492 }
1493 else
1494 {
1495 /* Inside cube - continue with FTB faces */
1496 paintOrder = FTB;
1497 glCullFace (cullInv);
1498 }
1499
1500 if (mInvert == 1 || cubeScreen->cubeShouldPaintAllViewports ())
1501 paintAllViewports (sa, transform, region, outputPtr, mask, mXRotations,
1502 size, hsize, paintOrder);
1503
1504 glCullFace (cullNorm);
1505
1506 gScreen->setTextureFilter (filter);
1507 }
1508
1509 bool
1510 PrivateCubeWindow::glPaint (const GLWindowPaintAttrib &attrib,
1511 const GLMatrix &transform,
1512 const CompRegion ®ion,
1513 unsigned int mask)
1514 {
1515
1516 if ((window->type () & CompWindowTypeDesktopMask) &&
1517 (attrib.opacity != cubeScreen->priv->mDesktopOpacity))
1518 {
1519 GLWindowPaintAttrib wAttrib = attrib;
1520
1521 wAttrib.opacity = cubeScreen->priv->mDesktopOpacity;
1522
1523 return gWindow->glPaint (wAttrib, transform, region, mask);
1524 }
1525 else
1526 return gWindow->glPaint (attrib, transform, region, mask);
1527
1528 }
1529
1530 const CompWindowList &
1531 PrivateCubeScreen::getWindowPaintList ()
1532 {
1533 if (mPaintOrder == FTB)
1534 return mReversedWindowList;
1535 else
1536 return cScreen->getWindowPaintList ();
1537 }
1538
1539 void
1540 PrivateCubeScreen::glApplyTransform (const GLScreenPaintAttrib &sAttrib,
1541 CompOutput *output,
1542 GLMatrix *transform)
1543 {
1544 transform->translate (mOutputXOffset, -mOutputYOffset, 0.0f);
1545 transform->scale (mOutputXScale, mOutputYScale, 1.0f);
1546
1547 gScreen->glApplyTransform (sAttrib, output, transform);
1548
1549 transform->scale (1.0f / mOutputXScale, 1.0 / mOutputYScale, 1.0f);
1550 transform->translate (-mOutputXOffset, mOutputYOffset, 0.0f);
1551 }
1552
1553 bool
1554 PrivateCubeScreen::unfold (CompAction *action,
1555 CompAction::State state,
1556 CompOption::Vector &options)
1557 {
1558 Window xid;
1559
1560 xid = CompOption::getIntOptionNamed (options, "root");
1561
1562 if (::screen->root () == xid)
1563 {
1564 CUBE_SCREEN (screen);
1565
1566 if (screen->vpSize ().width () * cs->priv->mNOutput < 4)
1567 return false;
1568
1569 if (screen->otherGrabExist ("rotate", "switcher", "cube", NULL))
1570 return false;
1571
1572 if (!cs->priv->mGrabIndex)
1573 cs->priv->mGrabIndex = screen->pushGrab (screen->invisibleCursor (), "cube");
1574
1575 if (cs->priv->mGrabIndex)
1576 {
1577 cs->priv->mUnfolded = true;
1578 cs->priv->cScreen->damageScreen ();
1579 }
1580
1581 if (state & CompAction::StateInitButton)
1582 action->setState (action->state () | CompAction::StateTermButton);
1583
1584 if (state & CompAction::StateInitKey)
1585 action->setState (action->state () | CompAction::StateTermKey);
1586 }
1587
1588 return false;
1589 }
1590
1591 bool
1592 PrivateCubeScreen::fold (CompAction *action,
1593 CompAction::State state,
1594 CompOption::Vector &options)
1595 {
1596 Window xid;
1597 xid = CompOption::getIntOptionNamed (options, "root");
1598
1599 if (!xid || ::screen->root () == xid)
1600 {
1601 CUBE_SCREEN (screen);
1602
1603 if (cs->priv->mGrabIndex)
1604 {
1605 cs->priv->mUnfolded = false;
1606 cs->priv->cScreen->damageScreen ();
1607 }
1608 }
1609
1610 action->setState (action->state () & ~(CompAction::StateTermButton | CompAction::StateTermKey));
1611
1612 return false;
1613 }
1614
1615 void
1616 PrivateCubeScreen::outputChangeNotify ()
1617 {
1618 updateOutputs ();
1619 updateGeometry (screen->vpSize ().width (), mInvert);
1620
1621 screen->outputChangeNotify ();
1622 }
1623
1624 bool
1625 PrivateCubeScreen::setOptionForPlugin (const char *plugin,
1626 const char *name,
1627 CompOption::Value &v)
1628 {
1629 bool status;
1630
1631 status = screen->setOptionForPlugin (plugin, name, v);
1632
1633 if (status)
1634 {
1635 if (strcmp (plugin, "core") == 0 && strcmp (name, "hsize") == 0)
1636 updateGeometry (screen->vpSize ().width (), mInvert);
1637 }
1638
1639 return status;
1640 }
1641
1642 PrivateCubeScreen::PrivateCubeScreen (CompScreen *s) :
1643 cScreen (CompositeScreen::get (s)),
1644 gScreen (GLScreen::get (s)),
1645 cubeScreen (CubeScreen::get (s))
1646 {
1647
1648 mPw = 0;
1649 mPh = 0;
1650
1651 mInvert = 1;
1652
1653 for (int i = 0; i < 8; i++)
1654 mTc[i] = 0.0f;
1655
1656 mNVertices = 0;
1657 mVertices = NULL;
1658
1659 mGrabIndex = 0;
1660
1661 mSrcOutput = 0;
1662
1663 mSkyListId = 0;
1664
1665 mImgCurFile = 0;
1666
1667 mUnfolded = false;
1668 mUnfold = 0.0f;
1669
1670 mUnfoldVelocity = 0.0f;
1671
1672 mPaintAllViewports = false;
1673 mFullscreenOutput = true;
1674
1675 mOutputXScale = 1.0f;
1676 mOutputYScale = 1.0f;
1677 mOutputXOffset = 0.0f;
1678 mOutputYOffset = 0.0f;
1679
1680 mRotationState = CubeScreen::RotationNone;
1681
1682 mDesktopOpacity = OPAQUE;
1683 mPaintOrder = BTF;
1684
1685 mLastOpacityIndex = CubeOptions::InactiveOpacity;
1686
1687
1688 mRecalcOutput = false;
1689
1690 memset (mCleared, 0, sizeof (mCleared));
1691
1692 updateOutputs ();
1693
1694 updateGeometry (screen->vpSize ().width (), mInvert);
1695
1696 optionSetUnfoldKeyInitiate (PrivateCubeScreen::unfold);
1697 optionSetUnfoldKeyTerminate (PrivateCubeScreen::fold);
1698
1699 ScreenInterface::setHandler (s);
1700 CompositeScreenInterface::setHandler (cScreen);
1701 GLScreenInterface::setHandler (gScreen);
1702 }
1703
1704 PrivateCubeScreen::~PrivateCubeScreen ()
1705 {
1706 if (mVertices)
1707 free (mVertices);
1708
1709 #ifndef USE_GLES
1710 if (mSkyListId)
1711 glDeleteLists (mSkyListId, 1);
1712 #endif
1713 }
1714
1715
1716 template class PluginClassHandler<PrivateCubeWindow, CompWindow, COMPIZ_CUBE_ABI>;
1717
1718 PrivateCubeWindow::PrivateCubeWindow (CompWindow *w) :
1719 PluginClassHandler<PrivateCubeWindow, CompWindow, COMPIZ_CUBE_ABI> (w),
1720 window (w),
1721 cWindow (CompositeWindow::get (w)),
1722 gWindow (GLWindow::get (w)),
1723 cubeScreen (CubeScreen::get (screen))
1724 {
1725 GLWindowInterface::setHandler (gWindow, true);
1726 }
1727
1728 PrivateCubeWindow::~PrivateCubeWindow ()
1729 {
1730 }
1731
1732 template class PluginClassHandler<CubeScreen, CompScreen, COMPIZ_CUBE_ABI>;
1733
1734 CubeScreen::CubeScreen (CompScreen *s) :
1735 PluginClassHandler<CubeScreen, CompScreen, COMPIZ_CUBE_ABI> (s),
1736 priv (new PrivateCubeScreen (s))
1737 {
1738 }
1739
1740 CubeScreen::~CubeScreen ()
1741 {
1742 delete priv;
1743 }
1744
1745
1746 CompOption::Vector &
1747 CubeScreen::getOptions ()
1748 {
1749 return priv->getOptions ();
1750 }
1751
1752 bool
1753 CubeScreen::setOption (const CompString &name,
1754 CompOption::Value &value)
1755 {
1756 return priv->setOption (name, value);
1757 }
1758
1759 bool
1760 CubePluginVTable::init ()
1761 {
1762 if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION) ||
1763 !CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI) ||
1764 !CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))
1765 return false;
1766
1767 CompPrivate p;
1768 p.uval = COMPIZ_CUBE_ABI;
1769 screen->storeValue ("cube_ABI", p);
1770
1771 return true;
1772 }
1773
1774 void
1775 CubePluginVTable::fini ()
1776 {
1777 screen->eraseValue ("cube_ABI");
1778 }