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
613 if (m_forceComposition || m_damaged)
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 (m_forceComposition || (*current)->damaged)
624 renderHWLayer(*current);
625 (*current)->damaged = false;
628 else if (m_forceComposition || m_damaged)
630 graphicSystem->beginLayer(*current);
631 graphicSystem->renderSWLayer();
632 graphicSystem->endLayer();
635 if (m_forceComposition || m_damaged)
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();
659 if (m_forceComposition || m_damaged)
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 */
671 m_forceComposition = false;
676 void X11WindowSystem::Screenshot()
678 /*LOG_INFO("X11WindowSystem","Locking List");*/
679 m_pScene->lockScene();
680 graphicSystem->activateGraphicContext();
681 graphicSystem->clearBackground();
682 if (takeScreenshot==ScreenshotOfDisplay)
684 LOG_DEBUG("X11WindowSystem", "Taking screenshot");
685 std::list<Layer*> layers = m_pScene->getCurrentRenderOrder();
687 for(std::list<Layer*>::const_iterator current = layers.begin(); current != layers.end(); current++)
689 if ((*current)->getLayerType() != Hardware)
691 graphicSystem->beginLayer(*current);
692 graphicSystem->renderSWLayer();
693 graphicSystem->endLayer();
697 else if(takeScreenshot==ScreenshotOfLayer)
699 LOG_DEBUG("X11WindowSystem", "Taking screenshot of layer");
700 Layer* currentLayer = m_pScene->getLayer(screenShotLayerID);
702 if (currentLayer!=NULL){
703 graphicSystem->beginLayer(currentLayer);
704 graphicSystem->renderSWLayer();
705 graphicSystem->endLayer();
708 else if(takeScreenshot==ScreenshotOfSurface)
710 LOG_DEBUG("X11WindowSystem", "Taking screenshot of surface");
711 Layer* currentLayer = m_pScene->getLayer(screenShotLayerID);
712 Surface* currentSurface = m_pScene->getSurface(screenShotSurfaceID);
714 if (currentLayer!=NULL && currentSurface!=NULL){
715 graphicSystem->beginLayer(currentLayer);
716 graphicSystem->renderSurface(currentSurface);
717 graphicSystem->endLayer();
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");*/
731 X11WindowSystem::error (Display *dpy, XErrorEvent *ev)
733 const char* name = NULL;
734 static char buffer[256];
736 if (ev->request_code == composite_opcode && ev->minor_code == X_CompositeRedirectSubwindows)
738 LOG_ERROR("X11WindowSystem", "Maybe another composite manager is already running");
744 XGetErrorText (dpy, ev->error_code, buffer, sizeof (buffer));
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);
753 bool X11WindowSystem::initXServer()
755 LOG_DEBUG("X11WindowSystem", "Initialising XServer connection");
759 if (!CreateCompositorWindow())
761 LOG_ERROR("X11WindowSystem", "Compositor Window creation failed " );
765 LOG_DEBUG("X11WindowSystem", "Compositor Window ID: " << CompositorWindow);
767 if ( CreatePixmapsForAllWindows() )
769 //unredirect our window
771 XCompositeUnredirectWindow(x11Display, background, CompositeRedirectManual);
773 XCompositeUnredirectWindow(x11Display, CompositorWindow, CompositeRedirectManual);
774 LOG_DEBUG("X11WindowSystem", "Initialised XServer connection complete");
776 LOG_ERROR("X11WindowSystem", "Initialised XServer connection failed");
784 * Thread in charge of the CompositorWindow eventloop
785 * Friend function of class X11WindowSystem
787 void * X11eventLoopCallback(void *ptr)
789 X11WindowSystem *windowsys = static_cast<X11WindowSystem*>( (X11WindowSystem*) ptr);
790 return windowsys->EventLoop();
793 void* X11WindowSystem::EventLoop()
796 LOG_DEBUG("X11WindowSystem", "Enter thread");
799 bool checkRedraw = false;
801 XSetErrorHandler(error);
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);
818 this->m_success = status;
819 this->m_initialized = true;
821 // Done with init, wait for lock to actually run (ie start/stop method called)
822 pthread_mutex_lock(&this->run_lock);
824 LOG_DEBUG("X11WindowSystem", "Starting Event loop");
825 Layer* defaultLayer = 0;
827 // run the main event loop while rendering
828 gettimeofday(&tv0, NULL);
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);
837 LOG_DEBUG("X11WindowSystem", "Enter render loop");
839 // clear screen to avoid garbage on startup
840 this->graphicSystem->clearBackground();
841 this->graphicSystem->swapBuffers();
842 XFlush(this->x11Display);
844 while (this->m_running)
846 #ifndef WITH_XTHREADS
847 if ( XPending(this->x11Display) > 0) {
848 #endif //WITH_XTHREADS
850 // blocking wait for event
851 XNextEvent(this->x11Display, &event);
852 this->m_pScene->lockScene();
859 LOG_DEBUG("X11WindowSystem", "CreateNotify Event");
860 Surface* s = this->m_pScene->createSurface(0);
862 this->NewWindow(s, event.xcreatewindow.window);
863 defaultLayer->addSurface(s);
867 case ConfigureNotify:
868 LOG_DEBUG("X11WindowSystem", "Configure notify Event");
869 this->configureSurfaceWindow( event.xconfigure.window);
874 LOG_DEBUG("X11WindowSystem", "Destroy Event");
875 this->DestroyWindow(event.xdestroywindow.window);
879 LOG_DEBUG("X11WindowSystem", "Expose Event");
883 LOG_DEBUG("X11WindowSystem", "Map Event");
884 this->MapWindow(event.xmap.window);
888 LOG_DEBUG("X11WindowSystem", "Unmap Event");
889 this->UnMapWindow(event.xunmap.window);
893 LOG_DEBUG("X11WindowSystem", "Reparent Event");
894 // if (event.xreparent.parent == root)
895 // renderer->NewWindow(event.xreparent.window);
897 // renderer->DestroyWindow(event.xreparent.window);
899 #ifdef WITH_INPUT_EVENTS
904 ManageXInputEvent(&event);
908 if (event.type == this->damage_event + XDamageNotify)
910 XDamageSubtract(this->x11Display, ((XDamageNotifyEvent*)(&event))->damage, None, None);
911 Surface* currentSurface = this->getSurfaceForWindow(((XDamageNotifyEvent*)(&event))->drawable);
912 if (currentSurface==NULL)
914 LOG_WARNING("X11WindowSystem", "Surface empty during damage notification");
917 if (currentSurface->platform != NULL)
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();
924 currentSurface->damaged = true;
925 currentSurface->updateCounter++;
930 this->m_pScene->unlockScene();
932 #ifndef WITH_XTHREADS
934 #endif //WITH_XTHREADS
935 if (this->m_systemState == REDRAW_STATE)
937 LOG_DEBUG("X11WindowSystem", "Enter Redraw State");
938 this->m_systemState = IDLE_STATE;
940 // check if we are supposed to take screenshot
941 if (this->takeScreenshot!=ScreenShotNone)
947 this->checkForNewSurfaceNativeContent();
952 else if (this->m_systemState == WAKEUP_STATE)
954 LOG_DEBUG("X11WindowSystem", "Enter Wake Up State");
962 #ifndef WITH_XTHREADS
964 /* put thread in sleep mode for 500 useconds due to safe cpu performance */
971 LOG_DEBUG("X11WindowSystem", "Renderer thread finished");
976 void X11WindowSystem::ManageXInputEvent(XEvent *pevent)
980 #ifdef WITH_INPUT_EVENTS
981 XEvent* currentEvent = pevent;
986 switch (currentEvent->type)
990 pX = &(((XButtonEvent*)currentEvent)->x);
991 pY = &(((XButtonEvent*)currentEvent)->y);
995 pX = &(((XMotionEvent*)currentEvent)->x);
996 pY = &(((XMotionEvent*)currentEvent)->y);
1002 surf = m_pScene->getSurfaceAt((unsigned int *) pX, (unsigned int *) pY, 0.1);
1005 pevent->xany.window = surf->getNativeContent();
1006 XSendEvent(x11Display, currentEvent->xany.window, false, 0, currentEvent);
1008 currentEvent = NULL;
1013 #ifdef WITH_XTHREADS
1014 static Display* displaySignal = NULL;
1015 #endif //WITH_XTHREADS
1016 void X11WindowSystem::wakeUpRendererThread()
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 )
1023 displaySignal = XOpenDisplay(m_displayEnvironment);
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
1034 void X11WindowSystem::signalRedrawEvent()
1036 // set flag that redraw is needed
1037 this->m_systemState = REDRAW_STATE;
1038 this->wakeUpRendererThread();
1041 void X11WindowSystem::cleanup(){
1042 LOG_DEBUG("X11WindowSystem", "Cleanup");
1043 if (None != CompositorWindow)
1045 Window root = RootWindow(x11Display, DefaultScreen(x11Display));
1046 XCompositeUnredirectSubwindows(x11Display,root,CompositeRedirectManual);
1047 XDestroyWindow(x11Display,CompositorWindow);
1055 #ifdef WITH_XTHREADS
1056 if ( NULL != displaySignal )
1058 XCloseDisplay(displaySignal);
1060 #endif //WITH_XTHREADS
1061 XCloseDisplay(x11Display);
1065 bool X11WindowSystem::init(BaseGraphicSystem<Display*,Window>* base)
1067 #ifdef WITH_XTHREADS
1069 #endif //WITH_XTHREADS
1070 X11WindowSystem *renderer = this;
1071 graphicSystem = base;
1072 int status = pthread_create( &renderThread, NULL, X11eventLoopCallback, (void*) renderer);
1078 while (!m_initialized)
1080 usleep(10000); // TODO
1081 LOG_DEBUG("X11WindowSystem","Waiting start complete " << m_initialized);
1083 LOG_INFO("X11WindowSystem","Start complete " << m_initialized << " success " << m_success);
1087 bool X11WindowSystem::start()
1090 LOG_DEBUG("X11WindowSystem", "Starting / Creating thread");
1091 // let thread actually run
1092 if ( m_xerror == false )
1094 this->m_running = true;
1095 pthread_mutex_unlock(&run_lock);
1097 this->m_running = false;
1098 pthread_mutex_unlock(&run_lock);
1104 void X11WindowSystem::stop()
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);
1114 void X11WindowSystem::allocatePlatformSurface(Surface* surface)
1116 LOG_DEBUG("X11WindowSystem","allocatePlatformSurface begin");
1117 XPlatformSurface* nativeSurface = (XPlatformSurface*)surface->platform;
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());
1125 LOG_DEBUG("X11WindowSystem","allocatePlatformSurface end");
1128 void X11WindowSystem::deallocatePlatformSurface(Surface* surface)
1130 LOG_DEBUG("X11WindowSystem","deallocatePlatformSurface begin");
1131 XPlatformSurface* nativeSurface = (XPlatformSurface*)surface->platform;
1134 LOG_DEBUG("X11WindowSystem","destroyingnative surface");
1135 graphicSystem->getTextureBinder()->destroyClientBuffer(surface);
1137 if (nativeSurface->pixmap)
1139 int result = XFreePixmap(x11Display, nativeSurface->pixmap);
1142 surface->renderPropertyChanged = true;
1143 delete surface->platform;
1144 surface->platform = NULL;
1146 LOG_DEBUG("X11WindowSystem","deallocatePlatformSurface end");
1149 void X11WindowSystem::doScreenShot(std::string fileName)
1151 takeScreenshot = ScreenshotOfDisplay;
1152 screenShotFile = fileName;
1155 void X11WindowSystem::doScreenShotOfLayer(std::string fileName, const uint id)
1157 takeScreenshot = ScreenshotOfLayer;
1158 screenShotFile = fileName;
1159 screenShotLayerID = id;
1162 void X11WindowSystem::doScreenShotOfSurface(std::string fileName, const uint id, const uint layer_id)
1164 takeScreenshot = ScreenshotOfSurface;
1165 screenShotFile = fileName;
1166 screenShotSurfaceID = id;
1167 screenShotLayerID = layer_id;