1 /***************************************************************************
3 * Copyright 2010,2011 BMW Car IT GmbH
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 ****************************************************************************/
20 #include "WindowSystems/X11WindowSystem.h"
27 #include <X11/Xutil.h>
28 #include <X11/Xatom.h>
29 #include <X11/extensions/Xcomposite.h>
30 #include <X11/extensions/Xdamage.h>
37 int X11WindowSystem::composite_opcode;
38 int X11WindowSystem::damage_opcode;
39 const char X11WindowSystem::CompositorWindowTitle[] = "LayerManager";
40 bool X11WindowSystem::m_xerror = false;
42 X11WindowSystem::X11WindowSystem(const char* displayname, int width, int height, Scene* pScene,GetVisualInfoFunction func)
43 : BaseWindowSystem(pScene)
44 , takeScreenshot(ScreenShotNone)
46 , screenShotSurfaceID(0)
48 , displayname(displayname)
51 , resolutionWidth(width)
52 , resolutionHeight(height)
62 , m_initialized(false)
64 , m_systemState(IDLE_STATE)
65 , m_displayEnvironment(NULL)
69 , windowHeight(height)
75 LOG_DEBUG("X11WindowSystem", "creating X11WindowSystem");
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);
82 X11WindowSystem::~X11WindowSystem()
90 XVisualInfo* X11WindowSystem::getDefaultVisual(Display *dpy)
92 XVisualInfo* windowVis = new XVisualInfo();
95 windowVis->depth = DefaultDepth(dpy, DefaultScreen(dpy));
96 if (!XMatchVisualInfo( dpy, 0, windowVis->depth, TrueColor, windowVis))
98 LOG_ERROR("X11WindowSystem", "Error: Required visual not found\n");
105 LOG_ERROR("X11WindowSystem", "Error: Unable to acquire visual\n");
110 bool X11WindowSystem::OpenDisplayConnection()
112 m_displayEnvironment = getenv("DISPLAY");
114 if (m_displayEnvironment == NULL )
116 m_displayEnvironment = ":0.0";
117 setenv("DISPLAY",m_displayEnvironment,1);
120 x11Display = XOpenDisplay(m_displayEnvironment);
123 LOG_ERROR("X11WindowSystem", "Couldn't open default display!");
126 LOG_DEBUG("X11WindowSystem", "Display connection: " << x11Display);
130 bool X11WindowSystem::checkForCompositeExtension()
132 if (x11Display == NULL || !XQueryExtension (x11Display, COMPOSITE_NAME, &composite_opcode, &composite_event, &composite_error))
134 LOG_ERROR("X11WindowSystem", "No composite extension");
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);
144 bool X11WindowSystem::checkForDamageExtension(){
145 if (x11Display == NULL || !XQueryExtension (x11Display, DAMAGE_NAME, &damage_opcode,
146 &damage_event, &damage_error))
148 LOG_ERROR("X11WindowSystem", "No damage extension");
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);
158 void X11WindowSystem::printDebug(){
159 // print stuff about layerlist
160 std::stringstream debugmessage;
161 debugmessage << "Layer: ID | X | Y | W | H | Al. \n";
163 LayerList list = m_pScene->getCurrentRenderOrder();
166 LayerListConstIterator iter = list.begin();
167 LayerListConstIterator iterEnd = list.end();
169 for(; iter != iterEnd; ++iter)
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";
174 debugmessage << " Surface: ID |Al.| SVP: X | Y | W | H DVP: X | Y | W | H \n";
176 // loop the surfaces of within each layer
177 SurfaceList surfaceList = (*iter)->getAllSurfaces();
178 SurfaceListIterator surfaceIter = surfaceList.begin();
179 SurfaceListIterator surfaceIterEnd = surfaceList.end();
181 for(; surfaceIter != surfaceIterEnd ; ++surfaceIter)
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";
188 LOG_DEBUG("X11WindowSystem",debugmessage.str());
191 Window * getListOfAllTopLevelWindows (Display *disp, unsigned int *len)
193 LOG_DEBUG("X11WindowSystem", "Getting list of all windows");
195 Window root_return, parent_return;
196 Window root = XDefaultRootWindow(disp);
197 XQueryTree (disp, root, &root_return, &parent_return, &children, len);
201 bool X11WindowSystem::isWindowValid(Window w)
203 // skip our own two windows
204 return (w!=None && w != CompositorWindow);
207 Surface* X11WindowSystem::getSurfaceForWindow(Window w)
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)
213 Surface* currentSurface = (*currentS).second;
218 if (currentSurface->getNativeContent() == static_cast<int>(w))
220 return currentSurface;
223 LOG_DEBUG("X11WindowSystem", "could not find surface for window " << w);
227 void X11WindowSystem::checkForNewSurfaceNativeContent()
229 m_pScene->lockScene();
230 LayerList layers = m_pScene->getCurrentRenderOrder();
231 for(LayerListConstIterator current = layers.begin(); current != layers.end(); current++)
233 SurfaceList surfaces = (*current)->getAllSurfaces();
234 for(SurfaceListConstIterator currentS = surfaces.begin(); currentS != surfaces.end(); currentS++)
236 if ((*currentS)->hasNativeContent())
238 allocatePlatformSurface(*currentS);
240 else // While we are at it, also cleanup any stale native content
242 deallocatePlatformSurface(*currentS);
246 m_pScene->unlockScene();
249 void X11WindowSystem::configureSurfaceWindow(Window window)
251 if (isWindowValid(window))
253 LOG_DEBUG("X11WindowSystem", "Updating window " << window);
256 XWindowAttributes att;
257 XGetWindowAttributes (x11Display, window, &att);
258 int winWidth = att.width;
259 int winHeight = att.height;
261 Surface* surface = getSurfaceForWindow(window);
264 LOG_WARNING("X11WindowSystem", "Could not find surface for window " << window);
267 if (!surface->platform)
269 LOG_WARNING("X11WindowSystem", "Platform surface not available for window " << window);
273 LOG_DEBUG("X11WindowSystem", "Updating surface " << surface->getID());
275 surface->OriginalSourceHeight = winHeight;
276 surface->OriginalSourceWidth = winWidth;
278 LOG_DEBUG("X11WindowSystem", "Done Updating window " << window);
282 void X11WindowSystem::MapWindow(Window window)
284 LOG_DEBUG("X11WindowSystem","Map window begin");
285 if (isWindowValid(window))
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)
294 LOG_DEBUG("X11WindowSystem", "Mapping surface to window " << window);
295 Surface* surface = getSurfaceForWindow(window);
298 LOG_WARNING("X11WindowSystem", "Could not map surface to window " << window);
301 if (!surface->platform)
303 LOG_WARNING("X11WindowSystem", "Platform surface not available for window " << window);
307 XPlatformSurface* x11surf = (XPlatformSurface*)surface->platform;
308 if (x11surf->isMapped)
310 LOG_WARNING("X11WindowSystem", "Platform surface already mapped");
313 x11surf->isMapped = true;
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));
327 int winWidth = att.width;
328 int winHeight = att.height;
330 surface->OriginalSourceHeight = winHeight;
331 surface->OriginalSourceWidth = winWidth;
332 surface->renderPropertyChanged = true;
334 graphicSystem->getTextureBinder()->createClientBuffer(surface);
335 XSync(x11Display, 0);
337 LOG_DEBUG("X11WindowSystem", "Mapping Surface " << surface->getID() << " to window " << window);
338 LOG_DEBUG("X11WindowSystem", "Mapping successfull");
341 LOG_DEBUG("X11WindowSystem","Map window end");
344 void X11WindowSystem::UnMapWindow(Window window)
346 LOG_DEBUG("X11WindowSystem", "Unmap begin");
347 if (isWindowValid(window))
349 LOG_DEBUG("X11WindowSystem", "Unmapping surface from window " << window);
350 Surface* surface = getSurfaceForWindow(window);
353 LOG_WARNING("X11WindowSystem", "Could not unmap window " << window);
356 if (!surface->platform)
358 LOG_WARNING("X11WindowSystem", "Platform surface not available for window " << window);
361 XPlatformSurface* x11surf = (XPlatformSurface*)surface->platform;
362 LOG_DEBUG("X11WindowSystem", "Unmapping surface " << surface->getID());
363 if (!x11surf->isMapped)
365 LOG_WARNING("X11WindowSystem", "Platform surface already unmapped");
368 x11surf->isMapped = false;
371 LOG_DEBUG("X11WindowSystem", "Destroying ClientBuffer");
372 graphicSystem->getTextureBinder()->destroyClientBuffer(surface);
373 XSync(x11Display, 0);
375 LOG_DEBUG("X11WindowSystem", "Removing X Pixmap");
378 int result = XFreePixmap(x11Display, x11surf->pixmap);
379 LOG_DEBUG("X11WindowSystem", "XFreePixmap() returned " << result);
382 surface->renderPropertyChanged = true;
384 LOG_DEBUG("X11WindowSystem", "Unmap finished");
387 void X11WindowSystem::NewWindow(Surface* surface, Window window)
389 if (isWindowValid(window))
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");
397 status = XFetchName(x11Display, window, &name);
398 LOG_DEBUG("X11WindowSystem", "Got window name");
399 if (status >= Success && name)
401 LOG_DEBUG("X11WindowSystem", "Found window: " << window << " " << name);
402 char GuiTitle[] = "Layermanager Remote GUI\0";
403 if (strcmp(name,GuiTitle)==0)
405 LOG_DEBUG("X11WindowSystem", "Found gui window: repositioning it");
406 XCompositeUnredirectWindow(x11Display,window,CompositeRedirectManual);
407 XMoveWindow(x11Display, window, 50, 500);
408 XMapRaised(x11Display, window);
413 LOG_DEBUG("X11WindowSystem", "Error fetching window name");
416 if (att.c_class == InputOutput)
418 LOG_DEBUG("X11WindowSystem","Creating New Damage for window - " << window);
419 XDamageCreate(x11Display,window,XDamageReportNonEmpty);
423 XLowerWindow(x11Display,window);
425 surface->setNativeContent(window);
426 XPlatformSurface * platformSurface = (XPlatformSurface*)graphicSystem->getTextureBinder()->createPlatformSurface(surface);
427 platformSurface->isMapped = false;
429 LOG_DEBUG("X11WindowSystem", "Created native Surface for X11 Window id " << window);
431 surface->platform = platformSurface;
433 int winWidth = att.width;
434 int winHeight = att.height;
436 surface->OriginalSourceHeight = winHeight;
437 surface->OriginalSourceWidth = winWidth;
439 LOG_DEBUG("X11WindowSystem", "Original width " << surface->OriginalSourceWidth);
440 LOG_DEBUG("X11WindowSystem", "Original heigth " << surface->OriginalSourceHeight);
444 LOG_DEBUG("X11WindowSystem", "skipping window");
446 LOG_DEBUG("X11WindowSystem", "created the new surface");
449 void X11WindowSystem::DestroyWindow(Window window)
451 if (isWindowValid(window))
453 LOG_DEBUG("X11WindowSystem", "Destroying Surface for window " << window);
454 Surface* surface = getSurfaceForWindow(window);
457 LOG_WARNING("X11WindowSystem", "Could not find surface for window " << window);
460 graphicSystem->getTextureBinder()->destroyClientBuffer(surface);
461 LOG_DEBUG("X11WindowSystem", "Unmapping window " << window);
463 LOG_DEBUG("X11WindowSystem", "Remove Native Content from Surface " << surface->getID());
464 surface->removeNativeContent();
465 delete surface->platform;
466 surface->platform = NULL;
470 bool X11WindowSystem::CreatePixmapsForAllWindows()
473 LOG_DEBUG("X11WindowSystem", "redirecting all windows");
474 Window root = RootWindow(x11Display, DefaultScreen(x11Display));
475 XCompositeRedirectSubwindows(x11Display,root,CompositeRedirectManual);
480 bool X11WindowSystem::CreateCompositorWindow()
482 LOG_DEBUG("X11WindowSystem", "Get root window");
484 CompositorWindow = None;
485 Window root = RootWindow(x11Display, DefaultScreen(x11Display));
487 LOG_DEBUG("X11WindowSystem", "Creating Compositor Window");
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;
495 attr.event_mask = ExposureMask | StructureNotifyMask;
497 attr.background_pixel = 0;
498 attr.border_pixel = 0;
499 windowVis = getVisualFunc(x11Display);
504 attr.colormap = XCreateColormap(x11Display, root, windowVis->visual, AllocNone);
505 attr.override_redirect = True;
507 Window compManager = XGetSelectionOwner(x11Display,XInternAtom(x11Display,"_NET_WM_CM_S0",0));
508 if ( None != compManager )
510 LOG_ERROR("X11WindowSystem", "Could not create compositor window, annother compisite manager is already running");
514 CompositorWindow = XCreateWindow(x11Display, root, 0, 0, windowWidth, windowHeight,
515 0, windowVis->depth, InputOutput,
516 windowVis->visual, CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &attr);
518 if (None == CompositorWindow)
520 LOG_ERROR("X11WindowSystem", "Could not create window");
524 LOG_DEBUG("X11WindowSystem", "Created the Compositor Window");
525 XSelectInput (x11Display, root,
526 SubstructureNotifyMask|
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);
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;
551 void X11WindowSystem::calculateSurfaceFps(Surface *currentSurface, float time )
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);
564 void X11WindowSystem::calculateFps()
566 // we have rendered a 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));
573 if (timeSinceLastCalc > 10.0f)
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++)
580 SurfaceList surfaceList = (*current)->getAllSurfaces();
581 SurfaceListIterator surfaceIter = surfaceList.begin();
582 SurfaceListIterator surfaceIterEnd = surfaceList.end();
583 for(; surfaceIter != surfaceIterEnd ; ++surfaceIter)
585 calculateSurfaceFps((*surfaceIter),timeSinceLastCalc);
588 LOG_INFO("X11WindowSystem", floatStringBuffer);
594 void X11WindowSystem::CheckRedrawAllLayers()
596 std::list<Layer*> layers = m_pScene->getCurrentRenderOrder();
597 for(std::list<Layer*>::const_iterator current = layers.begin(); current != layers.end(); current++)
599 Layer* currentLayer = (Layer*)*current;
600 graphicSystem->beginLayer(currentLayer);
601 graphicSystem->checkRenderLayer();
602 graphicSystem->endLayer();
606 void X11WindowSystem::RedrawAllLayers()
608 std::list<Layer*> layers = m_pScene->getCurrentRenderOrder();
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
615 graphicSystem->activateGraphicContext();
616 graphicSystem->clearBackground();
618 for(std::list<Layer*>::const_iterator current = layers.begin(); current != layers.end(); current++)
620 if ((*current)->getLayerType() == Hardware)
622 if ((*current)->damaged)
624 renderHWLayer(*current);
625 (*current)->damaged = false;
630 graphicSystem->beginLayer(*current);
631 graphicSystem->renderSWLayer();
632 graphicSystem->endLayer();
637 graphicSystem->swapBuffers();
638 graphicSystem->releaseGraphicContext();
642 void X11WindowSystem::renderHWLayer(Layer *layer)
647 void X11WindowSystem::Redraw()
649 // draw all the layers
650 //graphicSystem->clearBackground();
651 /*LOG_INFO("X11WindowSystem","Locking List");*/
652 m_pScene->lockScene();
654 CheckRedrawAllLayers();
657 m_pScene->unlockScene();
661 // TODO: This block won't be executed for HW only changes
662 // Is that acceptable?
670 /* Reset the damage flag, all is up to date */
675 void X11WindowSystem::Screenshot()
677 /*LOG_INFO("X11WindowSystem","Locking List");*/
678 m_pScene->lockScene();
679 graphicSystem->activateGraphicContext();
680 graphicSystem->clearBackground();
681 if (takeScreenshot==ScreenshotOfDisplay)
683 LOG_DEBUG("X11WindowSystem", "Taking screenshot");
684 std::list<Layer*> layers = m_pScene->getCurrentRenderOrder();
686 for(std::list<Layer*>::const_iterator current = layers.begin(); current != layers.end(); current++)
688 if ((*current)->getLayerType() != Hardware)
690 graphicSystem->beginLayer(*current);
691 graphicSystem->renderSWLayer();
692 graphicSystem->endLayer();
696 else if(takeScreenshot==ScreenshotOfLayer)
698 LOG_DEBUG("X11WindowSystem", "Taking screenshot of layer");
699 Layer* currentLayer = m_pScene->getLayer(screenShotLayerID);
701 if (currentLayer!=NULL){
702 graphicSystem->beginLayer(currentLayer);
703 graphicSystem->renderSWLayer();
704 graphicSystem->endLayer();
707 else if(takeScreenshot==ScreenshotOfSurface)
709 LOG_DEBUG("X11WindowSystem", "Taking screenshot of surface");
710 Layer* currentLayer = m_pScene->getLayer(screenShotLayerID);
711 Surface* currentSurface = m_pScene->getSurface(screenShotSurfaceID);
713 if (currentLayer!=NULL && currentSurface!=NULL){
714 graphicSystem->beginLayer(currentLayer);
715 graphicSystem->renderSurface(currentSurface);
716 graphicSystem->endLayer();
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");*/
730 X11WindowSystem::error (Display *dpy, XErrorEvent *ev)
732 const char* name = NULL;
733 static char buffer[256];
735 if (ev->request_code == composite_opcode && ev->minor_code == X_CompositeRedirectSubwindows)
737 LOG_ERROR("X11WindowSystem", "Maybe another composite manager is already running");
743 XGetErrorText (dpy, ev->error_code, buffer, sizeof (buffer));
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);
752 bool X11WindowSystem::initXServer()
754 LOG_DEBUG("X11WindowSystem", "Initialising XServer connection");
758 if (!CreateCompositorWindow())
760 LOG_ERROR("X11WindowSystem", "Compositor Window creation failed " );
764 LOG_DEBUG("X11WindowSystem", "Compositor Window ID: " << CompositorWindow);
766 if ( CreatePixmapsForAllWindows() )
768 //unredirect our window
770 XCompositeUnredirectWindow(x11Display, background, CompositeRedirectManual);
772 XCompositeUnredirectWindow(x11Display, CompositorWindow, CompositeRedirectManual);
773 LOG_DEBUG("X11WindowSystem", "Initialised XServer connection complete");
775 LOG_ERROR("X11WindowSystem", "Initialised XServer connection failed");
783 * Thread in charge of the CompositorWindow eventloop
784 * Friend function of class X11WindowSystem
786 void * X11eventLoopCallback(void *ptr)
788 X11WindowSystem *windowsys = static_cast<X11WindowSystem*>( (X11WindowSystem*) ptr);
789 return windowsys->EventLoop();
792 void* X11WindowSystem::EventLoop()
795 LOG_DEBUG("X11WindowSystem", "Enter thread");
798 bool checkRedraw = false;
800 XSetErrorHandler(error);
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);
817 this->m_success = status;
818 this->m_initialized = true;
820 // Done with init, wait for lock to actually run (ie start/stop method called)
821 pthread_mutex_lock(&this->run_lock);
823 LOG_DEBUG("X11WindowSystem", "Starting Event loop");
824 Layer* defaultLayer = 0;
826 // run the main event loop while rendering
827 gettimeofday(&tv0, NULL);
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);
836 LOG_DEBUG("X11WindowSystem", "Enter render loop");
838 // clear screen to avoid garbage on startup
839 this->graphicSystem->clearBackground();
840 this->graphicSystem->swapBuffers();
841 XFlush(this->x11Display);
843 while (this->m_running)
845 #ifndef WITH_XTHREADS
846 if ( XPending(this->x11Display) > 0) {
847 #endif //WITH_XTHREADS
849 // blocking wait for event
850 XNextEvent(this->x11Display, &event);
851 this->m_pScene->lockScene();
858 LOG_DEBUG("X11WindowSystem", "CreateNotify Event");
859 Surface* s = this->m_pScene->createSurface(0);
861 this->NewWindow(s, event.xcreatewindow.window);
862 defaultLayer->addSurface(s);
866 case ConfigureNotify:
867 LOG_DEBUG("X11WindowSystem", "Configure notify Event");
868 this->configureSurfaceWindow( event.xconfigure.window);
873 LOG_DEBUG("X11WindowSystem", "Destroy Event");
874 this->DestroyWindow(event.xdestroywindow.window);
878 LOG_DEBUG("X11WindowSystem", "Expose Event");
882 LOG_DEBUG("X11WindowSystem", "Map Event");
883 this->MapWindow(event.xmap.window);
887 LOG_DEBUG("X11WindowSystem", "Unmap Event");
888 this->UnMapWindow(event.xunmap.window);
892 LOG_DEBUG("X11WindowSystem", "Reparent Event");
893 // if (event.xreparent.parent == root)
894 // renderer->NewWindow(event.xreparent.window);
896 // renderer->DestroyWindow(event.xreparent.window);
898 #ifdef WITH_INPUT_EVENTS
903 ManageXInputEvent(&event);
907 if (event.type == this->damage_event + XDamageNotify)
909 XDamageSubtract(this->x11Display, ((XDamageNotifyEvent*)(&event))->damage, None, None);
910 Surface* currentSurface = this->getSurfaceForWindow(((XDamageNotifyEvent*)(&event))->drawable);
911 if (currentSurface==NULL)
913 LOG_WARNING("X11WindowSystem", "Surface empty during damage notification");
916 if (currentSurface->platform != NULL)
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();
923 currentSurface->damaged = true;
924 currentSurface->updateCounter++;
929 this->m_pScene->unlockScene();
931 #ifndef WITH_XTHREADS
933 #endif //WITH_XTHREADS
934 if (this->m_systemState == REDRAW_STATE)
936 LOG_DEBUG("X11WindowSystem", "Enter Redraw State");
937 this->m_systemState = IDLE_STATE;
939 // check if we are supposed to take screenshot
940 if (this->takeScreenshot!=ScreenShotNone)
946 this->checkForNewSurfaceNativeContent();
951 else if (this->m_systemState == WAKEUP_STATE)
953 LOG_DEBUG("X11WindowSystem", "Enter Wake Up State");
961 #ifndef WITH_XTHREADS
963 /* put thread in sleep mode for 500 useconds due to safe cpu performance */
970 LOG_DEBUG("X11WindowSystem", "Renderer thread finished");
975 void X11WindowSystem::ManageXInputEvent(XEvent *pevent)
979 #ifdef WITH_INPUT_EVENTS
980 XEvent* currentEvent = pevent;
985 switch (currentEvent->type)
989 pX = &(((XButtonEvent*)currentEvent)->x);
990 pY = &(((XButtonEvent*)currentEvent)->y);
994 pX = &(((XMotionEvent*)currentEvent)->x);
995 pY = &(((XMotionEvent*)currentEvent)->y);
1001 surf = m_pScene->getSurfaceAt((unsigned int *) pX, (unsigned int *) pY, 0.1);
1004 pevent->xany.window = surf->getNativeContent();
1005 XSendEvent(x11Display, currentEvent->xany.window, false, 0, currentEvent);
1007 currentEvent = NULL;
1012 #ifdef WITH_XTHREADS
1013 static Display* displaySignal = NULL;
1014 #endif //WITH_XTHREADS
1015 void X11WindowSystem::wakeUpRendererThread()
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 )
1022 displaySignal = XOpenDisplay(m_displayEnvironment);
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
1033 void X11WindowSystem::signalRedrawEvent()
1035 // set flag that redraw is needed
1036 this->m_systemState = REDRAW_STATE;
1037 this->wakeUpRendererThread();
1040 void X11WindowSystem::cleanup(){
1041 LOG_DEBUG("X11WindowSystem", "Cleanup");
1042 if (None != CompositorWindow)
1044 Window root = RootWindow(x11Display, DefaultScreen(x11Display));
1045 XCompositeUnredirectSubwindows(x11Display,root,CompositeRedirectManual);
1046 XDestroyWindow(x11Display,CompositorWindow);
1054 #ifdef WITH_XTHREADS
1055 if ( NULL != displaySignal )
1057 XCloseDisplay(displaySignal);
1059 #endif //WITH_XTHREADS
1060 XCloseDisplay(x11Display);
1064 bool X11WindowSystem::init(BaseGraphicSystem<Display*,Window>* base)
1066 #ifdef WITH_XTHREADS
1068 #endif //WITH_XTHREADS
1069 X11WindowSystem *renderer = this;
1070 graphicSystem = base;
1071 int status = pthread_create( &renderThread, NULL, X11eventLoopCallback, (void*) renderer);
1077 while (!m_initialized)
1079 usleep(10000); // TODO
1080 LOG_DEBUG("X11WindowSystem","Waiting start complete " << m_initialized);
1082 LOG_INFO("X11WindowSystem","Start complete " << m_initialized << " success " << m_success);
1086 bool X11WindowSystem::start()
1089 LOG_DEBUG("X11WindowSystem", "Starting / Creating thread");
1090 // let thread actually run
1091 if ( m_xerror == false )
1093 this->m_running = true;
1094 pthread_mutex_unlock(&run_lock);
1096 this->m_running = false;
1097 pthread_mutex_unlock(&run_lock);
1103 void X11WindowSystem::stop()
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);
1113 void X11WindowSystem::allocatePlatformSurface(Surface* surface)
1115 LOG_DEBUG("X11WindowSystem","allocatePlatformSurface begin");
1116 XPlatformSurface* nativeSurface = (XPlatformSurface*)surface->platform;
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());
1124 LOG_DEBUG("X11WindowSystem","allocatePlatformSurface end");
1127 void X11WindowSystem::deallocatePlatformSurface(Surface* surface)
1129 LOG_DEBUG("X11WindowSystem","deallocatePlatformSurface begin");
1130 XPlatformSurface* nativeSurface = (XPlatformSurface*)surface->platform;
1133 LOG_DEBUG("X11WindowSystem","destroyingnative surface");
1134 graphicSystem->getTextureBinder()->destroyClientBuffer(surface);
1136 if (nativeSurface->pixmap)
1138 int result = XFreePixmap(x11Display, nativeSurface->pixmap);
1141 surface->renderPropertyChanged = true;
1142 delete surface->platform;
1143 surface->platform = NULL;
1145 LOG_DEBUG("X11WindowSystem","deallocatePlatformSurface end");
1148 void X11WindowSystem::doScreenShot(std::string fileName)
1150 takeScreenshot = ScreenshotOfDisplay;
1151 screenShotFile = fileName;
1154 void X11WindowSystem::doScreenShotOfLayer(std::string fileName, const uint id)
1156 takeScreenshot = ScreenshotOfLayer;
1157 screenShotFile = fileName;
1158 screenShotLayerID = id;
1161 void X11WindowSystem::doScreenShotOfSurface(std::string fileName, const uint id, const uint layer_id)
1163 takeScreenshot = ScreenshotOfSurface;
1164 screenShotFile = fileName;
1165 screenShotSurfaceID = id;
1166 screenShotLayerID = layer_id;