namespace PluggIt { D_DEBUG_DOMAIN( PluggIt_Main, "PluggIt/Main", "PluggIt Main" ); D_DEBUG_DOMAIN( PluggIt_View, "PluggIt/View", "PluggIt View" ); class Main extends View { class Config { public DFBDimension m_size; public DFBPoint m_offset; public DFBDimension m_resolution; public DFBSurfacePixelFormat m_format; public std::string m_title; public bool m_interactive; public bool m_updating; public bool m_use_driver; public Config() : m_format(DSPF_UNKNOWN), m_interactive(false), m_updating(false) { } }; private Config m_config; private Options m_options; private Scaler m_scaler; private IDirectFB m_dfb; private IDirectFBDisplayLayer m_layer; private IDirectFBWindow m_window; private IDirectFBSurface m_surface; private IDirectFBEventBuffer m_events; private Source *m_source; private DFBDimension m_source_resolution; private DFBDimension m_view_size; private DFBDimension m_view_resolution; private bool m_view_visible; private DFBSurfacePixelFormat m_view_format; public Main() : m_source(NULL), m_view_visible(false) { D_DEBUG_AT( PluggIt_Main, "%s()\n", __FUNCTION__ ); m_options.addOption( new Options::OptionDimension( "-s", "--size", "x", "Size of view", m_config.m_size ) ); m_options.addOption( new Options::OptionPoint ( "-o", "--offset", ",", "Offset of view", m_config.m_offset ) ); m_options.addOption( new Options::OptionDimension( "-r", "--resolution", "x", "Resolution of view", m_config.m_resolution ) ); m_options.addOption( new Options::OptionFormat ( "-f", "--format", "", "Pixel format of view", m_config.m_format ) ); m_options.addOption( new Options::OptionString ( "-t", "--title", "", "Title of window to show", m_config.m_title ) ); m_options.addOption( new Options::OptionBool ( "-i", "--interactive", "", "Use interactive window picking", m_config.m_interactive ) ); m_options.addOption( new Options::OptionBool ( "-u", "--updating", "", "Update continuously", m_config.m_updating ) ); m_options.addOption( new Options::OptionBool ( "-d", "--driver", "", "Use driver mode", m_config.m_use_driver ) ); } public void main( int argc, char *argv[] ) { D_DEBUG_AT( PluggIt_Main, "%s()\n", __FUNCTION__ ); try { /* Initialize DirectFB. */ DirectFB::Init( &argc, &argv ); if (!m_options.parseCommandLine( argc, argv )) return; initDFB(); initSource(); run(); } catch (DFBException *e) { cerr << endl; cerr << "Caught exception!" << endl; cerr << " ==> " << e << endl; } catch (Exception *e) { cerr << endl; cerr << "Caught exception!" << endl; cerr << " ==> " << e << endl; } } private void initDFB() { D_DEBUG_AT( PluggIt_Main, "%s()\n", __FUNCTION__ ); /* Create the super interface. */ m_dfb = DirectFB::Create(); m_layer = m_dfb.GetDisplayLayer( DLID_PRIMARY ); m_events = m_dfb.CreateEventBuffer(); } private void initSource() { D_DEBUG_AT( PluggIt_Main, "%s()\n", __FUNCTION__ ); #ifdef __WIN32__ SourceWin32::Config config( m_config.m_interactive ? SourceWin32::Config::WINDOW_SELECTION_INTERACTIVE : (m_config.m_title.size() > 0 ? SourceWin32::Config::WINDOW_SELECTION_TITLE : SourceWin32::Config::WINDOW_SELECTION_NONE), m_config.m_title, m_config.m_updating, m_config.m_use_driver ); m_source = new SourceWin32( this, config ); #else SourceX11::Config config( m_config.m_interactive ? SourceX11::Config::WINDOW_SELECTION_INTERACTIVE : (m_config.m_title.size() > 0 ? SourceX11::Config::WINDOW_SELECTION_TITLE : SourceX11::Config::WINDOW_SELECTION_NONE), m_config.m_title ); m_source = new SourceX11( this, config ); #endif } private void run() { m_source->MainLoop(); } public virtual void config( DFBDimension &source_resolution ) { D_DEBUG_AT( PluggIt_View, "%s( %u, %u )\n", __FUNCTION__, source_resolution.w, source_resolution.h ); /* Ignore bogus events */ if (m_source_resolution == source_resolution) { D_DEBUG_AT( PluggIt_View, " -> unchanged source size\n" ); return; } m_source_resolution = source_resolution; /* Calculate view resolution */ DFBDimension resolution = m_config.m_resolution; if (!resolution.w) { if (!resolution.h) { resolution = source_resolution; D_DEBUG_AT( PluggIt_View, " -> no width/height\n" ); } else { resolution.w = resolution.h * source_resolution.w / source_resolution.h; D_DEBUG_AT( PluggIt_View, " -> no width\n" ); } } else if (!resolution.h) { resolution.h = resolution.w * source_resolution.h / source_resolution.w; D_DEBUG_AT( PluggIt_View, " -> no height\n" ); } D_DEBUG_AT( PluggIt_View, " -> resolution %ux%u\n", resolution.w, resolution.h ); /* Calculate view size */ DFBDimension size = m_config.m_size; if (!size.w) { if (!size.h) { size = resolution; D_DEBUG_AT( PluggIt_View, " -> no width/height\n" ); } else { size.w = size.h * resolution.w / resolution.h; D_DEBUG_AT( PluggIt_View, " -> no width\n" ); } } else if (!size.h) { size.h = size.w * resolution.h / resolution.w; D_DEBUG_AT( PluggIt_View, " -> no height\n" ); } D_DEBUG_AT( PluggIt_View, " -> %ux%u\n", size.w, size.h ); if (m_view_resolution == resolution) D_DEBUG_AT( PluggIt_View, " -> unchanged view resolution\n" ); if (m_view_size == size) { D_DEBUG_AT( PluggIt_View, " -> unchanged view size\n" ); return; } if (m_window) m_window.Resize( size.w, size.h ); else { /* Create the window. */ DFBWindowDescription desc; desc.flags = (DFBWindowDescriptionFlags)( DWDESC_POSX | DWDESC_POSY | DWDESC_WIDTH | DWDESC_HEIGHT | DWDESC_PIXELFORMAT ); desc.posx = 0; desc.posy = 0; desc.width = size.w; desc.height = size.h; desc.pixelformat = m_config.m_format; m_window = m_layer.CreateWindow( desc ); m_surface = m_window.GetSurface(); m_view_format = m_surface.GetPixelFormat(); m_window.AttachEventBuffer( m_events ); } m_view_size = size; m_view_resolution = resolution; D_DEBUG_AT( PluggIt_View, " -> view size %4ux%4u\n", m_view_size.w, m_view_size.h ); D_DEBUG_AT( PluggIt_View, " -> view resolution %4ux%4u\n", m_view_resolution.w, m_view_resolution.h ); D_DEBUG_AT( PluggIt_View, " -> source resolution %4ux%4u\n", m_source_resolution.w, m_source_resolution.h ); } public virtual void update( const vector &rects, void *ptr, int pitch ) { unsigned int i; DFBRegion clip( m_view_size ); const DFBPoint &offset = m_config.m_offset; bool first = true; DFBRegion flip; D_DEBUG_AT( PluggIt_View, "%s( [%u], %p, %d )\n", __FUNCTION__, rects.size(), ptr, pitch ); D_ASSERT( rects.size() > 0 ); D_ASSERT( ptr != NULL ); // m_dfb.WaitIdle(); if (m_source_resolution == m_view_resolution) { D_DEBUG_AT( PluggIt_View, " -> unscaled %4dx%4d\n", m_source_resolution.w, m_source_resolution.h ); if (m_view_format == DSPF_RGB16) { int tp = ((m_view_size.w * 2) + 7) & ~7; void *tmp = malloc( tp * m_view_size.h ); for (i=0; i [%2d] %4d,%4d-%4dx%4d (original)\n", i, DFB_RECTANGLE_VALS( &rects[i] ) ); DFBRegion region( DFBRectangle(rects[i]) - offset ); D_DEBUG_AT( PluggIt_View, " -> %4d,%4d-%4dx%4d (translated)\n", DFB_RECTANGLE_VALS_FROM_REGION( ®ion ) ); ptr = (void*)((char*) ptr + offset.x * 4 + offset.y * pitch); /* Clip update against our resolution */ if (dfb_region_region_intersect( ®ion, &clip )) { D_DEBUG_AT( PluggIt_View, " -> %4d,%4d-%4dx%4d (clipped update)\n", DFB_RECTANGLE_VALS_FROM_REGION( ®ion ) ); DFBRectangle rect( region ); dfb_convert_to_rgb16( DSPF_RGB32, (void*)((char*) ptr + rect.x * 4 + rect.y * pitch), pitch, m_view_size.h, (u16*) tmp, tp, rect.w, rect.h ); m_surface.Write( (char*) tmp + DFB_BYTES_PER_LINE( m_view_format, region.x1 ) + region.y1 * tp, tp, &rect ); if (first) { first = false; flip = region; } else flip.unionWith( region ); //m_surface.Flip( ®ion ); } } free( tmp ); } else { for (i=0; i [%2d] %4d,%4d-%4dx%4d (original)\n", i, DFB_RECTANGLE_VALS( &rects[i] ) ); DFBRegion region( DFBRectangle(rects[i]) - offset ); D_DEBUG_AT( PluggIt_View, " -> %4d,%4d-%4dx%4d (translated)\n", DFB_RECTANGLE_VALS_FROM_REGION( ®ion ) ); ptr = (void*)((char*) ptr + offset.x * 4 + offset.y * pitch); /* Clip update against our resolution */ if (dfb_region_region_intersect( ®ion, &clip )) { D_DEBUG_AT( PluggIt_View, " -> %4d,%4d-%4dx%4d (clipped update)\n", DFB_RECTANGLE_VALS_FROM_REGION( ®ion ) ); DFBRectangle rect( region ); if (m_view_format == DSPF_ARGB) { u32 *p = (u32*)((char*) ptr + rect.x * 4 + rect.y * pitch); for (int y=0; y Write...\n" ); m_surface.Write( (char*) ptr + DFB_BYTES_PER_LINE( m_view_format, region.x1 ) + region.y1 * pitch, pitch, &rect ); D_DEBUG_AT( PluggIt_View, " -> Write done.\n" ); if (first) { first = false; flip = region; } else flip.unionWith( region ); //m_surface.Flip( ®ion ); } } } } else { int tp = ((m_view_size.w * 4) + 7) & ~7; void *tmp = malloc( tp * m_view_size.h ); D_DEBUG_AT( PluggIt_View, " -> scaled %4dx%4d => %4dx%4d\n", m_source_resolution.w, m_source_resolution.h, m_view_resolution.w, m_view_resolution.h ); for (i=0; i [%2d] %4d,%4d-%4dx%4d (original)\n", i, DFB_RECTANGLE_VALS( &rects[i] ) ); DFBRegion region( DFBRectangle(rects[i]) - offset ); D_DEBUG_AT( PluggIt_View, " -> %4d,%4d-%4dx%4d (translated)\n", DFB_RECTANGLE_VALS_FROM_REGION( ®ion ) ); ptr = (void*)((char*) ptr + offset.x * 4 + offset.y * pitch); /* Transform source updates to view resolution */ region.x1 = region.x1 * m_view_resolution.w / m_source_resolution.w; region.y1 = region.y1 * m_view_resolution.h / m_source_resolution.h; region.x2 = region.x2 * m_view_resolution.w / m_source_resolution.w; region.y2 = region.y2 * m_view_resolution.h / m_source_resolution.h; if (region.x1 > 0) region.x1--; if (region.y1 > 0) region.y1--; if (region.x2 < m_view_resolution.w-1) region.x2++; if (region.x2 < m_view_resolution.w-1) region.x2++; if (region.y2 < m_view_resolution.h-1) region.y2++; if (region.y2 < m_view_resolution.h-1) region.y2++; D_DEBUG_AT( PluggIt_View, " -> %4d,%4d-%4dx%4d (scaled)\n", DFB_RECTANGLE_VALS_FROM_REGION( ®ion ) ); /* Clip update against our resolution */ if (dfb_region_region_intersect( ®ion, &clip )) { D_DEBUG_AT( PluggIt_View, " -> %4d,%4d-%4dx%4d (clipped)\n", DFB_RECTANGLE_VALS_FROM_REGION( ®ion ) ); DFBRectangle rect( region ); m_scaler.scale( m_view_format, tmp, tp, ptr, pitch, m_source_resolution.w, m_source_resolution.h, m_view_resolution.w, m_view_resolution.h, region ); m_surface.Write( (char*) tmp + DFB_BYTES_PER_LINE( m_view_format, region.x1 ) + region.y1 * tp, tp, &rect ); if (first) { first = false; flip = region; } else flip.unionWith( region ); //m_surface.Flip( ®ion ); } } free( tmp ); } m_surface.Flip( &flip ); if (!m_view_visible) { m_window.SetOpacity( 0xff ); m_view_visible = true; } } }; }