1 /*
2  * Compiz cube reflection and cylinder deformation plugin
3  *
4  * cubeaddon.c
5  *
6  * Copyright : (C) 2008 by Dennis Kasprzyk
7  * E-mail    : onestone@opencompositing.org
8  *
9  * includes code from cubecaps.c
10  *
11  * Copyright : (C) 2007 Guillaume Seguin
12  * E-mail    : guillaume@segu.in
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  */
25 
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdio.h>
29 #include <signal.h>
30 #include <unistd.h>
31 #include <math.h>
32 
33 #include <compiz-core.h>
34 #include <compiz-cube.h>
35 
36 #include "cubeaddon_options.h"
37 
38 static int CubeaddonDisplayPrivateIndex;
39 static int cubeDisplayPrivateIndex;
40 
41 #define CUBEADDON_GRID_SIZE    100
42 #define CAP_ELEMENTS 15
43 #define CAP_NVERTEX (((CAP_ELEMENTS * (CAP_ELEMENTS + 1)) + 2) * 3)
44 #define CAP_NIDX (CAP_ELEMENTS * (CAP_ELEMENTS - 1) * 4)
45 
46 #define CAP_NIMGVERTEX (((CAP_ELEMENTS + 1) * (CAP_ELEMENTS + 1)) * 5)
47 #define CAP_NIMGIDX (CAP_ELEMENTS * CAP_ELEMENTS * 4)
48 
49 typedef struct _CubeaddonDisplay
50 {
51     int screenPrivateIndex;
52 } CubeaddonDisplay;
53 
54 typedef struct _CubeCap
55 {
56     int		    current;
57     CompListValue   *files;
58 
59     Bool            loaded;
60 
61     CompTexture	    texture;
62     CompTransform   texMat;
63 } CubeCap;
64 
65 typedef struct _CubeaddonScreen
66 {
67     DonePaintScreenProc        donePaintScreen;
68     PaintOutputProc            paintOutput;
69     PaintTransformedOutputProc paintTransformedOutput;
70     AddWindowGeometryProc      addWindowGeometry;
71     DrawWindowProc	       drawWindow;
72     DrawWindowTextureProc      drawWindowTexture;
73 
74     CubeClearTargetOutputProc   clearTargetOutput;
75     CubeGetRotationProc	        getRotation;
76     CubeCheckOrientationProc    checkOrientation;
77     CubeShouldPaintViewportProc shouldPaintViewport;
78     CubePaintTopProc	        paintTop;
79     CubePaintBottomProc	        paintBottom;
80 
81     Bool reflection;
82     Bool first;
83 
84     CompOutput *last;
85 
86     float yTrans;
87     float zTrans;
88 
89     float backVRotate;
90     float vRot;
91 
92     float deform;
93     Bool  wasDeformed;
94 
95     Region tmpRegion;
96     BoxPtr tmpBox;
97     int    nTmpBox;
98 
99     GLfloat      *winNormals;
100     unsigned int winNormSize;
101 
102     GLfloat  capFill[CAP_NVERTEX];
103     GLfloat  capFillNorm[CAP_NVERTEX];
104     GLushort capFillIdx[CAP_NIDX];
105     float    capDeform;
106     float    capDistance;
107     int      capDeformType;
108 
109     CubeCap topCap;
110     CubeCap bottomCap;
111 } CubeaddonScreen;
112 
113 #define CUBEADDON_DISPLAY(d) PLUGIN_DISPLAY(d, Cubeaddon, ca)
114 #define CUBEADDON_SCREEN(s) PLUGIN_SCREEN(s, Cubeaddon, ca)
115 
116 /*
117  * Initiate a CubeCap
118  */
119 static void
cubeaddonInitCap(CompScreen * s,CubeCap * cap)120 cubeaddonInitCap (CompScreen *s, CubeCap *cap)
121 {
122     initTexture (s, &cap->texture);
123 
124     cap->current    = 0;
125     cap->files	    = NULL;
126     cap->loaded     = FALSE;
127 }
128 
129 /*
130  * Attempt to load current cap image (if any)
131  */
132 static void
cubeaddonLoadCap(CompScreen * s,CubeCap * cap,Bool scale,Bool aspect,Bool clamp)133 cubeaddonLoadCap (CompScreen *s,
134 		  CubeCap    *cap,
135 		  Bool       scale,
136 		  Bool       aspect,
137 		  Bool       clamp)
138 {
139     unsigned int width, height;
140     float        xScale, yScale;
141 
142     CUBE_SCREEN (s);
143 
144     finiTexture (s, &cap->texture);
145     initTexture (s, &cap->texture);
146 
147     cap->loaded = FALSE;
148 
149     if (!cap->files || !cap->files->nValue)
150 	return;
151 
152     cap->current = cap->current % cap->files->nValue;
153 
154     if (!readImageToTexture (s, &cap->texture,
155 			     cap->files->value[cap->current].s,
156 			     &width, &height))
157     {
158 	compLogMessage ("cubeaddon", CompLogLevelWarn,
159 			"Failed to load image: %s",
160 			cap->files->value[cap->current].s);
161 
162 	finiTexture (s, &cap->texture);
163 	initTexture (s, &cap->texture);
164 
165 	return;
166     }
167 
168     cap->loaded = TRUE;
169     matrixGetIdentity (&cap->texMat);
170 
171     cap->texMat.m[0] = cap->texture.matrix.xx;
172     cap->texMat.m[1] = cap->texture.matrix.yx;
173     cap->texMat.m[4] = cap->texture.matrix.xy;
174     cap->texMat.m[5] = cap->texture.matrix.yy;
175     cap->texMat.m[12] = cap->texture.matrix.x0;
176     cap->texMat.m[13] = cap->texture.matrix.y0;
177 
178     if (aspect)
179     {
180 	if (scale)
181 	    xScale = yScale = MIN (width, height);
182 	else
183 	    xScale = yScale = MAX (width, height);
184     }
185     else
186     {
187 	xScale = width;
188 	yScale = height;
189     }
190 
191     matrixTranslate (&cap->texMat, width / 2, height / 2.0, 0.0);
192     matrixScale (&cap->texMat, xScale / 2.0, yScale / 2.0, 1.0);
193 
194     if (scale)
195 	xScale = 1.0 / sqrtf (((cs->distance * cs->distance) + 0.25));
196     else
197 	xScale = 1.0 / sqrtf (((cs->distance * cs->distance) + 0.25) * 0.5);
198 
199     matrixScale (&cap->texMat, xScale, xScale, 1.0);
200 
201     enableTexture (s, &cap->texture, COMP_TEXTURE_FILTER_GOOD);
202     if (clamp)
203     {
204 	if (s->textureBorderClamp)
205 	{
206 	    glTexParameteri (cap->texture.target, GL_TEXTURE_WRAP_S,
207 			     GL_CLAMP_TO_BORDER);
208 	    glTexParameteri (cap->texture.target, GL_TEXTURE_WRAP_T,
209 			     GL_CLAMP_TO_BORDER);
210 	}
211 	else
212 	{
213 	    glTexParameteri (cap->texture.target, GL_TEXTURE_WRAP_S,
214 			     GL_CLAMP_TO_EDGE);
215 	    glTexParameteri (cap->texture.target, GL_TEXTURE_WRAP_T,
216 			     GL_CLAMP_TO_EDGE);
217 	}
218     }
219     else
220     {
221 	glTexParameteri (cap->texture.target, GL_TEXTURE_WRAP_S, GL_REPEAT);
222 	glTexParameteri (cap->texture.target, GL_TEXTURE_WRAP_T, GL_REPEAT);
223     }
224     disableTexture (s, &cap->texture);
225 }
226 
227 /* Settings handling -------------------------------------------------------- */
228 
229 /*
230  * Switch cap, load it and damage screen if possible
231  */
232 static void
cubeaddonChangeCap(CompScreen * s,Bool top,int change)233 cubeaddonChangeCap (CompScreen *s,
234 		    Bool       top,
235 		    int        change)
236 {
237     CUBEADDON_SCREEN (s);
238     CubeCap *cap = (top)? &cas->topCap : &cas->bottomCap;
239     if (cap->files && cap->files->nValue)
240     {
241 	int count = cap->files->nValue;
242 	cap->current = (cap->current + change + count) % count;
243 	if (top)
244 	{
245 	    cubeaddonLoadCap (s, cap, cubeaddonGetTopScale (s),
246 			      cubeaddonGetTopAspect (s),
247 			      cubeaddonGetTopClamp (s));
248 	}
249 	else
250 	{
251 	    cubeaddonLoadCap (s, cap, cubeaddonGetBottomScale (s),
252 			      cubeaddonGetBottomAspect (s),
253 			      cubeaddonGetBottomClamp (s));
254 	    matrixScale (&cap->texMat, 1.0, -1.0, 1.0);
255 	}
256 	damageScreen (s);
257     }
258 }
259 
260 /*
261  * Top images list changed, reload top cap if any
262  */
263 static void
cubeaddonTopImagesChanged(CompScreen * s,CompOption * opt,CubeaddonScreenOptions num)264 cubeaddonTopImagesChanged (CompScreen             *s,
265 			   CompOption             *opt,
266 			   CubeaddonScreenOptions num)
267 {
268     CUBEADDON_SCREEN (s);
269 
270     cas->topCap.files   = cubeaddonGetTopImages (s);
271     cas->topCap.current = 0;
272     cubeaddonChangeCap (s, TRUE, 0);
273 }
274 
275 /*
276  * Bottom images list changed, reload bottom cap if any
277  */
278 static void
cubeaddonBottomImagesChanged(CompScreen * s,CompOption * opt,CubeaddonScreenOptions num)279 cubeaddonBottomImagesChanged (CompScreen             *s,
280 			      CompOption             *opt,
281 			      CubeaddonScreenOptions num)
282 {
283     CUBEADDON_SCREEN (s);
284 
285     cas->bottomCap.files   = cubeaddonGetBottomImages (s);
286     cas->bottomCap.current = 0;
287     cubeaddonChangeCap (s, FALSE, 0);
288 }
289 
290 /*
291  * Top image attribute changed
292  */
293 static void
cubeaddonTopImageChanged(CompScreen * s,CompOption * opt,CubeaddonScreenOptions num)294 cubeaddonTopImageChanged (CompScreen             *s,
295 			  CompOption             *opt,
296 			  CubeaddonScreenOptions num)
297 {
298     cubeaddonChangeCap (s, TRUE, 0);
299 }
300 
301 /*
302  * Bottom images attribute changed
303  */
304 static void
cubeaddonBottomImageChanged(CompScreen * s,CompOption * opt,CubeaddonScreenOptions num)305 cubeaddonBottomImageChanged (CompScreen             *s,
306 			     CompOption             *opt,
307 			     CubeaddonScreenOptions num)
308 {
309     cubeaddonChangeCap (s, FALSE, 0);
310 }
311 
312 /* Actions handling --------------------------------------------------------- */
313 
314 /*
315  * Switch to next top image
316  */
317 static Bool
cubeaddonTopNext(CompDisplay * d,CompAction * action,CompActionState state,CompOption * option,int nOption)318 cubeaddonTopNext (CompDisplay     *d,
319 		  CompAction      *action,
320 		  CompActionState state,
321 		  CompOption      *option,
322 		  int             nOption)
323 {
324     CompScreen *s;
325     Window     xid;
326 
327     xid = getIntOptionNamed (option, nOption, "root", 0);
328 
329     s = findScreenAtDisplay (d, xid);
330 
331     if (s)
332 	cubeaddonChangeCap (s, TRUE, 1);
333 
334     return FALSE;
335 }
336 
337 /*
338  * Switch to previous top image
339  */
340 static Bool
cubeaddonTopPrev(CompDisplay * d,CompAction * action,CompActionState state,CompOption * option,int nOption)341 cubeaddonTopPrev (CompDisplay     *d,
342 		  CompAction      *action,
343 		  CompActionState state,
344 		  CompOption      *option,
345 		  int             nOption)
346 {
347     CompScreen *s;
348     Window     xid;
349 
350     xid = getIntOptionNamed (option, nOption, "root", 0);
351 
352     s = findScreenAtDisplay (d, xid);
353     if (s)
354 	cubeaddonChangeCap (s, TRUE, -1);
355 
356     return FALSE;
357 }
358 
359 /*
360  * Switch to next bottom image
361  */
362 static Bool
cubeaddonBottomNext(CompDisplay * d,CompAction * action,CompActionState state,CompOption * option,int nOption)363 cubeaddonBottomNext (CompDisplay     *d,
364 		     CompAction      *action,
365 		     CompActionState state,
366 		     CompOption      *option,
367 		     int             nOption)
368 {
369     CompScreen *s;
370     Window     xid;
371 
372     xid = getIntOptionNamed (option, nOption, "root", 0);
373 
374     s = findScreenAtDisplay (d, xid);
375 
376     if (s)
377 	cubeaddonChangeCap (s, FALSE, 1);
378 
379     return FALSE;
380 }
381 
382 /*
383  * Switch to previous bottom image
384  */
385 static Bool
cubeaddonBottomPrev(CompDisplay * d,CompAction * action,CompActionState state,CompOption * option,int nOption)386 cubeaddonBottomPrev (CompDisplay     *d,
387 		     CompAction      *action,
388 		     CompActionState state,
389 		     CompOption      *option,
390 		     int             nOption)
391 {
392     CompScreen *s;
393     Window     xid;
394 
395     xid = getIntOptionNamed (option, nOption, "root", 0);
396 
397     s = findScreenAtDisplay (d, xid);
398     if (s)
399 	cubeaddonChangeCap (s, FALSE, -1);
400 
401     return FALSE;
402 }
403 
404 static void
drawBasicGround(CompScreen * s)405 drawBasicGround (CompScreen *s)
406 {
407     float i;
408 
409     glPushMatrix ();
410 
411     glEnable (GL_BLEND);
412     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
413 
414     glLoadIdentity ();
415     glTranslatef (0.0, 0.0, -DEFAULT_Z_CAMERA);
416 
417     i = cubeaddonGetIntensity (s) * 2;
418 
419     glBegin (GL_QUADS);
420     glColor4f (0.0, 0.0, 0.0, MAX (0.0, 1.0 - i) );
421     glVertex2f (0.5, 0.0);
422     glVertex2f (-0.5, 0.0);
423     glColor4f (0.0, 0.0, 0.0, MIN (1.0, 1.0 - (i - 1.0) ) );
424     glVertex2f (-0.5, -0.5);
425     glVertex2f (0.5, -0.5);
426     glEnd ();
427 
428     if (cubeaddonGetGroundSize (s) > 0.0)
429     {
430 	glBegin (GL_QUADS);
431 	glColor4usv (cubeaddonGetGroundColor1 (s) );
432 	glVertex2f (-0.5, -0.5);
433 	glVertex2f (0.5, -0.5);
434 	glColor4usv (cubeaddonGetGroundColor2 (s) );
435 	glVertex2f (0.5, -0.5 + cubeaddonGetGroundSize (s) );
436 	glVertex2f (-0.5, -0.5 + cubeaddonGetGroundSize (s) );
437 	glEnd ();
438     }
439 
440     glColor4usv (defaultColor);
441 
442     glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
443     glDisable (GL_BLEND);
444     glPopMatrix ();
445 }
446 
447 static Bool
cubeaddonCheckOrientation(CompScreen * s,const ScreenPaintAttrib * sAttrib,const CompTransform * transform,CompOutput * outputPtr,CompVector * points)448 cubeaddonCheckOrientation (CompScreen              *s,
449 			   const ScreenPaintAttrib *sAttrib,
450 			   const CompTransform     *transform,
451 			   CompOutput              *outputPtr,
452 			   CompVector              *points)
453 {
454     Bool status;
455 
456     CUBEADDON_SCREEN (s);
457     CUBE_SCREEN (s);
458 
459     UNWRAP (cas, cs, checkOrientation);
460     status = (*cs->checkOrientation) (s, sAttrib, transform,
461 				      outputPtr, points);
462     WRAP (cas, cs, checkOrientation, cubeaddonCheckOrientation);
463 
464     if (cas->reflection)
465 	return !status;
466 
467     return status;
468 }
469 
470 static void
cubeaddonGetRotation(CompScreen * s,float * x,float * v,float * progress)471 cubeaddonGetRotation (CompScreen *s,
472 		      float      *x,
473 		      float      *v,
474 		      float      *progress)
475 {
476     CUBE_SCREEN (s);
477     CUBEADDON_SCREEN (s);
478 
479     UNWRAP (cas, cs, getRotation);
480     (*cs->getRotation) (s, x, v, progress);
481     WRAP (cas, cs, getRotation, cubeaddonGetRotation);
482 
483     if (cubeaddonGetMode (s) == ModeAbove && *v > 0.0 && cas->reflection)
484     {
485 	cas->vRot = *v;
486 	*v = 0.0;
487     }
488     else
489 	cas->vRot = 0.0;
490 }
491 
492 static void
cubeaddonClearTargetOutput(CompScreen * s,float xRotate,float vRotate)493 cubeaddonClearTargetOutput (CompScreen *s,
494 			    float      xRotate,
495 			    float      vRotate)
496 {
497     CUBEADDON_SCREEN (s);
498     CUBE_SCREEN (s);
499 
500     if (cas->reflection)
501 	glCullFace (GL_BACK);
502 
503     UNWRAP (cas, cs, clearTargetOutput);
504     (*cs->clearTargetOutput) (s, xRotate, cas->backVRotate);
505     WRAP (cas, cs, clearTargetOutput, cubeaddonClearTargetOutput);
506 
507     if (cas->reflection)
508 	glCullFace (GL_FRONT);
509 }
510 
511 static Bool
cubeaddonShouldPaintViewport(CompScreen * s,const ScreenPaintAttrib * sAttrib,const CompTransform * transform,CompOutput * outputPtr,PaintOrder order)512 cubeaddonShouldPaintViewport (CompScreen              *s,
513 			      const ScreenPaintAttrib *sAttrib,
514 			      const CompTransform     *transform,
515 			      CompOutput              *outputPtr,
516 			      PaintOrder              order)
517 {
518     Bool rv = FALSE;
519 
520     CUBEADDON_SCREEN (s);
521     CUBE_SCREEN (s);
522 
523     UNWRAP (cas, cs, shouldPaintViewport);
524     rv = (*cs->shouldPaintViewport) (s, sAttrib, transform,
525 				     outputPtr, order);
526     WRAP (cas, cs, shouldPaintViewport, cubeaddonShouldPaintViewport);
527 
528     if (rv || cs->unfolded)
529 	return rv;
530 
531     if (cas->deform > 0.0 && cubeaddonGetDeformation (s) == DeformationCylinder)
532     {
533 	float z[3];
534 	Bool  ftb1, ftb2, ftb3;
535 
536 	z[0] = cs->invert * cs->distance;
537 	z[1] = z[0] + (0.25 / cs->distance);
538 	z[2] = cs->invert * sqrtf (0.25 + (cs->distance * cs->distance));
539 
540 	CompVector vPoints[3][3] = { { {.v = { -0.5,  0.0, z[0], 1.0 } },
541 				       {.v = {  0.0,  0.5, z[1], 1.0 } },
542 				       {.v = {  0.0,  0.0, z[1], 1.0 } } },
543 				     { {.v = {  0.5,  0.0, z[0], 1.0 } },
544 				       {.v = {  0.0, -0.5, z[1], 1.0 } },
545 				       {.v = {  0.0,  0.0, z[1], 1.0 } } },
546 				     { {.v = { -0.5,  0.0, z[2], 1.0 } },
547 				       {.v = {  0.0,  0.5, z[2], 1.0 } },
548 				       {.v = {  0.0,  0.0, z[2], 1.0 } } } };
549 
550 	ftb1 = (*cs->checkOrientation) (s, sAttrib, transform,
551 					outputPtr, vPoints[0]);
552 	ftb2 = (*cs->checkOrientation) (s, sAttrib, transform,
553 					outputPtr, vPoints[1]);
554 	ftb3 = (*cs->checkOrientation) (s, sAttrib, transform,
555 					outputPtr, vPoints[2]);
556 
557 	rv = (order == FTB && (ftb1 || ftb2 || ftb3)) ||
558 	     (order == BTF && (!ftb1 || !ftb2 || !ftb3));
559     }
560     else if (cas->deform > 0.0 &&
561 	     cubeaddonGetDeformation (s) == DeformationSphere)
562     {
563 	float z[4];
564 	Bool  ftb1, ftb2, ftb3, ftb4;
565 
566 	z[0] = sqrtf (0.5 + (cs->distance * cs->distance));
567 	z[1] = z[0] + (0.25 / cs->distance);
568 	z[2] = sqrtf (0.25 + (cs->distance * cs->distance));
569 	z[3] = z[2] + 0.5;
570 
571 	CompVector vPoints[4][3] = { { {.v = {  0.0,  0.0, z[3], 1.0 } },
572 				       {.v = { -0.5,  0.5, z[2], 1.0 } },
573 				       {.v = {  0.0,  0.5, z[2], 1.0 } } },
574 				     { {.v = {  0.0,  0.0, z[3], 1.0 } },
575 				       {.v = {  0.5, -0.5, z[2], 1.0 } },
576 				       {.v = {  0.0, -0.5, z[2], 1.0 } } },
577 	   			     { {.v = {  0.0,  0.0, z[1], 1.0 } },
578 				       {.v = { -0.5, -0.5, z[0], 1.0 } },
579 				       {.v = { -0.5,  0.0, z[0], 1.0 } } },
580 				     { {.v = {  0.0,  0.0, z[1], 1.0 } },
581 				       {.v = {  0.5,  0.5, z[0], 1.0 } },
582 				       {.v = {  0.5,  0.0, z[0], 1.0 } } } };
583 
584 	ftb1 = (*cs->checkOrientation) (s, sAttrib, transform,
585 					outputPtr, vPoints[0]);
586 	ftb2 = (*cs->checkOrientation) (s, sAttrib, transform,
587 					outputPtr, vPoints[1]);
588 	ftb3 = (*cs->checkOrientation) (s, sAttrib, transform,
589 					outputPtr, vPoints[2]);
590 	ftb4 = (*cs->checkOrientation) (s, sAttrib, transform,
591 					outputPtr, vPoints[3]);
592 
593 	rv = (order == FTB && (ftb1 || ftb2 || ftb3 || ftb4)) ||
594 	     (order == BTF && (!ftb1 || !ftb2 || !ftb3 || !ftb4));
595     }
596 
597     return rv;
598 }
599 
600 static void
cubeaddonPaintCap(CompScreen * s,const ScreenPaintAttrib * sAttrib,const CompTransform * transform,CompOutput * output,int size,Bool top,Bool adjust,unsigned short * color)601 cubeaddonPaintCap (CompScreen		   *s,
602 		   const ScreenPaintAttrib *sAttrib,
603 		   const CompTransform     *transform,
604 		   CompOutput		   *output,
605 		   int			   size,
606 		   Bool                    top,
607 		   Bool                    adjust,
608 		   unsigned short          *color)
609 {
610     ScreenPaintAttrib sa;
611     CompTransform     sTransform;
612     int               i, l, opacity;
613     int               cullNorm, cullInv;
614     Bool              wasCulled = glIsEnabled (GL_CULL_FACE);
615     float             cInv = (top) ? 1.0: -1.0;
616     CubeCap           *cap;
617     Bool              cScale, cAspect;
618 
619     CUBE_SCREEN (s);
620     CUBEADDON_SCREEN (s);
621 
622     glGetIntegerv (GL_CULL_FACE_MODE, &cullNorm);
623     cullInv   = (cullNorm == GL_BACK)? GL_FRONT : GL_BACK;
624 
625     opacity = cs->desktopOpacity * color[3] / 0xffff;
626 
627     glPushMatrix ();
628     glEnable (GL_BLEND);
629 
630     if (top)
631     {
632 	cap     = &cas->topCap;
633 	cScale  = cubeaddonGetTopScale (s);
634 	cAspect = cubeaddonGetTopAspect (s);
635     }
636     else
637     {
638 	cap     = &cas->bottomCap;
639 	cScale  = cubeaddonGetBottomScale (s);
640 	cAspect = cubeaddonGetBottomAspect (s);
641     }
642 
643 
644     glDisableClientState (GL_TEXTURE_COORD_ARRAY);
645 
646     if (cubeaddonGetDeformation (s) == DeformationSphere &&
647         cubeaddonGetDeformCaps (s))
648 	glEnableClientState (GL_NORMAL_ARRAY);
649 
650     glVertexPointer (3, GL_FLOAT, 0, cas->capFill);
651 
652     glEnable(GL_CULL_FACE);
653 
654     for (l = 0; l < ((cs->invert == 1) ? 2 : 1); l++)
655     {
656 	if (cubeaddonGetDeformation (s) == DeformationSphere &&
657 	    cubeaddonGetDeformCaps (s))
658 	{
659 	    glNormalPointer (GL_FLOAT, 0, (l == 0) ? cas->capFill : cas->capFillNorm);
660 	}
661 	else
662 	    glNormal3f (0.0, (l == 0) ? 1.0 : -1.0, 0.0);
663 
664 	glCullFace(((l == 1) ^ top) ? cullInv : cullNorm);
665 
666 	for (i = 0; i < size; i++)
667 	{
668 	    sa = *sAttrib;
669 	    sTransform = *transform;
670 	    if (cs->invert == 1)
671 	    {
672 		sa.yRotate += (360.0f / size) * cs->xRotations;
673 		if (!adjust)
674 		    sa.yRotate -= (360.0f / size) * s->x;
675 	    }
676 	    else
677 	    {
678 		sa.yRotate += 180.0f;
679 		sa.yRotate -= (360.0f / size) * cs->xRotations;
680 		if (!adjust)
681 		    sa.yRotate += (360.0f / size) * s->x;
682 	    }
683 	    sa.yRotate += (360.0f / size) * i;
684 
685 	    (*s->applyScreenTransform) (s, &sa, output, &sTransform);
686 
687 	    glLoadMatrixf (sTransform.m);
688 	    glTranslatef (cs->outputXOffset, -cs->outputYOffset, 0.0f);
689 	    glScalef (cs->outputXScale, cs->outputYScale, 1.0f);
690 
691 	    glScalef (1.0, cInv, 1.0);
692 
693 	    glColor4us (color[0] * opacity / 0xffff,
694 		color[1] * opacity / 0xffff,
695 		color[2] * opacity / 0xffff,
696 		opacity);
697 
698 	    glDrawArrays (GL_TRIANGLE_FAN, 0, CAP_ELEMENTS + 2);
699 	    if (cubeaddonGetDeformation (s) == DeformationSphere &&
700 	        cubeaddonGetDeformCaps (s))
701 		glDrawElements (GL_QUADS, CAP_NIDX, GL_UNSIGNED_SHORT,
702 				cas->capFillIdx);
703 
704 	    if (cap->loaded)
705 	    {
706 		float s_gen[4], t_gen[4];
707 		CompTransform texMat = cap->texMat;
708 
709 		if (cs->invert != 1)
710 		    matrixScale (&texMat, -1.0, 1.0, 1.0);
711 
712 		glColor4us (cs->desktopOpacity, cs->desktopOpacity,
713 		    cs->desktopOpacity, cs->desktopOpacity);
714 	        enableTexture (s, &cap->texture, COMP_TEXTURE_FILTER_GOOD);
715 
716 		if (cAspect)
717 		{
718 		    float scale, xScale = 1.0, yScale = 1.0;
719 		    scale = (float)output->width / (float)output->height;
720 
721 		    if (output->width > output->height)
722 		    {
723 			xScale = 1.0;
724 			yScale = 1.0 / scale;
725 		    }
726 		    else
727 		    {
728 			xScale = scale;
729 			yScale = 1.0;
730 		    }
731 
732 		    if (cubeaddonGetTopScale(s))
733 		    {
734 			scale = xScale;
735 			xScale = 1.0 / yScale;
736 			yScale = 1.0 / scale;
737 		    }
738 
739 		    matrixScale (&texMat, xScale, yScale, 1.0);
740 		}
741 
742 		matrixRotate (&texMat, -(360.0f / size) * i, 0.0, 0.0, 1.0);
743 
744 		s_gen[0] = texMat.m[0];
745 		s_gen[1] = texMat.m[8];
746 		s_gen[2] = texMat.m[4];
747 		s_gen[3] = texMat.m[12];
748 		t_gen[0] = texMat.m[1];
749 		t_gen[1] = texMat.m[9];
750 		t_gen[2] = texMat.m[5];
751 		t_gen[3] = texMat.m[13];
752 
753 		glTexGenfv(GL_T, GL_OBJECT_PLANE, t_gen);
754 		glTexGenfv(GL_S, GL_OBJECT_PLANE, s_gen);
755 
756 		glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
757 		glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
758 
759 		glEnable(GL_TEXTURE_GEN_S);
760 		glEnable(GL_TEXTURE_GEN_T);
761 
762 		glDrawArrays (GL_TRIANGLE_FAN, 0, CAP_ELEMENTS + 2);
763 		if (cubeaddonGetDeformation (s) == DeformationSphere &&
764 	            cubeaddonGetDeformCaps (s))
765 		    glDrawElements (GL_QUADS, CAP_NIDX, GL_UNSIGNED_SHORT,
766 				    cas->capFillIdx);
767 
768 		glDisable(GL_TEXTURE_GEN_S);
769 		glDisable(GL_TEXTURE_GEN_T);
770 		disableTexture (s, &cas->topCap.texture);
771 	    }
772 	}
773     }
774 
775     glEnableClientState (GL_TEXTURE_COORD_ARRAY);
776     glDisableClientState (GL_NORMAL_ARRAY);
777     glDisable (GL_BLEND);
778     glNormal3f (0.0, -1.0, 0.0);
779 
780     glCullFace (cullNorm);
781     if (!wasCulled)
782 	glDisable (GL_CULL_FACE);
783 
784     glPopMatrix ();
785 
786     glColor4usv (defaultColor);
787 }
788 
789 static void
cubeaddonPaintTop(CompScreen * s,const ScreenPaintAttrib * sAttrib,const CompTransform * transform,CompOutput * output,int size)790 cubeaddonPaintTop (CompScreen		   *s,
791 		   const ScreenPaintAttrib *sAttrib,
792 		   const CompTransform     *transform,
793 		   CompOutput		   *output,
794 		   int			   size)
795 {
796     CUBE_SCREEN (s);
797     CUBEADDON_SCREEN (s);
798 
799     if ((!cubeaddonGetDrawBottom (s) && cs->invert == -1) ||
800         (!cubeaddonGetDrawTop (s) && cs->invert == 1))
801     {
802 	UNWRAP (cas, cs, paintTop);
803 	(*cs->paintTop) (s, sAttrib, transform, output, size);
804 	WRAP (cas, cs, paintTop, cubeaddonPaintTop);
805     }
806 
807     if (!cubeaddonGetDrawTop (s))
808         return;
809 
810     cubeaddonPaintCap (s, sAttrib, transform, output, size, TRUE,
811 		       cubeaddonGetAdjustTop (s),
812 		       cubeaddonGetTopColor(s));
813 }
814 
815 /*
816  * Paint bottom cube face
817  */
818 static void
cubeaddonPaintBottom(CompScreen * s,const ScreenPaintAttrib * sAttrib,const CompTransform * transform,CompOutput * output,int size)819 cubeaddonPaintBottom (CompScreen	      *s,
820 		      const ScreenPaintAttrib *sAttrib,
821 		      const CompTransform     *transform,
822 		      CompOutput	      *output,
823 		      int		      size)
824 {
825     CUBE_SCREEN (s);
826     CUBEADDON_SCREEN (s);
827 
828     if ((!cubeaddonGetDrawBottom (s) && cs->invert == 1) ||
829         (!cubeaddonGetDrawTop (s) && cs->invert == -1))
830     {
831 	UNWRAP (cas, cs, paintBottom);
832 	(*cs->paintBottom) (s, sAttrib, transform, output, size);
833 	WRAP (cas, cs, paintBottom, cubeaddonPaintBottom);
834     }
835 
836     if (!cubeaddonGetDrawBottom (s))
837         return;
838 
839     cubeaddonPaintCap (s, sAttrib, transform, output, size, FALSE,
840 		       cubeaddonGetAdjustBottom (s),
841 		       cubeaddonGetBottomColor(s));
842 }
843 
844 static void
cubeaddonAddWindowGeometry(CompWindow * w,CompMatrix * matrix,int nMatrix,Region region,Region clip)845 cubeaddonAddWindowGeometry (CompWindow *w,
846 			    CompMatrix *matrix,
847 			    int        nMatrix,
848 			    Region     region,
849 			    Region     clip)
850 {
851     CompScreen *s = w->screen;
852 
853     CUBEADDON_SCREEN (s);
854     CUBE_SCREEN (s);
855 
856     if (cas->deform > 0.0)
857     {
858 	int         x1, x2, y1, y2, yi, i, j, oldVCount = w->vCount;
859 	REGION      reg;
860 	GLfloat     *v;
861 	int         offX = 0, offY = 0;
862 	int         sx1, sx2, sw, sy1, sy2, sh, nBox, currBox, cLast;
863 	float       lastX, lastZ = 0.0, radSquare, last[2][4];
864 	Bool        found;
865 	float       inv = (cs->invert == 1) ? 1.0 : -1.0;
866 
867 	float       a1, a2, ang;
868 
869 	if (cubeaddonGetDeformation (s) == DeformationCylinder || cs->unfolded)
870 	{
871 	    yi = region->extents.y2 - region->extents.y1;
872 	    radSquare = (cs->distance * cs->distance) + 0.25;
873 	}
874 	else
875 	{
876 	    yi = CUBEADDON_GRID_SIZE;
877 	    radSquare = (cs->distance * cs->distance) + 0.5;
878 	}
879 
880 	nBox = (((region->extents.y2 - region->extents.y1) / yi) + 1) *
881 	       (((region->extents.x2 - region->extents.x1) /
882 	       CUBEADDON_GRID_SIZE) + 1);
883 
884 	reg.numRects = 1;
885 	reg.rects = &reg.extents;
886 
887 	y1 = region->extents.y1;
888 	y2 = MIN (y1 + yi, region->extents.y2);
889 
890 	UNWRAP (cas, s, addWindowGeometry);
891 
892 	if (region->numRects > 1)
893 	{
894 	    while (y1 < region->extents.y2)
895 	    {
896 		reg.extents.y1 = y1;
897 		reg.extents.y2 = y2;
898 
899 		x1 = region->extents.x1;
900 		x2 = MIN (x1 + CUBEADDON_GRID_SIZE, region->extents.x2);
901 
902 		while (x1 < region->extents.x2)
903 		{
904 		    reg.extents.x1 = x1;
905 		    reg.extents.x2 = x2;
906 
907 		    XIntersectRegion (region, &reg, cas->tmpRegion);
908 
909 		    if (!XEmptyRegion (cas->tmpRegion))
910 		    {
911 			(*w->screen->addWindowGeometry) (w, matrix, nMatrix,
912 							 cas->tmpRegion, clip);
913 		    }
914 
915 		    x1 = x2;
916 		    x2 = MIN (x2 + CUBEADDON_GRID_SIZE, region->extents.x2);
917 		}
918 		y1 = y2;
919 		y2 = MIN (y2 + yi, region->extents.y2);
920 	    }
921 	}
922 	else
923 	{
924 	    if (cas->nTmpBox < nBox)
925 	    {
926 		cas->tmpBox = realloc (cas->tmpBox, nBox * sizeof (BOX));
927 		if (!cas->tmpBox)
928 		    return;
929 		cas->nTmpBox = nBox;
930 	    }
931 
932 	    reg.extents = region->extents;
933 	    reg.rects = cas->tmpBox;
934 
935 	    currBox = 0;
936 	    while (y1 < region->extents.y2)
937 	    {
938 		x1 = region->extents.x1;
939 		x2 = MIN (x1 + CUBEADDON_GRID_SIZE, region->extents.x2);
940 
941 		while (x1 < region->extents.x2)
942 		{
943 		    reg.rects[currBox].y1 = y1;
944 		    reg.rects[currBox].y2 = y2;
945 		    reg.rects[currBox].x1 = x1;
946 		    reg.rects[currBox].x2 = x2;
947 
948 		    currBox++;
949 
950 		    x1 = x2;
951 		    x2 = MIN (x2 + CUBEADDON_GRID_SIZE, region->extents.x2);
952 	        }
953 		y1 = y2;
954 		y2 = MIN (y2 + yi, region->extents.y2);
955 	    }
956 	    reg.numRects = currBox;
957 	    (*w->screen->addWindowGeometry) (w, matrix, nMatrix, &reg, clip);
958 	}
959 	WRAP (cas, s, addWindowGeometry, cubeaddonAddWindowGeometry);
960 
961 	v  = w->vertices + (w->vertexStride - 3);
962 	v += w->vertexStride * oldVCount;
963 
964 	if (!windowOnAllViewports (w))
965 	{
966 	    getWindowMovementForOffset (w, s->windowOffsetX,
967                                         s->windowOffsetY, &offX, &offY);
968 	}
969 
970 	if (cs->moMode == CUBE_MOMODE_ONE)
971 	{
972 	    sx1 = 0;
973 	    sx2 = s->width;
974 	    sw  = s->width;
975 	    sy1 = 0;
976 	    sy2 = s->height;
977 	    sh  = s->height;
978 	}
979 	else if (cs->moMode == CUBE_MOMODE_MULTI)
980 	{
981 	    sx1 = cas->last->region.extents.x1;
982 	    sx2 = cas->last->region.extents.x2;
983 	    sw  = sx2 - sx1;
984 	    sy1 = cas->last->region.extents.y1;
985 	    sy2 = cas->last->region.extents.y2;
986 	    sh  = sy2 - sy1;
987 	}
988 	else
989 	{
990 	    if (cs->nOutput != s->nOutputDev)
991 	    {
992 		sx1 = 0;
993 		sx2 = s->width;
994 		sw  = s->width;
995 		sy1 = 0;
996 		sy2 = s->height;
997 		sh  = s->height;
998 	    }
999 	    else
1000 	    {
1001 		sx1 = s->outputDev[cs->srcOutput].region.extents.x1;
1002 		sx2 = s->outputDev[cs->srcOutput].region.extents.x2;
1003 		sw  = sx2 - sx1;
1004 		sy1 = s->outputDev[cs->srcOutput].region.extents.y1;
1005 		sy2 = s->outputDev[cs->srcOutput].region.extents.y2;
1006 		sh  = sy2 - sy1;
1007 	    }
1008 	}
1009 
1010 	if (cubeaddonGetDeformation (s) == DeformationCylinder || cs->unfolded)
1011 	{
1012 	    lastX = -1000000000.0;
1013 
1014 	    for (i = oldVCount; i < w->vCount; i++)
1015 	    {
1016 		if (v[0] == lastX)
1017 		{
1018 		    v[2] = lastZ;
1019 		}
1020 		else if (v[0] + offX >= sx1 - CUBEADDON_GRID_SIZE &&
1021 			 v[0] + offX < sx2 + CUBEADDON_GRID_SIZE)
1022 		{
1023 		    ang = (((v[0] + offX - sx1) / (float)sw) - 0.5);
1024 		    ang *= ang;
1025 		    if (ang < radSquare)
1026 		    {
1027 			v[2] = sqrtf (radSquare - ang) - cs->distance;
1028 			v[2] *= cas->deform * inv;
1029 		    }
1030 		}
1031 
1032 		lastX = v[0];
1033 		lastZ = v[2];
1034 
1035 		v += w->vertexStride;
1036 	    }
1037 	}
1038 	else
1039 	{
1040 
1041 	    last[0][0] = -1000000000.0;
1042 	    last[1][0] = -1000000000.0;
1043 
1044 	    cLast = 0;
1045 	    for (i = oldVCount; i < w->vCount; i++)
1046 	    {
1047 		found = FALSE;
1048 
1049 		for (j = 0; j < 2 && !found; j++)
1050 		    if (last[j][0] == v[0] && last[j][1] == v[1])
1051 		    {
1052 			v[0] = last[j][2];
1053 			v[2] = last[j][3];
1054 			found = TRUE;
1055 		    }
1056 
1057 		if (!found && v[0] + offX >= sx1 - CUBEADDON_GRID_SIZE &&
1058 		    v[0] + offX < sx2 + CUBEADDON_GRID_SIZE &&
1059 		    v[1] + offY >= sy1 - CUBEADDON_GRID_SIZE &&
1060 		    v[1] + offY < sy2 + CUBEADDON_GRID_SIZE)
1061 		{
1062 		    last[cLast][0] = v[0];
1063 		    last[cLast][1] = v[1];
1064 		    a1 = (((v[0] + offX - sx1) / (float)sw) - 0.5);
1065 		    a2 = (((v[1] + offY - sy1) / (float)sh) - 0.5);
1066 		    a2 *= a2;
1067 
1068 		    ang = atanf (a1 / cs->distance);
1069 		    a2 = sqrtf (radSquare - a2);
1070 
1071 		    v[2] += ((cosf (ang) * a2) - cs->distance) *
1072 			    cas->deform * inv;
1073 		    v[0] += ((sinf (ang) * a2) - a1) * sw * cas->deform;
1074 		    last[cLast][2] = v[0];
1075 		    last[cLast][3] = v[2];
1076 		    cLast = (cLast + 1) & 1;
1077 		}
1078 		v += w->vertexStride;
1079 	    }
1080 	}
1081     }
1082     else
1083     {
1084 	UNWRAP (cas, s, addWindowGeometry);
1085 	(*w->screen->addWindowGeometry) (w, matrix, nMatrix, region, clip);
1086 	WRAP (cas, s, addWindowGeometry, cubeaddonAddWindowGeometry);
1087     }
1088 }
1089 
1090 static Bool
cubeaddonDrawWindow(CompWindow * w,const CompTransform * transform,const FragmentAttrib * attrib,Region region,unsigned int mask)1091 cubeaddonDrawWindow (CompWindow	          *w,
1092 		     const CompTransform  *transform,
1093 		     const FragmentAttrib *attrib,
1094 		     Region		  region,
1095 		     unsigned int	  mask)
1096 {
1097     CompScreen *s = w->screen;
1098     Bool       status;
1099 
1100     CUBEADDON_SCREEN (s);
1101 
1102     if (!(mask & PAINT_WINDOW_TRANSFORMED_MASK) && cas->deform)
1103     {
1104 	int offX = 0, offY = 0;
1105 	int x1, x2;
1106 
1107 	if (!windowOnAllViewports (w))
1108 	{
1109 	    getWindowMovementForOffset (w, s->windowOffsetX,
1110                                         s->windowOffsetY, &offX, &offY);
1111 	}
1112 
1113 	x1 = w->attrib.x - w->output.left + offX;
1114 	x2 = w->attrib.x + w->width + w->output.right + offX;
1115 	if (x1 < 0 && x2 < 0)
1116 	    return FALSE;
1117 	if (x1 > s->width && x2 > s->width)
1118 	    return FALSE;
1119     }
1120 
1121     UNWRAP (cas, s, drawWindow);
1122     status = (*s->drawWindow) (w, transform, attrib, region, mask);
1123     WRAP (cas, s, drawWindow, cubeaddonDrawWindow);
1124 
1125     return status;
1126 }
1127 
1128 static void
cubeaddonDrawWindowTexture(CompWindow * w,CompTexture * texture,const FragmentAttrib * attrib,unsigned int mask)1129 cubeaddonDrawWindowTexture (CompWindow	         *w,
1130 			    CompTexture	         *texture,
1131 			    const FragmentAttrib *attrib,
1132 			    unsigned int	 mask)
1133 {
1134     CompScreen *s = w->screen;
1135 
1136     CUBEADDON_SCREEN (s);
1137 
1138     if (cas->deform > 0.0 && s->lighting)
1139     {
1140 	int     i;
1141 	int     sx1, sx2, sw, sy1, sy2, sh;
1142 	int     offX = 0, offY = 0;
1143 	float   x, y, ym;
1144 	GLfloat *v;
1145 	float   inv;
1146 
1147 	CUBE_SCREEN (s);
1148 
1149 	inv = (cs->invert == 1) ? 1.0: -1.0;
1150 	ym  = (cubeaddonGetDeformation (s) == DeformationCylinder) ? 0.0 : 1.0;
1151 
1152 	if (cas->winNormSize < w->vCount * 3)
1153 	{
1154 	    cas->winNormals = realloc (cas->winNormals,
1155 				       w->vCount * 3 * sizeof (GLfloat));
1156 	    if (!cas->winNormals)
1157 	    {
1158 		cas->winNormSize = 0;
1159 		return;
1160 	    }
1161 	    cas->winNormSize = w->vCount * 3;
1162 	}
1163 
1164 	if (!windowOnAllViewports (w))
1165 	{
1166 	    getWindowMovementForOffset (w, s->windowOffsetX,
1167                                         s->windowOffsetY, &offX, &offY);
1168 	}
1169 
1170 	if (cs->moMode == CUBE_MOMODE_ONE)
1171 	{
1172 	    sx1 = 0;
1173 	    sx2 = s->width;
1174 	    sw  = s->width;
1175 	    sy1 = 0;
1176 	    sy2 = s->height;
1177 	    sh  = s->height;
1178 	}
1179 	else if (cs->moMode == CUBE_MOMODE_MULTI)
1180 	{
1181 	    sx1 = cas->last->region.extents.x1;
1182 	    sx2 = cas->last->region.extents.x2;
1183 	    sw  = sx2 - sx1;
1184 	    sy1 = cas->last->region.extents.y1;
1185 	    sy2 = cas->last->region.extents.y2;
1186 	    sh  = sy2 - sy1;
1187 	}
1188 	else
1189 	{
1190 	    if (cs->nOutput != s->nOutputDev)
1191 	    {
1192 		sx1 = 0;
1193 		sx2 = s->width;
1194 		sw  = s->width;
1195 		sy1 = 0;
1196 		sy2 = s->height;
1197 		sh  = s->height;
1198 	    }
1199 	    else
1200 	    {
1201 		sx1 = s->outputDev[cs->srcOutput].region.extents.x1;
1202 		sx2 = s->outputDev[cs->srcOutput].region.extents.x2;
1203 		sw  = sx2 - sx1;
1204 		sy1 = s->outputDev[cs->srcOutput].region.extents.y1;
1205 		sy2 = s->outputDev[cs->srcOutput].region.extents.y2;
1206 		sh  = sy2 - sy1;
1207 	    }
1208 	}
1209 
1210 	v = w->vertices + (w->vertexStride - 3);
1211 
1212 	for (i = 0; i < w->vCount; i++)
1213 	{
1214 	    x = (((v[0] + offX - sx1) / (float)sw) - 0.5);
1215 	    y = (((v[1] + offY - sy1) / (float)sh) - 0.5);
1216 
1217 	    if (cs->paintOrder == FTB)
1218 	    {
1219 		cas->winNormals[i * 3] = x / sw * cas->deform;
1220 		cas->winNormals[(i * 3) + 1] = y / sh * cas->deform * ym;
1221 		cas->winNormals[(i * 3) + 2] = v[2] + cs->distance;
1222 	    }
1223 	    else
1224 	    {
1225 		cas->winNormals[i * 3] = -x / sw * cas->deform * inv;
1226 		cas->winNormals[(i * 3) + 1] = -y / sh * cas->deform * ym * inv;
1227 		cas->winNormals[(i * 3) + 2] = -(v[2] + cs->distance);
1228 	    }
1229 
1230 	    v += w->vertexStride;
1231 	}
1232 
1233 	glEnable (GL_NORMALIZE);
1234 	glNormalPointer (GL_FLOAT,0, cas->winNormals);
1235 
1236 	glEnableClientState (GL_NORMAL_ARRAY);
1237 
1238 	UNWRAP (cas, s, drawWindowTexture);
1239 	(*s->drawWindowTexture) (w, texture, attrib, mask);
1240 	WRAP (cas, s, drawWindowTexture, cubeaddonDrawWindowTexture);
1241 
1242 	glDisable (GL_NORMALIZE);
1243 	glDisableClientState (GL_NORMAL_ARRAY);
1244 	glNormal3f (0.0, 0.0, -1.0);
1245 	return;
1246     }
1247 
1248     UNWRAP (cas, s, drawWindowTexture);
1249     (*s->drawWindowTexture) (w, texture, attrib, mask);
1250     WRAP (cas, s, drawWindowTexture, cubeaddonDrawWindowTexture);
1251 }
1252 
1253 static void
cubeaddonPaintTransformedOutput(CompScreen * s,const ScreenPaintAttrib * sAttrib,const CompTransform * transform,Region region,CompOutput * output,unsigned int mask)1254 cubeaddonPaintTransformedOutput (CompScreen              *s,
1255 				 const ScreenPaintAttrib *sAttrib,
1256 				 const CompTransform     *transform,
1257 				 Region                  region,
1258 				 CompOutput              *output,
1259 				 unsigned int            mask)
1260 {
1261     static GLfloat light0Position[] = { -0.5f, 0.5f, -9.0f, 1.0f };
1262     CompTransform  sTransform = *transform;
1263 
1264     CUBEADDON_SCREEN (s);
1265     CUBE_SCREEN (s);
1266 
1267     if (cubeaddonGetDeformation (s) != DeformationNone
1268 	&& s->hsize * cs->nOutput > 2 && s->desktopWindowCount &&
1269 	(cs->rotationState == RotationManual ||
1270 	(cs->rotationState == RotationChange &&
1271 	!cubeaddonGetCylinderManualOnly (s)) || cas->wasDeformed) &&
1272         (!cs->unfolded || cubeaddonGetUnfoldDeformation (s)))
1273     {
1274 	float x, progress;
1275 
1276 	(*cs->getRotation) (s, &x, &x, &progress);
1277 	cas->deform = progress;
1278 
1279 	if (cubeaddonGetSphereAspect (s) > 0.0 && cs->invert == 1 &&
1280 	    cubeaddonGetDeformation (s) == DeformationSphere)
1281 	{
1282 	    float scale, val = cubeaddonGetSphereAspect (s) * cas->deform;
1283 
1284 	    if (output->width > output->height)
1285 	    {
1286 		scale = (float)output->height / (float)output->width;
1287 		scale = (scale * val) + 1.0 - val;
1288 		matrixScale (&sTransform, scale, 1.0, 1.0);
1289 	    }
1290 	    else
1291 	    {
1292 		scale = (float)output->width / (float)output->height;
1293 		scale = (scale * val) + 1.0 - val;
1294 		matrixScale (&sTransform, 1.0, scale, 1.0);
1295 	    }
1296 	}
1297     }
1298     else
1299     {
1300 	cas->deform = 0.0;
1301     }
1302 
1303     cs->paintAllViewports |= !cubeaddonGetDrawTop (s)			  ||
1304 			     !cubeaddonGetDrawBottom (s)		  ||
1305 			     (cubeaddonGetTopColorAlpha (s) != OPAQUE)	  ||
1306 			     (cubeaddonGetBottomColorAlpha (s) != OPAQUE) ||
1307 		             (cas->deform > 0.0);
1308 
1309     if (cas->capDistance != cs->distance)
1310     {
1311 	cubeaddonChangeCap (s, TRUE, 0);
1312 	cubeaddonChangeCap (s, FALSE, 0);
1313     }
1314 
1315     if (cas->deform != cas->capDeform || cas->capDistance != cs->distance ||
1316         cas->capDeformType != cubeaddonGetDeformation (s))
1317     {
1318 	float       *quad;
1319 	int         i, j;
1320 	float       rS, r, x, y, z, w;
1321 	if (cubeaddonGetDeformation (s) != DeformationSphere ||
1322 	    !cubeaddonGetDeformCaps (s))
1323 	{
1324 	    rS = (cs->distance * cs->distance) + 0.5;
1325 
1326 	    cas->capFill[0] = 0.0;
1327 	    cas->capFill[1] = 0.5;
1328 	    cas->capFill[2] = 0.0;
1329 	    cas->capFillNorm[0] = 0.0;
1330 	    cas->capFillNorm[1] = -1.0;
1331 	    cas->capFillNorm[2] = 0.0;
1332 
1333 	    z = cs->distance;
1334 	    r = 0.25 + (cs->distance * cs->distance);
1335 
1336 	    for (j = 0; j <= CAP_ELEMENTS; j++)
1337 	    {
1338 		x = -0.5 + ((float)j / (float)CAP_ELEMENTS);
1339 		z = ((sqrtf(r - (x * x)) - cs->distance) * cas->deform) +
1340 		    cs->distance;
1341 		y = 0.5;
1342 
1343 		quad = &cas->capFill[(1 + j) * 3];
1344 
1345 		quad[0] = x;
1346 		quad[1] = y;
1347 		quad[2] = z;
1348 
1349 		quad = &cas->capFillNorm[(1 + j) * 3];
1350 
1351 		quad[0] = -x;
1352 		quad[1] = -y;
1353 		quad[2] = -z;
1354 	    }
1355 	}
1356 	else
1357 	{
1358 	    rS = (cs->distance * cs->distance) + 0.5;
1359 
1360 	    cas->capFill[0] = 0.0;
1361 	    cas->capFill[1] = ((sqrtf (rS) - 0.5) * cas->deform) + 0.5;
1362 	    cas->capFill[2] = 0.0;
1363 	    cas->capFillNorm[0] = 0.0;
1364 	    cas->capFillNorm[1] = -1.0;
1365 	    cas->capFillNorm[2] = 0.0;
1366 
1367 	    for (i = 0; i < CAP_ELEMENTS; i++)
1368 	    {
1369 		w = (float)(i + 1) / (float)CAP_ELEMENTS;
1370 
1371 		r = (((w / 2.0) * (w / 2.0)) +
1372 		    (cs->distance * cs->distance * w * w));
1373 
1374 		for (j = 0; j <= CAP_ELEMENTS; j++)
1375 		{
1376 		    x = - (w / 2.0) + ((float)j * w / (float)CAP_ELEMENTS);
1377 		    z = ((sqrtf(r - (x * x)) - (cs->distance * w)) *
1378 			cas->deform) + (cs->distance * w);
1379 		    y = ((sqrtf(rS - (x * x) - (r - (x * x))) - 0.5) *
1380 			cas->deform) + 0.5;
1381 
1382 		    quad = &cas->capFill[(1 + (i * (CAP_ELEMENTS + 1)) +
1383 				         j) * 3];
1384 
1385 		    quad[0] = x;
1386 		    quad[1] = y;
1387 		    quad[2] = z;
1388 
1389 		    quad = &cas->capFillNorm[(1 + (i * (CAP_ELEMENTS + 1)) +
1390 					     j) * 3];
1391 
1392 		    quad[0] = -x;
1393 		    quad[1] = -y;
1394 		    quad[2] = -z;
1395 		}
1396 	    }
1397 	}
1398 
1399 	cas->capDeform     = cas->deform;
1400 	cas->capDistance   = cs->distance;
1401 	cas->capDeformType = cubeaddonGetDeformation (s);
1402     }
1403 
1404     if (cs->invert == 1 && cas->first && cubeaddonGetReflection (s))
1405     {
1406 	cas->first = FALSE;
1407 	cas->reflection = TRUE;
1408 
1409 	if (cs->grabIndex)
1410 	{
1411 	    CompTransform rTransform = sTransform;
1412 
1413 	    matrixTranslate (&rTransform, 0.0, -1.0, 0.0);
1414 	    matrixScale (&rTransform, 1.0, -1.0, 1.0);
1415 	    glCullFace (GL_FRONT);
1416 
1417 	    UNWRAP (cas, s, paintTransformedOutput);
1418 	    (*s->paintTransformedOutput) (s, sAttrib, &rTransform,
1419 					  region, output, mask);
1420 	    WRAP (cas, s, paintTransformedOutput,
1421 		  cubeaddonPaintTransformedOutput);
1422 
1423 	    glCullFace (GL_BACK);
1424 	    drawBasicGround (s);
1425 	}
1426 	else
1427 	{
1428 	    CompTransform rTransform = sTransform;
1429 	    CompTransform pTransform;
1430 	    float         angle = 360.0 / ((float) s->hsize * cs->nOutput);
1431 	    float         xRot, vRot, xRotate, xRotate2, vRotate, p;
1432 	    float         rYTrans;
1433 	    CompVector    point  = { .v = { -0.5, -0.5, cs->distance, 1.0 } };
1434 	    CompVector    point2 = { .v = { -0.5,  0.5, cs->distance, 1.0 } };
1435 	    float         deform;
1436 
1437 	    (*cs->getRotation) (s, &xRot, &vRot, &p);
1438 
1439 	    cas->backVRotate = 0.0;
1440 
1441 	    xRotate  = xRot;
1442 	    xRotate2 = xRot;
1443 	    vRotate  = vRot;
1444 
1445 	    if (vRotate < 0.0)
1446 		xRotate += 180;
1447 
1448 	    vRotate = fmod (fabs (vRotate), 180.0);
1449 	    xRotate = fmod (fabs (xRotate), angle);
1450 	    xRotate2 = fmod (fabs (xRotate2), angle);
1451 
1452 	    if (vRotate >= 90.0)
1453 		vRotate = 180.0 - vRotate;
1454 
1455 	    if (xRotate >= angle / 2.0)
1456 		xRotate = angle - xRotate;
1457 
1458 	    if (xRotate2 >= angle / 2.0)
1459 		xRotate2 = angle - xRotate2;
1460 
1461 	    xRotate = (cas->deform * angle * 0.5) +
1462 		      ((1.0 - cas->deform) * xRotate);
1463 	    xRotate2 = (cas->deform * angle * 0.5) +
1464 		       ((1.0 - cas->deform) * xRotate2);
1465 
1466 	    matrixGetIdentity (&pTransform);
1467 	    matrixRotate (&pTransform, xRotate, 0.0f, 1.0f, 0.0f);
1468 	    matrixRotate (&pTransform,
1469 			  vRotate, cosf (xRotate * DEG2RAD),
1470 			  0.0f, sinf (xRotate * DEG2RAD));
1471 
1472 	    matrixMultiplyVector (&point, &point, &pTransform);
1473 
1474 	    matrixGetIdentity (&pTransform);
1475 	    matrixRotate (&pTransform, xRotate2, 0.0f, 1.0f, 0.0f);
1476 	    matrixRotate (&pTransform,
1477 			  vRotate, cosf (xRotate2 * DEG2RAD),
1478 			  0.0f, sinf (xRotate2 * DEG2RAD));
1479 
1480 	    matrixMultiplyVector (&point2, &point2, &pTransform);
1481 
1482 	    switch (cubeaddonGetMode (s)) {
1483 	    case ModeJumpyReflection:
1484 		cas->yTrans    = 0.0;
1485 		if (cubeaddonGetDeformation (s) == DeformationSphere &&
1486 		    cubeaddonGetDeformCaps (s) && cubeaddonGetDrawBottom (s))
1487 		{
1488 		    rYTrans = sqrt (0.5 + (cs->distance * cs->distance)) *
1489 			      -2.0;
1490 		}
1491 		else
1492 		{
1493 		    rYTrans = point.y * 2.0;
1494 		}
1495 
1496 		break;
1497 	    case ModeDistance:
1498 		cas->yTrans = 0.0;
1499 		rYTrans     = sqrt (0.5 + (cs->distance * cs->distance)) * -2.0;
1500 		break;
1501 	    default:
1502 
1503 		if (cubeaddonGetDeformation (s) == DeformationSphere &&
1504 		    cubeaddonGetDeformCaps (s) && cubeaddonGetDrawBottom (s))
1505 		{
1506 		    cas->yTrans =  cas->capFill[1] - 0.5;
1507 		    rYTrans     = -cas->capFill[1] - 0.5;
1508 		}
1509 		else if (cubeaddonGetDeformation (s) == DeformationSphere &&
1510 		         vRotate > atan (cs->distance * 2) / DEG2RAD)
1511 		{
1512 		    cas->yTrans = sqrt (0.5 + (cs->distance * cs->distance)) - 0.5;
1513 		    rYTrans     = -sqrt (0.5 + (cs->distance * cs->distance)) - 0.5;
1514 		}
1515 		else
1516 		{
1517 		    cas->yTrans = -point.y - 0.5;
1518 		    rYTrans     =  point.y - 0.5;
1519 		}
1520 		break;
1521 	    }
1522 
1523 	    if (!cubeaddonGetAutoZoom (s) ||
1524 		((cs->rotationState != RotationManual) &&
1525 		 cubeaddonGetZoomManualOnly (s)))
1526 	    {
1527 		cas->zTrans = 0.0;
1528 	    }
1529 	    else
1530 		cas->zTrans = -point2.z + cs->distance;
1531 
1532 	    if (cubeaddonGetMode (s) == ModeAbove)
1533 		cas->zTrans = 0.0;
1534 
1535 	    if (cubeaddonGetDeformation (s) == DeformationCylinder)
1536 		deform = (sqrt (0.25 + (cs->distance * cs->distance)) -
1537 			  cs->distance) * -cas->deform;
1538 	    else if (cubeaddonGetDeformation (s) == DeformationSphere)
1539 		deform = (sqrt (0.5 + (cs->distance * cs->distance)) -
1540 			  cs->distance) * -cas->deform;
1541 
1542 	    if (cas->deform > 0.0)
1543 	        cas->zTrans = deform;
1544 
1545 	    if (cubeaddonGetMode (s) == ModeAbove && cas->vRot > 0.0)
1546 	    {
1547 		cas->backVRotate = cas->vRot;
1548 		if (cubeaddonGetDeformation (s) == DeformationSphere &&
1549 		    cubeaddonGetDeformCaps (s) && cubeaddonGetDrawBottom (s))
1550 		{
1551 		    cas->yTrans =  cas->capFill[1] - 0.5;
1552 		    rYTrans     = -cas->capFill[1] - 0.5;
1553 		}
1554 		else
1555 		{
1556 		    cas->yTrans = 0.0;
1557 		    rYTrans     = -1.0;
1558 		}
1559 
1560 		matrixGetIdentity (&pTransform);
1561 		applyScreenTransform (s, sAttrib, output, &pTransform);
1562 		point.x = point.y = 0.0;
1563 		point.z = -cs->distance;
1564 		point.z += deform;
1565 		point.w = 1.0;
1566 		matrixMultiplyVector (&point, &point, &pTransform);
1567 
1568 		matrixTranslate (&rTransform, 0.0, 0.0, point.z);
1569 		matrixRotate (&rTransform, cas->vRot, 1.0, 0.0, 0.0);
1570 		matrixScale (&rTransform, 1.0, -1.0, 1.0);
1571 		matrixTranslate (&rTransform, 0.0, -rYTrans,
1572 				 -point.z + cas->zTrans);
1573 	    }
1574 	    else
1575 	    {
1576 		matrixTranslate (&rTransform, 0.0, rYTrans, cas->zTrans);
1577 		matrixScale (&rTransform, 1.0, -1.0, 1.0);
1578 	    }
1579 
1580 	    glPushMatrix ();
1581 	    glLoadIdentity ();
1582 	    glScalef (1.0, -1.0, 1.0);
1583 	    glLightfv (GL_LIGHT0, GL_POSITION, light0Position);
1584 	    glPopMatrix ();
1585 	    glCullFace (GL_FRONT);
1586 
1587 	    UNWRAP (cas, s, paintTransformedOutput);
1588 	    (*s->paintTransformedOutput) (s, sAttrib, &rTransform,
1589 					  region, output, mask);
1590 	    WRAP (cas, s, paintTransformedOutput,
1591 		  cubeaddonPaintTransformedOutput);
1592 
1593 	    glCullFace (GL_BACK);
1594 	    glPushMatrix ();
1595 	    glLoadIdentity ();
1596 	    glLightfv (GL_LIGHT0, GL_POSITION, light0Position);
1597 	    glPopMatrix ();
1598 
1599 	    if (cubeaddonGetMode (s) == ModeAbove && cas->vRot > 0.0)
1600 	    {
1601 		int   j;
1602 		float i, c;
1603 		float v = MIN (1.0, cas->vRot / 30.0);
1604 		float col1[4], col2[4];
1605 
1606 		glPushMatrix ();
1607 
1608 		glEnable (GL_BLEND);
1609 		glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1610 
1611 		glLoadIdentity ();
1612 		glTranslatef (0.0, 0.0, -DEFAULT_Z_CAMERA);
1613 
1614 		i = cubeaddonGetIntensity (s) * 2;
1615 		c = cubeaddonGetIntensity (s);
1616 
1617 		glBegin (GL_QUADS);
1618 		glColor4f (0.0, 0.0, 0.0,
1619 			   ((1 - v) * MAX (0.0, 1.0 - i)) + (v * c));
1620 		glVertex2f (0.5, v / 2.0);
1621 		glVertex2f (-0.5, v / 2.0);
1622 		glColor4f (0.0, 0.0, 0.0,
1623 			   ((1 - v) * MIN (1.0, 1.0 - (i - 1.0))) + (v * c));
1624 		glVertex2f (-0.5, -0.5);
1625 		glVertex2f (0.5, -0.5);
1626 		glEnd ();
1627 
1628 		for (j = 0; j < 4; j++)
1629 		{
1630 		    col1[j] = (1.0 - v) * cubeaddonGetGroundColor1 (s) [j] +
1631 			      (v * (cubeaddonGetGroundColor1 (s) [j] +
1632 				    cubeaddonGetGroundColor2 (s) [j]) * 0.5);
1633 		    col1[j] /= 0xffff;
1634 		    col2[j] = (1.0 - v) * cubeaddonGetGroundColor2 (s) [j] +
1635 			      (v * (cubeaddonGetGroundColor1 (s) [j] +
1636 				    cubeaddonGetGroundColor2 (s) [j]) * 0.5);
1637 		    col2[j] /= 0xffff;
1638 		}
1639 
1640 		if (cubeaddonGetGroundSize (s) > 0.0)
1641 		{
1642 		    glBegin (GL_QUADS);
1643 		    glColor4fv (col1);
1644 		    glVertex2f (-0.5, -0.5);
1645 		    glVertex2f (0.5, -0.5);
1646 		    glColor4fv (col2);
1647 		    glVertex2f (0.5, -0.5 +
1648 				((1 - v) * cubeaddonGetGroundSize (s)) + v);
1649 		    glVertex2f (-0.5, -0.5 +
1650 				((1 - v) * cubeaddonGetGroundSize (s)) + v);
1651 		    glEnd ();
1652 		}
1653 
1654 		glColor4usv (defaultColor);
1655 
1656 		glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1657 		glDisable (GL_BLEND);
1658 		glPopMatrix ();
1659 	    }
1660 	    else
1661 		drawBasicGround (s);
1662 	}
1663 
1664 	memset (cs->capsPainted, 0, sizeof (Bool) * s->nOutputDev);
1665 	cas->reflection = FALSE;
1666     }
1667 
1668     if (!cubeaddonGetReflection (s))
1669     {
1670 	cas->yTrans = 0.0;
1671 	cas->zTrans = (sqrt (0.25 + (cs->distance * cs->distance)) -
1672 		     cs->distance) * -cas->deform;
1673     }
1674 
1675     matrixTranslate (&sTransform, 0.0, cas->yTrans, cas->zTrans);
1676 
1677     UNWRAP (cas, s, paintTransformedOutput);
1678     (*s->paintTransformedOutput) (s, sAttrib, &sTransform,
1679 				  region, output, mask);
1680     WRAP (cas, s, paintTransformedOutput, cubeaddonPaintTransformedOutput);
1681 }
1682 
1683 static Bool
cubeaddonPaintOutput(CompScreen * s,const ScreenPaintAttrib * sAttrib,const CompTransform * transform,Region region,CompOutput * output,unsigned int mask)1684 cubeaddonPaintOutput (CompScreen              *s,
1685 		      const ScreenPaintAttrib *sAttrib,
1686 		      const CompTransform     *transform,
1687 		      Region                  region,
1688 		      CompOutput              *output,
1689 		      unsigned int            mask)
1690 {
1691     Bool status;
1692 
1693     CUBEADDON_SCREEN (s);
1694 
1695     if (cas->last != output)
1696 	cas->first = TRUE;
1697 
1698     cas->last = output;
1699 
1700     UNWRAP (cas, s, paintOutput);
1701     status = (*s->paintOutput) (s, sAttrib, transform, region, output, mask);
1702     WRAP (cas, s, paintOutput, cubeaddonPaintOutput);
1703 
1704     return status;
1705 }
1706 
1707 static void
cubeaddonDonePaintScreen(CompScreen * s)1708 cubeaddonDonePaintScreen (CompScreen * s)
1709 {
1710     CUBEADDON_SCREEN (s);
1711 
1712     cas->first      = TRUE;
1713     cas->yTrans     = 0.0;
1714     cas->zTrans     = 0.0;
1715 
1716     cas->wasDeformed = (cas->deform > 0.0);
1717 
1718     if (cas->deform > 0.0 && cas->deform < 1.0)
1719     {
1720 	damageScreen (s);
1721 	cas->deform = 0.0;
1722     }
1723 
1724     UNWRAP (cas, s, donePaintScreen);
1725     (*s->donePaintScreen) (s);
1726     WRAP (cas, s, donePaintScreen, cubeaddonDonePaintScreen);
1727 }
1728 
1729 
1730 static Bool
cubeaddonInitDisplay(CompPlugin * p,CompDisplay * d)1731 cubeaddonInitDisplay (CompPlugin  *p,
1732 		      CompDisplay *d)
1733 {
1734     CubeaddonDisplay *cad;
1735 
1736     if (!checkPluginABI ("core", CORE_ABIVERSION) ||
1737 	!checkPluginABI ("cube", CUBE_ABIVERSION))
1738 	return FALSE;
1739 
1740     if (!getPluginDisplayIndex (d, "cube", &cubeDisplayPrivateIndex))
1741 	return FALSE;
1742 
1743     cad = malloc (sizeof (CubeaddonDisplay));
1744 
1745     if (!cad)
1746 	return FALSE;
1747 
1748     cad->screenPrivateIndex = allocateScreenPrivateIndex (d);
1749 
1750     if (cad->screenPrivateIndex < 0)
1751     {
1752 	free (cad);
1753 	return FALSE;
1754     }
1755 
1756     d->base.privates[CubeaddonDisplayPrivateIndex].ptr = cad;
1757 
1758     cubeaddonSetTopNextKeyInitiate (d, cubeaddonTopNext);
1759     cubeaddonSetTopPrevKeyInitiate (d, cubeaddonTopPrev);
1760     cubeaddonSetBottomNextKeyInitiate (d, cubeaddonBottomNext);
1761     cubeaddonSetBottomPrevKeyInitiate (d, cubeaddonBottomPrev);
1762 
1763     cubeaddonSetTopNextButtonInitiate (d, cubeaddonTopNext);
1764     cubeaddonSetTopPrevButtonInitiate (d, cubeaddonTopPrev);
1765     cubeaddonSetBottomNextButtonInitiate (d, cubeaddonBottomNext);
1766     cubeaddonSetBottomPrevButtonInitiate (d, cubeaddonBottomPrev);
1767 
1768     return TRUE;
1769 }
1770 
1771 static void
cubeaddonFiniDisplay(CompPlugin * p,CompDisplay * d)1772 cubeaddonFiniDisplay (CompPlugin  *p,
1773 		      CompDisplay *d)
1774 {
1775     CUBEADDON_DISPLAY (d);
1776 
1777     freeScreenPrivateIndex (d, cad->screenPrivateIndex);
1778     free (cad);
1779 }
1780 
1781 static Bool
cubeaddonInitScreen(CompPlugin * p,CompScreen * s)1782 cubeaddonInitScreen (CompPlugin *p,
1783 		     CompScreen *s)
1784 {
1785     CubeaddonScreen *cas;
1786     GLushort        *idx;
1787     int             i, j;
1788 
1789     CUBEADDON_DISPLAY (s->display);
1790     CUBE_SCREEN (s);
1791 
1792     cas = malloc (sizeof (CubeaddonScreen));
1793 
1794     if (!cas)
1795 	return FALSE;
1796 
1797     s->base.privates[cad->screenPrivateIndex].ptr = cas;
1798 
1799     cas->reflection  = FALSE;
1800     cas->first       = TRUE;
1801     cas->last        = NULL;
1802     cas->yTrans      = 0.0;
1803     cas->zTrans      = 0.0;
1804     cas->tmpRegion   = XCreateRegion ();
1805     cas->deform      = 0.0;
1806     cas->capDeform   = -1.0;
1807     cas->capDistance = cs->distance;
1808 
1809     cas->winNormals  = NULL;
1810     cas->winNormSize = 0;
1811 
1812     cas->tmpBox  = NULL;
1813     cas->nTmpBox = 0;
1814 
1815     idx = cas->capFillIdx;
1816     for (i = 0; i < CAP_ELEMENTS - 1; i++)
1817     {
1818 	for (j = 0; j < CAP_ELEMENTS; j++)
1819 	{
1820 	    idx[0] = 1 + (i * (CAP_ELEMENTS + 1)) + j;
1821 	    idx[1] = 1 + ((i + 1) * (CAP_ELEMENTS + 1)) + j;
1822 	    idx[2] = 2 + ((i + 1) * (CAP_ELEMENTS + 1)) + j;
1823 	    idx[3] = 2 + (i * (CAP_ELEMENTS + 1)) + j;
1824 	    idx += 4;
1825 	}
1826     }
1827 
1828     cubeaddonInitCap (s, &cas->topCap);
1829     cubeaddonInitCap (s, &cas->bottomCap);
1830 
1831     cas->topCap.files = cubeaddonGetTopImages (s);
1832     cas->bottomCap.files = cubeaddonGetBottomImages (s);
1833 
1834     cubeaddonSetTopImagesNotify (s, cubeaddonTopImagesChanged);
1835     cubeaddonSetBottomImagesNotify (s, cubeaddonBottomImagesChanged);
1836 
1837     cubeaddonSetTopScaleNotify (s, cubeaddonTopImageChanged);
1838     cubeaddonSetTopAspectNotify (s, cubeaddonTopImageChanged);
1839     cubeaddonSetTopClampNotify (s, cubeaddonTopImageChanged);
1840     cubeaddonSetBottomScaleNotify (s, cubeaddonBottomImageChanged);
1841     cubeaddonSetBottomAspectNotify (s, cubeaddonBottomImageChanged);
1842     cubeaddonSetBottomClampNotify (s, cubeaddonTopImageChanged);
1843 
1844     cubeaddonChangeCap (s, TRUE, 0);
1845     cubeaddonChangeCap (s, FALSE, 0);
1846 
1847     WRAP (cas, s, paintTransformedOutput, cubeaddonPaintTransformedOutput);
1848     WRAP (cas, s, paintOutput, cubeaddonPaintOutput);
1849     WRAP (cas, s, donePaintScreen, cubeaddonDonePaintScreen);
1850     WRAP (cas, s, addWindowGeometry, cubeaddonAddWindowGeometry);
1851     WRAP (cas, s, drawWindow, cubeaddonDrawWindow);
1852     WRAP (cas, s, drawWindowTexture, cubeaddonDrawWindowTexture);
1853 
1854 
1855     WRAP (cas, cs, clearTargetOutput, cubeaddonClearTargetOutput);
1856     WRAP (cas, cs, getRotation, cubeaddonGetRotation);
1857     WRAP (cas, cs, checkOrientation, cubeaddonCheckOrientation);
1858     WRAP (cas, cs, shouldPaintViewport, cubeaddonShouldPaintViewport);
1859     WRAP (cas, cs, paintTop, cubeaddonPaintTop);
1860     WRAP (cas, cs, paintBottom, cubeaddonPaintBottom);
1861 
1862     return TRUE;
1863 }
1864 
1865 static void
cubeaddonFiniScreen(CompPlugin * p,CompScreen * s)1866 cubeaddonFiniScreen (CompPlugin *p,
1867 		     CompScreen *s)
1868 {
1869     CUBEADDON_SCREEN (s);
1870     CUBE_SCREEN (s);
1871 
1872     if (cas->winNormals)
1873 	free (cas->winNormals);
1874 
1875     if (cas->tmpBox)
1876 	free (cas->tmpBox);
1877 
1878     XDestroyRegion (cas->tmpRegion);
1879 
1880     UNWRAP (cas, s, paintTransformedOutput);
1881     UNWRAP (cas, s, paintOutput);
1882     UNWRAP (cas, s, donePaintScreen);
1883     UNWRAP (cas, s, addWindowGeometry);
1884     UNWRAP (cas, s, drawWindow);
1885     UNWRAP (cas, s, drawWindowTexture);
1886 
1887     UNWRAP (cas, cs, clearTargetOutput);
1888     UNWRAP (cas, cs, getRotation);
1889     UNWRAP (cas, cs, checkOrientation);
1890     UNWRAP (cas, cs, shouldPaintViewport);
1891     UNWRAP (cas, cs, paintTop);
1892     UNWRAP (cas, cs, paintBottom);
1893 
1894     free (cas);
1895 }
1896 
1897 static Bool
cubeaddonInit(CompPlugin * p)1898 cubeaddonInit (CompPlugin *p)
1899 {
1900     CubeaddonDisplayPrivateIndex = allocateDisplayPrivateIndex ();
1901 
1902     if (CubeaddonDisplayPrivateIndex < 0)
1903 	return FALSE;
1904 
1905     return TRUE;
1906 }
1907 
1908 static void
cubeaddonFini(CompPlugin * p)1909 cubeaddonFini (CompPlugin *p)
1910 {
1911     freeDisplayPrivateIndex (CubeaddonDisplayPrivateIndex);
1912 }
1913 
1914 static CompBool
cubeaddonInitObject(CompPlugin * p,CompObject * o)1915 cubeaddonInitObject (CompPlugin *p,
1916 		     CompObject *o)
1917 {
1918     static InitPluginObjectProc dispTab[] = {
1919 	(InitPluginObjectProc) 0, /* InitCore */
1920 	(InitPluginObjectProc) cubeaddonInitDisplay,
1921 	(InitPluginObjectProc) cubeaddonInitScreen
1922     };
1923 
1924     RETURN_DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), TRUE, (p, o));
1925 }
1926 
1927 static void
cubeaddonFiniObject(CompPlugin * p,CompObject * o)1928 cubeaddonFiniObject (CompPlugin *p,
1929 		     CompObject *o)
1930 {
1931     static FiniPluginObjectProc dispTab[] = {
1932 	(FiniPluginObjectProc) 0, /* FiniCore */
1933 	(FiniPluginObjectProc) cubeaddonFiniDisplay,
1934 	(FiniPluginObjectProc) cubeaddonFiniScreen
1935     };
1936 
1937     DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), (p, o));
1938 }
1939 
1940 CompPluginVTable cubeaddonVTable = {
1941     "cubeaddon",
1942     0,
1943     cubeaddonInit,
1944     cubeaddonFini,
1945     cubeaddonInitObject,
1946     cubeaddonFiniObject,
1947     0,
1948     0
1949 };
1950 
1951 CompPluginVTable *
getCompPluginInfo(void)1952 getCompPluginInfo (void)
1953 {
1954     return &cubeaddonVTable;
1955 }
1956