From 90675197b38d6d2d7a53508388ab5372f3b0f567 Mon Sep 17 00:00:00 2001 From: Marek Pikarski Date: Tue, 1 Oct 2013 09:36:45 +0200 Subject: GraphicSystems: Added support for DirectFB Added the DirectFB graphics system which renders into DirectFB surfaces. It can deal with both HW/SW layers. Signed-off-by: Marek Pikarski --- .../include/GraphicSystems/DFBGraphicSystem.h | 68 ++++ .../src/GraphicSystems/DFBGraphicSystem.cpp | 391 +++++++++++++++++++++ 2 files changed, 459 insertions(+) create mode 100644 LayerManagerPlugins/Renderers/Graphic/include/GraphicSystems/DFBGraphicSystem.h create mode 100644 LayerManagerPlugins/Renderers/Graphic/src/GraphicSystems/DFBGraphicSystem.cpp diff --git a/LayerManagerPlugins/Renderers/Graphic/include/GraphicSystems/DFBGraphicSystem.h b/LayerManagerPlugins/Renderers/Graphic/include/GraphicSystems/DFBGraphicSystem.h new file mode 100644 index 0000000..6ca697d --- /dev/null +++ b/LayerManagerPlugins/Renderers/Graphic/include/GraphicSystems/DFBGraphicSystem.h @@ -0,0 +1,68 @@ +/*************************************************************************** + * + * 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 _DFBGRAPHICSYSTEM_H_ +#define _DFBGRAPHICSYSTEM_H_ + +#include "BaseGraphicSystem.h" +#include "PlatformSurfaces/DFBPlatformSurface.h" + +class DFBRenderer; +class DFBWindowSystem; + +class DFBGraphicSystem : public BaseGraphicSystem { +public: + DFBGraphicSystem(DFBRenderer *renderer, DFBWindowSystem *winsys, IDirectFB *dfb, int windowWidth, int windowHeight); + virtual ~DFBGraphicSystem(); + virtual bool init(DFBDisplay display, DFBWindow window); + + virtual void beginLayer(Layer* layer); + virtual void endLayer(); + + virtual bool needsRedraw(Layer *layer); + virtual bool needsRedraw(LayerList layers); + virtual void renderSWLayer(Layer *layer, bool clear); + virtual void renderSWLayers(LayerList layers, bool clear); + + virtual void clearBackground(); + virtual void swapBuffers(); + virtual void saveScreenShotOfFramebuffer(std::string fileToSave); + virtual void renderSurface(Surface* currentSurface); + virtual void activateGraphicContext(); + virtual void releaseGraphicContext(); +private: + DFBRenderer *m_renderer; + DFBWindowSystem *m_winsys; + int m_renderer_output; + int m_windowWidth; + int m_windowHeight; + DFBDisplay m_display; + DFBWindow m_window; + IDirectFB *m_dfb; + Layer *m_currentLayer; + IDirectFBSurface *m_single_surface; + int m_single_x; + int m_single_y; + + friend class DFBWindowSystem; +}; + +#endif + diff --git a/LayerManagerPlugins/Renderers/Graphic/src/GraphicSystems/DFBGraphicSystem.cpp b/LayerManagerPlugins/Renderers/Graphic/src/GraphicSystems/DFBGraphicSystem.cpp new file mode 100644 index 0000000..5516c2b --- /dev/null +++ b/LayerManagerPlugins/Renderers/Graphic/src/GraphicSystems/DFBGraphicSystem.cpp @@ -0,0 +1,391 @@ +/*************************************************************************** + * + * 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 "GraphicSystems/DFBGraphicSystem.h" +#include "WindowSystems/DFBWindowSystem.h" +#include "Bitmap.h" +#include + +extern "C" { + #include +} + +DFBGraphicSystem::DFBGraphicSystem(DFBRenderer *renderer, DFBWindowSystem *winsys, IDirectFB *dfb, int WindowWidth, int WindowHeight) +: m_renderer(renderer) +, m_winsys(winsys) +, m_renderer_output(0) +, m_windowWidth(WindowWidth) +, m_windowHeight(WindowHeight) +, m_display(0) +, m_window(0) +, m_dfb(dfb) +, m_currentLayer(NULL) +, m_single_surface(NULL) +, m_single_x(0) +, m_single_y(0) +{ +} + +DFBGraphicSystem::~DFBGraphicSystem() +{ +} + +void DFBGraphicSystem::activateGraphicContext() +{ +} + +void DFBGraphicSystem::releaseGraphicContext() +{ +} + +bool DFBGraphicSystem::init(DFBDisplay display, DFBWindow window) +{ + (void)window; + + LOG_DEBUG( "DFBGraphicsSystem", __FUNCTION__ << "(display=" << display << ", window=" << window << ")" ); + + m_display = display; + + return true; +} + +void DFBGraphicSystem::clearBackground() +{ + LOG_DEBUG( "DFBGraphicsSystem", __FUNCTION__ ); + + if (m_renderer_output < 0) { + LOG_WARNING( "DFBGraphicSystem", __FUNCTION__ << ": renderer output not set!\n" ); + return; + } + + if (!m_renderer->m_outputs[m_renderer_output].single) + m_renderer->m_outputs[m_renderer_output].surface->Clear( m_renderer->m_outputs[m_renderer_output].surface, 0, 0, 0, 0 ); +} + +void DFBGraphicSystem::swapBuffers() +{ + LOG_DEBUG( "DFBGraphicsSystem", __FUNCTION__ ); + + if (m_renderer_output < 0) { + LOG_WARNING( "DFBGraphicSystem", __FUNCTION__ << ": renderer output not set!\n" ); + return; + } + + if (!m_renderer->m_outputs[m_renderer_output].single) + m_renderer->m_outputs[m_renderer_output].surface->Flip( m_renderer->m_outputs[m_renderer_output].surface, NULL, DSFLIP_NONE ); +} + +void DFBGraphicSystem::beginLayer(Layer *currentLayer) +{ + int i; + + LOG_DEBUG( "DFBGraphicsSystem", __FUNCTION__ << "(" << currentLayer << ")" ); + + m_currentLayer = currentLayer; + m_renderer_output = -1; + + for (i = 0; i < m_renderer->m_num_outputs; i++) { + if (m_renderer->m_outputs[i].layer_id == (int)currentLayer->getID()) { + m_renderer_output = i; + break; + } + } +} + +bool DFBGraphicSystem::needsRedraw(Layer *layer) +{ + if (layer->renderPropertyChanged) + return true; + + if (layer->visibility && layer->opacity > 0.0) { + SurfaceList surfaces = layer->getAllSurfaces(); + for (SurfaceListConstIterator currentS = surfaces.begin(); currentS != surfaces.end(); currentS++) { + if ((*currentS)->renderPropertyChanged) + return true; + + if ((*currentS)->hasNativeContent() && (*currentS)->damaged && (*currentS)->visibility && (*currentS)->opacity > 0.0f) + return true; + } + } + + return false; +} + +bool DFBGraphicSystem::needsRedraw(LayerList layers) +{ + for (LayerListConstIterator layer = layers.begin(); layer != layers.end(); layer++) { + if ((*layer)->getLayerType() == Hardware && layers.size() > 1) + LOG_WARNING( "DFBGraphicSystem", __FUNCTION__ << ": called with layers not in the same composition" ); + + if (needsRedraw( *layer )) + return true; + } + + return false; +} + +void DFBGraphicSystem::renderSWLayer(Layer *layer, bool clear) +{ + LOG_DEBUG( "DFBGraphicsSystem", __FUNCTION__ << "(layer=" << layer << ", clear=" << clear << ")" ); + + beginLayer( layer ); + + if (layer->getLayerType() != Software_2D && layer->getLayerType() != Software_2_5D) + LOG_WARNING( "DFBGraphicSystem", __FUNCTION__ << ": called with a non-SW layer" ); + + if (layer->visibility && layer->opacity > 0.0f) { + if (m_currentLayer->getChromaKeyEnabled()) + LOG_WARNING( "DFBGraphicSystem", __FUNCTION__ << ": cannot handle chroma key" ); + + if (clear) + clearBackground(); + + SurfaceList surfaces = m_currentLayer->getAllSurfaces(); + for (std::list::const_iterator currentS = surfaces.begin(); currentS != surfaces.end(); ++currentS) { + if ((*currentS)->hasNativeContent() && (*currentS)->visibility && (*currentS)->opacity > 0.0f) + renderSurface( *currentS ); + } + } + + endLayer(); +} + +void DFBGraphicSystem::renderSWLayers(LayerList layers, bool clear) +{ + LOG_DEBUG( "DFBGraphicsSystem", __FUNCTION__ << "(clear=" << clear << ")" ); + + for (LayerListConstIterator layer = layers.begin(); layer != layers.end(); layer++) + renderSWLayer( *layer, clear ); +} + +void DFBGraphicSystem::endLayer() +{ + LOG_DEBUG( "DFBGraphicsSystem", __FUNCTION__ ); + + m_currentLayer = NULL; + m_renderer_output = -1; +} + +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; +} + +void DFBGraphicSystem::renderSurface(Surface *currentSurface) +{ + int num_surfaces = countVisibleSurfaces( m_currentLayer ); + FloatRectangle target_src; + FloatRectangle target_dst; + DFBRectangle src_rect; + DFBRectangle dst_rect; + DFBSurfaceBlittingFlags flags = DSBLIT_NOFX; + DFBSurfaceCapabilities caps; + DFBSurfacePixelFormat format; + double opacity = currentSurface->getOpacity(); + bool blitting_fallback = false; + + LOG_DEBUG( "DFBGraphicsSystem", __FUNCTION__ << "(surface=" << currentSurface << ")" ); + + if (m_renderer_output < 0) { + LOG_WARNING( "DFBGraphicSystem", __FUNCTION__ << ": renderer output not set!" ); + return; + } + + if (!currentSurface->platform) { + LOG_WARNING( "DFBGraphicSystem", __FUNCTION__ << ": Platform surface not available" ); + return; + } + + target_src = currentSurface->getTargetSourceRegion(); + src_rect.x = target_src.x; + src_rect.y = target_src.y; + src_rect.w = target_src.width; + src_rect.h = target_src.height; + + target_dst = currentSurface->getTargetDestinationRegion(); + dst_rect.x = target_dst.x; + dst_rect.y = target_dst.y; + dst_rect.w = target_dst.width; + dst_rect.h = target_dst.height; + + DFBPlatformSurface* platformSurface = (DFBPlatformSurface *)currentSurface->platform; + + LOG_DEBUG( "DFBGraphicsSystem", __FUNCTION__ << ": render DirectFB surface " << platformSurface->dfb_surface << + " (src " << src_rect.x << "," << src_rect.y << "," << src_rect.w << "," << src_rect.h << + ") (dst " << dst_rect.x << "," << dst_rect.y << "," << dst_rect.w << "," << dst_rect.h << + ") with id " << platformSurface->dfb_surface_id << " (visible surfaces on layer: " << num_surfaces << ")" ); + + if (m_currentLayer->getLayerType() != Hardware) + opacity *= m_currentLayer->getOpacity(); + + while (num_surfaces == 1) { + if (src_rect.w != dst_rect.w || src_rect.h != dst_rect.h) { + blitting_fallback = true; + break; + } + + if (!m_renderer->m_outputs[m_renderer_output].single || m_single_surface != platformSurface->dfb_surface) { + if (m_renderer->m_outputs[m_renderer_output].layer->SetSurface( m_renderer->m_outputs[m_renderer_output].layer, platformSurface->dfb_surface )) { + LOG_WARNING( "DFBGraphicSystem", __FUNCTION__ << ": failed to set surface " << platformSurface->dfb_surface << " on layer " << m_renderer->m_outputs[m_renderer_output].layer ); + } + else { + LOG_INFO( "DFBGraphicSystem", __FUNCTION__ << ": switching single mode ON for layer " << m_renderer->m_outputs[m_renderer_output].layer ); + + m_single_surface = platformSurface->dfb_surface; + m_renderer->m_outputs[m_renderer_output].single = true; + //m_winsys->m_ignore_surface_updates = true; + } + } + + if (m_single_x != dst_rect.x || m_single_y != dst_rect.y) { + if (m_renderer->m_outputs[m_renderer_output].layer->SetScreenPosition( m_renderer->m_outputs[m_renderer_output].layer, dst_rect.x, dst_rect.y )) { + LOG_WARNING( "DFBGraphicSystem", __FUNCTION__ << ": failed to set screen location of surface " << platformSurface->dfb_surface << " on layer " << m_renderer->m_outputs[m_renderer_output].layer ); + } + else { + m_single_x = dst_rect.x; + m_single_y = dst_rect.y; + + LOG_INFO( "DFBGraphicSystem", __FUNCTION__ << ": set screen location " << m_single_x << "," << m_single_y << " for layer " << m_renderer->m_outputs[m_renderer_output].layer ); + } + } + + break; + } + + if (num_surfaces > 1 || blitting_fallback) { + if (m_renderer->m_outputs[m_renderer_output].single || blitting_fallback) { + if (m_single_surface != m_renderer->m_outputs[m_renderer_output].surface) { + LOG_INFO( "DFBGraphicSystem", __FUNCTION__ << ": switching single mode OFF for layer " << m_renderer->m_outputs[m_renderer_output].layer ); + + if (m_renderer->m_outputs[m_renderer_output].layer->SetSurface( m_renderer->m_outputs[m_renderer_output].layer, m_renderer->m_outputs[m_renderer_output].surface )) { + LOG_WARNING( "DFBGraphicSystem", __FUNCTION__ << ": failed to set surface " << m_renderer->m_outputs[m_renderer_output].surface << " on layer " << m_renderer->m_outputs[m_renderer_output].layer ); + } + else { + m_single_surface = m_renderer->m_outputs[m_renderer_output].surface; + m_renderer->m_outputs[m_renderer_output].single = false; + m_winsys->m_ignore_surface_updates = false; + } + } + } + + if (opacity > 0 && opacity < 1) { + platformSurface->dfb_surface->SetPorterDuff( platformSurface->dfb_surface, DSPD_SRC_OVER ); + + if (platformSurface->dfb_surface->GetPixelFormat( platformSurface->dfb_surface, &format )) { + LOG_WARNING( "DFBGraphicSystem", __FUNCTION__ << ": failed to retrieve pixelformat from surface " << platformSurface->dfb_surface << " with id " << platformSurface->dfb_surface_id ); + } + else if (DFB_PIXELFORMAT_HAS_ALPHA(format)) + flags = (DFBSurfaceBlittingFlags)(flags | DSBLIT_BLEND_ALPHACHANNEL); + + if (platformSurface->dfb_surface->GetCapabilities( platformSurface->dfb_surface, &caps )) { + LOG_WARNING( "DFBGraphicSystem", __FUNCTION__ << ": failed to retrieve caps from surface " << platformSurface->dfb_surface << " with id " << platformSurface->dfb_surface_id ); + } + else { + if (caps & DSCAPS_PREMULTIPLIED) + flags = (DFBSurfaceBlittingFlags)(flags | DSBLIT_SRC_PREMULTCOLOR); + else + flags = (DFBSurfaceBlittingFlags)(flags | DSBLIT_BLEND_COLORALPHA | DSBLIT_SRC_PREMULTIPLY); + } + + m_renderer->m_outputs[m_renderer_output].surface->SetColor( m_renderer->m_outputs[m_renderer_output].surface, 0, 0, 0, opacity * 0xFF ); + } + + m_renderer->m_outputs[m_renderer_output].surface->SetBlittingFlags( m_renderer->m_outputs[m_renderer_output].surface, flags ); + m_renderer->m_outputs[m_renderer_output].surface->StretchBlit( m_renderer->m_outputs[m_renderer_output].surface, platformSurface->dfb_surface, &src_rect, &dst_rect ); + } +} + +void DFBGraphicSystem::saveScreenShotOfFramebuffer(std::string fileToSave) +{ + DFBResult ret; + IDirectFBSurface *primary; + DFBSurfacePixelFormat format; + void *primary_data; + int primary_pitch; + int primary_width; + int primary_height; + u8 *rgb_data; + + LOG_DEBUG( "DFBGraphicSystem", __FUNCTION__ << "(" << fileToSave << ") (output=" << m_renderer_output << ")" ); + + if (m_renderer_output < 0) { + LOG_WARNING( "DFBGraphicSystem", __FUNCTION__ << ": renderer output not set!" ); + return; + } + + ret = m_renderer->m_outputs[m_renderer_output].layer->GetSurface( m_renderer->m_outputs[m_renderer_output].layer, &primary ); + if (ret) { + LOG_ERROR( "DFBGraphicSystem", __FUNCTION__ << ": IDirectFBDisplayLayer::GetSurface() failed! (ret=" << ret << ")" ); + return; + } + + ret = primary->GetSize( primary, &primary_width, &primary_height ); + if (ret) { + LOG_ERROR( "DFBGraphicSystem", __FUNCTION__ << ": IDirectFBSurface::GetSize() failed! (ret=" << ret << ")" ); + primary->Release( primary ); + return; + } + + ret = primary->GetPixelFormat( primary, &format ); + if (ret) { + LOG_ERROR( "DFBGraphicSystem", __FUNCTION__ << ": failed to retrieve pixelformat from primary " << primary << "(ret=" << ret << ")" ); + return; + } + + ret = primary->Lock( primary, DSLF_READ, &primary_data, &primary_pitch ); + if (ret) { + LOG_ERROR( "DFBGraphicSystem", __FUNCTION__ << ": failed to lock primary " << primary << "(ret=" << ret << ")" ); + primary->Release( primary ); + return; + } + + rgb_data = (u8 *)malloc( primary_width * primary_height * 3 * sizeof(u8) ); + if (!rgb_data) { + LOG_ERROR( "DFBGraphicSystem", __FUNCTION__ << ": failed to allocate screenshot buffer for primary " << primary ); + primary->Unlock( primary ); + primary->Release( primary ); + return; + } + + dfb_convert_to_rgb24( format, primary_data, primary_pitch, NULL, 0, NULL, 0, primary_height, rgb_data, primary_width * 3, primary_width, primary_height ); + + primary->Unlock( primary ); + primary->Release( primary ); + + writeBitmap( fileToSave, (char *)rgb_data, primary_width, primary_height ); + + free( rgb_data ); +} -- cgit v1.2.1