1 #include "3d.h"
2
3 COMPIZ_PLUGIN_20090315 (td, TdPluginVTable);
4
5 const double PI = 3.14159265359f;
6
7 void
8 setFunctions (bool enabled)
9 {
10 TD_SCREEN (screen);
11
12 tds->gScreen->glPaintOutputSetEnabled (tds, enabled);
13 tds->gScreen->glApplyTransformSetEnabled (tds, enabled);
14 tds->cScreen->donePaintSetEnabled (tds, enabled);
15 tds->cubeScreen->cubePaintViewportSetEnabled (tds, enabled);
16 tds->cubeScreen->cubeShouldPaintViewportSetEnabled (tds, enabled);
17 tds->cubeScreen->cubeShouldPaintAllViewportsSetEnabled (tds, enabled);
18
19 foreach (CompWindow *w, screen->windows ())
20 {
21 TD_WINDOW (w);
22
23 tdw->gWindow->glPaintSetEnabled (tdw, enabled);
24 }
25 }
26
27 bool
28 TdWindow::is3D ()
29 {
30 if (window->overrideRedirect ())
31 return false;
32
33 if (!window->isViewable () || window->shaded ())
34 return false;
35
36 if (window->state () & (CompWindowStateSkipPagerMask |
37 CompWindowStateSkipTaskbarMask))
38 return false;
39
40 if (!TdScreen::get (screen)->optionGetWindowMatch ().evaluate (window))
41 return false;
42
43 return true;
44 }
45
46 void
47 TdScreen::preparePaint (int msSinceLastPaint)
48 {
49 bool active;
50
51 CUBE_SCREEN (screen);
52
53 active = (cs->rotationState () != CubeScreen::RotationNone) && screen->vpSize ().width () > 2 &&
54 !(optionGetManualOnly () && (cs->rotationState () != CubeScreen::RotationManual));
55
56 if (active || mBasicScale != 1.0)
57 {
58 float maxDiv = (float) optionGetMaxWindowSpace () / 100;
59 float minScale = (float) optionGetMinCubeSize () / 100;
60 float x, progress;
61
62 cs->cubeGetRotation (x, x, progress);
63
64 mMaxDepth = 0;
65 foreach (CompWindow *w, screen->windows ())
66 {
67 TD_WINDOW (w);
68 tdw->mIs3D = false;
69 tdw->mDepth = 0;
70
71 if (!tdw->is3D ())
72 continue;
73
74 tdw->mIs3D = true;
75 mMaxDepth++;
76 tdw->mDepth = mMaxDepth;
77
78 }
79
80 minScale = MAX (minScale, 1.0 - (mMaxDepth * maxDiv));
81 mBasicScale = 1.0 - ((1.0 - minScale) * progress);
82 mDamage = (progress != 0.0 && progress != 1.0);
83 }
84 else
85 {
86 mBasicScale = 1.0;
87 }
88
89 /* comparing float values with != is error prone, so better cache
90 the comparison and allow a small difference */
91 mActive = (fabs (mBasicScale - 1.0f) > 1e-4);
92 mCurrentScale = mBasicScale;
93
94 cScreen->preparePaint (msSinceLastPaint);
95
96 setFunctions (mActive);
97 }
98
99 #define DOBEVEL(corner) (tds->optionGetBevel##corner () ? bevel : 0)
100
101 #define SET_V \
102 for (int i = 0; i < 4; i++) \
103 v[i] = tPoint[i];
104
105 #define ADDQUAD(x1,y1,x2,y2) \
106 point[GLVector::x] = x1; point[GLVector::y] = y1; \
107 tPoint = transform * point; \
108 SET_V \
109 glVertex4fv (v); \
110 point[GLVector::x] = x2; point[GLVector::y] = y2; \
111 tPoint = transform * point; \
112 SET_V \
113 glVertex4fv (v); \
114 tPoint = tds->mBTransform * point; \
115 SET_V \
116 glVertex4fv (v); \
117 point[GLVector::x] = x1; point[GLVector::y] = y1; \
118 tPoint = tds->mBTransform * point; \
119 SET_V \
120 glVertex4fv (v); \
121
122 #define ADDBEVELQUAD(x1,y1,x2,y2,m1,m2) \
123 point[GLVector::x] = x1; point[GLVector::y] = y1; \
124 tPoint = m1 * point; \
125 SET_V \
126 glVertex4fv (v); \
127 tPoint = m2 * point; \
128 SET_V \
129 glVertex4fv (v); \
130 point[GLVector::x] = x2; point[GLVector::y] = y2; \
131 tPoint = m2 * point; \
132 SET_V \
133 glVertex4fv (v); \
134 tPoint = m1 * point; \
135 SET_V \
136 glVertex4fv (v); \
137
138 bool
139 TdWindow::glPaintWithDepth (const GLWindowPaintAttrib &attrib,
140 const GLMatrix &transform,
141 const CompRegion ®ion,
142 unsigned int mask)
143 {
144 bool status;
145 int wx, wy, ww, wh;
146 int bevel, cull, cullInv;
147 GLVector point, tPoint;
148 unsigned short *c;
149
150 TD_SCREEN (screen);
151 CUBE_SCREEN (screen);
152
153 glIsEnabled (GL_CULL_FACE);
154
155 wx = window->x () - window->input ().left;
156 wy = window->y () - window->input ().top;
157
158 ww = window->width () + window->input ().left + window->input ().right;
159 wh = window->height () + window->input ().top + window->input ().bottom;
160
161 bevel = tds->optionGetBevel ();
162
163 glGetIntegerv (GL_CULL_FACE_MODE, &cull);
164 cullInv = (cull == GL_BACK)? GL_FRONT : GL_BACK;
165
166 if (ww && wh && !(mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK) &&
167 ((cs->paintOrder () == FTB && mFtb) ||
168 (cs->paintOrder () == BTF && !mFtb)))
169 {
170 float v[4];
171 int temp;
172
173 /* Paint window depth. */
174 glPushMatrix ();
175 glLoadIdentity ();
176
177 if (cs->paintOrder () == BTF)
178 glCullFace (cullInv);
179
180 glEnable (GL_BLEND);
181 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
182
183 if (window->id () == screen->activeWindow ())
184 c = tds->optionGetWidthColor ();
185 else
186 c = tds->optionGetWidthColorInactive ();
187
188 temp = c[3] * gWindow->paintAttrib ().opacity;
189 temp /= 0xffff;
190 glColor4us (c[0], c[1], c[2], temp);
191
192 point[GLVector::z] = 0.0f;
193 point[GLVector::w] = 1.0f;
194
195 glBegin (GL_QUADS);
196
197 /* Top */
198 ADDQUAD (wx + ww - DOBEVEL (Topleft), wy + 0.01,
199 wx + DOBEVEL (Topright), wy + 0.01);
200
201 /* Bottom */
202 ADDQUAD (wx + DOBEVEL (Bottomleft), wy + wh - 0.01,
203 wx + ww - DOBEVEL (Bottomright), wy + wh - 0.01);
204
205 /* Left */
206 ADDQUAD (wx + 0.01, wy + DOBEVEL (Topleft),
207 wx + 0.01, wy + wh - DOBEVEL (Bottomleft));
208
209 /* Right */
210 ADDQUAD (wx + ww - 0.01, wy + wh - DOBEVEL (Topright),
211 wx + ww - 0.01, wy + DOBEVEL (Bottomright));
212
213 /* Top left bevel */
214 if (tds->optionGetBevelTopleft ())
215 {
216 ADDBEVELQUAD (wx + bevel / 2.0f,
217 wy + bevel - bevel / 1.2f,
218 wx, wy + bevel,
219 tds->mBTransform, transform);
220
221 ADDBEVELQUAD (wx + bevel / 2.0f,
222 wy + bevel - bevel / 1.2f,
223 wx + bevel, wy,
224 transform, tds->mBTransform);
225
226 }
227
228 /* Bottom left bevel */
229 if (tds->optionGetBevelBottomleft ())
230 {
231 ADDBEVELQUAD (wx + bevel / 2.0f,
232 wy + wh - bevel + bevel / 1.2f,
233 wx, wy + wh - bevel,
234 transform, tds->mBTransform);
235
236 ADDBEVELQUAD (wx + bevel / 2.0f,
237 wy + wh - bevel + bevel / 1.2f,
238 wx + bevel, wy + wh,
239 tds->mBTransform, transform);
240 }
241
242 /* Bottom right bevel */
243 if (tds->optionGetBevelBottomright ())
244 {
245 ADDBEVELQUAD (wx + ww - bevel / 2.0f,
246 wy + wh - bevel + bevel / 1.2f,
247 wx + ww - bevel, wy + wh,
248 transform, tds->mBTransform);
249
250 ADDBEVELQUAD (wx + ww - bevel / 2.0f,
251 wy + wh - bevel + bevel / 1.2f,
252 wx + ww, wy + wh - bevel,
253 tds->mBTransform, transform);
254
255
256 }
257
258 /* Top right bevel */
259 if (tds->optionGetBevelTopright ())
260 {
261 ADDBEVELQUAD (wx + ww - bevel, wy,
262 wx + ww - bevel / 2.0f,
263 wy + bevel - bevel / 1.2f,
264 transform, tds->mBTransform);
265
266 ADDBEVELQUAD (wx + ww, wy + bevel,
267 wx + ww - bevel / 2.0f,
268 wy + bevel - bevel / 1.2f,
269 tds->mBTransform, transform);
270 }
271 glEnd ();
272
273 glColor4usv (defaultColor);
274 glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
275 glPopMatrix ();
276
277 if (cs->paintOrder () == BTF)
278 glCullFace (cull);
279 }
280
281 if (cs->paintOrder () == BTF)
282 status = gWindow->glPaint (attrib, transform, region, mask);
283 else
284 status = gWindow->glPaint (attrib, tds->mBTransform, region,
285 mask | PAINT_WINDOW_TRANSFORMED_MASK);
286
287 return status;
288 }
289
290 bool
291 TdWindow::glPaint (const GLWindowPaintAttrib &attrib,
292 const GLMatrix &transform,
293 const CompRegion ®ion,
294 unsigned int mask)
295 {
296 bool status;
297
298 TD_SCREEN (screen);
299
300 if (mDepth != 0.0f && !tds->mPainting3D && tds->mActive)
301 mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK;
302
303 if (tds->mPainting3D && tds->optionGetWidth () && (mDepth != 0.0f) &&
304 tds->mWithDepth)
305 {
306 status = glPaintWithDepth (attrib, transform, region, mask);
307 }
308 else
309 {
310 status = gWindow->glPaint (attrib, transform, region, mask);
311 }
312
313 return status;
314 }
315
316 void
317 TdScreen::glApplyTransform (const GLScreenPaintAttrib &attrib,
318 CompOutput *output,
319 GLMatrix *transform)
320 {
321
322 gScreen->glApplyTransform (attrib, output, transform);
323
324 transform->scale (mCurrentScale, mCurrentScale, mCurrentScale);
325 }
326
327
328 void
329 TdScreen::cubePaintViewport (const GLScreenPaintAttrib &attrib,
330 const GLMatrix &transform,
331 const CompRegion ®ion,
332 CompOutput *output,
333 unsigned int mask)
334 {
335 CUBE_SCREEN (screen);
336
337 if (cs->paintOrder () == BTF)
338 {
339 cs->cubePaintViewport (attrib, transform,region, output, mask);
340 }
341
342 if (mActive)
343 {
344 GLMatrix mTransform; // NOT a member variable
345 GLMatrix screenSpace;
346 GLMatrix screenSpaceOffset;
347 TdWindow *tdw;
348 CompWindowList pl;
349 CompWindowList::iterator it;
350 float wDepth = 0.0;
351 float pointZ = cs->invert () * cs->distance ();
352 unsigned int newMask;
353
354 std::vector<GLVector> vPoints;
355 vPoints.push_back (GLVector (-0.5, 0.0, pointZ, 1.0));
356 vPoints.push_back (GLVector (0.0, 0.5, pointZ, 1.0));
357 vPoints.push_back (GLVector (0.0, 0.0, pointZ, 1.0));
358
359 if (mWithDepth)
360 wDepth = -MIN((optionGetWidth ()) / 30, (1.0 - mBasicScale) /
361 mMaxDepth);
362
363 if (wDepth != 0.0)
364 {
365 /* all BTF windows in normal order */
366 foreach (CompWindow *w, screen->windows ())
367 {
368 tdw = TdWindow::get (w);
369
370 if (!tdw->mIs3D)
371 continue;
372
373 mCurrentScale = mBasicScale +
374 (tdw->mDepth * ((1.0 - mBasicScale) /
375 mMaxDepth));
376
377 tdw->mFtb = cs->cubeCheckOrientation (attrib, transform, output,
378 vPoints);
379 }
380 }
381
382 mCurrentScale = mBasicScale;
383 mPainting3D = true;
384
385 gScreen->setLighting (true);
386
387 screenSpace.reset ();
388 screenSpace.toScreenSpace (output, -attrib.zTranslate);
389
390 glPushMatrix ();
391
392 pl = cScreen->getWindowPaintList ();
393
394 /* paint all windows from bottom to top */
395 for (it = pl.begin (); it != pl.end (); ++it)
396 {
397 CompWindow *w = (*it);
398 tdw = TdWindow::get (w);
399
400 if (w->destroyed ())
401 continue;
402
403 if (!w->shaded () || !w->isViewable ())
404 {
405 if (!tdw->cWindow->damaged ())
406 continue;
407 }
408
409 mTransform = transform;
410 newMask = PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK;
411
412 if (tdw->mDepth != 0.0f)
413 {
414 mCurrentScale = mBasicScale +
415 (tdw->mDepth * ((1.0 - mBasicScale) /
416 mMaxDepth));
417
418 if (wDepth != 0.0)
419 {
420 mCurrentScale += wDepth;
421 mBTransform = transform;
422 gScreen->glApplyTransform (attrib, output, &mBTransform);
423 mCurrentScale -= wDepth;
424 }
425
426 gScreen->glApplyTransform (attrib, output, &mTransform);
427
428 gScreen->glEnableOutputClipping (mTransform, region, output);
429
430 if ((cScreen->windowPaintOffset ().x () != 0 ||
431 cScreen->windowPaintOffset ().y () != 0) &&
432 !w->onAllViewports ())
433 {
434 CompPoint moveOffset;
435 moveOffset = w->getMovementForOffset (
436 cScreen->windowPaintOffset ());
437
438 screenSpaceOffset = screenSpace;
439 screenSpaceOffset.translate (moveOffset.x (),
440 moveOffset.y (), 0);
441
442 if (wDepth != 0.0)
443 mBTransform = mBTransform * screenSpaceOffset;
444 mTransform = mTransform * screenSpaceOffset;
445
446 newMask |= PAINT_WINDOW_WITH_OFFSET_MASK;
447 }
448 else
449 {
450 if (wDepth != 0.0)
451 mBTransform = mBTransform * screenSpace;
452 mTransform = mTransform * screenSpace;
453 }
454
455 glLoadMatrixf (mTransform.getMatrix ());
456
457 tdw->gWindow->glPaint (tdw->gWindow->paintAttrib (), mTransform,
458 infiniteRegion, newMask);
459
460 gScreen->glDisableOutputClipping ();
461
462 }
463 }
464
465 glPopMatrix ();
466
467 mPainting3D = false;
468 mCurrentScale = mBasicScale;
469
470 }
471
472
473 if (cs->paintOrder () == FTB)
474 {
475 cs->cubePaintViewport (attrib, transform, region, output, mask);
476 }
477 }
478
479 bool
480 TdScreen::cubeShouldPaintAllViewports ()
481 {
482 return true;
483 }
484
485 bool
486 TdScreen::cubeShouldPaintViewport (const GLScreenPaintAttrib &attrib,
487 const GLMatrix &transform,
488 CompOutput *outputPtr,
489 PaintOrder order)
490 {
491 bool rv = false;
492
493 CUBE_SCREEN (screen);
494
495 rv = cs->cubeShouldPaintViewport (attrib, transform, outputPtr, order);
496
497 if (mActive)
498 {
499 float pointZ = cs->invert () * cs->distance ();
500 bool ftb1, ftb2;
501
502 std::vector<GLVector> vPoints;
503
504 vPoints.push_back (GLVector (-0.5, 0.0, pointZ, 1.0));
505 vPoints.push_back (GLVector (0.0, 0.5, pointZ, 1.0));
506 vPoints.push_back (GLVector (0.0, 0.0, pointZ, 1.0));
507
508 mCurrentScale = 1.0;
509
510 ftb1 = cs->cubeCheckOrientation (attrib, transform, outputPtr, vPoints);
511
512 mCurrentScale = mBasicScale;
513
514 ftb2 = cs->cubeCheckOrientation (attrib, transform, outputPtr, vPoints);
515
516 return (order == FTB && (ftb1 || ftb2)) ||
517 (order == BTF && (!ftb1 || !ftb2)) || rv;
518 }
519
520 return true;
521 }
522
523 bool
524 TdScreen::glPaintOutput (const GLScreenPaintAttrib &attrib,
525 const GLMatrix &transform,
526 const CompRegion ®ion,
527 CompOutput *output,
528 unsigned int mask)
529 {
530 bool status;
531
532 if (mActive)
533 {
534 CompPlugin *p;
535
536 mask |= PAINT_SCREEN_TRANSFORMED_MASK |
537 PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK |
538 PAINT_SCREEN_NO_OCCLUSION_DETECTION_MASK;
539
540 mWithDepth = true;
541
542 p = CompPlugin::find ("cubeaddon");
543 if (p)
544 {
545 CompOption::Vector &options = p->vTable->getOptions ();
546 CompOption option;
547
548 mWithDepth = (CompOption::getIntOptionNamed
549 (options, "deformation", 0) == 0);
550 }
551 }
552
553
554 status = gScreen->glPaintOutput (attrib, transform, region, output, mask);
555
556 return status;
557 }
558
559 void
560 TdScreen::donePaint ()
561 {
562 if (mActive && mDamage)
563 {
564 mDamage = false;
565 cScreen->damageScreen ();
566 }
567
568 cScreen->donePaint ();
569 }
570
571 TdScreen::TdScreen (CompScreen *screen) :
572 PluginClassHandler <TdScreen, CompScreen> (screen),
573 cScreen (CompositeScreen::get (screen)),
574 gScreen (GLScreen::get (screen)),
575 cubeScreen (CubeScreen::get (screen)),
576 mActive (false),
577 mPainting3D (false),
578 mCurrentScale (1.0f),
579 mBasicScale (1.0f)
580 {
581 CompositeScreenInterface::setHandler (cScreen, false);
582 GLScreenInterface::setHandler (gScreen, false);
583 CubeScreenInterface::setHandler (cubeScreen, false);
584
585 cScreen->preparePaintSetEnabled (this, true);
CID 12589 - UNINIT_CTOR
Non-static class member "mMaxDepth" is not initialized in this constructor nor in any functions that it calls.
Non-static class member "mDamage" is not initialized in this constructor nor in any functions that it calls.
Non-static class member "mWithDepth" is not initialized in this constructor nor in any functions that it calls.
586 }
587
588 TdScreen::~TdScreen ()
589 {
590 }
591
592 TdWindow::TdWindow (CompWindow *window) :
593 PluginClassHandler <TdWindow, CompWindow> (window),
594 window (window),
595 cWindow (CompositeWindow::get (window)),
596 gWindow (GLWindow::get (window)),
597 mIs3D (false),
598 mFtb (false),
599 mDepth (0.0f)
600 {
601 GLWindowInterface::setHandler (gWindow, false);
602 }
603
604 TdWindow::~TdWindow ()
605 {
606 }
607
608 bool
609 TdPluginVTable::init ()
610 {
611 if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION) ||
612 !CompPlugin::checkPluginABI ("cube", COMPIZ_CUBE_ABI) ||
613 !CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI) ||
614 !CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))
615 return false;
616
617 return true;
618 }