X11WindowSystem : Fixing wrong composition.
[profile/ivi/layer-management.git] / LayerManagerPlugins / Renderers / Graphic / src / WindowSystems / X11WindowSystem.cpp
1 /***************************************************************************
2 *
3 * Copyright 2010,2011 BMW Car IT GmbH
4 *
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 *        http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 ****************************************************************************/
19
20 #include "WindowSystems/X11WindowSystem.h"
21 #include "config.h"
22 #include "Log.h"
23 #include "Layer.h"
24 #include <time.h>
25 #include <sys/time.h>
26 #include <X11/Xlib.h>
27 #include <X11/Xutil.h>
28 #include <X11/Xatom.h>
29 #include <X11/extensions/Xcomposite.h>
30 #include <X11/extensions/Xdamage.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35 #include <iomanip>
36
37 int     X11WindowSystem::composite_opcode;
38 int     X11WindowSystem::damage_opcode;
39 const char X11WindowSystem::CompositorWindowTitle[] = "LayerManager";
40 bool    X11WindowSystem::m_xerror = false;
41
42 X11WindowSystem::X11WindowSystem(const char* displayname, int width, int height, Scene* pScene,InputManager* pInputManager,GetVisualInfoFunction func)
43 : BaseWindowSystem(pScene, pInputManager)
44 , takeScreenshot(ScreenShotNone)
45 , screenShotFile()
46 , screenShotSurfaceID(0)
47 , screenShotLayerID()
48 , displayname(displayname)
49 , getVisualFunc(func)
50 , debugMode(false)
51 , resolutionWidth(width)
52 , resolutionHeight(height)
53 , composite_event(0)
54 , composite_error(0)
55 , composite_major(0)
56 , composite_minor(0)
57 , damage_event(0)
58 , damage_error(0)
59 , damage_major(0)
60 , damage_minor(0)
61 , m_running(false)
62 /*, m_initialized(false)*/
63 , m_success(false)
64 , m_systemState(IDLE_STATE)
65 , m_displayEnvironment(NULL)
66 , x11Display(0)
67 , renderThread(0)
68 , windowWidth(width)
69 , windowHeight(height)
70 , CompositorWindow(0)
71 , windowVis(0)
72 , run_lock()
73 , graphicSystem(0)
74 {
75     LOG_DEBUG("X11WindowSystem", "creating X11WindowSystem");
76
77     // init and take mutex, so windowsystem only does init phase until mutex is released again
78     pthread_mutex_init(&run_lock, NULL);
79     pthread_cond_init(&run_condition,NULL);
80     pthread_cond_init(&init_condition,NULL);
81     pthread_mutex_init(&init_lock, NULL);
82 }
83
84 X11WindowSystem::~X11WindowSystem()
85 {
86     if (windowVis)
87     {
88         delete windowVis;
89     }
90 }
91
92 XVisualInfo* X11WindowSystem::getDefaultVisual(Display *dpy)
93 {
94     XVisualInfo* windowVis = new XVisualInfo();
95     if (windowVis)
96     {
97         windowVis->depth = DefaultDepth(dpy, DefaultScreen(dpy));
98         if (!XMatchVisualInfo( dpy, 0, windowVis->depth, TrueColor, windowVis))
99         {
100             LOG_ERROR("X11WindowSystem", "Error: Required visual not found\n");
101             delete windowVis;
102             return NULL;
103         }
104     }
105     else
106     {
107         LOG_ERROR("X11WindowSystem", "Error: Unable to acquire visual\n");
108     }
109     return windowVis;
110 }
111
112 bool X11WindowSystem::OpenDisplayConnection()
113 {
114     m_displayEnvironment = getenv("DISPLAY");
115
116     if  (m_displayEnvironment == NULL )
117     {
118         m_displayEnvironment = ":0.0";
119         setenv("DISPLAY",m_displayEnvironment,1);
120     }
121
122     x11Display = XOpenDisplay(m_displayEnvironment);
123     if (!x11Display)
124     {
125         LOG_ERROR("X11WindowSystem", "Couldn't open default display!");
126         return false;
127     }
128     LOG_DEBUG("X11WindowSystem", "Display connection: " << x11Display);
129     return true;
130 }
131
132 bool X11WindowSystem::checkForCompositeExtension()
133 {
134     if (x11Display == NULL || !XQueryExtension (x11Display, COMPOSITE_NAME, &composite_opcode, &composite_event, &composite_error))
135     {
136         LOG_ERROR("X11WindowSystem", "No composite extension");
137         return false;
138     }
139     XCompositeQueryVersion (x11Display, &composite_major, &composite_minor);
140     LOG_DEBUG("X11WindowSystem", "Found composite extension: composite opcode: " << composite_opcode);
141     LOG_DEBUG("X11WindowSystem", "composite_major: " << composite_major);
142     LOG_DEBUG("X11WindowSystem", "composite_minor: " << composite_minor);
143     return true;
144 }
145
146 bool X11WindowSystem::checkForDamageExtension(){
147     if (x11Display == NULL || !XQueryExtension (x11Display, DAMAGE_NAME, &damage_opcode,
148                 &damage_event, &damage_error))
149     {
150         LOG_ERROR("X11WindowSystem", "No damage extension");
151         return false;
152     }
153     XDamageQueryVersion (x11Display, &damage_major, &damage_minor);
154     LOG_DEBUG("X11WindowSystem", "Found damage extension: damage opcode: " << damage_opcode);
155     LOG_DEBUG("X11WindowSystem", "damage_major: " << damage_major);
156     LOG_DEBUG("X11WindowSystem", "damage_minor: " << damage_minor);
157     return true;
158 }
159
160 void X11WindowSystem::printDebug(){
161     // print stuff about layerlist
162     std::stringstream debugmessage;
163     debugmessage << "Layer:  ID |   X  |   Y  |   W  |   H  | Al. \n";
164
165     LayerList list = m_pScene->getCurrentRenderOrder();
166
167     // loop the layers
168     LayerListConstIterator iter = list.begin();
169     LayerListConstIterator iterEnd = list.end();
170
171     for(; iter != iterEnd; ++iter)
172     {
173         Rectangle dest = (*iter)->getDestinationRegion();
174         debugmessage << "            " << std::setw(4) << (*iter)->getID() << " " << std::setw(3) << dest.x << " " << std::setw(3) << dest.y << " " << std::setw(3) << dest.width << " " << std::setw(3) << dest.height << " " << std::setw(3) << (*iter)->opacity << "\n";
175
176         debugmessage << "    Surface:  ID |Al.|  SVP: X |  Y |  W |  H     DVP:  X |  Y |  W |  H \n";
177
178         // loop the surfaces of within each layer
179         SurfaceList surfaceList = (*iter)->getAllSurfaces();
180         SurfaceListIterator surfaceIter = surfaceList.begin();
181         SurfaceListIterator surfaceIterEnd = surfaceList.end();
182
183         for(; surfaceIter != surfaceIterEnd ; ++surfaceIter)
184         {
185             Rectangle src = (*surfaceIter)->getSourceRegion();
186             Rectangle dest = (*surfaceIter)->getDestinationRegion();
187             debugmessage << "                        " << std::setw(4) << (*surfaceIter)->getID() << " " << std::setprecision(3) << (*surfaceIter)->opacity<< " " << std::setw(3) << src.x << " " << std::setw(3) << src.y << " " << std::setw(3) << src.width << " " << std::setw(3) << src.height << " " << std::setw(3) << dest.x << " " << std::setw(3) << dest.y << " " << std::setw(3) << dest.width << " " << std::setw(3) << dest.height  << "\n";
188         }
189     }
190     LOG_DEBUG("X11WindowSystem",debugmessage.str());
191 }
192
193 Window * getListOfAllTopLevelWindows (Display *disp, unsigned int *len)
194 {
195     LOG_DEBUG("X11WindowSystem", "Getting list of all windows");
196     Window *children;
197     Window    root_return, parent_return;
198     Window  root = XDefaultRootWindow(disp);
199     XQueryTree (disp, root, &root_return, &parent_return, &children, len);
200     return children;
201 }
202
203 bool X11WindowSystem::isWindowValid(Window w)
204 {
205     // skip our own two windows
206     return (w!=None && w != CompositorWindow);
207 }
208
209 Surface* X11WindowSystem::getSurfaceForWindow(Window w)
210 {
211     // go though all surfaces
212     const std::map<unsigned int,Surface*> surfaces = m_pScene->getAllSurfaces();
213     for(std::map<unsigned int, Surface*>::const_iterator currentS = surfaces.begin(); currentS != surfaces.end(); ++currentS)
214     {
215         Surface* currentSurface = (*currentS).second;
216         if (!currentSurface)
217         {
218             continue;
219         }
220         if (currentSurface->getNativeContent() == static_cast<int>(w))
221         {
222                 return currentSurface;
223         }
224     }
225     LOG_DEBUG("X11WindowSystem", "could not find surface for window " << w);
226     return NULL;
227 }
228
229 void X11WindowSystem::checkForNewSurfaceNativeContent()
230 {
231     m_pScene->lockScene();
232     LayerList layers = m_pScene->getCurrentRenderOrder();
233     for(LayerListConstIterator current = layers.begin(); current != layers.end(); current++)
234     {
235         SurfaceList surfaces = (*current)->getAllSurfaces();
236         for(SurfaceListConstIterator currentS = surfaces.begin(); currentS != surfaces.end(); currentS++)
237         {
238             if ((*currentS)->hasNativeContent())
239             {
240                 allocatePlatformSurface(*currentS);
241             }
242             else // While we are at it, also cleanup any stale native content
243             {
244                 deallocatePlatformSurface(*currentS);
245             }
246         }
247     }
248     m_pScene->unlockScene();
249 }
250
251 void X11WindowSystem::configureSurfaceWindow(Window window)
252 {
253     if (isWindowValid(window))
254     {
255         LOG_DEBUG("X11WindowSystem", "Updating window " << window);
256         UnMapWindow(window);
257         MapWindow(window);
258         XWindowAttributes att;
259         XGetWindowAttributes (x11Display, window, &att);
260         int winWidth = att.width;
261         int winHeight = att.height;
262
263         Surface* surface = getSurfaceForWindow(window);
264         if (!surface)
265         {
266              LOG_WARNING("X11WindowSystem", "Could not find surface for window " << window);
267             return;
268         }
269         if (!surface->platform)
270         {
271             LOG_WARNING("X11WindowSystem", "Platform surface not available for window " << window);
272             return;
273         }
274
275         LOG_DEBUG("X11WindowSystem", "Updating surface " << surface->getID());
276
277         surface->OriginalSourceHeight = winHeight;
278         surface->OriginalSourceWidth = winWidth;
279
280         LOG_DEBUG("X11WindowSystem", "Done Updating window " << window);
281     }
282 }
283
284 void X11WindowSystem::MapWindow(Window window)
285 {
286     LOG_DEBUG("X11WindowSystem","Map window begin");
287     if (isWindowValid(window))
288     {
289         XWindowAttributes att;
290         XGetWindowAttributes (x11Display, window, &att);
291 /*      LOG_DEBUG("X11WindowSystem", "XCompositeRedirectWindow()");
292         XCompositeRedirectWindow(x11Display, window, CompositeRedirectManual);
293         XSync(x11Display, 0);*/
294         if (att.map_state == IsViewable && att.override_redirect==0)
295         {
296             LOG_DEBUG("X11WindowSystem", "Mapping surface to window " << window);
297             Surface* surface = getSurfaceForWindow(window);
298             if (!surface)
299             {
300                 LOG_WARNING("X11WindowSystem", "Could not map surface to window " << window);
301                 return;
302             }
303             if (!surface->platform)
304             {
305                 LOG_WARNING("X11WindowSystem", "Platform surface not available for window " << window);
306                 return;
307             }
308
309             XPlatformSurface* x11surf = (XPlatformSurface*)surface->platform;
310             if (x11surf->isMapped)
311             {
312                 LOG_WARNING("X11WindowSystem", "Platform surface already mapped");
313                 return;
314             }
315             x11surf->isMapped = true;
316
317
318             LOG_DEBUG("X11WindowSystem", "getting pixmap for window");
319             LOG_DEBUG("X11WindowSystem", "window width: " << att.width);
320             LOG_DEBUG("X11WindowSystem", "window height: " << att.height);
321             LOG_DEBUG("X11WindowSystem", "map state: " << att.map_state);
322             LOG_DEBUG("X11WindowSystem", "window x: " << att.x);
323             LOG_DEBUG("X11WindowSystem", "window backing: " << att.backing_pixel);
324             LOG_DEBUG("X11WindowSystem", "window save under: " << att.save_under);
325             LOG_DEBUG("X11WindowSystem", "window orride: " << att.override_redirect);
326             LOG_DEBUG("X11WindowSystem", "parent/root: " << att.root);
327             LOG_DEBUG("X11WindowSystem", "root window: " << DefaultRootWindow(x11Display));
328
329             int winWidth = att.width;
330             int winHeight = att.height;
331
332             surface->OriginalSourceHeight = winHeight;
333             surface->OriginalSourceWidth = winWidth;
334             surface->renderPropertyChanged = true;
335
336             graphicSystem->getTextureBinder()->createClientBuffer(surface);
337             x11surf->enableRendering();
338             XSync(x11Display, 0);
339
340             LOG_DEBUG("X11WindowSystem", "Mapping Surface " << surface->getID() << " to window " << window);
341             LOG_DEBUG("X11WindowSystem", "Mapping successfull");
342         }
343     }
344     LOG_DEBUG("X11WindowSystem","Map window end");
345 }
346
347 void X11WindowSystem::UnMapWindow(Window window)
348 {
349     LOG_DEBUG("X11WindowSystem", "Unmap begin");
350     if (isWindowValid(window))
351     {
352         LOG_DEBUG("X11WindowSystem", "Unmapping surface from window " << window);
353         Surface* surface = getSurfaceForWindow(window);        
354         if (!surface)
355         {
356             LOG_WARNING("X11WindowSystem", "Could not unmap window " << window);
357             return;
358         }
359         if (!surface->platform)
360         {
361             LOG_WARNING("X11WindowSystem", "Platform surface not available for window " << window);
362             return;
363         }
364         XPlatformSurface* x11surf = (XPlatformSurface*)surface->platform;
365         x11surf->disableRendering();
366         LOG_DEBUG("X11WindowSystem", "Unmapping surface " << surface->getID());
367         if (!x11surf->isMapped)
368         {
369             LOG_WARNING("X11WindowSystem", "Platform surface already unmapped");
370             return;
371         }
372         x11surf->isMapped = false;
373
374
375         LOG_DEBUG("X11WindowSystem", "Destroying ClientBuffer");
376         graphicSystem->getTextureBinder()->destroyClientBuffer(surface);
377         XSync(x11Display, 0);
378
379         LOG_DEBUG("X11WindowSystem", "Removing X Pixmap");
380         if (x11surf->pixmap)
381         {
382             int result = XFreePixmap(x11Display, x11surf->pixmap);
383             LOG_DEBUG("X11WindowSystem", "XFreePixmap() returned " << result);
384         }
385
386         surface->renderPropertyChanged = true;
387     }
388     LOG_DEBUG("X11WindowSystem", "Unmap finished");
389 }
390
391 void X11WindowSystem::NewWindow(Surface* surface, Window window)
392 {
393     if (isWindowValid(window))
394     {
395         LOG_DEBUG("X11WindowSystem", "Creating Surface for new window " << window);
396         // get the windows attributes
397         XWindowAttributes att;
398         int status = XGetWindowAttributes (x11Display, window, &att);
399         LOG_DEBUG("X11WindowSystem", "Got window attrbutes");
400         char* name;
401         status = XFetchName(x11Display, window, &name);
402         LOG_DEBUG("X11WindowSystem", "Got window name");
403         if (status >= Success && name)
404         {
405             LOG_DEBUG("X11WindowSystem", "Found window: " << window << " " << name);
406             char GuiTitle[]  = "Layermanager Remote GUI\0";
407             if (strcmp(name,GuiTitle)==0)
408             {
409                 LOG_DEBUG("X11WindowSystem", "Found gui window: repositioning it");
410                 XCompositeUnredirectWindow(x11Display,window,CompositeRedirectManual);
411                 XMoveWindow(x11Display, window, 50, 500);
412                 XMapRaised(x11Display, window);
413             }
414         }
415         else
416         {
417             LOG_DEBUG("X11WindowSystem", "Error fetching window name");
418         }
419
420         if (att.c_class == InputOutput)
421         {
422             LOG_DEBUG("X11WindowSystem","Creating New Damage for window - " << window);
423             XDamageCreate(x11Display,window,XDamageReportNonEmpty);
424         }
425
426         XFree(name);
427         XLowerWindow(x11Display,window);
428
429         surface->setNativeContent(window);
430         XPlatformSurface * platformSurface = (XPlatformSurface*)graphicSystem->getTextureBinder()->createPlatformSurface(surface);
431         platformSurface->isMapped = false;
432
433         LOG_DEBUG("X11WindowSystem", "Created native Surface for X11 Window id " << window);
434
435         surface->platform = platformSurface;
436
437         int winWidth = att.width;
438         int winHeight = att.height;
439
440         surface->OriginalSourceHeight = winHeight;
441         surface->OriginalSourceWidth = winWidth;
442
443         LOG_DEBUG("X11WindowSystem", "Original width " << surface->OriginalSourceWidth);
444         LOG_DEBUG("X11WindowSystem", "Original heigth " << surface->OriginalSourceHeight);
445     }
446     else
447     {
448         LOG_DEBUG("X11WindowSystem", "skipping window");
449     }
450     LOG_DEBUG("X11WindowSystem", "created the new surface");
451 }
452
453 void X11WindowSystem::DestroyWindow(Window window)
454 {
455     if (isWindowValid(window))
456     {
457         LOG_DEBUG("X11WindowSystem", "Destroying Surface for window " << window);
458         Surface* surface = getSurfaceForWindow(window);        
459         if (!surface)
460         {
461             LOG_WARNING("X11WindowSystem", "Could not find surface for window " << window);
462             return;
463         }
464         graphicSystem->getTextureBinder()->destroyClientBuffer(surface);
465         LOG_DEBUG("X11WindowSystem", "Unmapping window " << window);
466         UnMapWindow(window);
467         LOG_DEBUG("X11WindowSystem", "Remove Native Content from Surface " << surface->getID());
468         surface->removeNativeContent();
469         /* To force a recomposition of all surface which are behind of that surface inside the Layer RenderOrder */
470         surface->renderPropertyChanged = true;
471         delete surface->platform;
472         surface->platform = NULL;
473     }
474 }
475
476 bool X11WindowSystem::CreatePixmapsForAllWindows()
477 {
478     bool result = true;
479     LOG_DEBUG("X11WindowSystem", "redirecting all windows");
480     Window root = RootWindow(x11Display, DefaultScreen(x11Display));
481     XCompositeRedirectSubwindows(x11Display,root,CompositeRedirectManual);
482     XSync(x11Display,0);
483     return result;
484 }
485
486 bool X11WindowSystem::CreateCompositorWindow()
487 {
488     LOG_DEBUG("X11WindowSystem", "Get root window");
489     bool result = true;
490     CompositorWindow = None;
491     Window root = RootWindow(x11Display, DefaultScreen(x11Display));
492
493     LOG_DEBUG("X11WindowSystem", "Creating Compositor Window");
494
495     XSetWindowAttributes attr;
496     // draw a black background the full size of the resolution
497     attr.override_redirect = True;
498     attr.event_mask =     ExposureMask
499                         | StructureNotifyMask
500                         | ButtonPressMask
501                         | ButtonReleaseMask
502                         | Button1MotionMask
503                         | KeyPressMask
504                         | KeyReleaseMask;
505     attr.background_pixel = 0;
506     attr.border_pixel = 0;
507     windowVis = getVisualFunc(x11Display);
508     if (!windowVis)
509     {
510         return false;
511     }
512     attr.colormap = XCreateColormap(x11Display, root, windowVis->visual, AllocNone);
513     attr.override_redirect = True;
514
515     Window compManager = XGetSelectionOwner(x11Display,XInternAtom(x11Display,"_NET_WM_CM_S0",0));
516     if ( None != compManager )
517     {
518         LOG_ERROR("X11WindowSystem", "Could not create compositor window, annother compisite manager is already running");
519         return false;
520     }
521
522     CompositorWindow = XCreateWindow(x11Display, root, 0, 0, windowWidth, windowHeight,
523             0, windowVis->depth, InputOutput,
524             windowVis->visual, CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &attr);
525
526     if (None == CompositorWindow)
527     {
528         LOG_ERROR("X11WindowSystem", "Could not create window");
529         return false;
530     }
531
532     LOG_DEBUG("X11WindowSystem", "Created the Compositor Window");
533     XSelectInput (x11Display, root,
534             SubstructureNotifyMask|
535             ExposureMask|
536             StructureNotifyMask|
537             PropertyChangeMask);
538
539     LOG_DEBUG("X11WindowSystem", "Created the window");
540     XSizeHints sizehints;
541     sizehints.width  = windowWidth;
542     sizehints.height = windowHeight;
543     sizehints.flags = USSize;
544     XSetNormalHints(x11Display, CompositorWindow, &sizehints);
545     XSetStandardProperties(x11Display, CompositorWindow, CompositorWindowTitle, CompositorWindowTitle,
546             None, (char **)NULL, 0, &sizehints);
547     XMapRaised(x11Display, CompositorWindow);
548     XFlush(x11Display);
549     return result;
550 }
551
552 static float timeSinceLastCalc = 0.0;
553 static float FPS = 0.0;
554 static struct timeval tv;
555 static struct timeval tv0;
556 static int Frame = 0;
557
558
559 void X11WindowSystem::calculateSurfaceFps(Surface *currentSurface, float time ) 
560 {
561         char floatStringBuffer[256];
562         float surfaceUpdateFps = ((float)(currentSurface->updateCounter)) / time ;
563         float surfaceDrawFps = ((float)(currentSurface->drawCounter)) / time ;
564         sprintf(floatStringBuffer, "0x%08x update fps: %3.2f", currentSurface->getID(),surfaceUpdateFps);
565         currentSurface->updateCounter = 0;      
566         LOG_INFO("X11WindowSystem", "Surface " << floatStringBuffer);        
567         sprintf(floatStringBuffer, "0x%08x draw fps: %3.2f", currentSurface->getID(),surfaceDrawFps);
568         currentSurface->drawCounter = 0;        
569         LOG_INFO("X11WindowSystem", "Surface " << floatStringBuffer);
570 }
571
572 void X11WindowSystem::calculateFps()
573 {
574     // we have rendered a frame
575     Frame ++;
576     std::list<Layer*> layers = m_pScene->getCurrentRenderOrder();
577     // every 3 seconds, calculate & print fps
578     gettimeofday(&tv, NULL);
579     timeSinceLastCalc = (float)(tv.tv_sec-tv0.tv_sec) + 0.000001*((float)(tv.tv_usec-tv0.tv_usec));
580
581     if (timeSinceLastCalc > 10.0f)
582     {
583         FPS = ((float)(Frame)) / timeSinceLastCalc;
584         char floatStringBuffer[256];
585         sprintf(floatStringBuffer, "Overall fps: %f", FPS);
586         for(std::list<Layer*>::const_iterator current = layers.begin(); current != layers.end(); current++)
587         {
588             SurfaceList surfaceList = (*current)->getAllSurfaces();
589             SurfaceListIterator surfaceIter = surfaceList.begin();
590             SurfaceListIterator surfaceIterEnd = surfaceList.end();
591             for(; surfaceIter != surfaceIterEnd ; ++surfaceIter)
592             {
593                 calculateSurfaceFps((*surfaceIter),timeSinceLastCalc);
594             }
595         }
596         LOG_INFO("X11WindowSystem", floatStringBuffer);
597         tv0 = tv;
598         Frame = 0;
599     }
600 }
601
602 void X11WindowSystem::RedrawAllLayers(bool clear, bool swap)
603 {
604     LayerList layers = m_pScene->getCurrentRenderOrder();
605     LayerList swLayers;
606
607     // Refresh HW Layers, find SW Layers
608     for(LayerListConstIterator current = layers.begin(); current != layers.end(); current++)
609     {
610         if ((*current)->getLayerType() == Hardware)
611         {
612             // Redraw HW layers independently of other layers
613             if (m_forceComposition || graphicSystem->needsRedraw(*current))
614             {
615                 renderHWLayer(*current);
616             }
617         }
618         else
619         {
620             swLayers.push_back(*current);
621         }
622     }
623
624     if (m_forceComposition || graphicSystem->needsRedraw(swLayers))
625     {
626         graphicSystem->renderSWLayers(swLayers, clear);
627
628         if (swap)
629         {
630             graphicSystem->swapBuffers();
631         }
632
633         if (debugMode)
634         {
635             printDebug();
636         }
637
638         calculateFps();
639     }
640 }
641
642 void X11WindowSystem::renderHWLayer(Layer *layer)
643 {
644     (void)layer;
645 }
646
647 void X11WindowSystem::Redraw()
648 {
649     // draw all the layers
650     /*LOG_INFO("X11WindowSystem","Locking List");*/
651     m_pScene->lockScene();
652
653     RedrawAllLayers(true, true);  // Clear and Swap
654     ClearDamage();
655
656     m_pScene->unlockScene();
657
658     m_forceComposition = false;
659 }
660
661 void X11WindowSystem::Screenshot()
662 {
663     /*LOG_INFO("X11WindowSystem","Locking List");*/
664     m_pScene->lockScene();
665     if (takeScreenshot == ScreenshotOfDisplay)
666     {
667         LOG_DEBUG("X11WindowSystem", "Taking screenshot");
668         RedrawAllLayers(true, false);  // Do clear, Don't swap
669     }
670     else if(takeScreenshot == ScreenshotOfLayer)
671     {
672         LOG_DEBUG("X11WindowSystem", "Taking screenshot of layer");
673         Layer* layer = m_pScene->getLayer(screenShotLayerID);
674
675         if (layer != NULL)
676         {
677             graphicSystem->renderSWLayer(layer, true); // Do clear
678         }
679     }
680     else if(takeScreenshot == ScreenshotOfSurface)
681     {
682         LOG_DEBUG("X11WindowSystem", "Taking screenshot of surface");
683         Layer* layer = m_pScene->getLayer(screenShotLayerID);
684         Surface* surface = m_pScene->getSurface(screenShotSurfaceID);
685
686         graphicSystem->clearBackground();
687         if (layer != NULL && surface != NULL)
688         {
689             graphicSystem->beginLayer(layer);
690             graphicSystem->renderSurface(surface);
691             graphicSystem->endLayer();
692         }
693     }
694
695     graphicSystem->saveScreenShotOfFramebuffer(screenShotFile);
696     takeScreenshot = ScreenShotNone;
697     LOG_DEBUG("X11WindowSystem", "Done taking screenshot");
698     m_pScene->unlockScene();
699     /*LOG_INFO("X11WindowSystem","UnLocking List");*/
700 }
701
702 int
703 X11WindowSystem::error (Display *dpy, XErrorEvent *ev)
704 {
705     const char* name = NULL;
706     static char buffer[256];
707
708     if (ev->request_code == composite_opcode && ev->minor_code == X_CompositeRedirectSubwindows)
709     {
710         LOG_ERROR("X11WindowSystem", "Maybe another composite manager is already running");
711     }
712
713     if (!name)
714     {
715         buffer[0] = '\0';
716         XGetErrorText (dpy, ev->error_code, buffer, sizeof (buffer));
717         name = buffer;
718     }
719     name = (strlen (name) > 0) ? name : "unknown";
720     LOG_ERROR("X11WindowSystem", "X Error: " << (int)ev->error_code << " " << name << " request : " << (int)ev->request_code << " minor: " <<  (int)ev->minor_code << " serial: " << (int)ev->serial);
721     m_xerror = true;
722     return 0;
723 }
724
725 bool X11WindowSystem::initXServer()
726 {
727     LOG_DEBUG("X11WindowSystem", "Initialising XServer connection");
728     bool result = true;
729
730     //setDisplayMode();
731     if (!CreateCompositorWindow())
732     {
733         LOG_ERROR("X11WindowSystem", "Compositor Window creation failed " );
734         return false;
735     }
736
737     LOG_DEBUG("X11WindowSystem", "Compositor Window ID: " << CompositorWindow);
738
739     if ( CreatePixmapsForAllWindows() )
740     {
741             //unredirect our window
742 #ifdef FULLSCREEN
743         XCompositeUnredirectWindow(x11Display, background, CompositeRedirectManual);
744 #endif
745         XCompositeUnredirectWindow(x11Display, CompositorWindow, CompositeRedirectManual);
746         LOG_DEBUG("X11WindowSystem", "Initialised XServer connection complete");
747     } else {
748         LOG_ERROR("X11WindowSystem", "Initialised XServer connection failed");
749         result = false;
750     }
751
752     return result;
753 }
754
755 /**
756  * Thread in charge of the CompositorWindow eventloop
757  * Friend function of class X11WindowSystem
758  */
759 void * X11eventLoopCallback(void *ptr)
760 {
761     X11WindowSystem *windowsys = static_cast<X11WindowSystem*>( (X11WindowSystem*) ptr);
762     return windowsys->EventLoop();
763 }
764
765 void* X11WindowSystem::EventLoop()
766 {
767     // INITALIZATION
768     LOG_INFO("X11WindowSystem", "XServer initialisation");
769     pthread_mutex_lock(&this->init_lock);
770     pthread_mutex_lock(&this->run_lock);
771     bool status = true;
772     bool checkRedraw = false;
773
774     XSetErrorHandler(error);
775     // init own stuff
776     LOG_DEBUG("X11WindowSystem", "open display connection");
777     status &= this->OpenDisplayConnection();
778     if ( status == false ) goto init_complete;
779     LOG_DEBUG("X11WindowSystem", "check for composite extension");
780     status &= this->checkForCompositeExtension();
781     if ( status == false ) goto init_complete;
782     LOG_DEBUG("X11WindowSystem", "check for damage extension");
783     status &= this->checkForDamageExtension();
784     if ( status == false ) goto init_complete;
785     LOG_DEBUG("X11WindowSystem", "init xserver");
786     status &= this->initXServer();
787     if ( status == false ) goto init_complete;
788     LOG_INFO("X11WindowSystem", "XServer initialisation completed");
789     LOG_DEBUG("X11WindowSystem", "Graphicsystem initialisation");
790     status &= this->graphicSystem->init(this->x11Display,this->CompositorWindow);
791     LOG_DEBUG("X11WindowSystem", "Graphicsystem initialisation complete");
792 init_complete:
793     this->m_success = status;
794     pthread_cond_signal(&this->init_condition);
795     pthread_mutex_unlock(&this->init_lock);
796     // Done with init, wait for lock to actually run (ie start/stop method called)
797     LOG_DEBUG("X11WindowSystem", "Waiting for startup");
798     pthread_cond_wait(&this->run_condition,&this->run_lock);
799     pthread_mutex_unlock(&this->run_lock);
800     LOG_DEBUG("X11WindowSystem", "Starting Event loop");
801     Layer* defaultLayer = 0;
802
803     // run the main event loop while rendering
804     gettimeofday(&tv0, NULL);
805     if (this->debugMode)
806     {
807         defaultLayer = this->m_pScene->createLayer(0);
808         defaultLayer->setOpacity(1.0);
809         defaultLayer->setDestinationRegion(Rectangle(0,0,this->resolutionWidth,this->resolutionHeight));
810         defaultLayer->setSourceRegion(Rectangle(0,0,this->resolutionWidth,this->resolutionHeight));
811         this->m_pScene->getCurrentRenderOrder().push_back(defaultLayer);
812     }
813     LOG_INFO("X11WindowSystem", "Enter render loop");
814
815     // clear screen to avoid garbage on startup
816     this->graphicSystem->clearBackground();
817     this->graphicSystem->swapBuffers();
818     XFlush(this->x11Display);
819
820     while (this->m_running)
821     {
822 #ifndef WITH_XTHREADS
823         if ( XPending(this->x11Display) > 0) {
824 #endif //WITH_XTHREADS
825             XEvent event;
826             // blocking wait for event
827             XNextEvent(this->x11Display, &event);
828             this->m_pScene->lockScene();
829             switch (event.type)
830             {
831             case CreateNotify:
832             {
833                 if (this->debugMode)
834                 {
835                     LOG_DEBUG("X11WindowSystem", "CreateNotify Event");
836                     Surface* s = this->m_pScene->createSurface(0);
837                     s->setOpacity(1.0);
838                     this->NewWindow(s, event.xcreatewindow.window);
839                     defaultLayer->addSurface(s);
840                 }
841                 break;
842             }
843             case ConfigureNotify:
844                 LOG_DEBUG("X11WindowSystem", "Configure notify Event");
845                 this->configureSurfaceWindow( event.xconfigure.window);
846                 checkRedraw = true;
847                 break;
848
849             case DestroyNotify:
850                 LOG_DEBUG("X11WindowSystem", "Destroy  Event");
851                 this->DestroyWindow(event.xdestroywindow.window);
852                 checkRedraw = true;
853                 break;
854             case Expose:
855                 LOG_DEBUG("X11WindowSystem", "Expose Event");
856                 checkRedraw = true;
857                 break;
858             case MapNotify:
859                 LOG_DEBUG("X11WindowSystem", "Map Event");
860                 this->MapWindow(event.xmap.window);
861                 checkRedraw = true;
862                 break;
863             case UnmapNotify:
864                 LOG_DEBUG("X11WindowSystem", "Unmap Event");
865                 this->UnMapWindow(event.xunmap.window);
866                 checkRedraw = true;
867                 break;
868             case ReparentNotify:
869                 LOG_DEBUG("X11WindowSystem", "Reparent Event");
870                 //           if (event.xreparent.parent == root)
871                 //               renderer->NewWindow(event.xreparent.window);
872                 //           else
873                 //               renderer->DestroyWindow(event.xreparent.window);
874                 break;
875
876             // Keyboard
877             case KeyPress:
878                 ManageXInputEvent(INPUT_DEVICE_KEYBOARD, INPUT_STATE_PRESSED, &event);
879                 break;
880             case KeyRelease:
881                  ManageXInputEvent(INPUT_DEVICE_KEYBOARD, INPUT_STATE_RELEASED, &event);
882                 break;
883
884             // Pointer
885             case ButtonPress:
886                 ManageXInputEvent(INPUT_DEVICE_POINTER, INPUT_STATE_PRESSED, &event);
887                 break;
888             case ButtonRelease:
889                 ManageXInputEvent(INPUT_DEVICE_POINTER, INPUT_STATE_RELEASED, &event);
890                 break;
891             case MotionNotify:
892                 ManageXInputEvent(INPUT_DEVICE_POINTER, INPUT_STATE_MOTION, &event);
893                 break;
894
895             // Touch
896             // TODO. See @ref<X11WindowSystem-MultiTouch> at the end of this file
897
898
899             default:
900                 if (event.type == this->damage_event + XDamageNotify)
901                 {
902                     XDamageSubtract(this->x11Display, ((XDamageNotifyEvent*)(&event))->damage, None, None);
903                     Surface* currentSurface = this->getSurfaceForWindow(((XDamageNotifyEvent*)(&event))->drawable);
904                     if (currentSurface==NULL)
905                     {
906                         LOG_WARNING("X11WindowSystem", "Surface empty during damage notification");
907                         break;
908                     } else {
909                         if (currentSurface->platform != NULL) 
910                         {
911                             /* Enable Rendering for Surface, after damage Notification was send successfully */
912                             /* This will ensure, that the content is not dirty */
913                             ((XPlatformSurface *)(currentSurface->platform))->enableRendering();
914                         }
915                     }
916                     currentSurface->damaged = true;
917                     currentSurface->updateCounter++;
918                     checkRedraw = true;
919                 }
920                 break;
921             }
922             this->m_pScene->unlockScene();
923
924 #ifndef WITH_XTHREADS
925         }
926 #endif //WITH_XTHREADS
927         if (this->m_systemState == REDRAW_STATE)
928         {
929             LOG_DEBUG("X11WindowSystem", "Enter Redraw State");
930             this->m_systemState = IDLE_STATE;
931
932             // check if we are supposed to take screenshot
933             if (this->takeScreenshot != ScreenShotNone)
934             {
935                 this->Screenshot();
936             }
937             else
938             {
939                 this->checkForNewSurfaceNativeContent();
940                 checkRedraw = true;
941             }
942
943         }
944         else if (this->m_systemState == WAKEUP_STATE)
945         {
946             LOG_DEBUG("X11WindowSystem", "Enter Wake Up State");
947             checkRedraw = false;
948             graphicSystem->releaseGraphicContext();
949             this->m_systemState = IDLE_STATE;
950             while (this->m_systemState != WAKEUP_STATE);
951             graphicSystem->activateGraphicContext();
952             this->m_systemState = IDLE_STATE;
953         }
954
955         if (checkRedraw)
956         {
957             this->Redraw();
958             checkRedraw = false;
959         }
960 #ifndef WITH_XTHREADS
961         else {
962             /* put thread in sleep mode for 500 useconds due to safe cpu performance */
963
964             usleep(500);
965         }
966 #endif
967     }
968     this->cleanup();
969     LOG_DEBUG("X11WindowSystem", "Renderer thread finished");
970     return NULL;
971 }
972
973
974 void X11WindowSystem::ManageXInputEvent(InputDevice type, InputEventState state, XEvent *pevent)
975  {
976     Surface * surf;
977
978     switch (type)
979     {
980         case INPUT_DEVICE_KEYBOARD:
981         {
982             surf = m_pInputManager->reportKeyboardEvent(state, ((XKeyEvent *) pevent)->keycode);
983             if (surf != NULL)
984             {
985                 pevent->xany.window = surf->getNativeContent();
986                 XSendEvent(x11Display, pevent->xany.window, false, 0, pevent);
987             }
988         }
989         break;
990
991         case INPUT_DEVICE_POINTER:
992         {
993             Point p = {state, ((XButtonEvent*)pevent)->x, ((XButtonEvent*)pevent)->y};
994             surf = m_pInputManager->reportPointerEvent(p);
995             if (surf != NULL)
996             {
997                 ((XButtonEvent*)pevent)->x = p.x;
998                 ((XButtonEvent*)pevent)->y = p.y;
999                 pevent->xany.window = surf->getNativeContent();
1000                 XSendEvent(x11Display, pevent->xany.window, false, 0, pevent);
1001             }
1002         }
1003         break;
1004
1005         case INPUT_DEVICE_TOUCH:
1006             /* TODO */
1007             break;
1008
1009
1010         default:
1011         case INPUT_DEVICE_ALL:
1012             break;
1013     }
1014 }
1015
1016
1017 #ifdef WITH_XTHREADS
1018 static Display* displaySignal = NULL;
1019 #endif //WITH_XTHREADS
1020 void X11WindowSystem::wakeUpRendererThread() 
1021 {
1022 #ifdef WITH_XTHREADS
1023     // send dummy expose event, to wake up blocking x11 event loop (XNextEvent)
1024     LOG_DEBUG("X11WindowSystem", "Sending dummy event to wake up renderer thread");
1025     if (NULL == displaySignal )
1026     {
1027         displaySignal = XOpenDisplay(m_displayEnvironment);
1028     }
1029     XExposeEvent ev = { Expose, 0, 1, displaySignal, CompositorWindow, 0, 0, 100, 100, 0 };
1030     XLockDisplay(displaySignal);
1031     XSendEvent(displaySignal, CompositorWindow, False, ExposureMask, (XEvent *) &ev);
1032     XUnlockDisplay(displaySignal);
1033     XFlush(displaySignal);
1034     LOG_DEBUG("X11WindowSystem", "Event successfully sent to renderer");
1035 #endif //WITH_XTHREADS
1036 }
1037
1038 void X11WindowSystem::signalRedrawEvent()
1039 {
1040     // set flag that redraw is needed
1041     this->m_systemState = REDRAW_STATE;
1042     this->wakeUpRendererThread();
1043 }
1044
1045 void X11WindowSystem::cleanup(){
1046     LOG_DEBUG("X11WindowSystem", "Cleanup");
1047     if (None != CompositorWindow)
1048     {
1049         Window root = RootWindow(x11Display, DefaultScreen(x11Display));
1050         XCompositeUnredirectSubwindows(x11Display,root,CompositeRedirectManual);
1051         XDestroyWindow(x11Display,CompositorWindow);
1052     }
1053
1054     if (windowVis)
1055     {
1056         delete windowVis;
1057     }
1058
1059 #ifdef WITH_XTHREADS
1060     if ( NULL  != displaySignal )
1061     {
1062         XCloseDisplay(displaySignal);
1063     }
1064 #endif //WITH_XTHREADS
1065     XCloseDisplay(x11Display);
1066     m_running = false;
1067 }
1068
1069 bool X11WindowSystem::init(BaseGraphicSystem<Display*,Window>* base)
1070 {
1071 #ifdef WITH_XTHREADS
1072     XInitThreads();
1073 #endif //WITH_XTHREADS
1074     X11WindowSystem *renderer = this;
1075     graphicSystem = base;
1076     LOG_INFO("X11WindowSystem","Initialization");    
1077     pthread_mutex_lock(&init_lock);
1078     int status = pthread_create( &renderThread, NULL, X11eventLoopCallback, (void*) renderer);
1079     if (0 != status )
1080     {
1081         pthread_mutex_unlock(&init_lock);
1082         return false;
1083     }
1084     pthread_cond_wait(&init_condition,&init_lock);
1085 /*  while (!m_initialized)
1086     {
1087         usleep(1000); // TODO
1088         LOG_DEBUG("X11WindowSystem","Waiting start complete " << m_initialized);
1089     } 
1090 */
1091     pthread_mutex_unlock(&init_lock);
1092     LOG_INFO("X11WindowSystem","Initialization complete success :" << m_success);
1093     return m_success;
1094 }
1095
1096 bool X11WindowSystem::start()
1097 {
1098     bool result = true;
1099     pthread_mutex_lock(&this->run_lock);
1100     LOG_DEBUG("X11WindowSystem", "Startup");
1101     // let thread actually run
1102     if ( m_xerror == false )
1103     {
1104         this->m_running = true;
1105         pthread_cond_signal(&this->run_condition);
1106         pthread_mutex_unlock(&this->run_lock);
1107     } else {
1108         this->m_running = false;
1109         pthread_cond_signal(&this->run_condition);
1110         pthread_mutex_unlock(&this->run_lock);
1111         result = false;
1112     }
1113     return result;
1114 }
1115
1116 void X11WindowSystem::stop()
1117 {
1118     LOG_INFO("X11WindowSystem","Stopping..");
1119     pthread_mutex_lock(&this->run_lock);
1120     this->m_running = false;
1121     // needed if start was never called, we wake up thread, so it can immediatly finish
1122     this->signalRedrawEvent();
1123     pthread_cond_signal(&this->run_condition);
1124     pthread_mutex_unlock(&this->run_lock);
1125     pthread_join(renderThread,NULL);
1126 }
1127
1128 void X11WindowSystem::allocatePlatformSurface(Surface* surface)
1129 {
1130     LOG_DEBUG("X11WindowSystem","allocatePlatformSurface begin");
1131     XPlatformSurface* nativeSurface = (XPlatformSurface*)surface->platform;
1132     if (!nativeSurface)
1133     {
1134         LOG_DEBUG("X11WindowSystem","creating native surface for new window");
1135         // this surface does not have a native platform surface attached yet!
1136         NewWindow(surface, surface->getNativeContent());
1137         MapWindow(surface->getNativeContent());
1138     }
1139     LOG_DEBUG("X11WindowSystem","allocatePlatformSurface end");
1140 }
1141
1142 void X11WindowSystem::deallocatePlatformSurface(Surface* surface)
1143 {
1144     LOG_DEBUG("X11WindowSystem","deallocatePlatformSurface begin");
1145     XPlatformSurface* nativeSurface = (XPlatformSurface*)surface->platform;
1146     if (nativeSurface)
1147     {
1148         LOG_DEBUG("X11WindowSystem","destroyingnative surface");
1149         graphicSystem->getTextureBinder()->destroyClientBuffer(surface);
1150
1151         if (nativeSurface->pixmap)
1152         {
1153             XFreePixmap(x11Display, nativeSurface->pixmap);
1154         }
1155
1156         surface->renderPropertyChanged = true;
1157         delete surface->platform;
1158         surface->platform = NULL;
1159     }
1160     LOG_DEBUG("X11WindowSystem","deallocatePlatformSurface end");
1161 }
1162
1163 void X11WindowSystem::doScreenShot(std::string fileName)
1164 {
1165     takeScreenshot = ScreenshotOfDisplay;
1166     screenShotFile = fileName;
1167 }
1168
1169 void X11WindowSystem::doScreenShotOfLayer(std::string fileName, const uint id)
1170 {
1171     takeScreenshot = ScreenshotOfLayer;
1172     screenShotFile = fileName;
1173     screenShotLayerID = id;
1174 }
1175
1176 void X11WindowSystem::doScreenShotOfSurface(std::string fileName, const uint id, const uint layer_id)
1177 {
1178     takeScreenshot = ScreenshotOfSurface;
1179     screenShotFile = fileName;
1180     screenShotSurfaceID = id;
1181     screenShotLayerID = layer_id;
1182 }
1183
1184
1185
1186 /**
1187  * @subsection <X11WindowSystem-MultiTouch> (Multi Touch)
1188  *
1189  *   X11 multi touch is not yet supported by Layer Manager.
1190  *
1191  *   TODO to add support:
1192  *     - Move all event management to xi2
1193  *     - For multi touch, make sure XInput protocol is > 2.2
1194  *         -> Via cmake ==> ?
1195  *         -> At runtime ==> http://who-t.blogspot.fr/2011/12/multitouch-in-x-getting-events.html
1196  *     - Register for XIDirectTouch. (No plan (yet?) to support XIDependentTouch)
1197  *     - Call m_pInputManager->reportTouchEvent() from ManageXInputEvent() to translate screen wide touch coordinates into surface wide coordinates
1198  *     - Forward the event to the native handle of the surface returned by m_pInputManager->reportTouchEvent()
1199  *
1200  *   Further reading:
1201  *     + XInput 2.x protocol : ftp://www.x.org/pub/xorg/current/doc/inputproto/XI2proto.txt
1202  *     + LWN article : http://lwn.net/Articles/475886/
1203  *
1204  */
1205