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 */
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include <math.h>
29
30 #include <compiz-core.h>
31
32 ScreenPaintAttrib defaultScreenPaintAttrib = {
33 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -DEFAULT_Z_CAMERA
34 };
35
36 WindowPaintAttrib defaultWindowPaintAttrib = {
37 OPAQUE, BRIGHT, COLOR, 1.0f, 1.0f, 0.0f, 0.0f
38 };
39
40 void
preparePaintScreen(CompScreen * screen,int msSinceLastPaint)41 preparePaintScreen (CompScreen *screen,
42 int msSinceLastPaint)
43 {
44 }
45
46 void
donePaintScreen(CompScreen * screen)47 donePaintScreen (CompScreen *screen)
48 {
49 }
50
51 void
applyScreenTransform(CompScreen * screen,const ScreenPaintAttrib * sAttrib,CompOutput * output,CompTransform * transform)52 applyScreenTransform (CompScreen *screen,
53 const ScreenPaintAttrib *sAttrib,
54 CompOutput *output,
55 CompTransform *transform)
56 {
57 matrixTranslate (transform,
58 sAttrib->xTranslate,
59 sAttrib->yTranslate,
60 sAttrib->zTranslate + sAttrib->zCamera);
61 matrixRotate (transform,
62 sAttrib->xRotate, 0.0f, 1.0f, 0.0f);
63 matrixRotate (transform,
64 sAttrib->vRotate,
65 cosf (sAttrib->xRotate * DEG2RAD),
66 0.0f,
67 sinf (sAttrib->xRotate * DEG2RAD));
68 matrixRotate (transform,
69 sAttrib->yRotate, 0.0f, 1.0f, 0.0f);
70 }
71
72 void
transformToScreenSpace(CompScreen * screen,CompOutput * output,float z,CompTransform * transform)73 transformToScreenSpace (CompScreen *screen,
74 CompOutput *output,
75 float z,
76 CompTransform *transform)
77 {
78 matrixTranslate (transform, -0.5f, -0.5f, z);
79 matrixScale (transform,
80 1.0f / output->width,
81 -1.0f / output->height,
82 1.0f);
83 matrixTranslate (transform,
84 -output->region.extents.x1,
85 -output->region.extents.y2,
86 0.0f);
87 }
88
89 void
prepareXCoords(CompScreen * screen,CompOutput * output,float z)90 prepareXCoords (CompScreen *screen,
91 CompOutput *output,
92 float z)
93 {
94 glTranslatef (-0.5f, -0.5f, z);
95 glScalef (1.0f / output->width,
96 -1.0f / output->height,
97 1.0f);
98 glTranslatef (-output->region.extents.x1,
99 -output->region.extents.y2,
100 0.0f);
101 }
102
103 void
paintCursor(CompCursor * c,const CompTransform * transform,Region region,unsigned int mask)104 paintCursor (CompCursor *c,
105 const CompTransform *transform,
106 Region region,
107 unsigned int mask)
108 {
109 int x1, y1, x2, y2;
110
111 if (!c->image)
112 return;
113
114 x1 = c->x;
115 y1 = c->y;
116 x2 = c->x + c->image->width;
117 y2 = c->y + c->image->height;
118
119 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
120 glEnable (GL_BLEND);
121
122 enableTexture (c->screen, &c->image->texture, COMP_TEXTURE_FILTER_FAST);
123
124 glBegin (GL_QUADS);
125
126 glTexCoord2f (COMP_TEX_COORD_X (&c->matrix, x1),
127 COMP_TEX_COORD_Y (&c->matrix, y2));
128 glVertex2i (x1, y2);
129 glTexCoord2f (COMP_TEX_COORD_X (&c->matrix, x2),
130 COMP_TEX_COORD_Y (&c->matrix, y2));
131 glVertex2i (x2, y2);
132 glTexCoord2f (COMP_TEX_COORD_X (&c->matrix, x2),
133 COMP_TEX_COORD_Y (&c->matrix, y1));
134 glVertex2i (x2, y1);
135 glTexCoord2f (COMP_TEX_COORD_X (&c->matrix, x1),
136 COMP_TEX_COORD_Y (&c->matrix, y1));
137 glVertex2i (x1, y1);
138
139 glEnd ();
140
141 disableTexture (c->screen, &c->image->texture);
142
143 glDisable (GL_BLEND);
144 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
145 }
146
147 static void
paintBackground(CompScreen * s,Region region,Bool transformed)148 paintBackground (CompScreen *s,
149 Region region,
150 Bool transformed)
151 {
152 CompTexture *bg = &s->backgroundTexture;
153 BoxPtr pBox = region->rects;
154 int n, nBox = region->numRects;
155 GLfloat *d, *data;
156
157 if (!nBox)
158 return;
159
160 if (s->desktopWindowCount)
161 {
162 if (bg->name)
163 {
164 finiTexture (s, bg);
165 initTexture (s, bg);
166 }
167
168 s->backgroundLoaded = FALSE;
169
170 return;
171 }
172 else
173 {
174 if (!s->backgroundLoaded)
175 updateScreenBackground (s, bg);
176
177 s->backgroundLoaded = TRUE;
178 }
179
180 data = malloc (sizeof (GLfloat) * nBox * 16);
181 if (!data)
182 return;
183
184 d = data;
185 n = nBox;
186 while (n--)
187 {
188 *d++ = COMP_TEX_COORD_X (&bg->matrix, pBox->x1);
189 *d++ = COMP_TEX_COORD_Y (&bg->matrix, pBox->y2);
190
191 *d++ = pBox->x1;
192 *d++ = pBox->y2;
193
194 *d++ = COMP_TEX_COORD_X (&bg->matrix, pBox->x2);
195 *d++ = COMP_TEX_COORD_Y (&bg->matrix, pBox->y2);
196
197 *d++ = pBox->x2;
198 *d++ = pBox->y2;
199
200 *d++ = COMP_TEX_COORD_X (&bg->matrix, pBox->x2);
201 *d++ = COMP_TEX_COORD_Y (&bg->matrix, pBox->y1);
202
203 *d++ = pBox->x2;
204 *d++ = pBox->y1;
205
206 *d++ = COMP_TEX_COORD_X (&bg->matrix, pBox->x1);
207 *d++ = COMP_TEX_COORD_Y (&bg->matrix, pBox->y1);
208
209 *d++ = pBox->x1;
210 *d++ = pBox->y1;
211
212 pBox++;
213 }
214
215 glTexCoordPointer (2, GL_FLOAT, sizeof (GLfloat) * 4, data);
216 glVertexPointer (2, GL_FLOAT, sizeof (GLfloat) * 4, data + 2);
217
218 if (bg->name)
219 {
220 if (transformed)
221 enableTexture (s, bg, COMP_TEXTURE_FILTER_GOOD);
222 else
223 enableTexture (s, bg, COMP_TEXTURE_FILTER_FAST);
224
225 glDrawArrays (GL_QUADS, 0, nBox * 4);
226
227 disableTexture (s, bg);
228 }
229 else
230 {
231 glColor4us (0, 0, 0, 0);
232 glDrawArrays (GL_QUADS, 0, nBox * 4);
233 glColor4usv (defaultColor);
234 }
235
236 free (data);
237 }
238
239
240 /* This function currently always performs occlusion detection to
241 minimize paint regions. OpenGL precision requirements are no good
242 enough to guarantee that the results from using occlusion detection
243 is the same as without. It's likely not possible to see any
244 difference with most hardware but occlusion detection in the
245 transformed screen case should be made optional for those who do
246 see a difference. */
247 static void
paintOutputRegion(CompScreen * screen,const CompTransform * transform,Region region,CompOutput * output,unsigned int mask)248 paintOutputRegion (CompScreen *screen,
249 const CompTransform *transform,
250 Region region,
251 CompOutput *output,
252 unsigned int mask)
253 {
254 static Region tmpRegion = NULL;
255 CompWindow *w;
256 CompCursor *c;
257 int count, windowMask, odMask, i;
258 CompWindow *fullscreenWindow = NULL;
259 CompWalker walk;
260 Bool status;
261 Bool withOffset = FALSE;
262 CompTransform vTransform;
263 int offX, offY;
264 Region clip = region;
265
266 if (!tmpRegion)
267 {
268 tmpRegion = XCreateRegion ();
269 if (!tmpRegion)
270 return;
271 }
272
273 if (mask & PAINT_SCREEN_TRANSFORMED_MASK)
274 {
275 windowMask = PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK;
276 count = 1;
277 }
278 else
279 {
280 windowMask = 0;
281 count = 0;
282 }
283
284 XSubtractRegion (region, &emptyRegion, tmpRegion);
285
286 (*screen->initWindowWalker) (screen, &walk);
287
288 if (!(mask & PAINT_SCREEN_NO_OCCLUSION_DETECTION_MASK))
289 {
290 /* detect occlusions */
291 for (w = (*walk.last) (screen); w; w = (*walk.prev) (w))
292 {
293 if (w->destroyed)
294 continue;
295
296 if (!w->shaded)
297 {
298 if (w->attrib.map_state != IsViewable || !w->damaged)
299 continue;
300 }
301
302 /* copy region */
303 XSubtractRegion (tmpRegion, &emptyRegion, w->clip);
304
305 odMask = PAINT_WINDOW_OCCLUSION_DETECTION_MASK;
306
307 if ((screen->windowOffsetX != 0 || screen->windowOffsetY != 0) &&
308 !windowOnAllViewports (w))
309 {
310 withOffset = TRUE;
311
312 getWindowMovementForOffset (w, screen->windowOffsetX,
313 screen->windowOffsetY,
314 &offX, &offY);
315
316 vTransform = *transform;
317 matrixTranslate (&vTransform, offX, offY, 0);
318
319 XOffsetRegion (w->clip, -offX, -offY);
320
321 odMask |= PAINT_WINDOW_WITH_OFFSET_MASK;
322 status = (*screen->paintWindow) (w, &w->paint, &vTransform,
323 tmpRegion, odMask);
324 }
325 else
326 {
327 withOffset = FALSE;
328 status = (*screen->paintWindow) (w, &w->paint, transform, tmpRegion,
329 odMask);
330 }
331
332 if (status)
333 {
334 if (withOffset)
335 {
336 XOffsetRegion (w->region, offX, offY);
337 XSubtractRegion (tmpRegion, w->region, tmpRegion);
338 XOffsetRegion (w->region, -offX, -offY);
339 }
340 else
341 XSubtractRegion (tmpRegion, w->region, tmpRegion);
342
343 /* unredirect top most fullscreen windows. */
344 if (count == 0 &&
345 screen->opt[COMP_SCREEN_OPTION_UNREDIRECT_FS].value.b)
346 {
347 if (XEqualRegion (w->region, &screen->region) &&
348 !REGION_NOT_EMPTY (tmpRegion))
349 {
350 fullscreenWindow = w;
351 }
352 else
353 {
354 for (i = 0; i < screen->nOutputDev; i++)
355 if (XEqualRegion (w->region,
356 &screen->outputDev[i].region))
357 fullscreenWindow = w;
358 }
359 }
360 }
361
362 if (!w->invisible)
363 count++;
364 }
365 }
366
367 if (fullscreenWindow)
368 unredirectWindow (fullscreenWindow);
369
370 if (!(mask & PAINT_SCREEN_NO_BACKGROUND_MASK))
371 paintBackground (screen, tmpRegion,
372 (mask & PAINT_SCREEN_TRANSFORMED_MASK));
373
374 /* paint all windows from bottom to top */
375 for (w = (*walk.first) (screen); w; w = (*walk.next) (w))
376 {
377 if (w->destroyed)
378 continue;
379
380 if (w == fullscreenWindow)
381 continue;
382
383 if (!w->shaded)
384 {
385 if (w->attrib.map_state != IsViewable || !w->damaged)
386 continue;
387 }
388
389 if (!(mask & PAINT_SCREEN_NO_OCCLUSION_DETECTION_MASK))
390 clip = w->clip;
391
392 if ((screen->windowOffsetX != 0 || screen->windowOffsetY != 0) &&
393 !windowOnAllViewports (w))
394 {
395 getWindowMovementForOffset (w, screen->windowOffsetX,
396 screen->windowOffsetY, &offX, &offY);
397
398 vTransform = *transform;
399 matrixTranslate (&vTransform, offX, offY, 0);
400 (*screen->paintWindow) (w, &w->paint, &vTransform, clip,
401 windowMask | PAINT_WINDOW_WITH_OFFSET_MASK);
402 }
403 else
404 {
405 (*screen->paintWindow) (w, &w->paint, transform, clip,
406 windowMask);
407 }
408 }
409
410 if (walk.fini)
411 (*walk.fini) (screen, &walk);
412
413 /* paint cursors */
414 for (c = screen->cursors; c; c = c->next)
415 (*screen->paintCursor) (c, transform, tmpRegion, 0);
416 }
417
418 void
enableOutputClipping(CompScreen * screen,const CompTransform * transform,Region region,CompOutput * output)419 enableOutputClipping (CompScreen *screen,
420 const CompTransform *transform,
421 Region region,
422 CompOutput *output)
423 {
424 GLdouble h = screen->height;
425
426 GLdouble p1[2] = { region->extents.x1, h - region->extents.y2 };
427 GLdouble p2[2] = { region->extents.x2, h - region->extents.y1 };
428
429 GLdouble halfW = output->width / 2.0;
430 GLdouble halfH = output->height / 2.0;
431
432 GLdouble cx = output->region.extents.x1 + halfW;
433 GLdouble cy = (h - output->region.extents.y2) + halfH;
434
435 GLdouble top[4] = { 0.0, halfH / (cy - p1[1]), 0.0, 0.5 };
436 GLdouble bottom[4] = { 0.0, halfH / (cy - p2[1]), 0.0, 0.5 };
437 GLdouble left[4] = { halfW / (cx - p1[0]), 0.0, 0.0, 0.5 };
438 GLdouble right[4] = { halfW / (cx - p2[0]), 0.0, 0.0, 0.5 };
439
440 glPushMatrix ();
441 glLoadMatrixf (transform->m);
442
443 glClipPlane (GL_CLIP_PLANE0, top);
444 glClipPlane (GL_CLIP_PLANE1, bottom);
445 glClipPlane (GL_CLIP_PLANE2, left);
446 glClipPlane (GL_CLIP_PLANE3, right);
447
448 glEnable (GL_CLIP_PLANE0);
449 glEnable (GL_CLIP_PLANE1);
450 glEnable (GL_CLIP_PLANE2);
451 glEnable (GL_CLIP_PLANE3);
452
453 glPopMatrix ();
454 }
455
456 void
disableOutputClipping(CompScreen * screen)457 disableOutputClipping (CompScreen *screen)
458 {
459 glDisable (GL_CLIP_PLANE0);
460 glDisable (GL_CLIP_PLANE1);
461 glDisable (GL_CLIP_PLANE2);
462 glDisable (GL_CLIP_PLANE3);
463 }
464
465 #define CLIP_PLANE_MASK (PAINT_SCREEN_TRANSFORMED_MASK | \
466 PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK)
467
468 void
paintTransformedOutput(CompScreen * screen,const ScreenPaintAttrib * sAttrib,const CompTransform * transform,Region region,CompOutput * output,unsigned int mask)469 paintTransformedOutput (CompScreen *screen,
470 const ScreenPaintAttrib *sAttrib,
471 const CompTransform *transform,
472 Region region,
473 CompOutput *output,
474 unsigned int mask)
475 {
476 CompTransform sTransform = *transform;
477
478 if (mask & PAINT_SCREEN_CLEAR_MASK)
479 clearTargetOutput (screen->display, GL_COLOR_BUFFER_BIT);
480
481 screenLighting (screen, TRUE);
482
483 (*screen->applyScreenTransform) (screen, sAttrib, output, &sTransform);
484
485 if ((mask & CLIP_PLANE_MASK) == CLIP_PLANE_MASK)
486 {
487 screen->enableOutputClipping (screen, &sTransform, region, output);
488
489 transformToScreenSpace (screen, output, -sAttrib->zTranslate,
490 &sTransform);
491
492 glPushMatrix ();
493 glLoadMatrixf (sTransform.m);
494
495 paintOutputRegion (screen, &sTransform, region, output, mask);
496
497 glPopMatrix ();
498
499 screen->disableOutputClipping (screen);
500 }
501 else
502 {
503 transformToScreenSpace (screen, output, -sAttrib->zTranslate,
504 &sTransform);
505
506 glPushMatrix ();
507 glLoadMatrixf (sTransform.m);
508
509 paintOutputRegion (screen, &sTransform, region, output, mask);
510
511 glPopMatrix ();
512 }
513 }
514
515 Bool
paintOutput(CompScreen * screen,const ScreenPaintAttrib * sAttrib,const CompTransform * transform,Region region,CompOutput * output,unsigned int mask)516 paintOutput (CompScreen *screen,
517 const ScreenPaintAttrib *sAttrib,
518 const CompTransform *transform,
519 Region region,
520 CompOutput *output,
521 unsigned int mask)
522 {
523 CompTransform sTransform = *transform;
524
525 if (mask & PAINT_SCREEN_REGION_MASK)
526 {
527 if (mask & PAINT_SCREEN_TRANSFORMED_MASK)
528 {
529 if (mask & PAINT_SCREEN_FULL_MASK)
530 {
531 region = &output->region;
532
533 (*screen->paintTransformedOutput) (screen, sAttrib,
534 &sTransform, region,
535 output, mask);
536
537 return TRUE;
538 }
539
540 return FALSE;
541 }
542
543 /* fall through and redraw region */
544 }
545 else if (mask & PAINT_SCREEN_FULL_MASK)
546 {
547 (*screen->paintTransformedOutput) (screen, sAttrib, &sTransform,
548 &output->region,
549 output, mask);
550
551 return TRUE;
552 }
553 else
554 return FALSE;
555
556 screenLighting (screen, FALSE);
557
558 transformToScreenSpace (screen, output, -DEFAULT_Z_CAMERA, &sTransform);
559
560 glPushMatrix ();
561 glLoadMatrixf (sTransform.m);
562
563 paintOutputRegion (screen, &sTransform, region, output, mask);
564
565 glPopMatrix ();
566
567 return TRUE;
568 }
569
570 #define ADD_RECT(data, m, n, x1, y1, x2, y2) \
571 for (it = 0; it < n; it++) \
572 { \
573 *(data)++ = COMP_TEX_COORD_X (&m[it], x1); \
574 *(data)++ = COMP_TEX_COORD_Y (&m[it], y1); \
575 } \
576 *(data)++ = (x1); \
577 *(data)++ = (y1); \
578 *(data)++ = 0.0; \
579 for (it = 0; it < n; it++) \
580 { \
581 *(data)++ = COMP_TEX_COORD_X (&m[it], x1); \
582 *(data)++ = COMP_TEX_COORD_Y (&m[it], y2); \
583 } \
584 *(data)++ = (x1); \
585 *(data)++ = (y2); \
586 *(data)++ = 0.0; \
587 for (it = 0; it < n; it++) \
588 { \
589 *(data)++ = COMP_TEX_COORD_X (&m[it], x2); \
590 *(data)++ = COMP_TEX_COORD_Y (&m[it], y2); \
591 } \
592 *(data)++ = (x2); \
593 *(data)++ = (y2); \
594 *(data)++ = 0.0; \
595 for (it = 0; it < n; it++) \
596 { \
597 *(data)++ = COMP_TEX_COORD_X (&m[it], x2); \
598 *(data)++ = COMP_TEX_COORD_Y (&m[it], y1); \
599 } \
600 *(data)++ = (x2); \
601 *(data)++ = (y1); \
602 *(data)++ = 0.0
603
604 #define ADD_QUAD(data, m, n, x1, y1, x2, y2) \
605 for (it = 0; it < n; it++) \
606 { \
607 *(data)++ = COMP_TEX_COORD_XY (&m[it], x1, y1); \
608 *(data)++ = COMP_TEX_COORD_YX (&m[it], x1, y1); \
609 } \
610 *(data)++ = (x1); \
611 *(data)++ = (y1); \
612 *(data)++ = 0.0; \
613 for (it = 0; it < n; it++) \
614 { \
615 *(data)++ = COMP_TEX_COORD_XY (&m[it], x1, y2); \
616 *(data)++ = COMP_TEX_COORD_YX (&m[it], x1, y2); \
617 } \
618 *(data)++ = (x1); \
619 *(data)++ = (y2); \
620 *(data)++ = 0.0; \
621 for (it = 0; it < n; it++) \
622 { \
623 *(data)++ = COMP_TEX_COORD_XY (&m[it], x2, y2); \
624 *(data)++ = COMP_TEX_COORD_YX (&m[it], x2, y2); \
625 } \
626 *(data)++ = (x2); \
627 *(data)++ = (y2); \
628 *(data)++ = 0.0; \
629 for (it = 0; it < n; it++) \
630 { \
631 *(data)++ = COMP_TEX_COORD_XY (&m[it], x2, y1); \
632 *(data)++ = COMP_TEX_COORD_YX (&m[it], x2, y1); \
633 } \
634 *(data)++ = (x2); \
635 *(data)++ = (y1); \
636 *(data)++ = 0.0;
637
638
639 Bool
moreWindowVertices(CompWindow * w,int newSize)640 moreWindowVertices (CompWindow *w,
641 int newSize)
642 {
643 if (newSize > w->vertexSize)
644 {
645 GLfloat *vertices;
646
647 vertices = realloc (w->vertices, sizeof (GLfloat) * newSize);
648 if (!vertices)
649 return FALSE;
650
651 w->vertices = vertices;
652 w->vertexSize = newSize;
653 }
654
655 return TRUE;
656 }
657
658 Bool
moreWindowIndices(CompWindow * w,int newSize)659 moreWindowIndices (CompWindow *w,
660 int newSize)
661 {
662 if (newSize > w->indexSize)
663 {
664 GLushort *indices;
665
666 indices = realloc (w->indices, sizeof (GLushort) * newSize);
667 if (!indices)
668 return FALSE;
669
670 w->indices = indices;
671 w->indexSize = newSize;
672 }
673
674 return TRUE;
675 }
676
677 static void
drawWindowGeometry(CompWindow * w)678 drawWindowGeometry (CompWindow *w)
679 {
680 int texUnit = w->texUnits;
681 int currentTexUnit = 0;
682 int stride = w->vertexStride;
683 GLfloat *vertices = w->vertices + (stride - 3);
684
685 stride *= sizeof (GLfloat);
686
687 glVertexPointer (3, GL_FLOAT, stride, vertices);
688
689 while (texUnit--)
690 {
691 if (texUnit != currentTexUnit)
692 {
693 (*w->screen->clientActiveTexture) (GL_TEXTURE0_ARB + texUnit);
694 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
695 currentTexUnit = texUnit;
696 }
697 vertices -= w->texCoordSize;
698 glTexCoordPointer (w->texCoordSize, GL_FLOAT, stride, vertices);
699 }
700
701 glDrawArrays (GL_QUADS, 0, w->vCount);
702
703 /* disable all texture coordinate arrays except 0 */
704 texUnit = w->texUnits;
705 if (texUnit > 1)
706 {
707 while (--texUnit)
708 {
709 (*w->screen->clientActiveTexture) (GL_TEXTURE0_ARB + texUnit);
710 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
711 }
712
713 (*w->screen->clientActiveTexture) (GL_TEXTURE0_ARB);
714 }
715 }
716
717 void
addWindowGeometry(CompWindow * w,CompMatrix * matrix,int nMatrix,Region region,Region clip)718 addWindowGeometry (CompWindow *w,
719 CompMatrix *matrix,
720 int nMatrix,
721 Region region,
722 Region clip)
723 {
724 BoxRec full;
725
726 w->texUnits = nMatrix;
727
728 full = clip->extents;
729 if (region->extents.x1 > full.x1)
730 full.x1 = region->extents.x1;
731 if (region->extents.y1 > full.y1)
732 full.y1 = region->extents.y1;
733 if (region->extents.x2 < full.x2)
734 full.x2 = region->extents.x2;
735 if (region->extents.y2 < full.y2)
736 full.y2 = region->extents.y2;
737
738 if (full.x1 < full.x2 && full.y1 < full.y2)
739 {
740 BoxPtr pBox;
741 int nBox;
742 BoxPtr pClip;
743 int nClip;
744 BoxRec cbox;
745 int vSize;
746 int n, it, x1, y1, x2, y2;
747 GLfloat *d;
748 Bool rect = TRUE;
749
750 for (it = 0; it < nMatrix; it++)
751 {
752 if (matrix[it].xy != 0.0f || matrix[it].yx != 0.0f)
753 {
754 rect = FALSE;
755 break;
756 }
757 }
758
759 pBox = region->rects;
760 nBox = region->numRects;
761
762 vSize = 3 + nMatrix * 2;
763
764 n = w->vCount / 4;
765
766 if ((n + nBox) * vSize * 4 > w->vertexSize)
767 {
768 if (!moreWindowVertices (w, (n + nBox) * vSize * 4))
769 return;
770 }
771
772 d = w->vertices + (w->vCount * vSize);
773
774 while (nBox--)
775 {
776 x1 = pBox->x1;
777 y1 = pBox->y1;
778 x2 = pBox->x2;
779 y2 = pBox->y2;
780
781 pBox++;
782
783 if (x1 < full.x1)
784 x1 = full.x1;
785 if (y1 < full.y1)
786 y1 = full.y1;
787 if (x2 > full.x2)
788 x2 = full.x2;
789 if (y2 > full.y2)
790 y2 = full.y2;
791
792 if (x1 < x2 && y1 < y2)
793 {
794 nClip = clip->numRects;
795
796 if (nClip == 1)
797 {
798 if (rect)
799 {
800 ADD_RECT (d, matrix, nMatrix, x1, y1, x2, y2);
801 }
802 else
803 {
804 ADD_QUAD (d, matrix, nMatrix, x1, y1, x2, y2);
805 }
806
807 n++;
808 }
809 else
810 {
811 pClip = clip->rects;
812
813 if (((n + nClip) * vSize * 4) > w->vertexSize)
814 {
815 if (!moreWindowVertices (w, (n + nClip) * vSize * 4))
816 return;
817
818 d = w->vertices + (n * vSize * 4);
819 }
820
821 while (nClip--)
822 {
823 cbox = *pClip;
824
825 pClip++;
826
827 if (cbox.x1 < x1)
828 cbox.x1 = x1;
829 if (cbox.y1 < y1)
830 cbox.y1 = y1;
831 if (cbox.x2 > x2)
832 cbox.x2 = x2;
833 if (cbox.y2 > y2)
834 cbox.y2 = y2;
835
836 if (cbox.x1 < cbox.x2 && cbox.y1 < cbox.y2)
837 {
838 if (rect)
839 {
840 ADD_RECT (d, matrix, nMatrix,
841 cbox.x1, cbox.y1, cbox.x2, cbox.y2);
842 }
843 else
844 {
845 ADD_QUAD (d, matrix, nMatrix,
846 cbox.x1, cbox.y1, cbox.x2, cbox.y2);
847 }
848
849 n++;
850 }
851 }
852 }
853 }
854 }
855
856 w->vCount = n * 4;
857 w->vertexStride = vSize;
858 w->texCoordSize = 2;
859 w->drawWindowGeometry = drawWindowGeometry;
860 }
861 }
862
863 static Bool
enableFragmentProgramAndDrawGeometry(CompWindow * w,CompTexture * texture,const FragmentAttrib * attrib,int filter,unsigned int mask)864 enableFragmentProgramAndDrawGeometry (CompWindow *w,
865 CompTexture *texture,
866 const FragmentAttrib *attrib,
867 int filter,
868 unsigned int mask)
869 {
870 FragmentAttrib fa = *attrib;
871 CompScreen *s = w->screen;
872 Bool blending;
873
874 if (s->canDoSaturated && attrib->saturation != COLOR)
875 {
876 int param, function;
877
878 param = allocFragmentParameters (&fa, 1);
879 function = getSaturateFragmentFunction (s, texture, param);
880
881 addFragmentFunction (&fa, function);
882
883 (*s->programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB, param,
884 RED_SATURATION_WEIGHT,
885 GREEN_SATURATION_WEIGHT,
886 BLUE_SATURATION_WEIGHT,
887 attrib->saturation / 65535.0f);
888 }
889
890 if (!enableFragmentAttrib (s, &fa, &blending))
891 return FALSE;
892
893 enableTexture (s, texture, filter);
894
895 if (mask & PAINT_WINDOW_BLEND_MASK)
896 {
897 if (blending)
898 glEnable (GL_BLEND);
899
900 if (attrib->opacity != OPAQUE || attrib->brightness != BRIGHT)
901 {
902 GLushort color;
903
904 color = (attrib->opacity * attrib->brightness) >> 16;
905
906 screenTexEnvMode (s, GL_MODULATE);
907 glColor4us (color, color, color, attrib->opacity);
908
909 (*w->drawWindowGeometry) (w);
910
911 glColor4usv (defaultColor);
912 screenTexEnvMode (s, GL_REPLACE);
913 }
914 else
915 {
916 (*w->drawWindowGeometry) (w);
917 }
918
919 if (blending)
920 glDisable (GL_BLEND);
921 }
922 else if (attrib->brightness != BRIGHT)
923 {
924 screenTexEnvMode (s, GL_MODULATE);
925 glColor4us (attrib->brightness, attrib->brightness,
926 attrib->brightness, BRIGHT);
927
928 (*w->drawWindowGeometry) (w);
929
930 glColor4usv (defaultColor);
931 screenTexEnvMode (s, GL_REPLACE);
932 }
933 else
934 {
935 (*w->drawWindowGeometry) (w);
936 }
937
938 disableTexture (w->screen, texture);
939
940 disableFragmentAttrib (s, &fa);
941
942 return TRUE;
943 }
944
945 static void
enableFragmentOperationsAndDrawGeometry(CompWindow * w,CompTexture * texture,const FragmentAttrib * attrib,int filter,unsigned int mask)946 enableFragmentOperationsAndDrawGeometry (CompWindow *w,
947 CompTexture *texture,
948 const FragmentAttrib *attrib,
949 int filter,
950 unsigned int mask)
951 {
952 CompScreen *s = w->screen;
953
954 if (s->canDoSaturated && attrib->saturation != COLOR)
955 {
956 GLfloat constant[4];
957
958 if (mask & PAINT_WINDOW_BLEND_MASK)
959 glEnable (GL_BLEND);
960
961 enableTexture (s, texture, filter);
962
963 glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
964
965 glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
966 glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
967 glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
968 glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PRIMARY_COLOR);
969 glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
970 glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
971 glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
972
973 glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
974 glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
975 glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
976
977 glColor4f (1.0f, 1.0f, 1.0f, 0.5f);
978
979 s->activeTexture (GL_TEXTURE1_ARB);
980
981 enableTexture (s, texture, filter);
982
983 glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
984
985 glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB);
986 glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
987 glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT);
988 glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
989 glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
990
991 if (s->canDoSlightlySaturated && attrib->saturation > 0)
992 {
993 glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
994 glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
995 glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
996
997 constant[0] = 0.5f + 0.5f * RED_SATURATION_WEIGHT;
998 constant[1] = 0.5f + 0.5f * GREEN_SATURATION_WEIGHT;
999 constant[2] = 0.5f + 0.5f * BLUE_SATURATION_WEIGHT;
1000 constant[3] = 1.0;
1001
1002 glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
1003
1004 s->activeTexture (GL_TEXTURE2_ARB);
1005
1006 enableTexture (s, texture, filter);
1007
1008 glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
1009
1010 glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
1011 glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE0);
1012 glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS);
1013 glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_CONSTANT);
1014 glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
1015 glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
1016 glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
1017
1018 glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
1019 glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
1020 glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
1021
1022 constant[3] = attrib->saturation / 65535.0f;
1023
1024 glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
1025
1026 if (attrib->opacity < OPAQUE || attrib->brightness != BRIGHT)
1027 {
1028 s->activeTexture (GL_TEXTURE3_ARB);
1029
1030 enableTexture (s, texture, filter);
1031
1032 constant[3] = attrib->opacity / 65535.0f;
1033 constant[0] = constant[1] = constant[2] = constant[3] *
1034 attrib->brightness / 65535.0f;
1035
1036 glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
1037
1038 glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
1039
1040 glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
1041 glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
1042 glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT);
1043 glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
1044 glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
1045
1046 glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
1047 glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
1048 glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_CONSTANT);
1049 glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
1050 glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
1051
1052 (*w->drawWindowGeometry) (w);
1053
1054 disableTexture (s, texture);
1055
1056 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1057
1058 s->activeTexture (GL_TEXTURE2_ARB);
1059 }
1060 else
1061 {
1062 (*w->drawWindowGeometry) (w);
1063 }
1064
1065 disableTexture (s, texture);
1066
1067 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1068
1069 s->activeTexture (GL_TEXTURE1_ARB);
1070 }
1071 else
1072 {
1073 glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
1074 glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
1075 glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_CONSTANT);
1076 glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
1077 glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
1078
1079 constant[3] = attrib->opacity / 65535.0f;
1080 constant[0] = constant[1] = constant[2] = constant[3] *
1081 attrib->brightness / 65535.0f;
1082
1083 constant[0] = 0.5f + 0.5f * RED_SATURATION_WEIGHT * constant[0];
1084 constant[1] = 0.5f + 0.5f * GREEN_SATURATION_WEIGHT * constant[1];
1085 constant[2] = 0.5f + 0.5f * BLUE_SATURATION_WEIGHT * constant[2];
1086
1087 glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
1088
1089 (*w->drawWindowGeometry) (w);
1090 }
1091
1092 disableTexture (s, texture);
1093
1094 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1095
1096 s->activeTexture (GL_TEXTURE0_ARB);
1097
1098 disableTexture (s, texture);
1099
1100 glColor4usv (defaultColor);
1101 screenTexEnvMode (s, GL_REPLACE);
1102
1103 if (mask & PAINT_WINDOW_BLEND_MASK)
1104 glDisable (GL_BLEND);
1105 }
1106 else
1107 {
1108 enableTexture (s, texture, filter);
1109
1110 if (mask & PAINT_WINDOW_BLEND_MASK)
1111 {
1112 glEnable (GL_BLEND);
1113 if (attrib->opacity != OPAQUE || attrib->brightness != BRIGHT)
1114 {
1115 GLushort color;
1116
1117 color = (attrib->opacity * attrib->brightness) >> 16;
1118
1119 screenTexEnvMode (s, GL_MODULATE);
1120 glColor4us (color, color, color, attrib->opacity);
1121
1122 (*w->drawWindowGeometry) (w);
1123
1124 glColor4usv (defaultColor);
1125 screenTexEnvMode (s, GL_REPLACE);
1126 }
1127 else
1128 {
1129 (*w->drawWindowGeometry) (w);
1130 }
1131
1132 glDisable (GL_BLEND);
1133 }
1134 else if (attrib->brightness != BRIGHT)
1135 {
1136 screenTexEnvMode (s, GL_MODULATE);
1137 glColor4us (attrib->brightness, attrib->brightness,
1138 attrib->brightness, BRIGHT);
1139
1140 (*w->drawWindowGeometry) (w);
1141
1142 glColor4usv (defaultColor);
1143 screenTexEnvMode (s, GL_REPLACE);
1144 }
1145 else
1146 {
1147 (*w->drawWindowGeometry) (w);
1148 }
1149
1150 disableTexture (w->screen, texture);
1151 }
1152 }
1153
1154 void
drawWindowTexture(CompWindow * w,CompTexture * texture,const FragmentAttrib * attrib,unsigned int mask)1155 drawWindowTexture (CompWindow *w,
1156 CompTexture *texture,
1157 const FragmentAttrib *attrib,
1158 unsigned int mask)
1159 {
1160 int filter;
1161
1162 if (mask & (PAINT_WINDOW_TRANSFORMED_MASK |
1163 PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK))
1164 filter = w->screen->filter[SCREEN_TRANS_FILTER];
1165 else
1166 filter = w->screen->filter[NOTHING_TRANS_FILTER];
1167
1168 if ((!attrib->nFunction && (!w->screen->lighting ||
1169 attrib->saturation == COLOR || attrib->saturation == 0)) ||
1170 !enableFragmentProgramAndDrawGeometry (w,
1171 texture,
1172 attrib,
1173 filter,
1174 mask))
1175 {
1176 enableFragmentOperationsAndDrawGeometry (w,
1177 texture,
1178 attrib,
1179 filter,
1180 mask);
1181 }
1182 }
1183
1184 Bool
drawWindow(CompWindow * w,const CompTransform * transform,const FragmentAttrib * fragment,Region region,unsigned int mask)1185 drawWindow (CompWindow *w,
1186 const CompTransform *transform,
1187 const FragmentAttrib *fragment,
1188 Region region,
1189 unsigned int mask)
1190 {
1191 if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
1192 region = &infiniteRegion;
1193
1194 if (!region->numRects)
1195 return TRUE;
1196
1197 if (w->attrib.map_state != IsViewable)
1198 return TRUE;
1199
1200 if (!w->texture->pixmap && !bindWindow (w))
1201 return FALSE;
1202
1203 if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
1204 mask |= PAINT_WINDOW_BLEND_MASK;
1205
1206 w->vCount = w->indexCount = 0;
1207 (*w->screen->addWindowGeometry) (w, &w->matrix, 1, w->region, region);
1208 if (w->vCount)
1209 (*w->screen->drawWindowTexture) (w, w->texture, fragment, mask);
1210
1211 return TRUE;
1212 }
1213
1214 Bool
paintWindow(CompWindow * w,const WindowPaintAttrib * attrib,const CompTransform * transform,Region region,unsigned int mask)1215 paintWindow (CompWindow *w,
1216 const WindowPaintAttrib *attrib,
1217 const CompTransform *transform,
1218 Region region,
1219 unsigned int mask)
1220 {
1221 FragmentAttrib fragment;
1222 Bool status;
1223
1224 w->lastPaint = *attrib;
1225
1226 if (w->alpha || attrib->opacity != OPAQUE)
1227 mask |= PAINT_WINDOW_TRANSLUCENT_MASK;
1228
1229 w->lastMask = mask;
1230
1231 if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
1232 {
1233 if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
1234 return FALSE;
1235
1236 if (mask & PAINT_WINDOW_NO_CORE_INSTANCE_MASK)
1237 return FALSE;
1238
1239 if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
1240 return FALSE;
1241
1242 if (w->shaded)
1243 return FALSE;
1244
1245 return TRUE;
1246 }
1247
1248 if (mask & PAINT_WINDOW_NO_CORE_INSTANCE_MASK)
1249 return TRUE;
1250
1251 initFragmentAttrib (&fragment, attrib);
1252
1253 if (mask & PAINT_WINDOW_TRANSFORMED_MASK ||
1254 mask & PAINT_WINDOW_WITH_OFFSET_MASK)
1255 {
1256 glPushMatrix ();
1257 glLoadMatrixf (transform->m);
1258 }
1259
1260 status = (*w->screen->drawWindow) (w, transform, &fragment, region, mask);
1261
1262 if (mask & PAINT_WINDOW_TRANSFORMED_MASK ||
1263 mask & PAINT_WINDOW_WITH_OFFSET_MASK)
1264 glPopMatrix ();
1265
1266 return status;
1267 }
1268