From 9d8a28302d3d7f3167d58b6d2839e3d688c3fb3c Mon Sep 17 00:00:00 2001 From: Marek Pikarski Date: Tue, 1 Oct 2013 09:38:23 +0200 Subject: [PATCH] WindowSystems: Added support for DirectFB Added DirectFB window system which manages all windows/surfaces as used by LM running on DirectFB. Signed-off-by: Marek Pikarski --- .../include/WindowSystems/DFBWindowSystem.h | 121 +++ .../Graphic/src/WindowSystems/DFBWindowSystem.cpp | 1116 ++++++++++++++++++++ 2 files changed, 1237 insertions(+) create mode 100644 LayerManagerPlugins/Renderers/Graphic/include/WindowSystems/DFBWindowSystem.h create mode 100644 LayerManagerPlugins/Renderers/Graphic/src/WindowSystems/DFBWindowSystem.cpp diff --git a/LayerManagerPlugins/Renderers/Graphic/include/WindowSystems/DFBWindowSystem.h b/LayerManagerPlugins/Renderers/Graphic/include/WindowSystems/DFBWindowSystem.h new file mode 100644 index 0000000..3d28256 --- /dev/null +++ b/LayerManagerPlugins/Renderers/Graphic/include/WindowSystems/DFBWindowSystem.h @@ -0,0 +1,121 @@ +/*************************************************************************** + * + * Copyright (c) 2013 DirectFB integrated media GmbH + * Copyright (c) 2013 Renesas Solutions Corp. + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ + +#ifndef _DFBWINDOWSYSTEM_H_ +#define _DFBWINDOWSYSTEM_H_ + +#include "GraphicSystems/DFBGraphicSystem.h" +#include "GraphicSystems/GLESGraphicSystem.h" +#include "WindowSystems/BaseWindowSystem.h" +#include "Surface.h" +#include "PlatformSurfaces/EglDFBPlatformSurface.h" +#include "ScreenShotType.h" + +extern "C" { +#include +} + +class DFBWindowSystem: public BaseWindowSystem { +public: + DFBWindowSystem(int width, int height, Scene* pScene, InputManager* pInputManager, IDirectFB *dfb, IDirectFBDisplayLayer *layer); + virtual ~DFBWindowSystem(); + bool init(BaseGraphicSystem* base, bool dfb_mode_hw); + bool start(int maxIterationDurationInMS); + void stop(); + void signalRedrawEvent(); + virtual void allocatePlatformSurface(Surface *surface); + virtual void deallocatePlatformSurface(Surface *surface); + void doScreenShot(std::string fileName, const uint screen_id); + void doScreenShotOfLayer(std::string fileName, const uint id); + void doScreenShotOfSurface(std::string fileName, const uint id, const uint layer_id); + DFBDisplay getNativeDisplayHandle(); + int getIterationCounter(); +private: + ScreenShotType takeScreenshot; + std::string screenShotFile; + uint screenShotSurfaceID; + uint screenShotLayerID; + uint screenShotScreenID; + int resolutionWidth; + int resolutionHeight; + bool m_running; + bool m_initialized; + bool m_checkWindows; + int m_primary_width; + int m_primary_height; + int m_mouse_x; + int m_mouse_y; + int m_mouse_x_min; + int m_mouse_y_min; + int m_mouse_x_max; + int m_mouse_y_max; + int m_adjusted_mouse_x; + int m_adjusted_mouse_y; + int m_iterationCounter; + int m_maxIterationDurationInMS; + std::list *m_sceneLayers; +protected: + IDirectFB *m_dfb; + IDirectFBDisplayLayer *m_layer; + DFBDisplay dfbDisplay; + IDirectFBSurface *m_primary; + DirectHash window_map; + DirectHash surface_map; + pthread_t renderThread; + int windowWidth; + int windowHeight; + bool m_dfb_mode_hw; + bool m_ignore_surface_updates; + DFBSurfaceID CompositorSurface; + IDirectFBEventBuffer *m_events; + pthread_mutex_t run_lock; + pthread_mutex_t init_lock; + pthread_cond_t init_condition; + BaseGraphicSystem* m_gfx; + virtual void RedrawAllLayers(bool clear, bool swap); + virtual void renderSWLayers(LayerList layers, bool clear, bool swap); + virtual void renderHWLayer(Layer* layer, bool clear); +private: + void cleanup(); + void Screenshot(); + void Redraw(bool clear); + void createSurfaceForWindow(DFBWindow w); + void configureSurfaceWindow(DFBWindow w); + Surface* getSurfaceForWindow(DFBWindow w); + void checkForNewSurfaceNativeContent(); + void destroy_surface(DFBWindow w); + void updateSurface(Surface* s, DFBWindow w, DFBPlatformSurface* dfbsurf); + void MapWindow(DFBWindow w); + void UnMapWindow(DFBWindow w); + bool NewWindow(Surface* s, DFBWindow w); + void DestroyWindow(DFBWindow w); + bool isWindowValid(DFBWindow w); + void EventLoop(); + void ManageDFBInputEvent(InputDevice type, InputEventState state, DFBEvent *pevent); + bool deleteOrphanWindow(void *win); + int selectOutput(DFBGraphicSystem *gfx, int id); + friend void *startEventLoop(void *); + friend bool checkOrphanWindow(DirectHash *hash, unsigned long key, void *value, void *ctx); + + friend class DFBGraphicSystem; +}; + +#endif + diff --git a/LayerManagerPlugins/Renderers/Graphic/src/WindowSystems/DFBWindowSystem.cpp b/LayerManagerPlugins/Renderers/Graphic/src/WindowSystems/DFBWindowSystem.cpp new file mode 100644 index 0000000..661b102 --- /dev/null +++ b/LayerManagerPlugins/Renderers/Graphic/src/WindowSystems/DFBWindowSystem.cpp @@ -0,0 +1,1116 @@ +/*************************************************************************** + * + * Copyright (c) 2013 DirectFB integrated media GmbH + * Copyright (c) 2013 Renesas Solutions Corp. + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************/ + +#include "DFBRenderer.h" +#include "WindowSystems/DFBWindowSystem.h" +#include "config.h" +#include "Layer.h" +#include +#include +#include +#include +#include +#include +#include + +typedef struct sManagedWindow +{ + DFBPlatformSurface *platform; + DFBWindowID winID; + IDirectFBWindow *win; + DFBSurfaceID surfID; + IDirectFBSurface *surf; + int x; + int y; + int w; + int h; +} sManagedWindow; + +DFBWindowSystem::DFBWindowSystem(int width, int height, Scene* pScene, InputManager* pInputManager, IDirectFB *dfb, IDirectFBDisplayLayer *layer) +: BaseWindowSystem(pScene, pInputManager) +, takeScreenshot(ScreenShotNone) +, screenShotFile() +, screenShotSurfaceID(0) +, screenShotLayerID() +, screenShotScreenID(0) +, resolutionWidth(width) +, resolutionHeight(height) +, m_running(false) +, m_initialized(false) +, m_checkWindows(false) +, m_primary_width(width) +, m_primary_height(height) +, m_mouse_x(0) +, m_mouse_y(0) +, m_mouse_x_min(-1) +, m_mouse_y_min(-1) +, m_mouse_x_max(-1) +, m_mouse_y_max(-1) +, m_adjusted_mouse_x(0) +, m_adjusted_mouse_y(0) +, m_iterationCounter(0) +, m_maxIterationDurationInMS(0) +, m_dfb(dfb) +, m_layer(layer) +, dfbDisplay(0) +, m_primary(NULL) +, renderThread(0) +, windowWidth(width) +, windowHeight(height) +, m_dfb_mode_hw(true) +, m_ignore_surface_updates(false) +, CompositorSurface(0) +, m_events(NULL) +, m_gfx(NULL) +{ + pthread_mutex_init( &run_lock, NULL ); + pthread_mutex_init( &init_lock, NULL ); + pthread_cond_init( &init_condition,NULL ); + direct_hash_init( &window_map, 17 ); + direct_hash_init( &surface_map, 17 ); + m_sceneLayers = new std::list; +} + +DFBWindowSystem::~DFBWindowSystem() +{ + pthread_mutex_destroy( &run_lock ); + pthread_mutex_destroy( &init_lock ); + pthread_cond_destroy( &init_condition ); + direct_hash_deinit( &window_map ); + direct_hash_deinit( &surface_map ); +} + +bool DFBWindowSystem::isWindowValid(DFBWindow w) +{ + sManagedWindow *win = (sManagedWindow *)direct_hash_lookup( &window_map, w ); + if (!win) + return true; + + return (w != 0 && win->surfID != CompositorSurface); +} + +Surface* DFBWindowSystem::getSurfaceForWindow(DFBWindow w) +{ + const std::map surfaces = m_pScene->getAllSurfaces(); + for (std::map::const_iterator currentS = surfaces.begin(); currentS != surfaces.end(); ++currentS) { + Surface* currentSurface = (*currentS).second; + if (!currentSurface) + continue; + + if (currentSurface->getNativeContent() == static_cast(w)) + return currentSurface; + } + + LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << ": could not get surface for window " << w ); + + return NULL; +} + +bool DFBWindowSystem::deleteOrphanWindow(void *win) +{ + sManagedWindow *managed = (sManagedWindow *)win; + + if (!getSurfaceForWindow( managed->winID )) { + LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << ": removing orphan window " << managed->winID ); + + direct_hash_remove( &window_map, managed->winID ); + direct_hash_remove( &surface_map, managed->surfID ); + + managed->win->DetachEventBuffer( managed->win, m_events ); + managed->surf->DetachEventBuffer( managed->surf, m_events ); + + delete managed->platform; + + return true; + } + + return false; +} + +bool checkOrphanWindow(DirectHash *hash, unsigned long key, void *value, void *ctx) +{ + (void)hash; + (void)key; + DFBWindowSystem *windowsys = static_cast((DFBWindowSystem *)ctx); + + windowsys->deleteOrphanWindow( value ); + + return true; +} + +void DFBWindowSystem::checkForNewSurfaceNativeContent() +{ + m_pScene->lockScene(); + + LayerList layers = m_pScene->getCurrentRenderOrder(0); + for (LayerListConstIterator current = layers.begin(); current != layers.end(); current++) { + SurfaceList surfaces = (*current)->getAllSurfaces(); + for (SurfaceListConstIterator currentS = surfaces.begin(); currentS != surfaces.end(); currentS++) { + if ((*currentS)->getNativeContent()) + allocatePlatformSurface( *currentS ); + else + deallocatePlatformSurface( *currentS ); + } + } + + if (direct_hash_count( &window_map )) + direct_hash_iterate( &window_map, checkOrphanWindow, this ); + + m_pScene->unlockScene(); + + m_checkWindows = false; +} + +void DFBWindowSystem::configureSurfaceWindow(DFBWindow window) +{ + if (isWindowValid( window )) { + int winWidth = 0; + int winHeight = 0; + + UnMapWindow( window ); + MapWindow( window ); + + Surface* surface = getSurfaceForWindow( window ); + if (!surface) { + LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": could not find surface for window " << window ); + return; + } + + if (!surface->platform) { + LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": Platform surface not available for window " << window ); + return; + } + + DFBPlatformSurface* platformSurface = (DFBPlatformSurface*)surface->platform; + platformSurface->dfb_surface->GetSize( platformSurface->dfb_surface, &winWidth, &winHeight ); + + surface->OriginalSourceHeight = winHeight; + surface->OriginalSourceWidth = winWidth; + + LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << ": successfully updated window " << window ); + } +} + +void DFBWindowSystem::MapWindow(DFBWindow window) +{ + LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << "(window=" << window << ")" ); + + if (isWindowValid( window )) { + Surface* surface = getSurfaceForWindow( window ); + if (!surface) { + LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": could not find surface for window " << window ); + return; + } + + if (!surface->platform) { + LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": Platform surface not available for window " << window ); + return; + } + + DFBPlatformSurface* dfbsurf = (DFBPlatformSurface*)surface->platform; + if (dfbsurf->isMapped) { + LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": Platform surface for window " << window << " was already mapped" ); + return; + } + + dfbsurf->isMapped = true; + + sManagedWindow *win = (sManagedWindow *)malloc( sizeof(sManagedWindow) ); + win->platform = dfbsurf; + win->winID = dfbsurf->dfb_window_id; + win->win = dfbsurf->dfb_window; + win->surfID = dfbsurf->dfb_surface_id; + win->surf = dfbsurf->dfb_surface; + dfbsurf->dfb_window->GetPosition( dfbsurf->dfb_window, &win->x, &win->y ); + dfbsurf->dfb_window->GetSize( dfbsurf->dfb_window, &win->w, &win->h ); + + direct_hash_insert( &window_map, dfbsurf->dfb_window_id, win ); + direct_hash_insert( &surface_map, dfbsurf->dfb_surface_id, win ); + + surface->OriginalSourceWidth = win->w; + surface->OriginalSourceHeight = win->h; + surface->renderPropertyChanged = true; + + m_gfx->getTextureBinder()->createClientBuffer( surface ); + dfbsurf->enableRendering(); + + LOG_INFO( "DFBWindowSystem", __FUNCTION__ << ": successfully mapped window " << window ); + } +} + +void DFBWindowSystem::UnMapWindow(DFBWindow window) +{ + LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << "(window=" << window << ")" ); + + if (isWindowValid( window )) { + Surface* surface = getSurfaceForWindow( window ); + if (!surface) { + LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": could not find surface for window " << window ); + return; + } + + if (!surface->platform) { + LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": Platform surface not available for window " << window ); + return; + } + + DFBPlatformSurface* dfbsurf = (DFBPlatformSurface*)surface->platform; + dfbsurf->disableRendering(); + if (!dfbsurf->isMapped) { + LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": Platform surface for window " << window << " was already unmapped" ); + return; + } + + dfbsurf->isMapped = false; + m_gfx->getTextureBinder()->destroyClientBuffer( surface ); + + if (dfbsurf->dfb_surface) { + dfbsurf->dfb_window->DetachEventBuffer( dfbsurf->dfb_window, m_events ); + dfbsurf->dfb_surface->DetachEventBuffer( dfbsurf->dfb_surface, m_events ); + direct_hash_remove( &window_map, dfbsurf->dfb_window_id ); + direct_hash_remove( &surface_map, dfbsurf->dfb_surface_id ); + dfbsurf->dfb_surface->Release( dfbsurf->dfb_surface ); + dfbsurf->dfb_window->Release( dfbsurf->dfb_window ); + } + + surface->renderPropertyChanged = true; + + LOG_INFO( "DFBWindowSystem", __FUNCTION__ << ": successfully unmapped window " << window ); + } +} + +bool DFBWindowSystem::NewWindow(Surface* surface, DFBWindow window) +{ + DFBResult ret; + int winWidth = 0; + int winHeight = 0; + + LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << "(surface=" << surface << ", window=" << window << ")" ); + + if (isWindowValid( window )) { + surface->setNativeContent( window ); + DFBPlatformSurface *platformSurface = (DFBPlatformSurface*)m_gfx->getTextureBinder()->createPlatformSurface( surface ); + platformSurface->isMapped = false; + + if (!platformSurface->dfb_surface) { + LOG_ERROR( "DFBWindowSystem", __FUNCTION__ << ": failed to create platform surface for window " << window ); + delete platformSurface; + return false; + } + + surface->platform = platformSurface; + + platformSurface->dfb_window->GetSize( platformSurface->dfb_window, &winWidth, &winHeight ); + + ret = platformSurface->dfb_window->AttachEventBuffer( platformSurface->dfb_window, m_events ); + if (ret) { + LOG_ERROR( "DFBWindowSystem", __FUNCTION__ << ": IDirectFBSurface::AttachEventBuffer() failed! (ret=" << ret << ")" ); + delete platformSurface; + surface->platform = NULL; + return false; + } + + ret = platformSurface->dfb_surface->AttachEventBuffer( platformSurface->dfb_surface, m_events ); + if (ret) { + LOG_ERROR( "DFBWindowSystem", __FUNCTION__ << ": IDirectFBSurface::AttachEventBuffer() failed! (ret=" << ret << ")" ); + delete platformSurface; + surface->platform = NULL; + return false; + } + + platformSurface->dfb_surface->MakeClient( platformSurface->dfb_surface ); + surface->OriginalSourceHeight = winHeight; + surface->OriginalSourceWidth = winWidth; + + LOG_INFO( "DFBWindowSystem", __FUNCTION__ << ": successfully created new surface " << platformSurface->dfb_surface << " for window " << window << " (w=" << winWidth << " h=" << winHeight << ")" ); + + return true; + } + + return false; +} + +void DFBWindowSystem::DestroyWindow(DFBWindow window) +{ + LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << "(window=" << window << ")" ); + + if (isWindowValid( window )) { + Surface* surface = getSurfaceForWindow( window ); + if (!surface) { + LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": could not find surface for window " << window ); + return; + } + + m_gfx->getTextureBinder()->destroyClientBuffer( surface ); + UnMapWindow( window ); + surface->removeNativeContent(); + + surface->renderPropertyChanged = true; + delete surface->platform; + surface->platform = NULL; + } +} + +int DFBWindowSystem::selectOutput(DFBGraphicSystem *gfx, int id) +{ + int ret = -1; + + for (int i = 0; i < gfx->m_renderer->m_num_outputs; i++) { + if (gfx->m_renderer->m_outputs[i].layer_id == id) { + ret = i; + break; + } + } + + return ret; +} + +void DFBWindowSystem::RedrawAllLayers(bool clear, bool swap) +{ + DFBGraphicSystem *gfx; + DFBDisplayLayerConfig config; + + LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << "(clear=" << clear << ", swap=" << swap << ")" ); + + LayerList layers = m_pScene->getCurrentRenderOrder( 0 ); + LayerList swLayers; + std::list orphan_ids = list( *m_sceneLayers ); + + m_sceneLayers->clear(); + + for (LayerListConstIterator current = layers.begin(); current != layers.end(); current++) { + m_sceneLayers->push_back( (*current)->getID() ); + orphan_ids.remove( (*current)->getID() ); + + if ((*current)->getLayerType() == Hardware) { + if (m_forceComposition || m_gfx->needsRedraw( *current )) + renderHWLayer( *current, clear ); + } + else + swLayers.push_back( *current ); + } + + if (m_dfb_mode_hw) { + gfx = (DFBGraphicSystem *)m_gfx; + + for(std::list::iterator list_iter = orphan_ids.begin(); list_iter != orphan_ids.end(); list_iter++) { + int output = selectOutput( gfx, *list_iter ); + if (output >= 0) { + if (!gfx->m_renderer->m_outputs[output].muted) { + LOG_INFO( "DFBWindowSystem", __FUNCTION__ << ": turning OFF orphan layer " << gfx->m_renderer->m_outputs[output].layer ); + + if (!gfx->m_renderer->m_outputs[output].layer->GetConfiguration( gfx->m_renderer->m_outputs[output].layer, &config )) { + config.options = DLOP_OPACITY; + + if (gfx->m_renderer->m_outputs[output].layer->SetConfiguration( gfx->m_renderer->m_outputs[output].layer, &config )) { + LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": failed to set layer configuration on layer " << gfx->m_renderer->m_outputs[output].layer ); + } + else { + if (gfx->m_renderer->m_outputs[output].layer->SetOpacity( gfx->m_renderer->m_outputs[output].layer, 0 )) { + LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": failed to set opacity on layer " << gfx->m_renderer->m_outputs[output].layer ); + } + else { + gfx->m_renderer->m_outputs[output].muted = true; + gfx->m_renderer->m_outputs[output].layer_opacity = 0; + } + } + } + } + } + } + } + + if (swLayers.size() > 0 && (m_forceComposition || m_gfx->needsRedraw( swLayers ))) { + if (m_dfb_mode_hw) + renderSWLayers( swLayers, clear, swap ); + else { + m_gfx->renderSWLayers( swLayers, clear ); + + if (swap) + m_gfx->swapBuffers(); + } + } +} + +void DFBWindowSystem::renderSWLayers(LayerList layers, bool clear, bool swap) +{ + DFBGraphicSystem *gfx = (DFBGraphicSystem *)m_gfx; + + LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << "(clear=" << clear << ", swap=" << swap << ")" ); + + for (LayerListConstIterator layer = layers.begin(); layer != layers.end(); layer++) { + gfx->renderSWLayer( *layer, clear ); + if (swap) { + gfx->beginLayer( *layer ); + if (gfx->m_renderer_output == -1) { + LOG_ERROR( "DFBWindowSystem", __FUNCTION__ << ": called with a non-existent layer" ); + gfx->endLayer(); + continue; + } + gfx->swapBuffers(); + gfx->endLayer(); + } + } +} + +static int countVisibleSurfaces(Layer *layer) +{ + int ret = 0; + FloatRectangle rect; + + SurfaceList surfaces = layer->getAllSurfaces(); + for (SurfaceListConstIterator currentS = surfaces.begin(); currentS != surfaces.end(); currentS++) { + if ((*currentS)->getOpacity() > 0 && (*currentS)->getVisibility()) { + rect = (*currentS)->getTargetSourceRegion(); + if (rect.width > 0 && rect.height > 0) { + rect = (*currentS)->getTargetDestinationRegion(); + if (rect.width > 0 && rect.height > 0) + ret++; + } + } + } + + return ret; +} + +static bool isSurfaceVisible(Surface *surface) +{ + FloatRectangle rect; + + if (surface->getOpacity() > 0 && surface->getVisibility()) { + rect = surface->getTargetSourceRegion(); + if (rect.width > 0 && rect.height > 0) { + rect = surface->getTargetDestinationRegion(); + if (rect.width > 0 && rect.height > 0) + return true; + } + } + + return false; +} + +void DFBWindowSystem::renderHWLayer(Layer *layer, bool clear) +{ + DFBGraphicSystem *gfx = (DFBGraphicSystem *)m_gfx; + DFBDisplayLayerConfig config; + int num_surfaces_curr = 0; + + LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << "(layer=" << layer << ", clear=" << clear << ")" ); + + gfx->beginLayer( layer ); + if (gfx->m_renderer_output == -1) { + LOG_ERROR( "DFBWindowSystem", __FUNCTION__ << ": called with a non-existent layer" ); + + gfx->endLayer(); + return; + } + + if (layer->getLayerType() != Hardware) + LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": called with a non-HW layer" ); + + if (!m_pScene->isLayerInCurrentRenderOrder( layer->getID() ) || layer->opacity == 0 || layer->visibility == 0) { + if (!gfx->m_renderer->m_outputs[gfx->m_renderer_output].muted) { + LOG_INFO( "DFBWindowSystem", __FUNCTION__ << ": turning OFF layer " << layer); + + if (!gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer->GetConfiguration( gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer, &config )) { + config.options = DLOP_OPACITY; + + if (gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer->SetConfiguration( gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer, &config )) { + LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": failed to set layer configuration on layer " << gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer ); + } + else { + if (gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer->SetOpacity( gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer, 0 )) { + LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": failed to set opacity on layer " << gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer ); + } + else { + gfx->m_renderer->m_outputs[gfx->m_renderer_output].muted = true; + gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer_opacity = 0; + } + } + } + } + } + else if (layer->visibility > 0 && layer->opacity > 0.0f) { + num_surfaces_curr = countVisibleSurfaces( layer ); + if (num_surfaces_curr > 0) { + if (layer->getChromaKeyEnabled()) + LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": cannot handle chroma key" ); + + if (clear) + gfx->clearBackground(); + + if (gfx->m_renderer->m_outputs[gfx->m_renderer_output].muted || gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer_opacity != layer->opacity) { + LOG_INFO( "DFBWindowSystem", __FUNCTION__ << ": turning ON layer " << layer << " with opacity=" << (int)(layer->opacity * 0xFF) ); + + if (!gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer->GetConfiguration( gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer, &config )) { + config.options = layer->opacity == 1 ? DLOP_NONE : (DFBDisplayLayerOptions)(DLOP_OPACITY | DLOP_ALPHACHANNEL); + + if (gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer->SetConfiguration( gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer, &config )) { + LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": failed to set layer configuration on layer " << gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer ); + } + else { + 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 )) { + LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": failed to set opacity on layer " << gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer ); + } + else { + gfx->m_renderer->m_outputs[gfx->m_renderer_output].muted = false; + gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer_opacity = layer->opacity; + } + } + } + } + + SurfaceList surfaces = layer->getAllSurfaces(); + for (std::list::const_iterator currentS = surfaces.begin(); currentS != surfaces.end(); ++currentS) { + if ((*currentS)->hasNativeContent() && isSurfaceVisible( (*currentS) )) + gfx->renderSurface( *currentS ); + } + } + else if (!gfx->m_renderer->m_outputs[gfx->m_renderer_output].muted) { + LOG_INFO( "DFBWindowSystem", __FUNCTION__ << ": tunring OFF layer " << layer); + + if (!gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer->GetConfiguration( gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer, &config )) { + config.options = DLOP_OPACITY; + + if (gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer->SetConfiguration( gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer, &config )) { + LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": failed to set layer configuration on layer " << gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer ); + } + else { + if (gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer->SetOpacity( gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer, 0 )) { + LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": failed to set opacity on layer " << gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer ); + } + else { + gfx->m_renderer->m_outputs[gfx->m_renderer_output].muted = true; + gfx->m_renderer->m_outputs[gfx->m_renderer_output].layer_opacity = 0; + } + } + } + } + + gfx->m_renderer->m_outputs[gfx->m_renderer_output].num_surfaces = num_surfaces_curr; + } + + gfx->swapBuffers(); + + gfx->endLayer(); +} + +void DFBWindowSystem::Redraw(bool clear) +{ + LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << "()" ); + + m_pScene->lockScene(); + + RedrawAllLayers( clear, true ); + ClearDamage(); + + m_pScene->unlockScene(); +} + +void DFBWindowSystem::Screenshot() +{ + LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << "()" ); + + m_pScene->lockScene(); + + if (takeScreenshot == ScreenshotOfDisplay) { + if (!m_dfb_mode_hw) { + RedrawAllLayers( true, false ); + m_gfx->saveScreenShotOfFramebuffer( screenShotFile ); + } + else + LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": Screetshot of FrameBuffer currently unsupported!" ); + } + else if (takeScreenshot == ScreenshotOfLayer) { + Layer* layer = m_pScene->getLayer( screenShotLayerID ); + if (layer != NULL) { + m_gfx->renderSWLayer( layer, true ); + if (m_dfb_mode_hw) + m_gfx->beginLayer( layer ); + m_gfx->saveScreenShotOfFramebuffer( screenShotFile ); + if (m_dfb_mode_hw) + m_gfx->endLayer(); + } + } + else if (takeScreenshot == ScreenshotOfSurface) { + Layer* layer = m_pScene->getLayer( screenShotLayerID ); + Surface* surface = m_pScene->getSurface( screenShotSurfaceID ); + if (layer != NULL && surface != NULL) { + m_gfx->clearBackground(); + m_gfx->beginLayer( layer ); + m_gfx->renderSurface( surface ); + m_gfx->saveScreenShotOfFramebuffer( screenShotFile ); + m_gfx->endLayer(); + } + } + + takeScreenshot = ScreenShotNone; + + m_pScene->unlockScene(); +} + +void *startEventLoop(void *ptr) +{ + DFBWindowSystem *windowsys = static_cast((DFBWindowSystem *)ptr); + windowsys->EventLoop(); + + return NULL; +} + +static void genWindowEventFromInput(const DFBInputEvent *inputEvent, DFBWindowID wid, DFBWindowEventType etype, int x, int y, int cx, int cy, DFBWindowEvent *windowEvent) +{ + memset( windowEvent, 0, sizeof(DFBWindowEvent) ); + + windowEvent->type = etype; + windowEvent->window_id = wid; + windowEvent->flags = DWEF_DEVICE_ID; + windowEvent->x = x; + windowEvent->y = y; + windowEvent->cx = cx; + windowEvent->cy = cy; + windowEvent->device_id = inputEvent->device_id; + windowEvent->timestamp = inputEvent->timestamp; + windowEvent->key_code = inputEvent->key_code; + windowEvent->key_id = inputEvent->key_id; + windowEvent->key_symbol = inputEvent->key_symbol; + windowEvent->modifiers = inputEvent->modifiers; + windowEvent->locks = inputEvent->locks; + windowEvent->button = inputEvent->button; + windowEvent->buttons = inputEvent->buttons; +} + +void DFBWindowSystem::EventLoop() +{ + Surface *surface; + sManagedWindow *win; + DFBPlatformSurface *surf; + DFBWindowEvent windowEvent; + DFBEvent event; + bool redraw = false; + + if (m_primary) { + LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << ": using compositor primary " << m_primary << " with id " << CompositorSurface << " (w=" << m_primary_width << " h=" << m_primary_height << ")" ); + + m_primary->Clear( m_primary, 0, 0, 0, 0 ); + m_primary->Flip( m_primary, NULL, DSFLIP_NONE ); + + m_gfx->init( dfbDisplay, (long)m_primary ); + m_gfx->activateGraphicContext(); + m_gfx->clearBackground(); + m_gfx->swapBuffers(); + } + + pthread_mutex_lock( &init_lock ); + m_running = true; + pthread_cond_signal( &init_condition ); + pthread_mutex_unlock( &init_lock ); + + while (m_running) { + if (m_checkWindows) { + checkForNewSurfaceNativeContent(); + Redraw( true ); + redraw = false; + } + else if (redraw) { + Redraw( true ); + redraw = false; + } + + if (takeScreenshot != ScreenShotNone) + Screenshot(); + + m_events->WaitForEventWithTimeout( m_events, 0, 300 ); + + pthread_mutex_lock( &run_lock ); + + while (m_events->GetEvent( m_events, &event ) == DFB_OK) { + switch (event.clazz) { + case DFEC_WINDOW: + switch (event.window.type) { + case DWET_POSITION: + LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << ": WINDOW POSITION event for window id " << event.window.window_id ); + + win = (sManagedWindow *)direct_hash_lookup( &window_map, event.window.window_id ); + if (win) { + win->x = event.window.x; + win->y = event.window.y; + } + else + LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": could not find window for id " << event.window.window_id ); + break; + default: + break; + } + break; + case DFEC_SURFACE: + switch (event.surface.type) { + case DSEVT_UPDATE: + if (!m_ignore_surface_updates) { + LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << ": SURFACE UPDATE event for surface id " << event.surface.surface_id ); + + win = (sManagedWindow *)direct_hash_lookup( &surface_map, event.surface.surface_id ); + if (win) { + LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << ": sending FrameAck for surface id " << event.surface.surface_id << " (frame=" << event.surface.flip_count << ")" ); + win->surf->FrameAck( win->surf, event.surface.flip_count ); + redraw = true; + } + else + LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": could not find surface for id " << event.surface.surface_id ); + } + else + LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << ": SURFACE UPDATE event for surface id " << event.surface.surface_id << " -- ignoring" ); + break; + default: + break; + } + break; + case DFEC_INPUT: + Point pos; + pos.x = m_adjusted_mouse_x; + pos.y = m_adjusted_mouse_y; + switch (event.input.type) { + case DIET_KEYPRESS: + LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << " --> KEYPRESS" ); + + surface = m_pInputManager->reportKeyboardEvent( INPUT_STATE_PRESSED, event.input.key_code ); + if (surface && surface->platform) { + surf = (DFBPlatformSurface *)surface->platform; + win = (sManagedWindow *)direct_hash_lookup( &window_map, event.window.window_id ); + if (!win) { + LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": could not find window for id " << event.window.window_id ); + break; + } + 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 ); + win->win->SendEvent( win->win, &windowEvent ); + } + break; + case DIET_KEYRELEASE: + LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << " --> KEYRELEASE" ); + + surface = m_pInputManager->reportKeyboardEvent( INPUT_STATE_RELEASED, event.input.key_code ); + if (surface && surface->platform) { + surf = (DFBPlatformSurface *)surface->platform; + win = (sManagedWindow *)direct_hash_lookup( &window_map, event.window.window_id ); + if (!win) { + LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": could not find window for id " << event.window.window_id ); + break; + } + 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 ); + win->win->SendEvent( win->win, &windowEvent ); + } + break; + case DIET_BUTTONPRESS: + LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << " --> BUTTONPRESS" ); + + pos.state = INPUT_STATE_PRESSED; + surface = m_pInputManager->reportPointerEvent( pos ); + if (surface && surface->platform) { + surf = (DFBPlatformSurface *)surface->platform; + win = (sManagedWindow *)direct_hash_lookup( &window_map, event.window.window_id ); + if (!win) { + LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": could not find window for id " << event.window.window_id ); + break; + } + 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 ); + win->win->SendEvent( win->win, &windowEvent ); + } + break; + case DIET_BUTTONRELEASE: + LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << " --> BUTTONRELEASE" ); + + pos.state = INPUT_STATE_RELEASED; + surface = m_pInputManager->reportPointerEvent( pos ); + if (surface && surface->platform) { + surf = (DFBPlatformSurface *)surface->platform; + win = (sManagedWindow *)direct_hash_lookup( &window_map, event.window.window_id ); + if (!win) { + LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": could not find window for id " << event.window.window_id ); + break; + } + 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 ); + win->win->SendEvent( win->win, &windowEvent ); + } + break; + case DIET_AXISMOTION: + pos.state = INPUT_STATE_MOTION; + if (event.input.flags & DIEF_AXISABS) { + switch (event.input.axis) { + case DIAI_X: + m_mouse_x = event.input.axisabs; + m_mouse_x_min = event.input.min; + m_mouse_x_max = event.input.max; + break; + case DIAI_Y: + m_mouse_y = event.input.axisabs; + m_mouse_y_min = event.input.min; + m_mouse_y_max = event.input.max; + break; + default: + break; + } + } + else if (event.input.flags & DIEF_AXISREL) { + switch (event.input.axis) { + case DIAI_X: + m_mouse_x += event.input.axisrel; + break; + case DIAI_Y: + m_mouse_y += event.input.axisrel; + break; + default: + break; + } + } + + if (m_mouse_y_min < m_mouse_y_max && m_mouse_x_min < m_mouse_x_max) { + m_adjusted_mouse_x = CLAMP(m_mouse_x, 0, m_mouse_x_max); + m_adjusted_mouse_y = CLAMP(m_mouse_y, 0, m_mouse_y_max); + m_adjusted_mouse_x = ((m_primary_width - 1) * m_adjusted_mouse_x) / m_mouse_x_max; + m_adjusted_mouse_y = ((m_primary_height - 1) * m_adjusted_mouse_y) / m_mouse_y_max; + } + else { + m_adjusted_mouse_x = CLAMP(m_mouse_x, 0, m_primary_width - 1); + m_adjusted_mouse_y = CLAMP(m_mouse_y, 0, m_primary_height - 1); + } + + LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << " --> MOTION at " << m_adjusted_mouse_x << "," << m_adjusted_mouse_y ); + + pos.x = m_adjusted_mouse_x; + pos.y = m_adjusted_mouse_y; + + surface = m_pInputManager->reportPointerEvent( pos ); + if (surface && surface->platform) { + surf = (DFBPlatformSurface *)surface->platform; + win = (sManagedWindow *)direct_hash_lookup( &window_map, event.window.window_id ); + if (!win) { + LOG_WARNING( "DFBWindowSystem", __FUNCTION__ << ": could not find window for id " << event.window.window_id ); + break; + } + 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 ); + win->win->SendEvent( win->win, &windowEvent ); + } + break; + default: + LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << " --> UNKNOWN INPUT EVENT" ); + break; + } + break; + default: + break; + } + } + + pthread_mutex_unlock( &run_lock ); + } + + cleanup(); + + LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << " --> finished" ); +} + +void DFBWindowSystem::signalRedrawEvent() +{ + LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << "()" ); + + pthread_mutex_lock( &run_lock ); + + m_checkWindows = true; + m_events->WakeUp( m_events ); + + pthread_mutex_unlock( &run_lock ); +} + +void DFBWindowSystem::cleanup() +{ + pthread_mutex_lock( &run_lock ); + + m_running = false; + m_initialized = false; + + if (m_events) { + m_events->Release( m_events ); + m_events = NULL; + } + + if (m_primary) { + m_primary->Release( m_primary ); + m_primary = NULL; + } + + pthread_mutex_unlock( &run_lock ); +} + +bool DFBWindowSystem::init(BaseGraphicSystem* base, bool dfb_mode_hw) +{ + DFBResult ret; + + LOG_INFO( "DFBWindowSystem", __FUNCTION__ << "(hw=" << dfb_mode_hw << ")" ); + + m_gfx = base; + m_dfb_mode_hw = dfb_mode_hw; + + m_forceComposition = true; + + ret = m_dfb->CreateInputEventBuffer( m_dfb, (DFBInputDeviceCapabilities)(DICAPS_KEYS | DICAPS_BUTTONS | DICAPS_AXES), DFB_FALSE, &m_events ); + if (ret) { + LOG_ERROR( "DFBWindowSystem", __FUNCTION__ << ": IDirectFB::CreateEventBuffer() failed! (ret=" << ret << ")" ); + return false; + } + + if (!m_dfb_mode_hw) { + DFBSurfaceID surf_id; + + ret = m_layer->GetSurface( m_layer, &m_primary ); + if (ret) { + LOG_ERROR( "DFBWindowSystem", __FUNCTION__ << ": IDirectFBDisplayLayer::GetSurface() failed! (ret=" << ret << ")" ); + m_events->Release( m_events ); + if (m_primary) + m_primary->Release( m_primary ); + + return false; + } + + m_primary->GetSize( m_primary, &m_primary_width, &m_primary_height ); + + LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << ": retrieved layer primary " << m_primary << " (w=" << m_primary_width << " h=" << m_primary_height << ")" ); + + m_primary->GetID( m_primary, &surf_id ); + CompositorSurface = surf_id; + } + + pthread_mutex_lock( &init_lock ); + + int status = pthread_create( &renderThread, NULL, startEventLoop, this ); + if (status) { + pthread_mutex_unlock( &init_lock ); + return false; + } + + if (!m_running) + pthread_cond_wait( &init_condition, &init_lock ); + + pthread_mutex_unlock( &init_lock ); + + LOG_INFO( "DFBWindowSystem", __FUNCTION__ << " --> initialized" ); + + return true; +} + +bool DFBWindowSystem::start(int maxIterationDurationInMS) +{ + LOG_INFO( "DFBWindowSystem", __FUNCTION__ << "(" << maxIterationDurationInMS << ")" ); + + pthread_mutex_lock( &run_lock ); + + LayerList layers = m_pScene->getCurrentRenderOrder( 0 ); + for (LayerListConstIterator current = layers.begin(); current != layers.end(); current++) + m_sceneLayers->push_back( (*current)->getID() ); + + m_maxIterationDurationInMS = maxIterationDurationInMS; + + m_running = true; + + m_checkWindows = true; + m_events->WakeUp( m_events ); + + pthread_mutex_unlock( &run_lock ); + + return true; +} + +void DFBWindowSystem::stop() +{ + LOG_INFO( "DFBWindowSystem", __FUNCTION__ << "()" ); + + pthread_mutex_lock( &run_lock ); + + m_sceneLayers->clear(); + + m_running = false; + m_events->WakeUp( m_events ); + + pthread_mutex_unlock( &run_lock ); + + pthread_join( renderThread, NULL ); +} + +void DFBWindowSystem::allocatePlatformSurface(Surface* surface) +{ + LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << "(" << surface << ")" ); + + DFBPlatformSurface* nativeSurface = (DFBPlatformSurface*)surface->platform; + if (!nativeSurface) { + if (NewWindow( surface, surface->getNativeContent() )) + MapWindow( surface->getNativeContent() ); + } +} + +void DFBWindowSystem::deallocatePlatformSurface(Surface* surface) +{ + LOG_DEBUG( "DFBWindowSystem", __FUNCTION__ << "(" << surface << ")" ); + + DFBPlatformSurface* nativeSurface = (DFBPlatformSurface*)surface->platform; + if (nativeSurface) { + m_gfx->getTextureBinder()->destroyClientBuffer( surface ); + + if (nativeSurface->dfb_surface) + nativeSurface->dfb_surface->Release( nativeSurface->dfb_surface ); + + if (nativeSurface->dfb_window) + nativeSurface->dfb_window->Release( nativeSurface->dfb_window ); + + surface->renderPropertyChanged = true; + delete surface->platform; + surface->platform = NULL; + } +} + +void DFBWindowSystem::doScreenShot(std::string fileName, const uint screen_id) +{ + takeScreenshot = ScreenshotOfDisplay; + screenShotFile = fileName; + screenShotScreenID = screen_id; +} + +void DFBWindowSystem::doScreenShotOfLayer(std::string fileName, const uint id) +{ + takeScreenshot = ScreenshotOfLayer; + screenShotFile = fileName; + screenShotLayerID = id; +} + +void DFBWindowSystem::doScreenShotOfSurface(std::string fileName, const uint id, const uint layer_id) +{ + takeScreenshot = ScreenshotOfSurface; + screenShotFile = fileName; + screenShotSurfaceID = id; + screenShotLayerID = layer_id; +} + +DFBDisplay DFBWindowSystem::getNativeDisplayHandle() +{ + return dfbDisplay; +} + +int DFBWindowSystem::getIterationCounter() +{ + return m_iterationCounter; +} + -- 2.7.4