From 27d1e03d7bdf8fcfe7292c06e40bc3e2fca9158e Mon Sep 17 00:00:00 2001 From: Denis Oliver Kropp Date: Tue, 19 Oct 2010 15:56:15 +0200 Subject: pluggit --- src/Main.cxx | 415 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 415 insertions(+) create mode 100644 src/Main.cxx (limited to 'src/Main.cxx') diff --git a/src/Main.cxx b/src/Main.cxx new file mode 100644 index 0000000..10013d8 --- /dev/null +++ b/src/Main.cxx @@ -0,0 +1,415 @@ +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; + } + } +}; + +} + -- cgit