8cee5df121c3bfa2a745d7509d97d32ce0babe8a
[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_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 ((*current)->damaged)
623             {
624                 renderHWLayer(*current);
625                 (*current)->damaged = false;
626             }
627         }
628         else if (m_damaged)
629         {
630             graphicSystem->beginLayer(*current);
631             graphicSystem->renderSWLayer();
632             graphicSystem->endLayer();
633         }
634     }
635     if (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_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_damaged = false;
672     }
673 }
674
675 void X11WindowSystem::Screenshot()
676 {
677     /*LOG_INFO("X11WindowSystem","Locking List");*/
678     m_pScene->lockScene();
679     graphicSystem->activateGraphicContext();
680     graphicSystem->clearBackground();
681     if (takeScreenshot==ScreenshotOfDisplay)
682     {
683         LOG_DEBUG("X11WindowSystem", "Taking screenshot");
684         std::list<Layer*> layers = m_pScene->getCurrentRenderOrder();
685
686         for(std::list<Layer*>::const_iterator current = layers.begin(); current != layers.end(); current++)
687         {
688             if ((*current)->getLayerType() != Hardware)
689             {
690                 graphicSystem->beginLayer(*current);
691                 graphicSystem->renderSWLayer();
692                 graphicSystem->endLayer();
693             }
694         }
695     }
696     else if(takeScreenshot==ScreenshotOfLayer)
697     {
698         LOG_DEBUG("X11WindowSystem", "Taking screenshot of layer");
699         Layer* currentLayer = m_pScene->getLayer(screenShotLayerID);
700
701         if (currentLayer!=NULL){
702             graphicSystem->beginLayer(currentLayer);
703             graphicSystem->renderSWLayer();
704             graphicSystem->endLayer();
705         }
706     }
707     else if(takeScreenshot==ScreenshotOfSurface)
708     {
709         LOG_DEBUG("X11WindowSystem", "Taking screenshot of surface");
710         Layer* currentLayer = m_pScene->getLayer(screenShotLayerID);
711         Surface* currentSurface = m_pScene->getSurface(screenShotSurfaceID);
712
713         if (currentLayer!=NULL && currentSurface!=NULL){
714             graphicSystem->beginLayer(currentLayer);
715             graphicSystem->renderSurface(currentSurface);
716             graphicSystem->endLayer();
717         }
718     }
719
720     graphicSystem->saveScreenShotOfFramebuffer(screenShotFile);
721 //  graphicSystem->swapBuffers();
722     takeScreenshot = ScreenShotNone;
723     LOG_DEBUG("X11WindowSystem", "Done taking screenshot");
724     graphicSystem->releaseGraphicContext();
725     m_pScene->unlockScene();
726     /*LOG_INFO("X11WindowSystem","UnLocking List");*/
727 }
728
729 int
730 X11WindowSystem::error (Display *dpy, XErrorEvent *ev)
731 {
732     const char* name = NULL;
733     static char buffer[256];
734
735     if (ev->request_code == composite_opcode && ev->minor_code == X_CompositeRedirectSubwindows)
736     {
737         LOG_ERROR("X11WindowSystem", "Maybe another composite manager is already running");
738     }
739
740     if (!name)
741     {
742         buffer[0] = '\0';
743         XGetErrorText (dpy, ev->error_code, buffer, sizeof (buffer));
744         name = buffer;
745     }
746     name = (strlen (name) > 0) ? name : "unknown";
747     LOG_ERROR("X11WindowSystem", "X Error: " << (int)ev->error_code << " " << name << " request : " << (int)ev->request_code << " minor: " <<  (int)ev->minor_code << " serial: " << (int)ev->serial);
748     m_xerror = true;
749     return 0;
750 }
751
752 bool X11WindowSystem::initXServer()
753 {
754     LOG_DEBUG("X11WindowSystem", "Initialising XServer connection");
755     bool result = true;
756
757     //setDisplayMode();
758     if (!CreateCompositorWindow())
759     {
760         LOG_ERROR("X11WindowSystem", "Compositor Window creation failed " );
761         return false;
762     }
763
764     LOG_DEBUG("X11WindowSystem", "Compositor Window ID: " << CompositorWindow);
765
766     if ( CreatePixmapsForAllWindows() )
767     {
768             //unredirect our window
769 #ifdef FULLSCREEN
770         XCompositeUnredirectWindow(x11Display, background, CompositeRedirectManual);
771 #endif
772         XCompositeUnredirectWindow(x11Display, CompositorWindow, CompositeRedirectManual);
773         LOG_DEBUG("X11WindowSystem", "Initialised XServer connection complete");
774     } else {
775         LOG_ERROR("X11WindowSystem", "Initialised XServer connection failed");
776         result = false;
777     }
778
779     return result;
780 }
781
782 /**
783  * Thread in charge of the CompositorWindow eventloop
784  * Friend function of class X11WindowSystem
785  */
786 void * X11eventLoopCallback(void *ptr)
787 {
788     X11WindowSystem *windowsys = static_cast<X11WindowSystem*>( (X11WindowSystem*) ptr);
789     return windowsys->EventLoop();
790 }
791
792 void* X11WindowSystem::EventLoop()
793 {
794     // INITALIZATION
795     LOG_DEBUG("X11WindowSystem", "Enter thread");
796
797     bool status = true;
798     bool checkRedraw = false;
799
800     XSetErrorHandler(error);
801     // init own stuff
802     LOG_DEBUG("X11WindowSystem", "open display connection");
803     status &= this->OpenDisplayConnection();
804     if ( status == false ) goto init_complete;
805     LOG_DEBUG("X11WindowSystem", "check for composite extension");
806     status &= this->checkForCompositeExtension();
807     if ( status == false ) goto init_complete;
808     LOG_DEBUG("X11WindowSystem", "check for damage extension");
809     status &= this->checkForDamageExtension();
810     if ( status == false ) goto init_complete;
811     LOG_DEBUG("X11WindowSystem", "init xserver");
812     status &= this->initXServer();
813     if ( status == false ) goto init_complete;
814     status &= this->graphicSystem->init(this->x11Display,this->CompositorWindow);
815
816 init_complete:
817     this->m_success = status;
818     this->m_initialized = true;
819
820     // Done with init, wait for lock to actually run (ie start/stop method called)
821     pthread_mutex_lock(&this->run_lock);
822
823     LOG_DEBUG("X11WindowSystem", "Starting Event loop");
824     Layer* defaultLayer = 0;
825
826     // run the main event loop while rendering
827     gettimeofday(&tv0, NULL);
828     if (this->debugMode)
829     {
830         defaultLayer = this->m_pScene->createLayer(0);
831         defaultLayer->setOpacity(1.0);
832         defaultLayer->setDestinationRegion(Rectangle(0,0,this->resolutionWidth,this->resolutionHeight));
833         defaultLayer->setSourceRegion(Rectangle(0,0,this->resolutionWidth,this->resolutionHeight));
834         this->m_pScene->getCurrentRenderOrder().push_back(defaultLayer);
835     }
836     LOG_DEBUG("X11WindowSystem", "Enter render loop");
837
838     // clear screen to avoid garbage on startup
839     this->graphicSystem->clearBackground();
840     this->graphicSystem->swapBuffers();
841     XFlush(this->x11Display);
842
843     while (this->m_running)
844     {
845 #ifndef WITH_XTHREADS
846         if ( XPending(this->x11Display) > 0) {
847 #endif //WITH_XTHREADS
848             XEvent event;
849             // blocking wait for event
850             XNextEvent(this->x11Display, &event);
851             this->m_pScene->lockScene();
852             switch (event.type)
853             {
854             case CreateNotify:
855             {
856                 if (this->debugMode)
857                 {
858                     LOG_DEBUG("X11WindowSystem", "CreateNotify Event");
859                     Surface* s = this->m_pScene->createSurface(0);
860                     s->setOpacity(1.0);
861                     this->NewWindow(s, event.xcreatewindow.window);
862                     defaultLayer->addSurface(s);
863                 }
864                 break;
865             }
866             case ConfigureNotify:
867                 LOG_DEBUG("X11WindowSystem", "Configure notify Event");
868                 this->configureSurfaceWindow( event.xconfigure.window);
869                 checkRedraw = true;
870                 break;
871
872             case DestroyNotify:
873                 LOG_DEBUG("X11WindowSystem", "Destroy  Event");
874                 this->DestroyWindow(event.xdestroywindow.window);
875                 checkRedraw = true;
876                 break;
877             case Expose:
878                 LOG_DEBUG("X11WindowSystem", "Expose Event");
879                 checkRedraw = true;
880                 break;
881             case MapNotify:
882                 LOG_DEBUG("X11WindowSystem", "Map Event");
883                 this->MapWindow(event.xmap.window);
884                 checkRedraw = true;
885                 break;
886             case UnmapNotify:
887                 LOG_DEBUG("X11WindowSystem", "Unmap Event");
888                 this->UnMapWindow(event.xunmap.window);
889                 checkRedraw = true;
890                 break;
891             case ReparentNotify:
892                 LOG_DEBUG("X11WindowSystem", "Reparent Event");
893                 //           if (event.xreparent.parent == root)
894                 //               renderer->NewWindow(event.xreparent.window);
895                 //           else
896                 //               renderer->DestroyWindow(event.xreparent.window);
897                 break;
898 #ifdef WITH_INPUT_EVENTS
899             case ButtonPress:
900             case ButtonRelease:
901
902             case MotionNotify:
903                 ManageXInputEvent(&event);
904                 break;
905 #endif
906             default:
907                 if (event.type == this->damage_event + XDamageNotify)
908                 {
909                     XDamageSubtract(this->x11Display, ((XDamageNotifyEvent*)(&event))->damage, None, None);
910                     Surface* currentSurface = this->getSurfaceForWindow(((XDamageNotifyEvent*)(&event))->drawable);
911                     if (currentSurface==NULL)
912                     {
913                         LOG_WARNING("X11WindowSystem", "Surface empty during damage notification");
914                         break;
915                     } else {
916                         if (currentSurface->platform != NULL) 
917                         {
918                             /* Enable Rendering for Surface, after damage Notification was send successfully */
919                             /* This will ensure, that the content is not dirty */
920                             ((XPlatformSurface *)(currentSurface->platform))->enableRendering();
921                         }
922                     }
923                     currentSurface->damaged = true;
924                     currentSurface->updateCounter++;
925                     checkRedraw = true;
926                 }
927                 break;
928             }
929             this->m_pScene->unlockScene();
930
931 #ifndef WITH_XTHREADS
932         }
933 #endif //WITH_XTHREADS
934         if (this->m_systemState == REDRAW_STATE)
935         {
936             LOG_DEBUG("X11WindowSystem", "Enter Redraw State");
937             this->m_systemState = IDLE_STATE;
938
939             // check if we are supposed to take screenshot
940             if (this->takeScreenshot!=ScreenShotNone)
941             {
942                 this->Screenshot();
943             }
944             else
945             {
946                 this->checkForNewSurfaceNativeContent();
947                 checkRedraw = true;
948             }
949
950         } 
951         else if (this->m_systemState == WAKEUP_STATE)         
952         {
953             LOG_DEBUG("X11WindowSystem", "Enter Wake Up State");
954         }
955
956         if (checkRedraw)
957         {
958             this->Redraw();
959             checkRedraw = false;
960         }
961 #ifndef WITH_XTHREADS
962         else {
963             /* put thread in sleep mode for 500 useconds due to safe cpu performance */
964
965             usleep(500);
966         }
967 #endif
968     }
969     this->cleanup();
970     LOG_DEBUG("X11WindowSystem", "Renderer thread finished");
971     return NULL;
972 }
973
974
975 void X11WindowSystem::ManageXInputEvent(XEvent *pevent)
976 {
977     (void)pevent;
978
979 #ifdef WITH_INPUT_EVENTS
980     XEvent* currentEvent = pevent;
981     Surface * surf;
982     int *pX = NULL;
983     int *pY = NULL;
984
985     switch (currentEvent->type)
986     {
987         case ButtonRelease:
988         case ButtonPress:
989             pX = &(((XButtonEvent*)currentEvent)->x);
990             pY = &(((XButtonEvent*)currentEvent)->y);
991             break;
992
993         case MotionNotify:
994             pX = &(((XMotionEvent*)currentEvent)->x);
995             pY = &(((XMotionEvent*)currentEvent)->y);
996             break;
997         default:
998             break;
999     }
1000
1001     surf = m_pScene->getSurfaceAt((unsigned int *) pX, (unsigned int *) pY, 0.1);
1002     if (surf != NULL)
1003     {
1004         pevent->xany.window = surf->getNativeContent();
1005         XSendEvent(x11Display, currentEvent->xany.window, false, 0, currentEvent);
1006     }
1007     currentEvent = NULL;
1008 #endif
1009 }
1010
1011
1012 #ifdef WITH_XTHREADS
1013 static Display* displaySignal = NULL;
1014 #endif //WITH_XTHREADS
1015 void X11WindowSystem::wakeUpRendererThread() 
1016 {
1017 #ifdef WITH_XTHREADS
1018     // send dummy expose event, to wake up blocking x11 event loop (XNextEvent)
1019     LOG_DEBUG("X11WindowSystem", "Sending dummy event to wake up renderer thread");
1020     if (NULL == displaySignal )
1021     {
1022         displaySignal = XOpenDisplay(m_displayEnvironment);
1023     }
1024     XExposeEvent ev = { Expose, 0, 1, displaySignal, CompositorWindow, 0, 0, 100, 100, 0 };
1025     XLockDisplay(displaySignal);
1026     XSendEvent(displaySignal, CompositorWindow, False, ExposureMask, (XEvent *) &ev);
1027     XUnlockDisplay(displaySignal);
1028     XFlush(displaySignal);
1029     LOG_DEBUG("X11WindowSystem", "Event successfully sent to renderer");
1030 #endif //WITH_XTHREADS
1031 }
1032
1033 void X11WindowSystem::signalRedrawEvent()
1034 {
1035     // set flag that redraw is needed
1036     this->m_systemState = REDRAW_STATE;
1037     this->wakeUpRendererThread();
1038 }
1039
1040 void X11WindowSystem::cleanup(){
1041     LOG_DEBUG("X11WindowSystem", "Cleanup");
1042     if (None != CompositorWindow)
1043     {
1044         Window root = RootWindow(x11Display, DefaultScreen(x11Display));
1045         XCompositeUnredirectSubwindows(x11Display,root,CompositeRedirectManual);
1046         XDestroyWindow(x11Display,CompositorWindow);
1047     }
1048
1049     if (windowVis)
1050     {
1051         delete windowVis;
1052     }
1053
1054 #ifdef WITH_XTHREADS
1055     if ( NULL  != displaySignal )
1056     {
1057         XCloseDisplay(displaySignal);
1058     }
1059 #endif //WITH_XTHREADS
1060     XCloseDisplay(x11Display);
1061     m_running = false;
1062 }
1063
1064 bool X11WindowSystem::init(BaseGraphicSystem<Display*,Window>* base)
1065 {
1066 #ifdef WITH_XTHREADS
1067     XInitThreads();
1068 #endif //WITH_XTHREADS
1069     X11WindowSystem *renderer = this;
1070     graphicSystem = base;
1071     int status = pthread_create( &renderThread, NULL, X11eventLoopCallback, (void*) renderer);
1072     if (0 != status )
1073     {
1074         return false;
1075     }
1076
1077     while (!m_initialized)
1078     {
1079         usleep(10000); // TODO
1080         LOG_DEBUG("X11WindowSystem","Waiting start complete " << m_initialized);
1081     }
1082     LOG_INFO("X11WindowSystem","Start complete " << m_initialized << " success " << m_success);
1083     return m_success;
1084 }
1085
1086 bool X11WindowSystem::start()
1087 {
1088     bool result = true;
1089     LOG_DEBUG("X11WindowSystem", "Starting / Creating thread");
1090     // let thread actually run
1091     if ( m_xerror == false )
1092     {
1093         this->m_running = true;
1094         pthread_mutex_unlock(&run_lock);
1095     } else {
1096         this->m_running = false;
1097         pthread_mutex_unlock(&run_lock);
1098         result = false;
1099     }
1100     return result;
1101 }
1102
1103 void X11WindowSystem::stop()
1104 {
1105     LOG_INFO("X11WindowSystem","Stopping..");
1106     this->m_running = false;
1107     // needed if start was never called, we wake up thread, so it can immediatly finish
1108     this->signalRedrawEvent();
1109     pthread_mutex_unlock(&run_lock);
1110     pthread_join(renderThread,NULL);
1111 }
1112
1113 void X11WindowSystem::allocatePlatformSurface(Surface* surface)
1114 {
1115     LOG_DEBUG("X11WindowSystem","allocatePlatformSurface begin");
1116     XPlatformSurface* nativeSurface = (XPlatformSurface*)surface->platform;
1117     if (!nativeSurface)
1118     {
1119         LOG_DEBUG("X11WindowSystem","creating native surface for new window");
1120         // this surface does not have a native platform surface attached yet!
1121         NewWindow(surface, surface->getNativeContent());
1122         MapWindow(surface->getNativeContent());
1123     }
1124     LOG_DEBUG("X11WindowSystem","allocatePlatformSurface end");
1125 }
1126
1127 void X11WindowSystem::deallocatePlatformSurface(Surface* surface)
1128 {
1129     LOG_DEBUG("X11WindowSystem","deallocatePlatformSurface begin");
1130     XPlatformSurface* nativeSurface = (XPlatformSurface*)surface->platform;
1131     if (nativeSurface)
1132     {
1133         LOG_DEBUG("X11WindowSystem","destroyingnative surface");
1134         graphicSystem->getTextureBinder()->destroyClientBuffer(surface);
1135
1136         if (nativeSurface->pixmap)
1137         {
1138             int result = XFreePixmap(x11Display, nativeSurface->pixmap);
1139         }
1140
1141         surface->renderPropertyChanged = true;
1142         delete surface->platform;
1143         surface->platform = NULL;
1144     }
1145     LOG_DEBUG("X11WindowSystem","deallocatePlatformSurface end");
1146 }
1147
1148 void X11WindowSystem::doScreenShot(std::string fileName)
1149 {
1150     takeScreenshot = ScreenshotOfDisplay;
1151     screenShotFile = fileName;
1152 }
1153
1154 void X11WindowSystem::doScreenShotOfLayer(std::string fileName, const uint id)
1155 {
1156     takeScreenshot = ScreenshotOfLayer;
1157     screenShotFile = fileName;
1158     screenShotLayerID = id;
1159 }
1160
1161 void X11WindowSystem::doScreenShotOfSurface(std::string fileName, const uint id, const uint layer_id)
1162 {
1163     takeScreenshot = ScreenshotOfSurface;
1164     screenShotFile = fileName;
1165     screenShotSurfaceID = id;
1166     screenShotLayerID = layer_id;
1167 }
1168