1 /***************************************************************************
3 * Copyright (c) 2013 DirectFB integrated media GmbH
4 * Copyright (c) 2013 Renesas Solutions Corp.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 ****************************************************************************/
21 #include "DFBRenderer.h"
22 #include "WindowSystems/DFBWindowSystem.h"
33 typedef struct sManagedWindow
35 DFBPlatformSurface *platform;
39 IDirectFBSurface *surf;
46 DFBWindowSystem::DFBWindowSystem(int width, int height, Scene* pScene, InputManager* pInputManager, IDirectFB *dfb, IDirectFBDisplayLayer *layer)
47 : BaseWindowSystem(pScene, pInputManager)
48 , takeScreenshot(ScreenShotNone)
50 , screenShotSurfaceID(0)
52 , screenShotScreenID(0)
53 , resolutionWidth(width)
54 , resolutionHeight(height)
56 , m_initialized(false)
57 , m_checkWindows(false)
58 , m_primary_width(width)
59 , m_primary_height(height)
66 , m_adjusted_mouse_x(0)
67 , m_adjusted_mouse_y(0)
68 , m_iterationCounter(0)
69 , m_maxIterationDurationInMS(0)
76 , windowHeight(height)
78 , m_ignore_surface_updates(false)
79 , CompositorSurface(0)
83 pthread_mutex_init( &run_lock, NULL );
84 pthread_mutex_init( &init_lock, NULL );
85 pthread_cond_init( &init_condition,NULL );
86 direct_hash_init( &window_map, 17 );
87 direct_hash_init( &surface_map, 17 );
88 m_sceneLayers = new std::list<int>;
91 DFBWindowSystem::~DFBWindowSystem()
93 pthread_mutex_destroy( &run_lock );
94 pthread_mutex_destroy( &init_lock );
95 pthread_cond_destroy( &init_condition );
96 direct_hash_deinit( &window_map );
97 direct_hash_deinit( &surface_map );
100 bool DFBWindowSystem::isWindowValid(DFBWindow w)
102 sManagedWindow *win = (sManagedWindow *)direct_hash_lookup( &window_map, w );
106 return (w != 0 && win->surfID != CompositorSurface);
109 Surface* DFBWindowSystem::getSurfaceForWindow(DFBWindow w)
111 const std::map<unsigned int,Surface*> surfaces = m_pScene->getAllSurfaces();
112 for (std::map<unsigned int, Surface*>::const_iterator currentS = surfaces.begin(); currentS != surfaces.end(); ++currentS) {
113 Surface* currentSurface = (*currentS).second;
117 if (currentSurface->getNativeContent() == static_cast<long>(w))
118 return currentSurface;
121 LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << ": could not get surface for window " << w );
126 bool DFBWindowSystem::deleteOrphanWindow(void *win)
128 sManagedWindow *managed = (sManagedWindow *)win;
130 if (!getSurfaceForWindow( managed->winID )) {
131 LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << ": removing orphan window " << managed->winID );
133 direct_hash_remove( &window_map, managed->winID );
134 direct_hash_remove( &surface_map, managed->surfID );
136 managed->win->DetachEventBuffer( managed->win, m_events );
137 managed->surf->DetachEventBuffer( managed->surf, m_events );
139 delete managed->platform;
147 bool checkOrphanWindow(DirectHash *hash, unsigned long key, void *value, void *ctx)
151 DFBWindowSystem *windowsys = static_cast<DFBWindowSystem *>((DFBWindowSystem *)ctx);
153 windowsys->deleteOrphanWindow( value );
158 void DFBWindowSystem::checkForNewSurfaceNativeContent()
160 m_pScene->lockScene();
162 LayerList layers = m_pScene->getCurrentRenderOrder(0);
163 for (LayerListConstIterator current = layers.begin(); current != layers.end(); current++) {
164 SurfaceList surfaces = (*current)->getAllSurfaces();
165 for (SurfaceListConstIterator currentS = surfaces.begin(); currentS != surfaces.end(); currentS++) {
166 if ((*currentS)->getNativeContent())
167 allocatePlatformSurface( *currentS );
169 deallocatePlatformSurface( *currentS );
173 if (direct_hash_count( &window_map ))
174 direct_hash_iterate( &window_map, checkOrphanWindow, this );
176 m_pScene->unlockScene();
178 m_checkWindows = false;
181 void DFBWindowSystem::configureSurfaceWindow(DFBWindow window)
183 if (isWindowValid( window )) {
187 UnMapWindow( window );
190 Surface* surface = getSurfaceForWindow( window );
192 LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": could not find surface for window " << window );
196 if (!surface->platform) {
197 LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": Platform surface not available for window " << window );
201 DFBPlatformSurface* platformSurface = (DFBPlatformSurface*)surface->platform;
202 platformSurface->dfb_surface->GetSize( platformSurface->dfb_surface, &winWidth, &winHeight );
204 surface->OriginalSourceHeight = winHeight;
205 surface->OriginalSourceWidth = winWidth;
207 LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << ": successfully updated window " << window );
211 void DFBWindowSystem::MapWindow(DFBWindow window)
213 LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << "(window=" << window << ")" );
215 if (isWindowValid( window )) {
216 Surface* surface = getSurfaceForWindow( window );
218 LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": could not find surface for window " << window );
222 if (!surface->platform) {
223 LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": Platform surface not available for window " << window );
227 DFBPlatformSurface* dfbsurf = (DFBPlatformSurface*)surface->platform;
228 if (dfbsurf->isMapped) {
229 LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": Platform surface for window " << window << " was already mapped" );
233 dfbsurf->isMapped = true;
235 sManagedWindow *win = (sManagedWindow *)malloc( sizeof(sManagedWindow) );
236 win->platform = dfbsurf;
237 win->winID = dfbsurf->dfb_window_id;
238 win->win = dfbsurf->dfb_window;
239 win->surfID = dfbsurf->dfb_surface_id;
240 win->surf = dfbsurf->dfb_surface;
241 dfbsurf->dfb_window->GetPosition( dfbsurf->dfb_window, &win->x, &win->y );
242 dfbsurf->dfb_window->GetSize( dfbsurf->dfb_window, &win->w, &win->h );
244 direct_hash_insert( &window_map, dfbsurf->dfb_window_id, win );
245 direct_hash_insert( &surface_map, dfbsurf->dfb_surface_id, win );
247 surface->OriginalSourceWidth = win->w;
248 surface->OriginalSourceHeight = win->h;
249 surface->renderPropertyChanged = true;
251 m_gfx->getTextureBinder()->createClientBuffer( surface );
252 dfbsurf->enableRendering();
254 LOG_INFO( "DFBWindowSystem", __FUNCTION__ << ": successfully mapped window " << window );
258 void DFBWindowSystem::UnMapWindow(DFBWindow window)
260 LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << "(window=" << window << ")" );
262 if (isWindowValid( window )) {
263 Surface* surface = getSurfaceForWindow( window );
265 LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": could not find surface for window " << window );
269 if (!surface->platform) {
270 LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": Platform surface not available for window " << window );
274 DFBPlatformSurface* dfbsurf = (DFBPlatformSurface*)surface->platform;
275 dfbsurf->disableRendering();
276 if (!dfbsurf->isMapped) {
277 LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": Platform surface for window " << window << " was already unmapped" );
281 dfbsurf->isMapped = false;
282 m_gfx->getTextureBinder()->destroyClientBuffer( surface );
284 if (dfbsurf->dfb_surface) {
285 dfbsurf->dfb_window->DetachEventBuffer( dfbsurf->dfb_window, m_events );
286 dfbsurf->dfb_surface->DetachEventBuffer( dfbsurf->dfb_surface, m_events );
287 direct_hash_remove( &window_map, dfbsurf->dfb_window_id );
288 direct_hash_remove( &surface_map, dfbsurf->dfb_surface_id );
289 dfbsurf->dfb_surface->Release( dfbsurf->dfb_surface );
290 dfbsurf->dfb_window->Release( dfbsurf->dfb_window );
293 surface->renderPropertyChanged = true;
295 LOG_INFO( "DFBWindowSystem", __FUNCTION__ << ": successfully unmapped window " << window );
299 bool DFBWindowSystem::NewWindow(Surface* surface, DFBWindow window)
305 LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << "(surface=" << surface << ", window=" << window << ")" );
307 if (isWindowValid( window )) {
308 surface->setNativeContent( window );
309 DFBPlatformSurface *platformSurface = (DFBPlatformSurface*)m_gfx->getTextureBinder()->createPlatformSurface( surface );
310 platformSurface->isMapped = false;
312 if (!platformSurface->dfb_surface) {
313 LOG_ERROR( "DFBWindowSystem", __FUNCTION__ << ": failed to create platform surface for window " << window );
314 delete platformSurface;
318 surface->platform = platformSurface;
320 platformSurface->dfb_window->GetSize( platformSurface->dfb_window, &winWidth, &winHeight );
322 ret = platformSurface->dfb_window->AttachEventBuffer( platformSurface->dfb_window, m_events );
324 LOG_ERROR( "DFBWindowSystem", __FUNCTION__ << ": IDirectFBSurface::AttachEventBuffer() failed! (ret=" << ret << ")" );
325 delete platformSurface;
326 surface->platform = NULL;
330 ret = platformSurface->dfb_surface->AttachEventBuffer( platformSurface->dfb_surface, m_events );
332 LOG_ERROR( "DFBWindowSystem", __FUNCTION__ << ": IDirectFBSurface::AttachEventBuffer() failed! (ret=" << ret << ")" );
333 delete platformSurface;
334 surface->platform = NULL;
338 platformSurface->dfb_surface->MakeClient( platformSurface->dfb_surface );
339 surface->OriginalSourceHeight = winHeight;
340 surface->OriginalSourceWidth = winWidth;
342 LOG_INFO( "DFBWindowSystem", __FUNCTION__ << ": successfully created new surface " << platformSurface->dfb_surface << " for window " << window << " (w=" << winWidth << " h=" << winHeight << ")" );
350 void DFBWindowSystem::DestroyWindow(DFBWindow window)
352 LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << "(window=" << window << ")" );
354 if (isWindowValid( window )) {
355 Surface* surface = getSurfaceForWindow( window );
357 LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": could not find surface for window " << window );
361 m_gfx->getTextureBinder()->destroyClientBuffer( surface );
362 UnMapWindow( window );
363 surface->removeNativeContent();
365 surface->renderPropertyChanged = true;
366 delete surface->platform;
367 surface->platform = NULL;
371 int DFBWindowSystem::selectOutput(DFBGraphicSystem *gfx, int id)
375 for (int i = 0; i < gfx->m_renderer->m_num_outputs; i++) {
376 if (gfx->m_renderer->m_outputs[i].layer_id == id) {
385 void DFBWindowSystem::RedrawAllLayers(bool clear, bool swap)
387 DFBGraphicSystem *gfx;
388 DFBDisplayLayerConfig config;
390 LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << "(clear=" << clear << ", swap=" << swap << ")" );
392 LayerList layers = m_pScene->getCurrentRenderOrder( 0 );
394 std::list<int> orphan_ids = list<int>( *m_sceneLayers );
396 m_sceneLayers->clear();
398 for (LayerListConstIterator current = layers.begin(); current != layers.end(); current++) {
399 m_sceneLayers->push_back( (*current)->getID() );
400 orphan_ids.remove( (*current)->getID() );
402 if ((*current)->getLayerType() == Hardware) {
403 if (m_forceComposition || m_gfx->needsRedraw( *current ))
404 renderHWLayer( *current, clear );
407 swLayers.push_back( *current );
411 gfx = (DFBGraphicSystem *)m_gfx;
413 for(std::list<int>::iterator list_iter = orphan_ids.begin(); list_iter != orphan_ids.end(); list_iter++) {
414 int output = selectOutput( gfx, *list_iter );
416 if (!gfx->m_renderer->m_outputs[output].muted) {
417 LOG_INFO( "DFBWindowSystem", __FUNCTION__ << ": turning OFF orphan layer " << gfx->m_renderer->m_outputs[output].layer );
419 if (!gfx->m_renderer->m_outputs[output].layer->GetConfiguration( gfx->m_renderer->m_outputs[output].layer, &config )) {
420 config.options = DLOP_OPACITY;
422 if (gfx->m_renderer->m_outputs[output].layer->SetConfiguration( gfx->m_renderer->m_outputs[output].layer, &config )) {
423 LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": failed to set layer configuration on layer " << gfx->m_renderer->m_outputs[output].layer );
426 if (gfx->m_renderer->m_outputs[output].layer->SetOpacity( gfx->m_renderer->m_outputs[output].layer, 0 )) {
427 LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": failed to set opacity on layer " << gfx->m_renderer->m_outputs[output].layer );
430 gfx->m_renderer->m_outputs[output].muted = true;
431 gfx->m_renderer->m_outputs[output].layer_opacity = 0;
440 if (swLayers.size() > 0 && (m_forceComposition || m_gfx->needsRedraw( swLayers ))) {
442 renderSWLayers( swLayers, clear, swap );
444 m_gfx->renderSWLayers( swLayers, clear );
447 m_gfx->swapBuffers();
452 void DFBWindowSystem::renderSWLayers(LayerList layers, bool clear, bool swap)
454 DFBGraphicSystem *gfx = (DFBGraphicSystem *)m_gfx;
456 LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << "(clear=" << clear << ", swap=" << swap << ")" );
458 for (LayerListConstIterator layer = layers.begin(); layer != layers.end(); layer++) {
459 gfx->renderSWLayer( *layer, clear );
461 gfx->beginLayer( *layer );
462 if (gfx->m_renderer_output == -1) {
463 LOG_ERROR( "DFBWindowSystem", __FUNCTION__ << ": called with a non-existent layer" );
473 static int countVisibleSurfaces(Layer *layer)
478 SurfaceList surfaces = layer->getAllSurfaces();
479 for (SurfaceListConstIterator currentS = surfaces.begin(); currentS != surfaces.end(); currentS++) {
480 if ((*currentS)->getOpacity() > 0 && (*currentS)->getVisibility()) {
481 rect = (*currentS)->getTargetSourceRegion();
482 if (rect.width > 0 && rect.height > 0) {
483 rect = (*currentS)->getTargetDestinationRegion();
484 if (rect.width > 0 && rect.height > 0)
493 static bool isSurfaceVisible(Surface *surface)
497 if (surface->getOpacity() > 0 && surface->getVisibility()) {
498 rect = surface->getTargetSourceRegion();
499 if (rect.width > 0 && rect.height > 0) {
500 rect = surface->getTargetDestinationRegion();
501 if (rect.width > 0 && rect.height > 0)
509 void DFBWindowSystem::renderHWLayer(Layer *layer, bool clear)
511 DFBGraphicSystem *gfx = (DFBGraphicSystem *)m_gfx;
512 DFBDisplayLayerConfig config;
513 int num_surfaces_curr = 0;
515 LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << "(layer=" << layer << ", clear=" << clear << ")" );
517 gfx->beginLayer( layer );
518 if (gfx->m_renderer_output == -1) {
519 LOG_ERROR( "DFBWindowSystem", __FUNCTION__ << ": called with a non-existent layer" );
525 if (layer->getLayerType() != Hardware)
526 LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": called with a non-HW layer" );
528 if (!m_pScene->isLayerInCurrentRenderOrder( layer->getID() ) || layer->opacity == 0 || layer->visibility == 0) {
529 if (!gfx->m_renderer->m_outputs[gfx->m_renderer_output].muted) {
530 LOG_INFO( "DFBWindowSystem", __FUNCTION__ << ": turning OFF layer " << layer);
532 if (!gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer->GetConfiguration( gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer, &config )) {
533 config.options = DLOP_OPACITY;
535 if (gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer->SetConfiguration( gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer, &config )) {
536 LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": failed to set layer configuration on layer " << gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer );
539 if (gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer->SetOpacity( gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer, 0 )) {
540 LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": failed to set opacity on layer " << gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer );
543 gfx->m_renderer->m_outputs[gfx->m_renderer_output].muted = true;
544 gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer_opacity = 0;
550 else if (layer->visibility > 0 && layer->opacity > 0.0f) {
551 num_surfaces_curr = countVisibleSurfaces( layer );
552 if (num_surfaces_curr > 0) {
553 if (layer->getChromaKeyEnabled())
554 LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": cannot handle chroma key" );
557 gfx->clearBackground();
559 if (gfx->m_renderer->m_outputs[gfx->m_renderer_output].muted || gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer_opacity != layer->opacity) {
560 LOG_INFO( "DFBWindowSystem", __FUNCTION__ << ": turning ON layer " << layer << " with opacity=" << (int)(layer->opacity * 0xFF) );
562 if (!gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer->GetConfiguration( gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer, &config )) {
563 config.options = layer->opacity == 1 ? DLOP_NONE : (DFBDisplayLayerOptions)(DLOP_OPACITY | DLOP_ALPHACHANNEL);
565 if (gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer->SetConfiguration( gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer, &config )) {
566 LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": failed to set layer configuration on layer " << gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer );
569 if (gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer->SetOpacity( gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer, layer->opacity * 0xFF )) {
570 LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": failed to set opacity on layer " << gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer );
573 gfx->m_renderer->m_outputs[gfx->m_renderer_output].muted = false;
574 gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer_opacity = layer->opacity;
580 SurfaceList surfaces = layer->getAllSurfaces();
581 for (std::list<Surface*>::const_iterator currentS = surfaces.begin(); currentS != surfaces.end(); ++currentS) {
582 if ((*currentS)->hasNativeContent() && isSurfaceVisible( (*currentS) ))
583 gfx->renderSurface( *currentS );
586 else if (!gfx->m_renderer->m_outputs[gfx->m_renderer_output].muted) {
587 LOG_INFO( "DFBWindowSystem", __FUNCTION__ << ": tunring OFF layer " << layer);
589 if (!gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer->GetConfiguration( gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer, &config )) {
590 config.options = DLOP_OPACITY;
592 if (gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer->SetConfiguration( gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer, &config )) {
593 LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": failed to set layer configuration on layer " << gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer );
596 if (gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer->SetOpacity( gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer, 0 )) {
597 LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": failed to set opacity on layer " << gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer );
600 gfx->m_renderer->m_outputs[gfx->m_renderer_output].muted = true;
601 gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer_opacity = 0;
607 gfx->m_renderer->m_outputs[gfx->m_renderer_output].num_surfaces = num_surfaces_curr;
615 void DFBWindowSystem::Redraw(bool clear)
617 LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << "()" );
619 m_pScene->lockScene();
621 RedrawAllLayers( clear, true );
624 m_pScene->unlockScene();
627 void DFBWindowSystem::Screenshot()
629 LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << "()" );
631 m_pScene->lockScene();
633 if (takeScreenshot == ScreenshotOfDisplay) {
634 if (!m_dfb_mode_hw) {
635 RedrawAllLayers( true, false );
636 m_gfx->saveScreenShotOfFramebuffer( screenShotFile );
639 LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": Screetshot of FrameBuffer currently unsupported!" );
641 else if (takeScreenshot == ScreenshotOfLayer) {
642 Layer* layer = m_pScene->getLayer( screenShotLayerID );
644 m_gfx->renderSWLayer( layer, true );
646 m_gfx->beginLayer( layer );
647 m_gfx->saveScreenShotOfFramebuffer( screenShotFile );
652 else if (takeScreenshot == ScreenshotOfSurface) {
653 Layer* layer = m_pScene->getLayer( screenShotLayerID );
654 Surface* surface = m_pScene->getSurface( screenShotSurfaceID );
655 if (layer != NULL && surface != NULL) {
656 m_gfx->clearBackground();
657 m_gfx->beginLayer( layer );
658 m_gfx->renderSurface( surface );
659 m_gfx->saveScreenShotOfFramebuffer( screenShotFile );
664 takeScreenshot = ScreenShotNone;
666 m_pScene->unlockScene();
669 void *startEventLoop(void *ptr)
671 DFBWindowSystem *windowsys = static_cast<DFBWindowSystem *>((DFBWindowSystem *)ptr);
672 windowsys->EventLoop();
677 static void genWindowEventFromInput(const DFBInputEvent *inputEvent, DFBWindowID wid, DFBWindowEventType etype, int x, int y, int cx, int cy, DFBWindowEvent *windowEvent)
679 memset( windowEvent, 0, sizeof(DFBWindowEvent) );
681 windowEvent->type = etype;
682 windowEvent->window_id = wid;
683 windowEvent->flags = DWEF_DEVICE_ID;
686 windowEvent->cx = cx;
687 windowEvent->cy = cy;
688 windowEvent->device_id = inputEvent->device_id;
689 windowEvent->timestamp = inputEvent->timestamp;
690 windowEvent->key_code = inputEvent->key_code;
691 windowEvent->key_id = inputEvent->key_id;
692 windowEvent->key_symbol = inputEvent->key_symbol;
693 windowEvent->modifiers = inputEvent->modifiers;
694 windowEvent->locks = inputEvent->locks;
695 windowEvent->button = inputEvent->button;
696 windowEvent->buttons = inputEvent->buttons;
699 void DFBWindowSystem::EventLoop()
703 DFBPlatformSurface *surf;
704 DFBWindowEvent windowEvent;
709 LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << ": using compositor primary " << m_primary << " with id " << CompositorSurface << " (w=" << m_primary_width << " h=" << m_primary_height << ")" );
711 m_primary->Clear( m_primary, 0, 0, 0, 0 );
712 m_primary->Flip( m_primary, NULL, DSFLIP_NONE );
714 m_gfx->init( dfbDisplay, (long)m_primary );
715 m_gfx->activateGraphicContext();
716 m_gfx->clearBackground();
717 m_gfx->swapBuffers();
720 pthread_mutex_lock( &init_lock );
722 pthread_cond_signal( &init_condition );
723 pthread_mutex_unlock( &init_lock );
726 if (m_checkWindows) {
727 checkForNewSurfaceNativeContent();
736 if (takeScreenshot != ScreenShotNone)
739 m_events->WaitForEventWithTimeout( m_events, 0, 300 );
741 pthread_mutex_lock( &run_lock );
743 while (m_events->GetEvent( m_events, &event ) == DFB_OK) {
744 switch (event.clazz) {
746 switch (event.window.type) {
748 LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << ": WINDOW POSITION event for window id " << event.window.window_id );
750 win = (sManagedWindow *)direct_hash_lookup( &window_map, event.window.window_id );
752 win->x = event.window.x;
753 win->y = event.window.y;
756 LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": could not find window for id " << event.window.window_id );
763 switch (event.surface.type) {
765 if (!m_ignore_surface_updates) {
766 LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << ": SURFACE UPDATE event for surface id " << event.surface.surface_id );
768 win = (sManagedWindow *)direct_hash_lookup( &surface_map, event.surface.surface_id );
770 LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << ": sending FrameAck for surface id " << event.surface.surface_id << " (frame=" << event.surface.flip_count << ")" );
771 win->surf->FrameAck( win->surf, event.surface.flip_count );
775 LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": could not find surface for id " << event.surface.surface_id );
778 LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << ": SURFACE UPDATE event for surface id " << event.surface.surface_id << " -- ignoring" );
786 pos.x = m_adjusted_mouse_x;
787 pos.y = m_adjusted_mouse_y;
788 switch (event.input.type) {
790 LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << " --> KEYPRESS" );
792 surface = m_pInputManager->reportKeyboardEvent( INPUT_STATE_PRESSED, event.input.key_code );
793 if (surface && surface->platform) {
794 surf = (DFBPlatformSurface *)surface->platform;
795 win = (sManagedWindow *)direct_hash_lookup( &window_map, event.window.window_id );
797 LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": could not find window for id " << event.window.window_id );
800 genWindowEventFromInput( &event.input, surf->dfb_window_id, DWET_KEYDOWN, m_adjusted_mouse_x, m_adjusted_mouse_y, m_adjusted_mouse_x - win->x, m_adjusted_mouse_y - win->y, &windowEvent );
801 win->win->SendEvent( win->win, &windowEvent );
804 case DIET_KEYRELEASE:
805 LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << " --> KEYRELEASE" );
807 surface = m_pInputManager->reportKeyboardEvent( INPUT_STATE_RELEASED, event.input.key_code );
808 if (surface && surface->platform) {
809 surf = (DFBPlatformSurface *)surface->platform;
810 win = (sManagedWindow *)direct_hash_lookup( &window_map, event.window.window_id );
812 LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": could not find window for id " << event.window.window_id );
815 genWindowEventFromInput( &event.input, surf->dfb_window_id, DWET_KEYUP, m_adjusted_mouse_x, m_adjusted_mouse_y, m_adjusted_mouse_x - win->x, m_adjusted_mouse_y - win->y, &windowEvent );
816 win->win->SendEvent( win->win, &windowEvent );
819 case DIET_BUTTONPRESS:
820 LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << " --> BUTTONPRESS" );
822 pos.state = INPUT_STATE_PRESSED;
823 surface = m_pInputManager->reportPointerEvent( pos );
824 if (surface && surface->platform) {
825 surf = (DFBPlatformSurface *)surface->platform;
826 win = (sManagedWindow *)direct_hash_lookup( &window_map, event.window.window_id );
828 LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": could not find window for id " << event.window.window_id );
831 genWindowEventFromInput( &event.input, surf->dfb_window_id, DWET_BUTTONDOWN, m_adjusted_mouse_x, m_adjusted_mouse_y, m_adjusted_mouse_x - win->x, m_adjusted_mouse_y - win->y, &windowEvent );
832 win->win->SendEvent( win->win, &windowEvent );
835 case DIET_BUTTONRELEASE:
836 LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << " --> BUTTONRELEASE" );
838 pos.state = INPUT_STATE_RELEASED;
839 surface = m_pInputManager->reportPointerEvent( pos );
840 if (surface && surface->platform) {
841 surf = (DFBPlatformSurface *)surface->platform;
842 win = (sManagedWindow *)direct_hash_lookup( &window_map, event.window.window_id );
844 LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": could not find window for id " << event.window.window_id );
847 genWindowEventFromInput( &event.input, surf->dfb_window_id, DWET_BUTTONUP, m_adjusted_mouse_x, m_adjusted_mouse_y, m_adjusted_mouse_x - win->x, m_adjusted_mouse_y - win->y, &windowEvent );
848 win->win->SendEvent( win->win, &windowEvent );
851 case DIET_AXISMOTION:
852 pos.state = INPUT_STATE_MOTION;
853 if (event.input.flags & DIEF_AXISABS) {
854 switch (event.input.axis) {
856 m_mouse_x = event.input.axisabs;
857 m_mouse_x_min = event.input.min;
858 m_mouse_x_max = event.input.max;
861 m_mouse_y = event.input.axisabs;
862 m_mouse_y_min = event.input.min;
863 m_mouse_y_max = event.input.max;
869 else if (event.input.flags & DIEF_AXISREL) {
870 switch (event.input.axis) {
872 m_mouse_x += event.input.axisrel;
875 m_mouse_y += event.input.axisrel;
882 if (m_mouse_y_min < m_mouse_y_max && m_mouse_x_min < m_mouse_x_max) {
883 m_adjusted_mouse_x = CLAMP(m_mouse_x, 0, m_mouse_x_max);
884 m_adjusted_mouse_y = CLAMP(m_mouse_y, 0, m_mouse_y_max);
885 m_adjusted_mouse_x = ((m_primary_width - 1) * m_adjusted_mouse_x) / m_mouse_x_max;
886 m_adjusted_mouse_y = ((m_primary_height - 1) * m_adjusted_mouse_y) / m_mouse_y_max;
889 m_adjusted_mouse_x = CLAMP(m_mouse_x, 0, m_primary_width - 1);
890 m_adjusted_mouse_y = CLAMP(m_mouse_y, 0, m_primary_height - 1);
893 LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << " --> MOTION at " << m_adjusted_mouse_x << "," << m_adjusted_mouse_y );
895 pos.x = m_adjusted_mouse_x;
896 pos.y = m_adjusted_mouse_y;
898 surface = m_pInputManager->reportPointerEvent( pos );
899 if (surface && surface->platform) {
900 surf = (DFBPlatformSurface *)surface->platform;
901 win = (sManagedWindow *)direct_hash_lookup( &window_map, event.window.window_id );
903 LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": could not find window for id " << event.window.window_id );
906 genWindowEventFromInput( &event.input, surf->dfb_window_id, DWET_MOTION, m_adjusted_mouse_x, m_adjusted_mouse_y, m_adjusted_mouse_x - win->x, m_adjusted_mouse_y - win->y, &windowEvent );
907 win->win->SendEvent( win->win, &windowEvent );
911 LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << " --> UNKNOWN INPUT EVENT" );
920 pthread_mutex_unlock( &run_lock );
925 LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << " --> finished" );
928 void DFBWindowSystem::signalRedrawEvent()
930 LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << "()" );
932 pthread_mutex_lock( &run_lock );
934 m_checkWindows = true;
935 m_events->WakeUp( m_events );
937 pthread_mutex_unlock( &run_lock );
940 void DFBWindowSystem::cleanup()
942 pthread_mutex_lock( &run_lock );
945 m_initialized = false;
948 m_events->Release( m_events );
953 m_primary->Release( m_primary );
957 pthread_mutex_unlock( &run_lock );
960 bool DFBWindowSystem::init(BaseGraphicSystem<DFBDisplay, DFBWindow>* base, bool dfb_mode_hw)
964 LOG_INFO( "DFBWindowSystem", __FUNCTION__ << "(hw=" << dfb_mode_hw << ")" );
967 m_dfb_mode_hw = dfb_mode_hw;
969 m_forceComposition = true;
971 ret = m_dfb->CreateInputEventBuffer( m_dfb, (DFBInputDeviceCapabilities)(DICAPS_KEYS | DICAPS_BUTTONS | DICAPS_AXES), DFB_FALSE, &m_events );
973 LOG_ERROR( "DFBWindowSystem", __FUNCTION__ << ": IDirectFB::CreateEventBuffer() failed! (ret=" << ret << ")" );
977 if (!m_dfb_mode_hw) {
978 DFBSurfaceID surf_id;
980 ret = m_layer->GetSurface( m_layer, &m_primary );
982 LOG_ERROR( "DFBWindowSystem", __FUNCTION__ << ": IDirectFBDisplayLayer::GetSurface() failed! (ret=" << ret << ")" );
983 m_events->Release( m_events );
985 m_primary->Release( m_primary );
990 m_primary->GetSize( m_primary, &m_primary_width, &m_primary_height );
992 LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << ": retrieved layer primary " << m_primary << " (w=" << m_primary_width << " h=" << m_primary_height << ")" );
994 m_primary->GetID( m_primary, &surf_id );
995 CompositorSurface = surf_id;
998 pthread_mutex_lock( &init_lock );
1000 int status = pthread_create( &renderThread, NULL, startEventLoop, this );
1002 pthread_mutex_unlock( &init_lock );
1007 pthread_cond_wait( &init_condition, &init_lock );
1009 pthread_mutex_unlock( &init_lock );
1011 LOG_INFO( "DFBWindowSystem", __FUNCTION__ << " --> initialized" );
1016 bool DFBWindowSystem::start(int maxIterationDurationInMS)
1018 LOG_INFO( "DFBWindowSystem", __FUNCTION__ << "(" << maxIterationDurationInMS << ")" );
1020 pthread_mutex_lock( &run_lock );
1022 LayerList layers = m_pScene->getCurrentRenderOrder( 0 );
1023 for (LayerListConstIterator current = layers.begin(); current != layers.end(); current++)
1024 m_sceneLayers->push_back( (*current)->getID() );
1026 m_maxIterationDurationInMS = maxIterationDurationInMS;
1030 m_checkWindows = true;
1031 m_events->WakeUp( m_events );
1033 pthread_mutex_unlock( &run_lock );
1038 void DFBWindowSystem::stop()
1040 LOG_INFO( "DFBWindowSystem", __FUNCTION__ << "()" );
1042 pthread_mutex_lock( &run_lock );
1044 m_sceneLayers->clear();
1047 m_events->WakeUp( m_events );
1049 pthread_mutex_unlock( &run_lock );
1051 pthread_join( renderThread, NULL );
1054 void DFBWindowSystem::allocatePlatformSurface(Surface* surface)
1056 LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << "(" << surface << ")" );
1058 DFBPlatformSurface* nativeSurface = (DFBPlatformSurface*)surface->platform;
1059 if (!nativeSurface) {
1060 if (NewWindow( surface, surface->getNativeContent() ))
1061 MapWindow( surface->getNativeContent() );
1065 void DFBWindowSystem::deallocatePlatformSurface(Surface* surface)
1067 LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << "(" << surface << ")" );
1069 DFBPlatformSurface* nativeSurface = (DFBPlatformSurface*)surface->platform;
1070 if (nativeSurface) {
1071 m_gfx->getTextureBinder()->destroyClientBuffer( surface );
1073 if (nativeSurface->dfb_surface)
1074 nativeSurface->dfb_surface->Release( nativeSurface->dfb_surface );
1076 if (nativeSurface->dfb_window)
1077 nativeSurface->dfb_window->Release( nativeSurface->dfb_window );
1079 surface->renderPropertyChanged = true;
1080 delete surface->platform;
1081 surface->platform = NULL;
1085 void DFBWindowSystem::doScreenShot(std::string fileName, const uint screen_id)
1087 takeScreenshot = ScreenshotOfDisplay;
1088 screenShotFile = fileName;
1089 screenShotScreenID = screen_id;
1092 void DFBWindowSystem::doScreenShotOfLayer(std::string fileName, const uint id)
1094 takeScreenshot = ScreenshotOfLayer;
1095 screenShotFile = fileName;
1096 screenShotLayerID = id;
1099 void DFBWindowSystem::doScreenShotOfSurface(std::string fileName, const uint id, const uint layer_id)
1101 takeScreenshot = ScreenshotOfSurface;
1102 screenShotFile = fileName;
1103 screenShotSurfaceID = id;
1104 screenShotLayerID = layer_id;
1107 DFBDisplay DFBWindowSystem::getNativeDisplayHandle()
1112 int DFBWindowSystem::getIterationCounter()
1114 return m_iterationCounter;