1 /*
2 * Compiz splash plugin
3 *
4 * splash.cpp
5 *
6 * Copyright : (C) 2006 by Dennis Kasprzyk
7 * E-mail : onestone@beryl-project.org
8 *
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 */
21
22 #include "splash.h"
23
24 COMPIZ_PLUGIN_20090315 (splash, SplashPluginVTable);
25
26 const std::string SPLASH_BACKGROUND_DEFAULT("");
27 const std::string SPLASH_LOGO_DEFAULT("");
28
29 void
30 SplashScreen::preparePaint (int ms)
31 {
32 bool lastShot = false;
33
34 fade_in -= ms;
35
36 if (fade_in < 0)
37 {
38 time += fade_in;
39 fade_in = 0;
40
41 if (time < 0)
42 {
43 if (fade_out > 0 && fade_out <= ms)
44 lastShot = true;
45
46 fade_out += time;
47
48 time = 0;
49
50 if (fade_out < 0)
51 fade_out = 0;
52 }
53 }
54
55 if (initiate)
56 {
57 fade_in = fade_out = optionGetFadeTime () * 1000.0;
58 time = optionGetDisplayTime () * 1000.0;
59 initiate = false;
60 }
61
62 if (fade_in || fade_out || time || lastShot)
63 {
64 active = true;
65 mMove += ms / 500.0;
66
67 if (!hasInit)
68 {
69 hasInit = true;
70 mMove = 0.0;
71 CompString back_s (optionGetBackground ());
72 CompString logo_s (optionGetLogo ());
73 CompString pname ("splash");
74
75 back_img =
76 GLTexture::readImageToTexture (back_s, pname,
77 backSize);
78 logo_img =
79 GLTexture::readImageToTexture (logo_s, pname,
80 logoSize);
81
82 if (!back_img.size ())
83 {
84 CompString defaultBack (SPLASH_BACKGROUND_DEFAULT);
85 back_img =
86 GLTexture::readImageToTexture (defaultBack, pname, backSize);
87
88 if (back_img.size ())
89 {
90 compLogMessage ("splash", CompLogLevelWarn,
91 "Could not load splash background image "
92 "\"%s\" using default!",
93 back_s.c_str () );
94 }
95 }
96
97 if (!logo_img.size ())
98 {
99 CompString defaultLogo (SPLASH_LOGO_DEFAULT);
100 logo_img =
101 GLTexture::readImageToTexture (defaultLogo, pname, logoSize);
102
103 if (logo_img.size ())
104 {
105 compLogMessage ("splash", CompLogLevelWarn,
106 "Could not load splash logo image "
107 "\"%s\" using default!",
108 logo_s.c_str () );
109 }
110 }
111
112 if (!back_img.size ())
113 compLogMessage ("splash", CompLogLevelWarn,
114 "Could not load splash background image "
115 "\"%s\" !", back_s.c_str () );
116
117 if (!logo_img.size ())
118 compLogMessage ("splash", CompLogLevelWarn,
119 "Could not load splash logo image \"%s\" !",
120 logo_s.c_str () );
121 }
122 }
123 else
124 {
125 active = false;
126
127 if (hasInit)
128 hasInit = false;
129
130 cScreen->preparePaintSetEnabled (this, false);
131 gScreen->glPaintOutputSetEnabled (this, false);
132 cScreen->donePaintSetEnabled (this, false);
133
134 foreach (CompWindow *w, screen->windows ())
135 {
136 SPLASH_WINDOW (w);
137
138 sw->gWindow->glPaintSetEnabled (sw, false);
139 }
140
141 }
142
143 cScreen->preparePaint (ms);
144
145 }
146
147 void
148 SplashScreen::donePaint ()
149 {
150 if (fade_in || fade_out || time)
151 cScreen->damageScreen ();
152
153 cScreen->donePaint ();
154 }
155
156 static CompRect
157 splashGetCurrentOutputRect ()
158 {
159 int root_x = 0, root_y = 0;
160 int ignore_i;
161 unsigned int ignore_ui;
162 int output;
163 Window ignore_w;
164
165
166 if (screen->outputDevs ().size () == 1)
167 output = 0;
168 else
169 {
170 XQueryPointer (screen->dpy (), screen->root (), &ignore_w, &ignore_w,
171 &root_x, &root_y, &ignore_i, &ignore_i, &ignore_ui);
172 output = screen->outputDeviceForPoint (root_x, root_y);
173 }
174
175 CompRect rect (screen->outputDevs ()[output]);
176
177 return rect;
178
179 }
180
181 bool
182 SplashScreen::glPaintOutput (const GLScreenPaintAttrib &attrib,
183 const GLMatrix &transform,
184 const CompRegion ®ion,
185 CompOutput *output,
186 unsigned int mask)
187 {
188 GLMatrix sTransform = transform;
189
190 bool status = true;
191
192 float alpha = 0.0;
193
194 if (active)
195 {
196 alpha = (1.0 - (fade_in / (optionGetFadeTime () * 1000.0) ) ) *
197 (fade_out / (optionGetFadeTime () * 1000.0) );
198 saturation = 1.0 -
199 ((1.0 - (optionGetSaturation () / 100.0) ) * alpha);
200 brightness = 1.0 -
201 ((1.0 - (optionGetBrightness () / 100.0) ) * alpha);
202 }
203
204 status = gScreen->glPaintOutput (attrib, transform, region, output, mask);
205
206 if (!active)
207 return status;
208
209 sTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
210
211 glPushMatrix ();
212 glLoadMatrixf (sTransform.getMatrix ());
213 glEnable (GL_BLEND);
214 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
215 glColor4f (1.0, 1.0, 1.0, alpha);
216 glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
217
218 if (back_img.size ())
219 {
220 int x, y;
221
222 for (x = 0; x < MESH_W; x++)
223 {
224 for (y = 0; y < MESH_H; y++)
225 {
226 mesh[x][y][0] =
227 (x / (MESH_W - 1.0) ) +
228 (0.02 * sin ( (y / (MESH_H - 1.0) * 8) + mMove) );
229 mesh[x][y][1] =
230 (y / (MESH_H - 1.0) ) +
231 (0.02 * sin ( (mesh[x][y][0] * 8) + mMove) );
232 ;
233 }
234 }
235
236 foreach (GLTexture* tex, back_img)
237 {
238 tex->enable (GLTexture::Good);
239
CID 12419 - CONSTANT_EXPRESSION_RESULT
"!screen->outputDevs()->size() > 1" is always false regardless of the values of its operands. This occurs as the logical operand of if.
240 if (!screen->outputDevs ().size () > 1)
241 {
242 CompRect headOutputRect =
243 splashGetCurrentOutputRect ();
244
245 x = (headOutputRect.width () - backSize.width ()) / 2;
246 y = (headOutputRect.height () - backSize.height ()) / 2;
247
248 x += headOutputRect.x ();
249 y += headOutputRect.y ();
250 }
251 else
252 {
253 x = (screen->width () - backSize.width ()) / 2;
254 y = (screen->height () - backSize.height ()) / 2;
255 }
256
257 GLTexture::Matrix mat = tex->matrix ();
258
259 glTranslatef (x, y, 0);
260
261 float cx1, cx2, cy1, cy2;
262
263 glBegin (GL_QUADS);
264
265 for (x = 0; x < MESH_W - 1; x++)
266 {
267 for (y = 0; y < MESH_H - 1; y++)
268 {
269 cx1 = (x / (MESH_W - 1.0) ) * backSize.width ();
270 cx2 = ( (x + 1) / (MESH_W - 1.0) ) * backSize.width ();
271 cy1 = (y / (MESH_H - 1.0) ) * backSize.height ();
272 cy2 = ( (y + 1) / (MESH_H - 1.0) ) * backSize.height ();
273
274 glTexCoord2f (COMP_TEX_COORD_X (mat, cx1),
275 COMP_TEX_COORD_Y (mat, cy1) );
276 glVertex2f (mesh[x][y][0] *
277 backSize.width (),
278 mesh[x][y][1] * backSize.height ());
279 glTexCoord2f (COMP_TEX_COORD_X (mat, cx1),
280 COMP_TEX_COORD_Y (mat, cy2) );
281 glVertex2f (mesh[x][y + 1][0] *
282 backSize.width (),
283 mesh[x][y + 1][1] * backSize.height ());
284 glTexCoord2f (COMP_TEX_COORD_X (mat, cx2),
285 COMP_TEX_COORD_Y (mat, cy2) );
286 glVertex2f (mesh[x + 1][y + 1][0] *
287 backSize.width (),
288 mesh[x + 1][y + 1][1] * backSize.height ());
289 glTexCoord2f (COMP_TEX_COORD_X (mat, cx2),
290 COMP_TEX_COORD_Y (mat, cy1) );
291 glVertex2f (mesh[x + 1][y][0] *
292 backSize.width (),
293 mesh[x + 1][y][1] * backSize.height ());
294 }
295 }
296
297 glEnd ();
298
299 if (screen->outputDevs ().size () > 1)
300 {
301 CompRect headOutputRect =
302 splashGetCurrentOutputRect ();
303
304 x = (headOutputRect.width () - backSize.width ()) / 2;
305 y = (headOutputRect.height () - backSize.height ()) / 2;
306
307 x += headOutputRect.x ();
308 y += headOutputRect.y ();
309 }
310 else
311 {
312 x = (screen->width () - backSize.width ()) / 2;
313 y = (screen->height () - backSize.height ()) / 2;
314 }
315
316 glTranslatef (-x, -y, 0);
317
318 tex->disable ();
319
320 }
321 }
322
323 if (logo_img.size ())
324 {
325 foreach (GLTexture* tex, logo_img)
326 {
327 tex->enable (GLTexture::Good);
328 int x, y;
329
330 if (screen->outputDevs ().size () > 1)
331 {
332 CompRect headOutputRect =
333 splashGetCurrentOutputRect ();
334
335 x = (headOutputRect.width () - logoSize.width ()) / 2;
336 y = (headOutputRect.height () - logoSize.height ()) / 2;
337
338 x += headOutputRect.x ();
339 y += headOutputRect.y ();
340 }
341 else
342 {
343 x = (screen->width () - logoSize.width ()) / 2;
344 y = (screen->height () - logoSize.height ()) / 2;
345 }
346
347 GLTexture::Matrix mat = tex->matrix ();
348
349 glTranslatef (x, y, 0);
350
351 glBegin (GL_QUADS);
352 glTexCoord2f (COMP_TEX_COORD_X (mat, 0), COMP_TEX_COORD_Y (mat, 0) );
353 glVertex2f (0, 0);
354 glTexCoord2f (COMP_TEX_COORD_X (mat, 0),
355 COMP_TEX_COORD_Y (mat, logoSize.height ()) );
356 glVertex2f (0, logoSize.height ());
357 glTexCoord2f (COMP_TEX_COORD_X (mat, logoSize.width ()),
358 COMP_TEX_COORD_Y (mat, logoSize.height ()) );
359 glVertex2f (logoSize.width (), logoSize.height ());
360 glTexCoord2f (COMP_TEX_COORD_X (mat, logoSize.width ()),
361 COMP_TEX_COORD_Y (mat, 0) );
362 glVertex2f (logoSize.width (), 0);
363 glEnd ();
364
365 glTranslatef (-x, -y, 0);
366
367 tex->disable ();
368 }
369 }
370
371 glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
372
373 glDisable (GL_BLEND);
374 glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
375 glColor4usv (defaultColor);
376 glPopMatrix ();
377 return status;
378 }
379
380 bool
381 SplashWindow::glPaint (const GLWindowPaintAttrib &attrib,
382 const GLMatrix &transform,
383 const CompRegion ®ion,
384 unsigned int mask)
385 {
386 bool status;
387
388 SPLASH_SCREEN (screen);
389
390 if (ss->active)
391 {
392 GLWindowPaintAttrib pA = attrib;
393 pA.brightness = (attrib.brightness * ss->brightness);
394 pA.saturation = (attrib.saturation * ss->saturation);
395
396 status = gWindow->glPaint (pA, transform, region, mask);
397 }
398 else
399 {
400 status = gWindow->glPaint (attrib, transform, region, mask);
401 }
402
403 return status;
404 }
405
406
407 bool
408 SplashScreen::initiateSplash (CompAction *action,
409 CompAction::State state,
410 CompOption::Vector options)
411 {
412 initiate = true;
413
414 cScreen->preparePaintSetEnabled (this, true);
415 gScreen->glPaintOutputSetEnabled (this, true);
416 cScreen->donePaintSetEnabled (this, true);
417
418 foreach (CompWindow *w, screen->windows ())
419 {
420 SPLASH_WINDOW (w);
421
422 sw->gWindow->glPaintSetEnabled (sw, true);
423 }
424
425 return false;
426 }
427
428 /* replace with ctor, dtor, init etc */
429
430 SplashScreen::SplashScreen (CompScreen *screen) :
431 PluginClassHandler <SplashScreen, CompScreen> (screen),
432 SplashOptions (),
433 cScreen (CompositeScreen::get (screen)),
434 gScreen (GLScreen::get (screen)),
435 splashAtom (XInternAtom (screen->dpy (), "_COMPIZ_WM_SPLASH", 0)),
436 fade_in (0),
437 fade_out (0),
438 time (0),
439 backSize (0, 0),
440 logoSize (0, 0),
441 hasInit (false),
442 hasLogo (false),
443 hasBack (false),
444 mMove (0.0),
445 brightness (0),
446 saturation (0),
447 initiate (false),
448 active (false)
449 {
450
451 CompositeScreenInterface::setHandler (cScreen, false);
452 GLScreenInterface::setHandler (gScreen, false);
453
454 if (optionGetFirststart () )
455 {
456 Atom actual;
457 int result, format;
458 unsigned long n, left;
459 unsigned char *propData;
460
461 result = XGetWindowProperty (screen->dpy (), screen->root (),
462 splashAtom, 0L, 8192L, false,
463 XA_INTEGER, &actual, &format,
464 &n, &left, &propData);
465
466 if (result == Success && n && propData)
467 {
468 XFree (propData);
469 }
470 else
471 {
472 int value = 1;
473 XChangeProperty (screen->dpy (), screen->root (), splashAtom,
474 XA_INTEGER, 32, PropModeReplace,
475 (unsigned char *) &value, 1);
476 }
477
478 initiate = true; // should fix later
479
480 if (initiate)
481 {
482 cScreen->preparePaintSetEnabled (this, true);
483 gScreen->glPaintOutputSetEnabled (this, true);
484 cScreen->donePaintSetEnabled (this, true);
485 }
486 }
487
488 optionSetInitiateKeyInitiate (boost::bind (&SplashScreen::initiateSplash,
489 this, _1, _2, _3));
490
491 }
492
493 SplashWindow::SplashWindow (CompWindow *window) :
494 PluginClassHandler <SplashWindow, CompWindow> (window),
495 window (window),
496 gWindow (GLWindow::get (window))
497 {
498 GLWindowInterface::setHandler (gWindow, false);
499
500 SPLASH_SCREEN (screen);
501
502 if (ss->initiate)
503 {
504 gWindow->glPaintSetEnabled (this, true);
505 }
506 }
507
508 bool
509 SplashPluginVTable::init ()
510 {
511 if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION) ||
512 !CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI) ||
513 !CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))
514 return false;
515
516 return true;
517 }