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