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/Clock.cxx | 32 + src/Exception.cxx | 59 + src/Exception.h | 18 + src/FPS.cxx | 43 + src/Main.cxx | 415 +++++ src/Makefile.am | 38 + src/Makefile.in | 545 ++++++ src/Makefile.win | 62 + src/Options.cxx | 275 +++ src/OutOfMemoryException.cxx | 10 + src/Random.cxx | 11 + src/Runnable.cxx | 9 + src/Scaler.cxx | 170 ++ src/ScreenHooks.h | 34 + src/Source.cxx | 22 + src/SourceWin32.cxx | 653 +++++++ src/SourceX11.cxx | 534 ++++++ src/Thread.cxx | 71 + src/Updates.cxx | 78 + src/View.cxx | 13 + src/classes.cpp | 4047 ++++++++++++++++++++++++++++++++++++++++++ src/classes.h | 64 + src/gen_classes.sh | 33 + src/main.c | 11 + src/stretch_hvx_16.h | 469 +++++ src/stretch_hvx_32.h | 168 ++ src/stretch_hvx_N.h | 42 + src/stretch_up_down_16.h | 68 + src/stretch_up_down_32.h | 68 + src/stretch_up_down_table.h | 59 + src/videodriver.cpp | 905 ++++++++++ src/videodriver.h | 76 + src/videodrivercheck.cpp | 154 ++ 33 files changed, 9256 insertions(+) create mode 100644 src/Clock.cxx create mode 100644 src/Exception.cxx create mode 100644 src/Exception.h create mode 100644 src/FPS.cxx create mode 100644 src/Main.cxx create mode 100644 src/Makefile.am create mode 100644 src/Makefile.in create mode 100644 src/Makefile.win create mode 100644 src/Options.cxx create mode 100644 src/OutOfMemoryException.cxx create mode 100644 src/Random.cxx create mode 100644 src/Runnable.cxx create mode 100644 src/Scaler.cxx create mode 100644 src/ScreenHooks.h create mode 100644 src/Source.cxx create mode 100644 src/SourceWin32.cxx create mode 100644 src/SourceX11.cxx create mode 100644 src/Thread.cxx create mode 100644 src/Updates.cxx create mode 100644 src/View.cxx create mode 100644 src/classes.cpp create mode 100644 src/classes.h create mode 100755 src/gen_classes.sh create mode 100644 src/main.c create mode 100644 src/stretch_hvx_16.h create mode 100644 src/stretch_hvx_32.h create mode 100644 src/stretch_hvx_N.h create mode 100644 src/stretch_up_down_16.h create mode 100644 src/stretch_up_down_32.h create mode 100644 src/stretch_up_down_table.h create mode 100644 src/videodriver.cpp create mode 100644 src/videodriver.h create mode 100644 src/videodrivercheck.cpp (limited to 'src') diff --git a/src/Clock.cxx b/src/Clock.cxx new file mode 100644 index 0000000..bacf373 --- /dev/null +++ b/src/Clock.cxx @@ -0,0 +1,32 @@ +namespace PluggIt { + +class Clock +{ + private long long base; + private char str[20]; + + public Clock() { + Reset(); + } + + public void Reset() { + base = direct_clock_get_micros(); + } + + public float GetTime() { + return (direct_clock_get_micros() - base) / 1000000.0f; + } + + public const char *GetString() { + float time = GetTime(); + int seconds = (int) time; + int minutes = seconds / 60; + + snprintf( str, sizeof(str), "%02d:%02d", minutes, seconds ); + + return str; + } +}; + +} + diff --git a/src/Exception.cxx b/src/Exception.cxx new file mode 100644 index 0000000..2d19769 --- /dev/null +++ b/src/Exception.cxx @@ -0,0 +1,59 @@ +namespace PluggIt { + +class Exception +{ + private string m_message; + + + public Exception( string message ) { + m_message = message; + } + + public Exception( const char *format, ... ) D_FORMAT_PRINTF(2) { + va_list args; + int len; + char buf[200]; + char *ptr = buf; + + va_start( args, format ); + len = vsnprintf( buf, sizeof(buf), format, args ); + va_end( args ); + + if (len < 0) + abort(); + + if (len >= (int)sizeof(buf)) { + ptr = (char*) malloc( len+1 ); + if (!ptr) + abort(); + + va_start( args, format ); + len = vsnprintf( ptr, len+1, format, args ); + va_end( args ); + + if (len < 0) { + free( ptr ); + abort(); + } + } + + m_message = string( ptr ); + + if (ptr != buf) + free( ptr ); + } + + public string getMessage() { + return m_message; + } + + + friend std::ostream &operator << (std::ostream &stream, Exception *ex) { + stream << ex->getMessage(); + + return stream; + } +}; + +} + diff --git a/src/Exception.h b/src/Exception.h new file mode 100644 index 0000000..821f569 --- /dev/null +++ b/src/Exception.h @@ -0,0 +1,18 @@ +#include + +namespace PluggIt { + +class Exception +{ +public: + Exception( std::string message ); + + Exception( const char *format, ... ) D_FORMAT_PRINTF(2); + + std::string getMessage(); + + friend std::ostream &operator << (std::ostream &stream, Exception *ex); +}; + +} + diff --git a/src/FPS.cxx b/src/FPS.cxx new file mode 100644 index 0000000..3c0dd54 --- /dev/null +++ b/src/FPS.cxx @@ -0,0 +1,43 @@ +namespace PluggIt { + +class FPS +{ + private int frames; + private char str[20]; + + private Clock clock; + + + public FPS() { + Reset(); + } + + public void Reset() { + frames = 0; + str[0] = 0; + + clock.Reset(); + } + + public void Count( float interval ) { + float time = clock.GetTime(); + + frames++; + + if (time >= interval) { + float fps = frames / time; + + snprintf( str, sizeof(str), "%.1f", fps ); + + frames = 0; + clock.Reset(); + } + } + + public const char *GetFPS() { + return str; + } +}; + +} + 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; + } + } +}; + +} + diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..9cee335 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,38 @@ +## Makefile.am for PluggIt/src + +AM_CPPFLAGS = -DDATADIR=\"@DATADIR@/\" + +INCLUDES = @DFB_CFLAGS@ +LDADD = @DFB_LIBS@ -lX11 -lXext -lXdamage + +bin_PROGRAMS = pluggit + +pluggit_SOURCES = \ + classes.cpp + +pluggit_LDADD = $(LDADD) + +CLASSES = \ + Exception.cxx \ + OutOfMemoryException.cxx \ + \ + Clock.cxx \ + FPS.cxx \ + Options.cxx \ + Random.cxx \ + Updates.cxx \ + \ + Runnable.cxx \ + Thread.cxx \ + \ + Scaler.cxx \ + \ + View.cxx \ + Source.cxx \ + SourceX11.cxx \ + \ + Main.cxx + +classes.cpp: $(CLASSES) *.h Makefile gen_classes.sh main.c + ./gen_classes.sh $(CLASSES) > classes.cpp + diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..90a45f1 --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,545 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +bin_PROGRAMS = pluggit$(EXEEXT) +subdir = src +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am_pluggit_OBJECTS = classes.$(OBJEXT) +pluggit_OBJECTS = $(am_pluggit_OBJECTS) +am__DEPENDENCIES_1 = +pluggit_DEPENDENCIES = $(am__DEPENDENCIES_1) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(pluggit_SOURCES) +DIST_SOURCES = $(pluggit_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DFB_CFLAGS = @DFB_CFLAGS@ +DFB_LIBS = @DFB_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CPPFLAGS = -DDATADIR=\"@DATADIR@/\" +INCLUDES = @DFB_CFLAGS@ +LDADD = @DFB_LIBS@ -lX11 -lXext -lXdamage +pluggit_SOURCES = \ + classes.cpp + +pluggit_LDADD = $(LDADD) +CLASSES = \ + Exception.cxx \ + OutOfMemoryException.cxx \ + \ + Clock.cxx \ + FPS.cxx \ + Options.cxx \ + Random.cxx \ + Updates.cxx \ + \ + Runnable.cxx \ + Thread.cxx \ + \ + Scaler.cxx \ + \ + View.cxx \ + Source.cxx \ + SourceX11.cxx \ + \ + Main.cxx + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p || test -f $$p1; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +pluggit$(EXEEXT): $(pluggit_OBJECTS) $(pluggit_DEPENDENCIES) + @rm -f pluggit$(EXEEXT) + $(CXXLINK) $(pluggit_OBJECTS) $(pluggit_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/classes.Po@am__quote@ + +.cpp.o: +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic clean-libtool ctags distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-binPROGRAMS install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-binPROGRAMS + + +classes.cpp: $(CLASSES) *.h Makefile gen_classes.sh main.c + ./gen_classes.sh $(CLASSES) > classes.cpp + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/Makefile.win b/src/Makefile.win new file mode 100644 index 0000000..8205892 --- /dev/null +++ b/src/Makefile.win @@ -0,0 +1,62 @@ +## Makefile.am for PluggIt/src + +DFB = /cygdrive/c/DirectFB +PPDFB = /cygdrive/c/++DFB + +INCLUDES = -I. \ + -I$(DFB)/include \ + -I$(DFB)/lib \ + -I$(DFB)/src \ + -I$(PPDFB)/include + +CPPFLAGS = \ + -D__WIN32__ + +LDADD = \ + $(DFB)/proxy/dispatcher/*.o \ + $(DFB)/proxy/requestor/*.o \ + -lppdfb -ldirectfb -lvoodoo -lfusion -ldirect \ + -lgdi32 -luser32 -lversion + #-lX11 -lXext -lXdamage -lXfixes + +all: /tmp/pluggit + +OBJECTS = \ + classes.o \ + videodriver.o \ + videodrivercheck.o + +/tmp/pluggit: $(OBJECTS) + $(CXX) $+ $(LDADD) -o /tmp/pluggit + +.cpp.o: + $(CXX) -o $@ -c $< $(INCLUDES) $(CPPFLAGS) + + +CLASSES = \ + Exception.cxx \ + OutOfMemoryException.cxx \ + \ + Clock.cxx \ + FPS.cxx \ + Options.cxx \ + Random.cxx \ + Updates.cxx \ + \ + Runnable.cxx \ + Thread.cxx \ + \ + Scaler.cxx \ + \ + View.cxx \ + Source.cxx \ + SourceWin32.cxx \ + \ + Main.cxx + + +export CPPFLAGS + +classes.cpp: $(CLASSES) *.h Makefile.win gen_classes.sh main.c + ./gen_classes.sh $(CLASSES) > classes.cpp + diff --git a/src/Options.cxx b/src/Options.cxx new file mode 100644 index 0000000..27e8924 --- /dev/null +++ b/src/Options.cxx @@ -0,0 +1,275 @@ +namespace PluggIt { + +static const DirectFBPixelFormatNames(m_formats); + +class Options +{ + class Option { + friend class Options; + + protected const char *m_short_name; + protected const char *m_long_name; + protected const char *m_arg_name; + protected const char *m_arg_desc; + protected bool m_need_arg; + + public Option( const char *short_name, + const char *long_name, + const char *arg_name, + const char *arg_desc ) + { + m_short_name = short_name; + m_long_name = long_name; + m_arg_name = arg_name; + m_arg_desc = arg_desc; + m_need_arg = true; + } + + public virtual bool Parse( const char *arg ) = 0; + }; + + public class OptionBool extends Option { + private bool &m_value; + + public OptionBool( const char *short_name, + const char *long_name, + const char *arg_name, + const char *arg_desc, + bool &value ) : Option( short_name, long_name, arg_name, arg_desc ), m_value( value ) + { + m_need_arg = false; + } + + public virtual bool Parse( const char *arg ) { + m_value = true; + + return true; + } + }; + + public class OptionLong extends Option { + private long &m_value; + private int m_base; + + public OptionLong( const char *short_name, + const char *long_name, + const char *arg_name, + const char *arg_desc, + long &value, + int base = 10 ) : Option( short_name, long_name, arg_name, arg_desc ), m_value( value ) + { + m_base = base; + } + + public virtual bool Parse( const char *arg ) { + long ret; + char *end; + + ret = strtol( arg, &end, m_base ); + + if (*end) { + D_ERROR( "Option/Long: Invalid argument to '%s' or '%s'!\n", m_short_name, m_long_name ); + return false; + } + + m_value = ret; + + return true; + } + }; + + public class OptionULong extends Option { + private unsigned long &m_value; + private int m_base; + + public OptionULong( const char *short_name, + const char *long_name, + const char *arg_name, + const char *arg_desc, + unsigned long &value, + int base = 10 ) : Option( short_name, long_name, arg_name, arg_desc ), m_value( value ) + { + m_base = base; + } + + public virtual bool Parse( const char *arg ) { + unsigned long ret; + char *end; + + ret = strtoul( arg, &end, m_base ); + + if (*end) { + D_ERROR( "Option/ULong: Invalid argument to '%s' or '%s'!\n", m_short_name, m_long_name ); + return false; + } + + m_value = ret; + + return true; + } + }; + + public class OptionFormat extends Option { + private DFBSurfacePixelFormat &m_value; + + public OptionFormat( const char *short_name, + const char *long_name, + const char *arg_name, + const char *arg_desc, + DFBSurfacePixelFormat &value ) : Option( short_name, long_name, arg_name, arg_desc ), m_value( value ) + { + } + + public virtual bool Parse( const char *arg ) { + unsigned int i; + + for (i=0; i m_options; + + public void addOption( Option *option ) { + m_options.push_back( option ); + } + + public bool parseCommandLine( int argc, char *argv[] ) { + int n; + + for (n = 1; n < argc; n++) { + bool ok = false; + const char *arg = argv[n]; + + if (strcmp (arg, "-h") == 0 || strcmp (arg, "--help") == 0) { + printUsage (argv[0]); + return false; + } + + if (strcmp (arg, "-v") == 0 || strcmp (arg, "--version") == 0) { +// fprintf (stderr, "dfbscreen version %s\n", DIRECTFB_VERSION); + return false; + } + + vector::iterator itr = m_options.begin(); + + for (; itr != m_options.end(); itr++) { + Option *option = *itr; + + if (!strcmp (arg, option->m_short_name) || !strcmp (arg, option->m_long_name)) { + if (option->m_need_arg && ++n == argc) { + printUsage (argv[0]); + return false; + } + + if (!option->Parse( argv[n] )) + return false; + + ok = true; + + break; + } + } + + if (!ok) { + printUsage (argv[0]); + return false; + } + } + + return true; + } + + public void printUsage( const char *prg_name ) { + //fprintf (stderr, "\nDirectFB Screen Configuration (version %s)\n\n", DIRECTFB_VERSION); + fprintf (stderr, "Usage: %s [options]\n\n", prg_name); + fprintf (stderr, "Options:\n"); + fprintf (stderr, " -h --help Show this help message\n"); + fprintf (stderr, " -v --version Print version information\n"); + + + vector::const_iterator itr = m_options.begin(); + + for (; itr != m_options.end(); itr++) { + const Option *option = *itr; + + fprintf( stderr, " %-3s %-16s %-12s %s\n", + option->m_short_name, option->m_long_name, option->m_arg_name, option->m_arg_desc ); + } + + fprintf( stderr, "\n" ); + } +}; + +} + diff --git a/src/OutOfMemoryException.cxx b/src/OutOfMemoryException.cxx new file mode 100644 index 0000000..9fee368 --- /dev/null +++ b/src/OutOfMemoryException.cxx @@ -0,0 +1,10 @@ +namespace PluggIt { + +class OutOfMemoryException extends Exception +{ + public OutOfMemoryException() : Exception( "Out of memory!" ) { + } +}; + +} + diff --git a/src/Random.cxx b/src/Random.cxx new file mode 100644 index 0000000..62c53a3 --- /dev/null +++ b/src/Random.cxx @@ -0,0 +1,11 @@ +namespace PluggIt { + +class Random +{ + public static float nextFloat( float min, float max ) { + return min + rand() * (max - min) / (float) RAND_MAX; + } +}; + +} + diff --git a/src/Runnable.cxx b/src/Runnable.cxx new file mode 100644 index 0000000..5a5bed8 --- /dev/null +++ b/src/Runnable.cxx @@ -0,0 +1,9 @@ +namespace PluggIt { + +class Runnable +{ + public virtual void run() = 0; +}; + +} + diff --git a/src/Scaler.cxx b/src/Scaler.cxx new file mode 100644 index 0000000..9e9af3c --- /dev/null +++ b/src/Scaler.cxx @@ -0,0 +1,170 @@ +namespace PluggIt { + +D_DEBUG_DOMAIN( PluggIt_Scaler, "PluggIt/Scaler", "PluggIt Scaler" ); + + +typedef struct { + DFBRegion clip; + const void *colors; + unsigned long protect; + unsigned long key; +} StretchCtx; + +typedef void (*StretchHVx)( void *dst, + int dpitch, + const void *src, + int spitch, + int width, + int height, + int dst_width, + int dst_height, + const StretchCtx *ctx ); + +#define STRETCH_NONE 0 +#define STRETCH_SRCKEY 1 +#define STRETCH_PROTECT 2 +#define STRETCH_SRCKEY_PROTECT 3 +#define STRETCH_NUM 4 + +#define PIXEL_RGB16(r,g,b) ( (((r)&0xF8) << 8) | \ + (((g)&0xFC) << 3) | \ + (((b)&0xF8) >> 3) ) + +/**********************************************************************************************************************/ +/*** 16 bit RGB 565 scalers *******************************************************************************************/ +/**********************************************************************************************************************/ + +#define DST_FORMAT DSPF_RGB16 +#define TABLE_NAME stretch_hvx_RGB16 +#define FUNC_NAME(UPDOWN,K,P,F) stretch_hvx_RGB16_ ## UPDOWN ## _ ## K ## P ## _ ## F +#define SHIFT_R5 5 +#define SHIFT_R6 6 +#define X_F81F 0xf81f +#define X_07E0 0x07e0 +#define MASK_RGB 0xffff + +#define FORMAT_RGB16 +#include "stretch_up_down_16.h" +#undef FORMAT_RGB16 + +#undef DST_FORMAT +#undef TABLE_NAME +#undef FUNC_NAME +#undef SHIFT_R5 +#undef SHIFT_R6 +#undef X_F81F +#undef X_07E0 +#undef MASK_RGB + +/**********************************************************************************************************************/ +/*** 32 bit RGB 8888 scalers ******************************************************************************************/ +/**********************************************************************************************************************/ + +#define DST_FORMAT DSPF_ARGB +#define TABLE_NAME stretch_hvx_ARGB +#define FUNC_NAME(UPDOWN,K,P,F) stretch_hvx_ARGB_ ## UPDOWN ## _ ## K ## P ## _ ## F +#define SHIFT_R8 8 +#define SHIFT_L8 8 +#define X_00FF00FF 0x00ff00ff +#define X_FF00FF00 0xff00ff00 +#define MASK_RGB 0x00ffffff + +#define FORMAT_ARGB +#include "stretch_up_down_32.h" +#undef FORMAT_ARGB + +#undef DST_FORMAT +#undef TABLE_NAME +#undef FUNC_NAME +#undef SHIFT_R8 +#undef SHIFT_L8 +#undef X_00FF00FF +#undef X_FF00FF00 +#undef MASK_RGB + +/**********************************************************************************************************************/ +/*** 32 bit RGB 8888 scalers ******************************************************************************************/ +/**********************************************************************************************************************/ + +#define DST_FORMAT DSPF_RGB32 +#define TABLE_NAME stretch_hvx_RGB32 +#define FUNC_NAME(UPDOWN,K,P,F) stretch_hvx_RGB32_ ## UPDOWN ## _ ## K ## P ## _ ## F +#define SHIFT_R8 8 +#define SHIFT_L8 8 +#define X_00FF00FF 0x00ff00ff +#define X_FF00FF00 0x0000ff00 +#define MASK_RGB 0x00ffffff + +#define FORMAT_RGB32 +#include "stretch_up_down_32.h" +#undef FORMAT_RGB32 + +#undef DST_FORMAT +#undef TABLE_NAME +#undef FUNC_NAME +#undef SHIFT_R8 +#undef SHIFT_L8 +#undef X_00FF00FF +#undef X_FF00FF00 +#undef MASK_RGB + + +class Scaler +{ + + public Scaler() { + } + + public void scale( DFBSurfacePixelFormat format, + void *dst, + int dpitch, + const void *src, + int spitch, + int width, + int height, + int dst_width, + int dst_height, + const DFBRegion &clip ) + { + D_DEBUG_AT( PluggIt_Scaler, "%s( %s, %p [%d], %p [%d], %dx%d -> %dx%d, clip %4d,%4d-%4dx%4d )\n", + __FUNCTION__, dfb_pixelformat_name( format ), dst, dpitch, src, spitch, width, height, + dst_width, dst_height, DFB_RECTANGLE_VALS_FROM_REGION( &clip ) ); + + + StretchCtx ctx; + + ctx.clip = clip; + + switch (format) { + case DSPF_RGB16: + if (width <= dst_width || height <= dst_height) + stretch_hvx_RGB16_up____DSPF_RGB32( dst, dpitch, src, spitch, width, height, dst_width, dst_height, &ctx ); + else + stretch_hvx_RGB16_down____DSPF_RGB32( dst, dpitch, src, spitch, width, height, dst_width, dst_height, &ctx ); + break; + + case DSPF_RGB32: + if (width <= dst_width || height <= dst_height) + stretch_hvx_RGB32_up____DSPF_RGB32( dst, dpitch, src, spitch, width, height, dst_width, dst_height, &ctx ); + else + stretch_hvx_RGB32_down____DSPF_RGB32( dst, dpitch, src, spitch, width, height, dst_width, dst_height, &ctx ); + break; + + case DSPF_ARGB: + if (width <= dst_width || height <= dst_height) + stretch_hvx_ARGB_up____DSPF_RGB32( dst, dpitch, src, spitch, width, height, dst_width, dst_height, &ctx ); + else + stretch_hvx_ARGB_down____DSPF_RGB32( dst, dpitch, src, spitch, width, height, dst_width, dst_height, &ctx ); + break; + + default: + D_UNIMPLEMENTED(); + break; + } + } +}; + + + +} + diff --git a/src/ScreenHooks.h b/src/ScreenHooks.h new file mode 100644 index 0000000..ea40b6b --- /dev/null +++ b/src/ScreenHooks.h @@ -0,0 +1,34 @@ +// Copyright (C) 2008, 2009, 2010 GlavSoft LLC. +// All rights reserved. +// +//------------------------------------------------------------------------- +// This file is part of the TightVNC software. Please visit our Web site: +// +// http://www.tightvnc.com/ +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +//------------------------------------------------------------------------- +// + +#ifndef __SCREENHOOKS_H__ +#define __SCREENHOOKS_H__ + +extern "C" +{ + __declspec(dllexport) bool setHook(HWND targedWinHwnd); + __declspec(dllexport) bool unsetHook(); +} + +#endif diff --git a/src/Source.cxx b/src/Source.cxx new file mode 100644 index 0000000..871e796 --- /dev/null +++ b/src/Source.cxx @@ -0,0 +1,22 @@ +namespace PluggIt { + +class Source +{ + protected class Config { + protected Config() {} + }; + + + protected View *m_view; + protected const Config &m_config; + + public Source( View *view, const Config &config ) : m_config(config) { + m_view = view; + } + + + public virtual int MainLoop() = 0; +}; + +} + diff --git a/src/SourceWin32.cxx b/src/SourceWin32.cxx new file mode 100644 index 0000000..25ac45b --- /dev/null +++ b/src/SourceWin32.cxx @@ -0,0 +1,653 @@ +namespace PluggIt { + +D_DEBUG_DOMAIN( PluggIt_SourceWin32, "PluggIt/SourceWin32", "PluggIt Source Win32" ); + + +#include "ScreenHooks.h" + +const UINT specIpcCode = RegisterWindowMessage("HOOK.MESSAGE.CODE"); + + +class SourceWin32 extends Source, Runnable +{ + private HINSTANCE m_hInstance; + + private HWND m_root; + private HWND m_window; + + private DFBPoint m_position; + private DFBDimension m_size; + + private HBITMAP m_bitmap; + private void *m_pixels; + private int m_pitch; + + private HBITMAP m_bitmap2; + private void *m_pixels2; + private int m_pitch2; + + private HDC m_window_dc; + private HDC m_bitmap_dc; + private HDC m_bitmap_dc2; + + private Thread *m_thread; + + private Updates m_updates; + + private VIDEODRIVER m_driver; + private bool m_using_driver; + + private pthread_mutex_t m_lock; + private pthread_cond_t m_cond; + + + public class Config extends Source::Config { + friend class SourceWin32; + + public typedef enum { + WINDOW_SELECTION_NONE, + WINDOW_SELECTION_TITLE, + WINDOW_SELECTION_INTERACTIVE + } WindowSelection; + + private WindowSelection m_selection; + private std::string m_title; + private bool m_updating; + private bool m_use_driver; + + + public Config( WindowSelection selection, + const std::string &title = std::string(), + bool updating = false, bool use_driver = true ) + { + m_selection = selection; + m_title = title; + m_updating = updating; + m_use_driver = use_driver; + } + }; + + + public SourceWin32( View *view, const Config &config ) : Source( view, config ), m_updates(16) { + D_DEBUG_AT( PluggIt_SourceWin32, "%s( %p )\n", __FUNCTION__, view ); + + m_hInstance = GetModuleHandle( NULL ); + + D_DEBUG_AT( PluggIt_SourceWin32, " -> hInstance %p\n", m_hInstance ); + + + m_root = GetDesktopWindow(); + + switch (config.m_selection) { + case Config::WINDOW_SELECTION_NONE: + m_window = m_root; + break; + + case Config::WINDOW_SELECTION_TITLE: + m_window = findWindow( config.m_title ); + if (m_window == 0) + throw new Exception( "Could not find window with title containing '%s'\n", config.m_title.c_str() ); + break; + + case Config::WINDOW_SELECTION_INTERACTIVE: + pickWindow(); + if (m_window == 0) + throw new Exception( "Could not interactively pick a window\n" ); + break; + + default: + throw new Exception( "Invalid window selection method\n" ); + } + + + RECT rect; + + GetClientRect( m_window, &rect ); + + m_position.x = rect.left; + m_position.y = rect.top; + + m_size.w = rect.right - rect.left; + m_size.h = rect.bottom - rect.top; + + queueUpdate( 0, 0, m_size.w - 1, m_size.h - 1 ); + + + std::string t = getWindowTitle( m_window ); + + D_INFO( "Source/Win32: Window %d,%d-%ux%u, name '%s'\n", + m_position.x, m_position.y, m_size.w, m_size.h, t.c_str() ); + + if (config.m_use_driver) + m_driver.VIDEODRIVER_start( m_position.x, m_position.y, m_size.w, m_size.h ); + + m_using_driver = m_driver.mypchangebuf != NULL; + + m_view->config( m_size ); + + + m_window_dc = GetDC( m_window ); + m_bitmap_dc = CreateCompatibleDC( m_window_dc ); + m_bitmap_dc2 = CreateCompatibleDC( m_window_dc ); + + + BITMAPINFO bitmap_info = {{ + biSize: sizeof(BITMAPINFOHEADER), + biWidth: m_size.w, + biHeight: m_size.h, + biPlanes: 1, + biBitCount: 32, + biCompression: BI_RGB, + biSizeImage: 0, + biXPelsPerMeter: 0, + biYPelsPerMeter: 0, + biClrUsed: 0, + biClrImportant: 0, + }}; + + m_bitmap = CreateDIBSection( m_window_dc, &bitmap_info, DIB_RGB_COLORS, &m_pixels, NULL, 0 ); + m_bitmap2 = CreateDIBSection( m_window_dc, &bitmap_info, DIB_RGB_COLORS, &m_pixels2, NULL, 0 ); + + + BITMAP bitmap; + + GetObject( m_bitmap, sizeof(BITMAP), &bitmap ); + + m_pitch = bitmap.bmWidthBytes; + + GetObject( m_bitmap2, sizeof(BITMAP), &bitmap ); + + m_pitch2 = bitmap.bmWidthBytes; + + + SelectObject( m_bitmap_dc, m_bitmap ); + SelectObject( m_bitmap_dc2, m_bitmap2 ); + + + pthread_mutex_init( &m_lock, NULL ); + pthread_cond_init( &m_cond, NULL ); + + + if (!m_using_driver) { + HWND w; + + WNDCLASSEX wndClass; + + ZeroMemory( &wndClass, sizeof(wndClass) ); + + wndClass.cbSize = sizeof(wndClass); + wndClass.style = CS_HREDRAW | CS_VREDRAW; + wndClass.lpfnWndProc = MsgWndProc; + wndClass.cbClsExtra = 0; + wndClass.cbWndExtra = 0; + wndClass.hInstance = GetModuleHandle(NULL); + wndClass.hIcon = NULL; + wndClass.hIconSm = NULL; + wndClass.hCursor = LoadCursor( NULL, IDC_UPARROW ); + wndClass.hbrBackground = (HBRUSH) GetStockObject( NULL_BRUSH ); + wndClass.lpszMenuName = NULL; + wndClass.lpszClassName = "MsgWindow"; + + if (!RegisterClassEx( &wndClass )) + throw new Exception( "RegisterClassEx() failed!" ); + + + w = CreateWindowEx( 0, + "MsgWindow", + "MsgWindow", + WS_POPUP,// | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_BORDER, + CW_USEDEFAULT, + CW_USEDEFAULT, + 1, + 1, + NULL, + NULL, + GetModuleHandle(NULL), + this ); + + if (!setHook( w )) + throw new Exception( "Failed to set hooks!" ); + } + + + /* Create the thread object. */ + m_thread = new Thread( this, "SourceWin32" ); + + m_thread->start(); + } + + virtual ~SourceWin32() { + m_thread->interrupt(); + m_thread->join(); + delete m_thread; + + pthread_mutex_destroy( &m_lock ); + pthread_cond_destroy( &m_cond ); + + DeleteDC( m_window_dc ); + DeleteDC( m_bitmap_dc ); + DeleteDC( m_bitmap_dc2 ); + + DeleteObject( m_bitmap ); + DeleteObject( m_bitmap2 ); + } + + private void addRect( const RECT &rect ) { + if (rect.left >= rect.right) + return; + + if (rect.top >= rect.bottom) + return; + + DFBRegion region( rect.left, + rect.top, + rect.right - 1, + rect.bottom - 1 ); + + m_updates.addRegion( region ); + } + + private void run() { + if (m_using_driver) { + D_ASSERT( m_driver.mypchangebuf != NULL ); + + unsigned int counter = m_driver.mypchangebuf->counter; + unsigned int i; + + long long last_time = direct_clock_get_abs_millis(); + + D_DEBUG_AT( PluggIt_SourceWin32, "%s()\n", __FUNCTION__ ); + + while (!m_thread->isInterrupted()) { + if (m_driver.mypchangebuf->counter < 1 || + m_driver.mypchangebuf->counter >= MAXCHANGES_BUF || + counter == m_driver.mypchangebuf->counter) + usleep( 10000 ); + + if (counter != m_driver.mypchangebuf->counter) { + D_DEBUG_AT( PluggIt_SourceWin32, " -> counter: %d -> %d\n", counter, m_driver.mypchangebuf->counter ); + + if (counter < m_driver.mypchangebuf->counter) { + for (i=counter+1; i<=m_driver.mypchangebuf->counter; i++) { + addRect( m_driver.mypchangebuf->pointrect[i].rect ); + } + } + else if (counter > m_driver.mypchangebuf->counter) { + for (i=counter+1; ipointrect[i].rect ); + } + for (i=1; i<=m_driver.mypchangebuf->counter; i++) { + addRect( m_driver.mypchangebuf->pointrect[i].rect ); + } + } + + counter = m_driver.mypchangebuf->counter; + } + + if (direct_clock_get_abs_millis() - last_time > 2000) { + DFBRegion region( 0, + 0, + m_size.w - 1, + m_size.h - 1 ); + + m_updates.addRegion( region ); + + last_time = direct_clock_get_abs_millis(); + } + + if (m_updates.num_regions() > 0) { + vector rects; + + m_updates.GetRectangles( rects ); + + + const DFBRegion &bounding = m_updates.bounding(); + + D_DEBUG_AT( PluggIt_SourceWin32, " -> %4d,%4d-%4dx%4d (%d regions, %d rectangles)\n", + DFB_RECTANGLE_VALS_FROM_REGION( &bounding ), m_updates.num_regions(), rects.size() ); + + m_updates.reset(); + + flushUpdates( rects ); + } + } + } + else { + D_DEBUG_AT( PluggIt_SourceWin32, "%s()\n", __FUNCTION__ ); + + long long last_time = direct_clock_get_abs_millis(); + + while (!m_thread->isInterrupted()) { + if (((const Config&)m_config).m_updating) { + usleep( 100000 ); + + queueUpdate( 0, 0, m_size.w - 1, m_size.h - 1 ); + + pthread_mutex_lock( &m_lock ); + } + else { + pthread_mutex_lock( &m_lock ); + + if (m_updates.num_regions() == 0) + usleep( 10000 ); + //pthread_cond_wait( &m_cond, &m_lock ); + } + + if (direct_clock_get_abs_millis() - last_time > 2000) { + DFBRegion region( 0, + 0, + m_size.w - 1, + m_size.h - 1 ); + + m_updates.addRegion( region ); + + last_time = direct_clock_get_abs_millis(); + } + + + vector rects; + + if (m_updates.num_regions() > 0) { + m_updates.GetRectangles( rects ); + + + const DFBRegion &bounding = m_updates.bounding(); + + D_DEBUG_AT( PluggIt_SourceWin32, " -> %4d,%4d-%4dx%4d (%d regions, %d rectangles)\n", + DFB_RECTANGLE_VALS_FROM_REGION( &bounding ), m_updates.num_regions(), rects.size() ); + + m_updates.reset(); + } + + pthread_mutex_unlock( &m_lock ); + + if (!rects.empty()) + flushUpdates( rects ); + } + } + } + +/**********************************************************************************************************************/ + + private void queueUpdate( int x1, int y1, int x2, int y2 ) { + D_DEBUG_AT( PluggIt_SourceWin32, "%s( %d,%d-%dx%d )\n", __FUNCTION__, x1, y1, x2 - x1 + 1, y2 - y1 + 1 ); + + pthread_mutex_lock( &m_lock ); + + DFBRegion damage( x1, y1, x2, y2 ); + + m_updates.addRegion( damage ); + + pthread_mutex_unlock( &m_lock ); + + pthread_cond_signal( &m_cond ); + } + + private bool flushUpdates( vector &rects ) { + D_DEBUG_AT( PluggIt_SourceWin32, "%s()\n", __FUNCTION__ ); + + if (m_using_driver) { + m_view->update( rects, m_driver.myframebuffer, m_pitch ); + } + else { + for (unsigned int i=0; iupdate( rects, (void*)((char*) m_pixels + m_pitch * (m_size.h - 1)), - m_pitch ); + } + + D_DEBUG_AT( PluggIt_SourceWin32, " -> flush done\n" ); + + return true; + } + + + +/**********************************************************************************************************************/ + + private static std::string getWindowTitle( HWND window ) { + char buf[1024] = { 0 }; + + GetWindowText( window, buf, sizeof(buf) ); + + D_DEBUG_AT( PluggIt_SourceWin32, "%s( %p ) -> '%s'\n", __FUNCTION__, window, buf ); + + return buf; + } + + +/**********************************************************************************************************************/ + + class EnumContext { + public const std::string &title; + public HWND window; + + public EnumContext( const std::string &title ) : title(title), window(0) {} + }; + + private static BOOL CALLBACK enumWindowsProc( HWND hwnd, + LPARAM lParam ) + { + EnumContext *ctx = reinterpret_cast( lParam ); + + D_DEBUG_AT( PluggIt_SourceWin32, "%s( %p )\n", __FUNCTION__, hwnd ); + + std::string title = getWindowTitle( hwnd ); + + if (title == ctx->title || title.find( ctx->title ) < title.size()) + ctx->window = hwnd; + + return ctx->window == NULL; + } + + private HWND findWindow( const std::string &title ) { + D_DEBUG_AT( PluggIt_SourceWin32, "%s( %s )\n", __FUNCTION__, title.c_str() ); + + EnumContext ctx( title ); + + EnumWindows( enumWindowsProc, reinterpret_cast( &ctx ) ); + + return ctx.window; + } + + +/**********************************************************************************************************************/ + + static LRESULT CALLBACK WndProc( HWND hwnd, // handle to window + UINT uMsg, // message identifier + WPARAM wParam, // first message parameter + LPARAM lParam ) // second message parameter + { + static SourceWin32 *thiz; + POINT point; + CREATESTRUCT *create; + + switch (uMsg) { + case WM_CREATE: + create = reinterpret_cast( lParam ); + thiz = reinterpret_cast( create->lpCreateParams ); + + SetCursor( LoadCursor( NULL, IDC_CROSS ) ); + break; + + case WM_LBUTTONDOWN: + ShowWindow( hwnd, SW_HIDE ); + + + GetCursorPos( &point ); + + D_DEBUG_AT( PluggIt_SourceWin32, " -> Cursor position is %ld,%ld\n", point.x, point.y ); + + + thiz->m_window = WindowFromPoint( point ); + if (thiz->m_window) { + HWND parent; + + while ((parent = GetParent( thiz->m_window )) != NULL) + thiz->m_window = parent; + } + + D_DEBUG_AT( PluggIt_SourceWin32, " -> Window at cursor is %p: %s\n", + thiz->m_window, getWindowTitle( thiz->m_window ).c_str() ); + + DestroyWindow( hwnd ); + break; + + case WM_TIMER: + if (wParam == 666) + DestroyWindow( hwnd ); + break; + + case WM_DESTROY: + KillTimer( hwnd, 666 ); + PostQuitMessage( 0 ); + break; + + default: + SetTimer( hwnd, 666, 5000, NULL ); + + return DefWindowProc( hwnd, uMsg, wParam, lParam ); + } + + return 0; + } + + private void pickWindow() { + D_DEBUG_AT( PluggIt_SourceWin32, "%s()\n", __FUNCTION__ ); + + HDC hdc; + + hdc = GetDC( NULL ); + if (!hdc) + throw new Exception( "GetDC() returned NULL" ); + + RECT rect; + + GetClipBox( hdc, &rect ); + + D_DEBUG_AT( PluggIt_SourceWin32, " -> Desktop size: %ldx%ld\n", + rect.right - rect.left, rect.bottom - rect.top ); + + ReleaseDC( NULL, hdc ); + + + + WNDCLASSEX wndClass; + + ZeroMemory( &wndClass, sizeof(wndClass) ); + + wndClass.cbSize = sizeof(wndClass); + wndClass.style = CS_HREDRAW | CS_VREDRAW; + wndClass.lpfnWndProc = WndProc; + wndClass.cbClsExtra = 0; + wndClass.cbWndExtra = 0; + wndClass.hInstance = m_hInstance; + wndClass.hIcon = NULL; + wndClass.hIconSm = NULL; + wndClass.hCursor = LoadCursor( NULL, IDC_UPARROW ); + wndClass.hbrBackground = (HBRUSH) GetStockObject( NULL_BRUSH ); + wndClass.lpszMenuName = NULL; + wndClass.lpszClassName = "GrabWindow"; + + if (!RegisterClassEx( &wndClass )) + throw new Exception( "RegisterClassEx() failed!\n" ); + + + AdjustWindowRect( &rect, WS_CAPTION, FALSE ); + + + HWND grabwin; + + grabwin = CreateWindowEx( 0, + "GrabWindow", + "GrabWindow", + WS_POPUP,// | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_BORDER, + CW_USEDEFAULT, + CW_USEDEFAULT, + rect.right - rect.left, + rect.bottom - rect.top, + NULL, + NULL, + m_hInstance, + this ); + + SetWindowLong( grabwin, GWL_EXSTYLE, + GetWindowLong( grabwin, GWL_EXSTYLE ) | WS_EX_TRANSPARENT | WS_EX_TOPMOST ); + + ShowWindow( grabwin, SW_SHOW ); + + + + MSG msg; + + while (GetMessage( &msg, 0, 0, 0 )) { + TranslateMessage( &msg ); + + D_DEBUG_AT( PluggIt_SourceWin32, " -> Dispatching event (id %u)...\n", msg.message ); + + DispatchMessage( &msg ); + } + } + +/**********************************************************************************************************************/ + + static LRESULT CALLBACK MsgWndProc( HWND hwnd, // handle to window + UINT uMsg, // message identifier + WPARAM wParam, // first message parameter + LPARAM lParam ) // second message parameter + { + static SourceWin32 *thiz; + CREATESTRUCT *create; + + switch (uMsg) { + case WM_CREATE: + create = reinterpret_cast( lParam ); + thiz = reinterpret_cast( create->lpCreateParams ); + break; + + case WM_DESTROY: + PostQuitMessage( 0 ); + break; + + default: + if (uMsg == specIpcCode) { + int x1 = wParam >> 16; + int y1 = wParam & 0xffff; + int x2 = lParam >> 16; + int y2 = lParam & 0xffff; + + if (x1 < x2 && y1 < y2) + thiz->queueUpdate( x1, y1, x2 - 1, y2 - 1 ); + + break; + } + + return DefWindowProc( hwnd, uMsg, wParam, lParam ); + } + + return 0; + } + + public virtual int MainLoop() { + MSG msg; + + while (GetMessage( &msg, 0, 0, 0 )) { + TranslateMessage( &msg ); + DispatchMessage( &msg ); + } + + return 0; + } +}; + +} + diff --git a/src/SourceX11.cxx b/src/SourceX11.cxx new file mode 100644 index 0000000..339c8e7 --- /dev/null +++ b/src/SourceX11.cxx @@ -0,0 +1,534 @@ +extern "C" { +#include +} + +namespace PluggIt { + +D_DEBUG_DOMAIN( PluggIt_SourceX11, "PluggIt/SourceX11", "PluggIt Source X11" ); + + +class SourceX11 extends Source, Runnable +{ + private Display *m_display; + private Screen *m_screen; + private Window m_window; + private Window m_root; + + private DFBPoint m_position; + private DFBDimension m_size; + private unsigned int m_depth; + + private XImage *m_image; + private Pixmap m_pixmap; + + private Bool m_shm; + private int m_shm_major; + private int m_shm_minor; + private XShmSegmentInfo m_shm_info; + + private Damage m_xdamage; + private int m_xdamage_notify_event; + private XserverRegion m_xdamage_region; + private GC m_xdamage_copy_gc; + + private Thread *m_thread; + + private Updates m_updates; + + + + public class Config extends Source::Config { + friend class SourceX11; + + public typedef enum { + WINDOW_SELECTION_NONE, + WINDOW_SELECTION_TITLE, + WINDOW_SELECTION_INTERACTIVE + } WindowSelection; + + private WindowSelection m_selection; + private std::string m_title; + + + public Config( WindowSelection selection, const std::string &title = std::string() ) { + m_selection = selection; + m_title = title; + } + }; + + + public SourceX11( View *view, const Config &config ) : m_updates(16), Source( view, config ) { + D_DEBUG_AT( PluggIt_SourceX11, "%s( %p )\n", __FUNCTION__, view ); + + XInitThreads(); + + m_display = XOpenDisplay( getenv("DISPLAY") ); + if (!m_display) + throw new Exception( "Error in XOpenDisplay for '%s'!\n", getenv("DISPLAY") ); + + XLockDisplay( m_display ); + + m_screen = DefaultScreenOfDisplay( m_display ); + m_root = RootWindowOfScreen( m_screen ); + + switch (config.m_selection) { + case Config::WINDOW_SELECTION_NONE: + m_window = m_root; + break; + + case Config::WINDOW_SELECTION_TITLE: + m_window = findWindow( config.m_title ); + if (m_window == None) + throw new Exception( "Could not find window with title containing '%s'\n", config.m_title.c_str() ); + break; + + case Config::WINDOW_SELECTION_INTERACTIVE: + m_window = pickWindow(); + if (m_window == None) + throw new Exception( "Could not interactively pick a window\n" ); + break; + + default: + throw new Exception( "Invalid window selection method\n" ); + } + + unsigned int tmp_u; + int tmp_i; + + XGetGeometry( m_display, m_window, &m_root, &m_position.x, &m_position.y, + (unsigned int*) &m_size.w, (unsigned int*) &m_size.h, &tmp_u, &m_depth ); + + + std::string t = getWindowTitle( m_window ); + + D_INFO( "Source/X11: Window %d,%d-%ux%u, depth %u, name '%s'\n", + m_position.x, m_position.y, m_size.w, m_size.h, m_depth, t.c_str() ); + + + if (XShmQueryExtension( m_display )) + XShmQueryVersion( m_display, &m_shm_major, &m_shm_minor, &m_shm ); + + initXDamage(); + + if (m_shm) { + if (!initXShmImage()) { + m_shm = false; + + initXImage(); + } + } + else + initXImage(); + + XUnlockDisplay( m_display ); + + + m_view->config( m_size ); + + + /* Create the thread object. */ + m_thread = new Thread( this, "SourceX11" ); + + m_thread->start(); + } + + virtual ~SourceX11() { + XDestroyImage( m_image ); + + if (m_shm) { + XShmDetach( m_display, &m_shm_info ); + + shmdt( m_shm_info.shmaddr ); + } + } + + +/**********************************************************************************************************************/ + + private void run() { + D_DEBUG_AT( PluggIt_SourceX11, "%s()\n", __FUNCTION__ ); + + XLockDisplay( m_display ); + + while (true) { + XEvent event; + + XNextEvent( m_display, &event ); + + if (event.type == m_xdamage_notify_event) + handleXDamage( reinterpret_cast( &event ) ); + + if (!XPending( m_display )) + flushXDamage(); + } + + XUnlockDisplay( m_display ); + } + + +/**********************************************************************************************************************/ + + private void initXDamage() { + int event_base, error_base; + int major, minor; + XGCValues values; + + D_DEBUG_AT( PluggIt_SourceX11, "%s()\n", __FUNCTION__ ); + + if (!XDamageQueryExtension( m_display, &event_base, &error_base )) + throw new Exception( "XDamageQueryExtension" ); + + if (!XDamageQueryVersion( m_display, &major, &minor ) || major != 1) + throw new Exception( "XDamageQueryVersion" ); + + m_xdamage_notify_event = event_base + XDamageNotify; + + m_xdamage = XDamageCreate( m_display, m_window, XDamageReportDeltaRectangles ); + if (m_xdamage == None) + throw new Exception( "XDamageCreate" ); + + m_xdamage_region = XFixesCreateRegion( m_display, NULL, 0 ); + if (m_xdamage_region == None) { + XDamageDestroy( m_display, m_xdamage ); + m_xdamage = None; + throw new Exception( "XFixesCreateRegion" ); + } + + values.subwindow_mode = IncludeInferiors; + + m_xdamage_copy_gc = XCreateGC( m_display, m_window, GCSubwindowMode, &values ); + } + + private void handleXDamage( const XDamageNotifyEvent *event ) { + D_DEBUG_AT( PluggIt_SourceX11, "%s()\n", __FUNCTION__ ); + + D_DEBUG_AT( PluggIt_SourceX11, " -> %4d,%4d-%4dx%4d\n", + event->area.x, event->area.y, event->area.width, event->area.height ); + + + DFBRegion damage( event->area.x, event->area.y, + event->area.x + event->area.width - 1, + event->area.y + event->area.height - 1 ); + + m_updates.addRegion( damage ); + } + + private void flushXDamage() { + vector rects; + + D_DEBUG_AT( PluggIt_SourceX11, "%s()\n", __FUNCTION__ ); + + m_updates.GetRectangles( rects ); + + if (rects.empty()) + return; + + const DFBRegion &bounding = m_updates.bounding(); + + D_DEBUG_AT( PluggIt_SourceX11, " -> %4d,%4d-%4dx%4d (%d regions, %d rectangles)\n", + DFB_RECTANGLE_VALS_FROM_REGION( &bounding ), m_updates.num_regions(), rects.size() ); + + m_updates.reset(); + + + XRectangle xdamage[rects.size()]; + + for (int i=0; i [%2d] %4d,%4d-%4dx%4d\n", i, DFB_RECTANGLE_VALS( &rects[i] ) ); + + xdamage[i].x = rects[i].x; + xdamage[i].y = rects[i].y; + xdamage[i].width = rects[i].w; + xdamage[i].height = rects[i].h; + } + + XFixesSetRegion( m_display, m_xdamage_region, xdamage, rects.size() ); + XDamageSubtract( m_display, m_xdamage, m_xdamage_region, None ); + + + if (m_shm) { + for (int i=0; i [%2d] %4d,%4d-%4dx%4d\n", i, DFB_RECTANGLE_VALS( &rects[i] ) ); + } + + m_view->update( rects, m_image->data, m_image->bytes_per_line ); + } + +/**********************************************************************************************************************/ + + private bool initXShmImage() { + m_image = XShmCreateImage( m_display, + DefaultVisual( m_display, 0 ), + m_depth, + ZPixmap, + NULL, + &m_shm_info, + m_size.w, + m_size.h ); + if (!m_image) + return false; + + m_shm_info.shmid = shmget( IPC_PRIVATE, m_image->bytes_per_line * m_image->height, IPC_CREAT | 0600 ); + if (m_shm_info.shmid == -1) { + XDestroyImage( m_image ); + return false; + } + + m_shm_info.readOnly = False; + m_shm_info.shmaddr = (char*) shmat( m_shm_info.shmid, 0, 0 ); + + if (m_shm_info.shmaddr == (char*) -1) { + shmctl( m_shm_info.shmid, IPC_RMID, 0 ); + XDestroyImage( m_image ); + return false; + } + + m_image->data = m_shm_info.shmaddr; + + + XShmAttach( m_display, &m_shm_info ); + XSync( m_display, False ); + + shmctl( m_shm_info.shmid, IPC_RMID, 0 ); + + + m_pixmap = XShmCreatePixmap( m_display, m_window, m_image->data, &m_shm_info, + m_image->width, m_image->height, m_image->depth ); + if (!m_pixmap) { + shmdt( m_shm_info.shmaddr ); + XShmDetach( m_display, &m_shm_info ); + XDestroyImage( m_image ); + return false; + } + + return true; + } + + private void initXImage() { + m_image = XCreateImage( m_display, + DefaultVisual( m_display, 0 ), + m_depth, + ZPixmap, + 0, + NULL, + m_size.w, + m_size.h, + 32, + 0 ); + if (!m_image) + throw new Exception( "XCreateImage" ); + + m_image->data = (char*) malloc( m_image->bytes_per_line * m_image->height ); + if (!m_image->data) { + XDestroyImage( m_image ); + throw new OutOfMemoryException(); + } + } + + +/**********************************************************************************************************************/ + + private std::string getWindowTitle( Window window ) { + std::string str; + char *name = NULL; + Atom actual_type; + int format; + unsigned long n; + unsigned long extra; + + XGetWindowProperty( m_display, window, XA_WM_NAME, 0L, 100L, + False, AnyPropertyType, &actual_type, &format, &n, + &extra, (unsigned char **) &name ); + + D_DEBUG_AT( PluggIt_SourceX11, "%s( %u ) -> '%s'\n", __FUNCTION__, window, name ); + + if (name) { + str.append( name ); + + XFree( name ); + } + + return str; + } + + private Window checkWindow( Window window, + const std::string &title ) + { + std::string t; + Window w = None, root, parent, *children; + unsigned int num_children; + + D_DEBUG_AT( PluggIt_SourceX11, "%s( %u, %s )\n", __FUNCTION__, window, title.c_str() ); + + t = getWindowTitle( window ); + if (t == title || t.find( title ) < t.size()) + return window; + + XQueryTree( m_display, window, &root, &parent, &children, &num_children ); + + for (unsigned int i=0; i not found\n" ); + + return None; + } + + +/**********************************************************************************************************************/ + + private Window pickWindow() { + int loops; + Window win = None; + + D_DEBUG_AT( PluggIt_SourceX11, "%s()\n", __FUNCTION__ ); + + D_DEBUG_AT( PluggIt_SourceX11, " -> Grabbing pointer...\n" ); + + XGrabPointer( m_display, m_root, False, ButtonPressMask | PointerMotionMask, + GrabModeAsync, GrabModeAsync, None, XCreateFontCursor( m_display, XC_cross ), CurrentTime ); + + for (loops=0; loops < 100 && win == None; loops++) { + XEvent event; + + D_DEBUG_AT( PluggIt_SourceX11, " -> Waiting for event...\n" ); + + if (!XPending( m_display )) { + usleep( 40000 ); + continue; + } + + XNextEvent( m_display, &event ); + + D_DEBUG_AT( PluggIt_SourceX11, " -> event type %d\n", event.type ); + + switch (event.type) { + case ButtonPress: + D_DEBUG_AT( PluggIt_SourceX11, " -> button %d press at %d,%d\n", + event.xbutton.button, event.xbutton.x, event.xbutton.y ); + + D_DEBUG_AT( PluggIt_SourceX11, " -> sub window %u: '%s'\n", + event.xbutton.subwindow, getWindowTitle( event.xbutton.subwindow ).c_str() ); + + win = lookupManagedWindow( event.xbutton.subwindow ); + break; + + default: + break; + } + + loops = 0; + } + + XUngrabPointer( m_display, CurrentTime ); + + return win; + } + + +/**********************************************************************************************************************/ + + private Window lookupManagedWindow( Window window ) { + int i, result; + unsigned long nitems; + unsigned long bytes_after; + unsigned long *prop; + Atom ret_type = None; + int ret_format; + Atom wm_state_atom; + + D_DEBUG_AT( PluggIt_SourceX11, "%s()\n", __FUNCTION__ ); + + wm_state_atom = XInternAtom( m_display, "WM_STATE", False ); + + + D_DEBUG_AT( PluggIt_SourceX11, " -> Retrieving WM_STATE (Atom %d)...\n", wm_state_atom ); + + result = XGetWindowProperty( m_display, window, wm_state_atom, + 0, LONG_MAX, False, wm_state_atom, + &ret_type, &ret_format, &nitems, + &bytes_after, (unsigned char**) &prop ); + if (result == Success) { + XFree( prop ); + + if (ret_type == wm_state_atom) { + D_DEBUG_AT( PluggIt_SourceX11, " -> OK\n" ); + return window; + } + } + + + + Window root; + Window parent; + Window *children = NULL; + Window win = None; + unsigned int num_children; + + result = XQueryTree( m_display, window, &root, &parent, &children, &num_children ); + if (!result) + return None; + + for (i=0; irun(); + + return NULL; + } +}; + +} + diff --git a/src/Updates.cxx b/src/Updates.cxx new file mode 100644 index 0000000..49f69d5 --- /dev/null +++ b/src/Updates.cxx @@ -0,0 +1,78 @@ +namespace PluggIt { + +class Updates +{ + private DFBUpdates m_updates; + private DFBRegion *m_regions; + + public Updates( unsigned int max_regions = 8 ) { + m_regions = (DFBRegion*) D_CALLOC( max_regions ?: 1, sizeof(DFBRegion) ); + + dfb_updates_init( &m_updates, m_regions, max_regions ); + } + + virtual ~Updates() { + dfb_updates_deinit( &m_updates ); + + D_FREE( m_regions ); + } + + + public void addRegion( const DFBRegion ®ion ) { + dfb_updates_add( &m_updates, ®ion ); + } + + public DFBRegion bounding() const { + return m_updates.bounding; + } + + public void get_rectangles( DFBRectangle *ret_rects, int *ret_num ) { + dfb_updates_get_rectangles( &m_updates, ret_rects, ret_num ); + } + + public unsigned int num_regions() const { + return m_updates.num_regions; + } + + public void reset() { + dfb_updates_reset( &m_updates ); + } + + + public void GetRectangles( vector &rects ) { + D_MAGIC_ASSERT( &m_updates, DFBUpdates ); + D_ASSERT( m_updates.regions != NULL ); + D_ASSERT( m_updates.num_regions >= 0 ); + D_ASSERT( m_updates.num_regions <= m_updates.max_regions ); + + switch (m_updates.num_regions) { + case 0: + break; + + default: { + int n, d, total, bounding; + + dfb_updates_stat( &m_updates, &total, &bounding ); + + n = m_updates.max_regions - m_updates.num_regions + 1; + d = n + 1; + + /* Try to optimize updates. Use individual regions only if not too much overhead. */ + if (total < bounding * n / d) { + for (n=0; n &rects, + void *ptr, + int pitch ) = 0; +}; + +} + diff --git a/src/classes.cpp b/src/classes.cpp new file mode 100644 index 0000000..a0ecb67 --- /dev/null +++ b/src/classes.cpp @@ -0,0 +1,4047 @@ +# 1 "classes.h" +#define DIRECT_ENABLE_DEBUG + + +#include +#include + +using namespace std; + + +/* + * ++DFB + */ +#include <++dfb.h> + + + +/* + * Direct + */ +extern "C" { +#include + +#include +#include +#include +#include +#include +#include + +#include +} + + +/* + * Win32 + */ +#ifdef __WIN32__ +#define CreateWindow CreateWindowWin32 +#include +#include +#include +#include "videodriver.h" +#undef CreateWindow + +#else + +/* + * X11 + */ +extern "C" { +#include /* fundamentals X datas structures */ +#include /* datas definitions for various functions */ +#include /* for a perfect use of keyboard events */ +#include +#include + +#include +#include +#include +#include +} + +#endif + +class Exception; +class OutOfMemoryException; +class Clock; +class FPS; +class Options; +class Random; +class Updates; +class Runnable; +class Thread; +class Scaler; +class View; +class Source; +class SourceWin32; +class Main; +# 1 "Exception.cxx" +# 1 "" +# 1 "" +# 1 "Exception.cxx" +namespace PluggIt { + +class Exception +{ + private: string m_message; + + + public: Exception( string message ) { + m_message = message; + } + + public: Exception( const char *format, ... ) D_FORMAT_PRINTF(2) { + va_list args; + int len; + char buf[200]; + char *ptr = buf; + + va_start( args, format ); + len = vsnprintf( buf, sizeof(buf), format, args ); + va_end( args ); + + if (len < 0) + abort(); + + if (len >= (int)sizeof(buf)) { + ptr = (char*) malloc( len+1 ); + if (!ptr) + abort(); + + va_start( args, format ); + len = vsnprintf( ptr, len+1, format, args ); + va_end( args ); + + if (len < 0) { + free( ptr ); + abort(); + } + } + + m_message = string( ptr ); + + if (ptr != buf) + free( ptr ); + } + + public: string getMessage() { + return m_message; + } + + + friend std::ostream &operator << (std::ostream &stream, Exception *ex) { + stream << ex->getMessage(); + + return stream; + } +}; + +} +# 1 "OutOfMemoryException.cxx" +# 1 "" +# 1 "" +# 1 "OutOfMemoryException.cxx" +namespace PluggIt { + +class OutOfMemoryException :public Exception +{ + public: OutOfMemoryException() : Exception( "Out of memory!" ) { + } +}; + +} +# 1 "Clock.cxx" +# 1 "" +# 1 "" +# 1 "Clock.cxx" +namespace PluggIt { + +class Clock +{ + private: long long base; + private: char str[20]; + + public: Clock() { + Reset(); + } + + public: void Reset() { + base = direct_clock_get_micros(); + } + + public: float GetTime() { + return (direct_clock_get_micros() - base) / 1000000.0f; + } + + public: const char *GetString() { + float time = GetTime(); + int seconds = (int) time; + int minutes = seconds / 60; + + snprintf( str, sizeof(str), "%02d:%02d", minutes, seconds ); + + return str; + } +}; + +} +# 1 "FPS.cxx" +# 1 "" +# 1 "" +# 1 "FPS.cxx" +namespace PluggIt { + +class FPS +{ + private: int frames; + private: char str[20]; + + private: Clock clock; + + + public: FPS() { + Reset(); + } + + public: void Reset() { + frames = 0; + str[0] = 0; + + clock.Reset(); + } + + public: void Count( float interval ) { + float time = clock.GetTime(); + + frames++; + + if (time >= interval) { + float fps = frames / time; + + snprintf( str, sizeof(str), "%.1f", fps ); + + frames = 0; + clock.Reset(); + } + } + + public: const char *GetFPS() { + return str; + } +}; + +} +# 1 "Options.cxx" +# 1 "" +# 1 "" +# 1 "Options.cxx" +namespace PluggIt { + +static const DirectFBPixelFormatNames(m_formats); + +class Options +{ + class Option { + friend class Options; + + protected: const char *m_short_name; + protected: const char *m_long_name; + protected: const char *m_arg_name; + protected: const char *m_arg_desc; + protected: bool m_need_arg; + + public: Option( const char *short_name, + const char *long_name, + const char *arg_name, + const char *arg_desc ) + { + m_short_name = short_name; + m_long_name = long_name; + m_arg_name = arg_name; + m_arg_desc = arg_desc; + m_need_arg = true; + } + + public: virtual bool Parse( const char *arg ) = 0; + }; + + public: class OptionBool :public Option { + private: bool &m_value; + + public: OptionBool( const char *short_name, + const char *long_name, + const char *arg_name, + const char *arg_desc, + bool &value ) : Option( short_name, long_name, arg_name, arg_desc ), m_value( value ) + { + m_need_arg = false; + } + + public: virtual bool Parse( const char *arg ) { + m_value = true; + + return true; + } + }; + + public: class OptionLong :public Option { + private: long &m_value; + private: int m_base; + + public: OptionLong( const char *short_name, + const char *long_name, + const char *arg_name, + const char *arg_desc, + long &value, + int base = 10 ) : Option( short_name, long_name, arg_name, arg_desc ), m_value( value ) + { + m_base = base; + } + + public: virtual bool Parse( const char *arg ) { + long ret; + char *end; + + ret = strtol( arg, &end, m_base ); + + if (*end) { + D_ERROR( "Option/Long: Invalid argument to '%s' or '%s'!\n", m_short_name, m_long_name ); + return false; + } + + m_value = ret; + + return true; + } + }; + + public: class OptionULong :public Option { + private: unsigned long &m_value; + private: int m_base; + + public: OptionULong( const char *short_name, + const char *long_name, + const char *arg_name, + const char *arg_desc, + unsigned long &value, + int base = 10 ) : Option( short_name, long_name, arg_name, arg_desc ), m_value( value ) + { + m_base = base; + } + + public: virtual bool Parse( const char *arg ) { + unsigned long ret; + char *end; + + ret = strtoul( arg, &end, m_base ); + + if (*end) { + D_ERROR( "Option/ULong: Invalid argument to '%s' or '%s'!\n", m_short_name, m_long_name ); + return false; + } + + m_value = ret; + + return true; + } + }; + + public: class OptionFormat :public Option { + private: DFBSurfacePixelFormat &m_value; + + public: OptionFormat( const char *short_name, + const char *long_name, + const char *arg_name, + const char *arg_desc, + DFBSurfacePixelFormat &value ) : Option( short_name, long_name, arg_name, arg_desc ), m_value( value ) + { + } + + public: virtual bool Parse( const char *arg ) { + unsigned int i; + + for (i=0; i m_options; + + public: void addOption( Option *option ) { + m_options.push_back( option ); + } + + public: bool parseCommandLine( int argc, char *argv[] ) { + int n; + + for (n = 1; n < argc; n++) { + bool ok = false; + const char *arg = argv[n]; + + if (strcmp (arg, "-h") == 0 || strcmp (arg, "--help") == 0) { + printUsage (argv[0]); + return false; + } + + if (strcmp (arg, "-v") == 0 || strcmp (arg, "--version") == 0) { + + return false; + } + + vector::iterator itr = m_options.begin(); + + for (; itr != m_options.end(); itr++) { + Option *option = *itr; + + if (!strcmp (arg, option->m_short_name) || !strcmp (arg, option->m_long_name)) { + if (option->m_need_arg && ++n == argc) { + printUsage (argv[0]); + return false; + } + + if (!option->Parse( argv[n] )) + return false; + + ok = true; + + break; + } + } + + if (!ok) { + printUsage (argv[0]); + return false; + } + } + + return true; + } + + public: void printUsage( const char *prg_name ) { + + fprintf (stderr, "Usage: %s [options]\n\n", prg_name); + fprintf (stderr, "Options:\n"); + fprintf (stderr, " -h --help Show this help message\n"); + fprintf (stderr, " -v --version Print version information\n"); + + + vector::const_iterator itr = m_options.begin(); + + for (; itr != m_options.end(); itr++) { + const Option *option = *itr; + + fprintf( stderr, " %-3s %-16s %-12s %s\n", + option->m_short_name, option->m_long_name, option->m_arg_name, option->m_arg_desc ); + } + + fprintf( stderr, "\n" ); + } +}; + +} +# 1 "Random.cxx" +# 1 "" +# 1 "" +# 1 "Random.cxx" +namespace PluggIt { + +class Random +{ + public: static float nextFloat( float min, float max ) { + return min + rand() * (max - min) / (float) RAND_MAX; + } +}; + +} +# 1 "Updates.cxx" +# 1 "" +# 1 "" +# 1 "Updates.cxx" +namespace PluggIt { + +class Updates +{ + private: DFBUpdates m_updates; + private: DFBRegion *m_regions; + + public: Updates( unsigned int max_regions = 8 ) { + m_regions = (DFBRegion*) D_CALLOC( max_regions ?: 1, sizeof(DFBRegion) ); + + dfb_updates_init( &m_updates, m_regions, max_regions ); + } + + virtual ~Updates() { + dfb_updates_deinit( &m_updates ); + + D_FREE( m_regions ); + } + + + public: void addRegion( const DFBRegion ®ion ) { + dfb_updates_add( &m_updates, ®ion ); + } + + public: DFBRegion bounding() const { + return m_updates.bounding; + } + + public: void get_rectangles( DFBRectangle *ret_rects, int *ret_num ) { + dfb_updates_get_rectangles( &m_updates, ret_rects, ret_num ); + } + + public: unsigned int num_regions() const { + return m_updates.num_regions; + } + + public: void reset() { + dfb_updates_reset( &m_updates ); + } + + + public: void GetRectangles( vector &rects ) { + D_MAGIC_ASSERT( &m_updates, DFBUpdates ); + D_ASSERT( m_updates.regions != NULL ); + D_ASSERT( m_updates.num_regions >= 0 ); + D_ASSERT( m_updates.num_regions <= m_updates.max_regions ); + + switch (m_updates.num_regions) { + case 0: + break; + + default: { + int n, d, total, bounding; + + dfb_updates_stat( &m_updates, &total, &bounding ); + + n = m_updates.max_regions - m_updates.num_regions + 1; + d = n + 1; + + + if (total < bounding * n / d) { + for (n=0; n" +# 1 "" +# 1 "Runnable.cxx" +namespace PluggIt { + +class Runnable +{ + public: virtual void run() = 0; +}; + +} +# 1 "Thread.cxx" +# 1 "" +# 1 "" +# 1 "Thread.cxx" +namespace PluggIt { + +class Thread +{ + private: Runnable *m_target; + private: string m_name; + + private: DirectThread *m_thread; + private: volatile bool m_interrupted; + + + public: Thread( Runnable *target, string name = "" ) { + m_target = target; + m_name = name; + + m_thread = NULL; + m_interrupted = false; + } + + virtual ~Thread() { + if (m_thread) + direct_thread_destroy( m_thread ); + } + + public: bool start() { + if (m_thread) + return false; + + m_thread = direct_thread_create( DTT_DEFAULT, main, m_target, m_name.c_str() ); + + return m_thread != NULL; + } + + public: bool interrupt() { + if (!m_thread) + return false; + + m_interrupted = true; + + return true; + } + + public: bool isInterrupted() { + return m_interrupted; + } + + public: bool join() { + if (!m_thread) + return false; + + direct_thread_join( m_thread ); + direct_thread_destroy( m_thread ); + + m_thread = NULL; + m_interrupted = false; + + return true; + } + + + private: static void *main( DirectThread *thread, void *arg ) { + Runnable *target = (Runnable*) arg; + + target->run(); + + return NULL; + } +}; + +} +# 1 "Scaler.cxx" +# 1 "" +# 1 "" +# 1 "Scaler.cxx" +namespace PluggIt { + +D_DEBUG_DOMAIN( PluggIt_Scaler, "PluggIt/Scaler", "PluggIt Scaler" ); + + +typedef struct { + DFBRegion clip; + const void *colors; + unsigned long protect; + unsigned long key; +} StretchCtx; + +typedef void (*StretchHVx)( void *dst, + int dpitch, + const void *src, + int spitch, + int width, + int height, + int dst_width, + int dst_height, + const StretchCtx *ctx ); +# 47 "Scaler.cxx" +# 1 "stretch_up_down_16.h" 1 +# 20 "stretch_up_down_16.h" +# 1 "stretch_hvx_N.h" 1 +# 9 "stretch_hvx_N.h" +static void stretch_hvx_RGB16_up____DSPF_RGB16 +# 1 "stretch_hvx_16.h" 1 +# 35 "stretch_hvx_16.h" + ( void *dst, + int dpitch, + const void *src, + int spitch, + int width, + int height, + int dst_width, + int dst_height, + const StretchCtx *ctx ) +{ + long x, y, r = 0; + long head = ((((unsigned long) dst) & 2) >> 1) ^ (ctx->clip.x1 & 1); + long cw = ctx->clip.x2 - ctx->clip.x1 + 1; + long ch = ctx->clip.y2 - ctx->clip.y1 + 1; + long tail = (cw - head) & 1; + long w2 = (cw - head) / 2; + long hfraq = ((long)(width - 1) << 18) / (long)(dst_width); + long vfraq = ((long)(height - 1) << 18) / (long)(dst_height); + long dp4 = dpitch / 4; + long point0 = 0 + ctx->clip.x1 * hfraq; + long point = point0; + long line = 0 + ctx->clip.y1 * vfraq; + long ratios[cw]; + u32 *dst32; + + + + + + + u32 _lbT[w2+8]; + u32 _lbB[w2+8]; + + u32 *lbX; + u32 *lbT = (u32*)((((unsigned long)(&_lbT[0])) + 31) & ~31); + u32 *lbB = (u32*)((((unsigned long)(&_lbB[0])) + 31) & ~31); + + long lineT = -2000; + + for (x=0; x> (18-6) ); + + point += hfraq; + } + + do {} while (0); + + + dst = (void*)((char*) dst + ctx->clip.x1 * 2 + ctx->clip.y1 * dpitch); + + dst32 = (u32*) dst; + + if (head) { + u32 dpT, dpB, L, R; + + u16 *dst16 = (u16*) dst; + + point = point0; + + for (y=0; y> (18-5) ); + + const u16 *srcT = (const u16 *)((char*) src + spitch * ( (((line)) >> 18) )); + const u16 *srcB = (const u16 *)((char*) src + spitch * ( (((line)) >> 18) + 1 )); + + + + + long pl = ( (((point)) >> 18) ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + L = (srcT[pl]); + R = (srcT[pl+1]); + + dpT = (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) >> 6; + + L = (srcB[pl]); + R = (srcB[pl+1]); + + dpB = (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) >> 6; +# 138 "stretch_hvx_16.h" + dst16[0] = ((((((dpB & 0xf81f) - (dpT & 0xf81f))*X) >> 5) + (dpT & 0xf81f)) & 0xf81f) + + ((((((dpB>>5) & (0x07e0>>5)) - ((dpT>>5) & (0x07e0>>5)))*X) + (dpT & 0x07e0)) & 0x07e0); + + + dst16 += dpitch / 2; + line += vfraq; + } + + + point0 += hfraq; + dst32 = (u32*)((char*) dst + 2); + + + line = 0 + ctx->clip.y1 * vfraq; + } + + + + + for (y=0; y> 18) ); + + D_ASSERT( nlT >= 0 ); + D_ASSERT( nlT < height-1 ); + + + + + if (nlT != lineT) { + u32 L, R, dpT, dpB; + const u16 *srcT = (const u16 *)((char*) src + spitch * nlT); + const u16 *srcB = (const u16 *)((char*) src + spitch * (nlT + 1)); + long diff = nlT - lineT; + + if (diff > 1) { + + + + for (x=0, r=head, point=point0; x> 18) ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + L = (srcT[pl]); + R = (srcT[pl+1]); + + dpT = (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) + + + + >> 6; + + + L = (srcB[pl]); + R = (srcB[pl+1]); + + dpB = (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) + + + + >> 6; + + + point += hfraq; + r++; + + + pl = ( (((point)) >> 18) ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + + L = (srcT[pl]); + R = (srcT[pl+1]); + + dpT |= (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) + + + + << (16-6); + + + L = (srcB[pl]); + R = (srcB[pl+1]); + + dpB |= (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) + + + + << (16-6); + + + point += hfraq; + r++; + + + lbT[x] = dpT; + lbB[x] = dpB; + } + } + else { + + lbX = lbT; + lbT = lbB; + lbB = lbX; + + + + + for (x=0, r=head, point=point0; x> 18) ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + L = (srcB[pl]); + R = (srcB[pl+1]); + + dpB = (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) + + + + >> 6; + + + point += hfraq; + r++; + + + pl = ( (((point)) >> 18) ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + + L = (srcB[pl]); + R = (srcB[pl+1]); + + dpB |= (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) + + + + << (16-6); + + + point += hfraq; + r++; + + + lbB[x] = dpB; + } + } + + lineT = nlT; + } + + + + + X = ( ((line) & 0x3ffff) >> (18-5) ); + + for (x=0; x> 5) + (lbT[x] & ((0x07e0<<16) | 0xf81f))) & ((0x07e0<<16) | 0xf81f)) + + ((((((lbB[x]>>5) & (((0xf81f<<16) | 0x07e0)>>5)) - ((lbT[x]>>5) & (((0xf81f<<16) | 0x07e0)>>5)))*X) + (lbT[x] & ((0xf81f<<16) | 0x07e0))) & ((0xf81f<<16) | 0x07e0)); + + + } + + dst32 += dp4; + line += vfraq; + } + + if (tail) { + u32 dpT, dpB, L, R; + + u16 *dst16 = (u16*)((char*) dst + cw * 2 - 2); + + + line = 0 + ctx->clip.y1 * vfraq; + + for (y=0; y> (18-5) ); + + const u16 *srcT = (const u16 *)((char*) src + spitch * ( (((line)) >> 18) )); + const u16 *srcB = (const u16 *)((char*) src + spitch * ( (((line)) >> 18) + 1 )); + + + + + long pl = ( (((point)) >> 18) ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + L = (srcT[pl]); + R = (srcT[pl+1]); + + dpT = (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) >> 6; + + L = (srcB[pl]); + R = (srcB[pl+1]); + + dpB = (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) >> 6; +# 434 "stretch_hvx_16.h" + dst16[0] = ((((((dpB & 0xf81f) - (dpT & 0xf81f))*X) >> 5) + (dpT & 0xf81f)) & 0xf81f) + + ((((((dpB>>5) & (0x07e0>>5)) - ((dpT>>5) & (0x07e0>>5)))*X) + (dpT & 0x07e0)) & 0x07e0); + + + dst16 += dpitch / 2; + line += vfraq; + } + } +} +# 11 "stretch_hvx_N.h" 2 +# 20 "stretch_hvx_N.h" +static void stretch_hvx_RGB16_up____DSPF_RGB32 +# 1 "stretch_hvx_16.h" 1 +# 35 "stretch_hvx_16.h" + ( void *dst, + int dpitch, + const void *src, + int spitch, + int width, + int height, + int dst_width, + int dst_height, + const StretchCtx *ctx ) +{ + long x, y, r = 0; + long head = ((((unsigned long) dst) & 2) >> 1) ^ (ctx->clip.x1 & 1); + long cw = ctx->clip.x2 - ctx->clip.x1 + 1; + long ch = ctx->clip.y2 - ctx->clip.y1 + 1; + long tail = (cw - head) & 1; + long w2 = (cw - head) / 2; + long hfraq = ((long)(width - 1) << 18) / (long)(dst_width); + long vfraq = ((long)(height - 1) << 18) / (long)(dst_height); + long dp4 = dpitch / 4; + long point0 = 0 + ctx->clip.x1 * hfraq; + long point = point0; + long line = 0 + ctx->clip.y1 * vfraq; + long ratios[cw]; + u32 *dst32; + + + + + + + u32 _lbT[w2+8]; + u32 _lbB[w2+8]; + + u32 *lbX; + u32 *lbT = (u32*)((((unsigned long)(&_lbT[0])) + 31) & ~31); + u32 *lbB = (u32*)((((unsigned long)(&_lbB[0])) + 31) & ~31); + + long lineT = -2000; + + for (x=0; x> (18-6) ); + + point += hfraq; + } + + do {} while (0); + + + dst = (void*)((char*) dst + ctx->clip.x1 * 2 + ctx->clip.y1 * dpitch); + + dst32 = (u32*) dst; + + if (head) { + u32 dpT, dpB, L, R; + + u16 *dst16 = (u16*) dst; + + point = point0; + + for (y=0; y> (18-5) ); + + const u32 *srcT = (const u32 *)((char*) src + spitch * ( (((line)) >> 18) )); + const u32 *srcB = (const u32 *)((char*) src + spitch * ( (((line)) >> 18) + 1 )); + + + + + long pl = ( (((point)) >> 18) ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + L = ( (((((srcT[pl]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcT[pl]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcT[pl]) & 0x0000ff))&0xF8) >> 3) ); + R = ( (((((srcT[pl+1]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcT[pl+1]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcT[pl+1]) & 0x0000ff))&0xF8) >> 3) ); + + dpT = (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) >> 6; + + L = ( (((((srcB[pl]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcB[pl]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcB[pl]) & 0x0000ff))&0xF8) >> 3) ); + R = ( (((((srcB[pl+1]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcB[pl+1]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcB[pl+1]) & 0x0000ff))&0xF8) >> 3) ); + + dpB = (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) >> 6; +# 138 "stretch_hvx_16.h" + dst16[0] = ((((((dpB & 0xf81f) - (dpT & 0xf81f))*X) >> 5) + (dpT & 0xf81f)) & 0xf81f) + + ((((((dpB>>5) & (0x07e0>>5)) - ((dpT>>5) & (0x07e0>>5)))*X) + (dpT & 0x07e0)) & 0x07e0); + + + dst16 += dpitch / 2; + line += vfraq; + } + + + point0 += hfraq; + dst32 = (u32*)((char*) dst + 2); + + + line = 0 + ctx->clip.y1 * vfraq; + } + + + + + for (y=0; y> 18) ); + + D_ASSERT( nlT >= 0 ); + D_ASSERT( nlT < height-1 ); + + + + + if (nlT != lineT) { + u32 L, R, dpT, dpB; + const u32 *srcT = (const u32 *)((char*) src + spitch * nlT); + const u32 *srcB = (const u32 *)((char*) src + spitch * (nlT + 1)); + long diff = nlT - lineT; + + if (diff > 1) { + + + + for (x=0, r=head, point=point0; x> 18) ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + L = ( (((((srcT[pl]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcT[pl]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcT[pl]) & 0x0000ff))&0xF8) >> 3) ); + R = ( (((((srcT[pl+1]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcT[pl+1]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcT[pl+1]) & 0x0000ff))&0xF8) >> 3) ); + + dpT = (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) + + + + >> 6; + + + L = ( (((((srcB[pl]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcB[pl]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcB[pl]) & 0x0000ff))&0xF8) >> 3) ); + R = ( (((((srcB[pl+1]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcB[pl+1]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcB[pl+1]) & 0x0000ff))&0xF8) >> 3) ); + + dpB = (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) + + + + >> 6; + + + point += hfraq; + r++; + + + pl = ( (((point)) >> 18) ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + + L = ( (((((srcT[pl]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcT[pl]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcT[pl]) & 0x0000ff))&0xF8) >> 3) ); + R = ( (((((srcT[pl+1]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcT[pl+1]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcT[pl+1]) & 0x0000ff))&0xF8) >> 3) ); + + dpT |= (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) + + + + << (16-6); + + + L = ( (((((srcB[pl]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcB[pl]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcB[pl]) & 0x0000ff))&0xF8) >> 3) ); + R = ( (((((srcB[pl+1]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcB[pl+1]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcB[pl+1]) & 0x0000ff))&0xF8) >> 3) ); + + dpB |= (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) + + + + << (16-6); + + + point += hfraq; + r++; + + + lbT[x] = dpT; + lbB[x] = dpB; + } + } + else { + + lbX = lbT; + lbT = lbB; + lbB = lbX; + + + + + for (x=0, r=head, point=point0; x> 18) ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + L = ( (((((srcB[pl]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcB[pl]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcB[pl]) & 0x0000ff))&0xF8) >> 3) ); + R = ( (((((srcB[pl+1]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcB[pl+1]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcB[pl+1]) & 0x0000ff))&0xF8) >> 3) ); + + dpB = (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) + + + + >> 6; + + + point += hfraq; + r++; + + + pl = ( (((point)) >> 18) ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + + L = ( (((((srcB[pl]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcB[pl]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcB[pl]) & 0x0000ff))&0xF8) >> 3) ); + R = ( (((((srcB[pl+1]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcB[pl+1]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcB[pl+1]) & 0x0000ff))&0xF8) >> 3) ); + + dpB |= (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) + + + + << (16-6); + + + point += hfraq; + r++; + + + lbB[x] = dpB; + } + } + + lineT = nlT; + } + + + + + X = ( ((line) & 0x3ffff) >> (18-5) ); + + for (x=0; x> 5) + (lbT[x] & ((0x07e0<<16) | 0xf81f))) & ((0x07e0<<16) | 0xf81f)) + + ((((((lbB[x]>>5) & (((0xf81f<<16) | 0x07e0)>>5)) - ((lbT[x]>>5) & (((0xf81f<<16) | 0x07e0)>>5)))*X) + (lbT[x] & ((0xf81f<<16) | 0x07e0))) & ((0xf81f<<16) | 0x07e0)); + + + } + + dst32 += dp4; + line += vfraq; + } + + if (tail) { + u32 dpT, dpB, L, R; + + u16 *dst16 = (u16*)((char*) dst + cw * 2 - 2); + + + line = 0 + ctx->clip.y1 * vfraq; + + for (y=0; y> (18-5) ); + + const u32 *srcT = (const u32 *)((char*) src + spitch * ( (((line)) >> 18) )); + const u32 *srcB = (const u32 *)((char*) src + spitch * ( (((line)) >> 18) + 1 )); + + + + + long pl = ( (((point)) >> 18) ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + L = ( (((((srcT[pl]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcT[pl]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcT[pl]) & 0x0000ff))&0xF8) >> 3) ); + R = ( (((((srcT[pl+1]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcT[pl+1]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcT[pl+1]) & 0x0000ff))&0xF8) >> 3) ); + + dpT = (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) >> 6; + + L = ( (((((srcB[pl]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcB[pl]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcB[pl]) & 0x0000ff))&0xF8) >> 3) ); + R = ( (((((srcB[pl+1]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcB[pl+1]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcB[pl+1]) & 0x0000ff))&0xF8) >> 3) ); + + dpB = (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) >> 6; +# 434 "stretch_hvx_16.h" + dst16[0] = ((((((dpB & 0xf81f) - (dpT & 0xf81f))*X) >> 5) + (dpT & 0xf81f)) & 0xf81f) + + ((((((dpB>>5) & (0x07e0>>5)) - ((dpT>>5) & (0x07e0>>5)))*X) + (dpT & 0x07e0)) & 0x07e0); + + + dst16 += dpitch / 2; + line += vfraq; + } + } +} +# 22 "stretch_hvx_N.h" 2 +# 21 "stretch_up_down_16.h" 2 +# 49 "stretch_up_down_16.h" +# 1 "stretch_hvx_N.h" 1 +# 9 "stretch_hvx_N.h" +static void stretch_hvx_RGB16_down____DSPF_RGB16 +# 1 "stretch_hvx_16.h" 1 +# 35 "stretch_hvx_16.h" + ( void *dst, + int dpitch, + const void *src, + int spitch, + int width, + int height, + int dst_width, + int dst_height, + const StretchCtx *ctx ) +{ + long x, y, r = 0; + long head = ((((unsigned long) dst) & 2) >> 1) ^ (ctx->clip.x1 & 1); + long cw = ctx->clip.x2 - ctx->clip.x1 + 1; + long ch = ctx->clip.y2 - ctx->clip.y1 + 1; + long tail = (cw - head) & 1; + long w2 = (cw - head) / 2; + long hfraq = ((long)(width - 0) << 18) / (long)(dst_width); + long vfraq = ((long)(height - 0) << 18) / (long)(dst_height); + long dp4 = dpitch / 4; + long point0 = hfraq + ctx->clip.x1 * hfraq; + long point = point0; + long line = vfraq + ctx->clip.y1 * vfraq; + long ratios[cw]; + u32 *dst32; + + + + + + + u32 _lbT[w2+8]; + u32 _lbB[w2+8]; + + u32 *lbX; + u32 *lbT = (u32*)((((unsigned long)(&_lbT[0])) + 31) & ~31); + u32 *lbB = (u32*)((((unsigned long)(&_lbB[0])) + 31) & ~31); + + long lineT = -2000; + + for (x=0; xclip.x1 * 2 + ctx->clip.y1 * dpitch); + + dst32 = (u32*) dst; + + if (head) { + u32 dpT, dpB, L, R; + + u16 *dst16 = (u16*) dst; + + point = point0; + + for (y=0; y> 18) - 1 )); + const u16 *srcB = (const u16 *)((char*) src + spitch * ( (((line)-1) >> 18) )); + + + + + long pl = ( (((point)-1) >> 18) - 1 ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + L = (srcT[pl]); + R = (srcT[pl+1]); + + dpT = (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) >> 6; + + L = (srcB[pl]); + R = (srcB[pl+1]); + + dpB = (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) >> 6; +# 138 "stretch_hvx_16.h" + dst16[0] = ((((((dpB & 0xf81f) - (dpT & 0xf81f))*X) >> 5) + (dpT & 0xf81f)) & 0xf81f) + + ((((((dpB>>5) & (0x07e0>>5)) - ((dpT>>5) & (0x07e0>>5)))*X) + (dpT & 0x07e0)) & 0x07e0); + + + dst16 += dpitch / 2; + line += vfraq; + } + + + point0 += hfraq; + dst32 = (u32*)((char*) dst + 2); + + + line = vfraq + ctx->clip.y1 * vfraq; + } + + + + + for (y=0; y> 18) - 1 ); + + D_ASSERT( nlT >= 0 ); + D_ASSERT( nlT < height-1 ); + + + + + if (nlT != lineT) { + u32 L, R, dpT, dpB; + const u16 *srcT = (const u16 *)((char*) src + spitch * nlT); + const u16 *srcB = (const u16 *)((char*) src + spitch * (nlT + 1)); + long diff = nlT - lineT; + + if (diff > 1) { + + + + for (x=0, r=head, point=point0; x> 18) - 1 ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + L = (srcT[pl]); + R = (srcT[pl+1]); + + dpT = (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) + + + + >> 6; + + + L = (srcB[pl]); + R = (srcB[pl+1]); + + dpB = (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) + + + + >> 6; + + + point += hfraq; + r++; + + + pl = ( (((point)-1) >> 18) - 1 ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + + L = (srcT[pl]); + R = (srcT[pl+1]); + + dpT |= (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) + + + + << (16-6); + + + L = (srcB[pl]); + R = (srcB[pl+1]); + + dpB |= (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) + + + + << (16-6); + + + point += hfraq; + r++; + + + lbT[x] = dpT; + lbB[x] = dpB; + } + } + else { + + lbX = lbT; + lbT = lbB; + lbB = lbX; + + + + + for (x=0, r=head, point=point0; x> 18) - 1 ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + L = (srcB[pl]); + R = (srcB[pl+1]); + + dpB = (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) + + + + >> 6; + + + point += hfraq; + r++; + + + pl = ( (((point)-1) >> 18) - 1 ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + + L = (srcB[pl]); + R = (srcB[pl+1]); + + dpB |= (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) + + + + << (16-6); + + + point += hfraq; + r++; + + + lbB[x] = dpB; + } + } + + lineT = nlT; + } + + + + + X = ( (((((line)) & 0x3ffff) ? : 0x40000) << 5) / (vfraq) ); + + for (x=0; x> 5) + (lbT[x] & ((0x07e0<<16) | 0xf81f))) & ((0x07e0<<16) | 0xf81f)) + + ((((((lbB[x]>>5) & (((0xf81f<<16) | 0x07e0)>>5)) - ((lbT[x]>>5) & (((0xf81f<<16) | 0x07e0)>>5)))*X) + (lbT[x] & ((0xf81f<<16) | 0x07e0))) & ((0xf81f<<16) | 0x07e0)); + + + } + + dst32 += dp4; + line += vfraq; + } + + if (tail) { + u32 dpT, dpB, L, R; + + u16 *dst16 = (u16*)((char*) dst + cw * 2 - 2); + + + line = vfraq + ctx->clip.y1 * vfraq; + + for (y=0; y> 18) - 1 )); + const u16 *srcB = (const u16 *)((char*) src + spitch * ( (((line)-1) >> 18) )); + + + + + long pl = ( (((point)-1) >> 18) - 1 ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + L = (srcT[pl]); + R = (srcT[pl+1]); + + dpT = (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) >> 6; + + L = (srcB[pl]); + R = (srcB[pl+1]); + + dpB = (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) >> 6; +# 434 "stretch_hvx_16.h" + dst16[0] = ((((((dpB & 0xf81f) - (dpT & 0xf81f))*X) >> 5) + (dpT & 0xf81f)) & 0xf81f) + + ((((((dpB>>5) & (0x07e0>>5)) - ((dpT>>5) & (0x07e0>>5)))*X) + (dpT & 0x07e0)) & 0x07e0); + + + dst16 += dpitch / 2; + line += vfraq; + } + } +} +# 11 "stretch_hvx_N.h" 2 +# 20 "stretch_hvx_N.h" +static void stretch_hvx_RGB16_down____DSPF_RGB32 +# 1 "stretch_hvx_16.h" 1 +# 35 "stretch_hvx_16.h" + ( void *dst, + int dpitch, + const void *src, + int spitch, + int width, + int height, + int dst_width, + int dst_height, + const StretchCtx *ctx ) +{ + long x, y, r = 0; + long head = ((((unsigned long) dst) & 2) >> 1) ^ (ctx->clip.x1 & 1); + long cw = ctx->clip.x2 - ctx->clip.x1 + 1; + long ch = ctx->clip.y2 - ctx->clip.y1 + 1; + long tail = (cw - head) & 1; + long w2 = (cw - head) / 2; + long hfraq = ((long)(width - 0) << 18) / (long)(dst_width); + long vfraq = ((long)(height - 0) << 18) / (long)(dst_height); + long dp4 = dpitch / 4; + long point0 = hfraq + ctx->clip.x1 * hfraq; + long point = point0; + long line = vfraq + ctx->clip.y1 * vfraq; + long ratios[cw]; + u32 *dst32; + + + + + + + u32 _lbT[w2+8]; + u32 _lbB[w2+8]; + + u32 *lbX; + u32 *lbT = (u32*)((((unsigned long)(&_lbT[0])) + 31) & ~31); + u32 *lbB = (u32*)((((unsigned long)(&_lbB[0])) + 31) & ~31); + + long lineT = -2000; + + for (x=0; xclip.x1 * 2 + ctx->clip.y1 * dpitch); + + dst32 = (u32*) dst; + + if (head) { + u32 dpT, dpB, L, R; + + u16 *dst16 = (u16*) dst; + + point = point0; + + for (y=0; y> 18) - 1 )); + const u32 *srcB = (const u32 *)((char*) src + spitch * ( (((line)-1) >> 18) )); + + + + + long pl = ( (((point)-1) >> 18) - 1 ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + L = ( (((((srcT[pl]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcT[pl]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcT[pl]) & 0x0000ff))&0xF8) >> 3) ); + R = ( (((((srcT[pl+1]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcT[pl+1]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcT[pl+1]) & 0x0000ff))&0xF8) >> 3) ); + + dpT = (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) >> 6; + + L = ( (((((srcB[pl]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcB[pl]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcB[pl]) & 0x0000ff))&0xF8) >> 3) ); + R = ( (((((srcB[pl+1]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcB[pl+1]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcB[pl+1]) & 0x0000ff))&0xF8) >> 3) ); + + dpB = (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) >> 6; +# 138 "stretch_hvx_16.h" + dst16[0] = ((((((dpB & 0xf81f) - (dpT & 0xf81f))*X) >> 5) + (dpT & 0xf81f)) & 0xf81f) + + ((((((dpB>>5) & (0x07e0>>5)) - ((dpT>>5) & (0x07e0>>5)))*X) + (dpT & 0x07e0)) & 0x07e0); + + + dst16 += dpitch / 2; + line += vfraq; + } + + + point0 += hfraq; + dst32 = (u32*)((char*) dst + 2); + + + line = vfraq + ctx->clip.y1 * vfraq; + } + + + + + for (y=0; y> 18) - 1 ); + + D_ASSERT( nlT >= 0 ); + D_ASSERT( nlT < height-1 ); + + + + + if (nlT != lineT) { + u32 L, R, dpT, dpB; + const u32 *srcT = (const u32 *)((char*) src + spitch * nlT); + const u32 *srcB = (const u32 *)((char*) src + spitch * (nlT + 1)); + long diff = nlT - lineT; + + if (diff > 1) { + + + + for (x=0, r=head, point=point0; x> 18) - 1 ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + L = ( (((((srcT[pl]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcT[pl]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcT[pl]) & 0x0000ff))&0xF8) >> 3) ); + R = ( (((((srcT[pl+1]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcT[pl+1]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcT[pl+1]) & 0x0000ff))&0xF8) >> 3) ); + + dpT = (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) + + + + >> 6; + + + L = ( (((((srcB[pl]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcB[pl]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcB[pl]) & 0x0000ff))&0xF8) >> 3) ); + R = ( (((((srcB[pl+1]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcB[pl+1]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcB[pl+1]) & 0x0000ff))&0xF8) >> 3) ); + + dpB = (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) + + + + >> 6; + + + point += hfraq; + r++; + + + pl = ( (((point)-1) >> 18) - 1 ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + + L = ( (((((srcT[pl]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcT[pl]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcT[pl]) & 0x0000ff))&0xF8) >> 3) ); + R = ( (((((srcT[pl+1]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcT[pl+1]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcT[pl+1]) & 0x0000ff))&0xF8) >> 3) ); + + dpT |= (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) + + + + << (16-6); + + + L = ( (((((srcB[pl]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcB[pl]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcB[pl]) & 0x0000ff))&0xF8) >> 3) ); + R = ( (((((srcB[pl+1]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcB[pl+1]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcB[pl+1]) & 0x0000ff))&0xF8) >> 3) ); + + dpB |= (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) + + + + << (16-6); + + + point += hfraq; + r++; + + + lbT[x] = dpT; + lbB[x] = dpB; + } + } + else { + + lbX = lbT; + lbT = lbB; + lbB = lbX; + + + + + for (x=0, r=head, point=point0; x> 18) - 1 ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + L = ( (((((srcB[pl]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcB[pl]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcB[pl]) & 0x0000ff))&0xF8) >> 3) ); + R = ( (((((srcB[pl+1]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcB[pl+1]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcB[pl+1]) & 0x0000ff))&0xF8) >> 3) ); + + dpB = (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) + + + + >> 6; + + + point += hfraq; + r++; + + + pl = ( (((point)-1) >> 18) - 1 ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + + L = ( (((((srcB[pl]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcB[pl]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcB[pl]) & 0x0000ff))&0xF8) >> 3) ); + R = ( (((((srcB[pl+1]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcB[pl+1]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcB[pl+1]) & 0x0000ff))&0xF8) >> 3) ); + + dpB |= (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) + + + + << (16-6); + + + point += hfraq; + r++; + + + lbB[x] = dpB; + } + } + + lineT = nlT; + } + + + + + X = ( (((((line)) & 0x3ffff) ? : 0x40000) << 5) / (vfraq) ); + + for (x=0; x> 5) + (lbT[x] & ((0x07e0<<16) | 0xf81f))) & ((0x07e0<<16) | 0xf81f)) + + ((((((lbB[x]>>5) & (((0xf81f<<16) | 0x07e0)>>5)) - ((lbT[x]>>5) & (((0xf81f<<16) | 0x07e0)>>5)))*X) + (lbT[x] & ((0xf81f<<16) | 0x07e0))) & ((0xf81f<<16) | 0x07e0)); + + + } + + dst32 += dp4; + line += vfraq; + } + + if (tail) { + u32 dpT, dpB, L, R; + + u16 *dst16 = (u16*)((char*) dst + cw * 2 - 2); + + + line = vfraq + ctx->clip.y1 * vfraq; + + for (y=0; y> 18) - 1 )); + const u32 *srcB = (const u32 *)((char*) src + spitch * ( (((line)-1) >> 18) )); + + + + + long pl = ( (((point)-1) >> 18) - 1 ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + L = ( (((((srcT[pl]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcT[pl]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcT[pl]) & 0x0000ff))&0xF8) >> 3) ); + R = ( (((((srcT[pl+1]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcT[pl+1]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcT[pl+1]) & 0x0000ff))&0xF8) >> 3) ); + + dpT = (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) >> 6; + + L = ( (((((srcB[pl]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcB[pl]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcB[pl]) & 0x0000ff))&0xF8) >> 3) ); + R = ( (((((srcB[pl+1]) & 0xff0000) >> 16)&0xF8) << 8) | (((((srcB[pl+1]) & 0x00ff00) >> 8)&0xFC) << 3) | (((((srcB[pl+1]) & 0x0000ff))&0xF8) >> 3) ); + + dpB = (((((R & 0xf81f)-(L & 0xf81f))*ratios[r] + ((L & 0xf81f)<<6)) & (0xf81f<<6)) + + ((((R & 0x07e0)-(L & 0x07e0))*ratios[r] + ((L & 0x07e0)<<6)) & (0x07e0<<6))) >> 6; +# 434 "stretch_hvx_16.h" + dst16[0] = ((((((dpB & 0xf81f) - (dpT & 0xf81f))*X) >> 5) + (dpT & 0xf81f)) & 0xf81f) + + ((((((dpB>>5) & (0x07e0>>5)) - ((dpT>>5) & (0x07e0>>5)))*X) + (dpT & 0x07e0)) & 0x07e0); + + + dst16 += dpitch / 2; + line += vfraq; + } + } +} +# 22 "stretch_hvx_N.h" 2 +# 50 "stretch_up_down_16.h" 2 +# 48 "Scaler.cxx" 2 +# 73 "Scaler.cxx" +# 1 "stretch_up_down_32.h" 1 +# 20 "stretch_up_down_32.h" +# 1 "stretch_hvx_N.h" 1 +# 9 "stretch_hvx_N.h" +static void stretch_hvx_ARGB_up____DSPF_ARGB +# 1 "stretch_hvx_32.h" 1 +# 11 "stretch_hvx_32.h" + ( void *dst, + int dpitch, + const void *src, + int spitch, + int width, + int height, + int dst_width, + int dst_height, + const StretchCtx *ctx ) +{ + long x, y = 0; + long cw = ctx->clip.x2 - ctx->clip.x1 + 1; + long ch = ctx->clip.y2 - ctx->clip.y1 + 1; + long hfraq = ((long)(width - 1) << 18) / (long)(dst_width); + long vfraq = ((long)(height - 1) << 18) / (long)(dst_height); + long dp4 = dpitch / 4; + long point0 = 0 + ctx->clip.x1 * hfraq; + long point = point0; + long line = 0 + ctx->clip.y1 * vfraq; + long ratios[cw]; + u32 *dst32; + + + + + + u32 _lbT[cw+8]; + u32 _lbB[cw+8]; + + u32 *lbX; + u32 *lbT = (u32*)((((unsigned long)(&_lbT[0])) + 31) & ~31); + u32 *lbB = (u32*)((((unsigned long)(&_lbB[0])) + 31) & ~31); + + long lineT = -2000; + + for (x=0; x> (18-8) ); + + point += hfraq; + } + + do {} while (0); + + dst = (void*)((char*) dst + ctx->clip.x1 * 4 + ctx->clip.y1 * dpitch); + + dst32 = (u32*) dst; + + + + + for (y=0; y> 18) ); + + D_ASSERT( nlT >= 0 ); + D_ASSERT( nlT < height-1 ); + + + + + if (nlT != lineT) { + u32 L, R; + const u32 *srcT = (const u32 *)((const char*) src + spitch * nlT); + const u32 *srcB = (const u32 *)((const char*) src + spitch * (nlT + 1)); + long diff = nlT - lineT; + + if (diff > 1) { + + + + for (x=0, point=point0; x> 18) ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + + L = (srcT[pl]); + R = (srcT[pl+1]); + + lbT[x]= ((((((R & 0x00ff00ff) - (L & 0x00ff00ff))*ratios[x]) >> 8) + (L & 0x00ff00ff)) & 0x00ff00ff) + + ((((((R>>8) & 0x00ff00ff) - ((L>>8) & 0x00ff00ff))*ratios[x]) + (L & 0xff00ff00)) & 0xff00ff00); + + L = (srcB[pl]); + R = (srcB[pl+1]); + + lbB[x] = ((((((R & 0x00ff00ff) - (L & 0x00ff00ff))*ratios[x]) >> 8) + (L & 0x00ff00ff)) & 0x00ff00ff) + + ((((((R>>8) & 0x00ff00ff) - ((L>>8) & 0x00ff00ff))*ratios[x]) + (L & 0xff00ff00)) & 0xff00ff00); + } + } + else { + + lbX = lbT; + lbT = lbB; + lbB = lbX; + + + + + for (x=0, point=point0; x> 18) ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + + L = (srcB[pl]); + R = (srcB[pl+1]); + + lbB[x] = ((((((R & 0x00ff00ff) - (L & 0x00ff00ff))*ratios[x]) >> 8) + (L & 0x00ff00ff)) & 0x00ff00ff) + + ((((((R>>8) & 0x00ff00ff) - ((L>>8) & 0x00ff00ff))*ratios[x]) + (L & 0xff00ff00)) & 0xff00ff00); + } + } + + lineT = nlT; + } + + + + + X = ( ((line) & 0x3ffff) >> (18-8) ); + + for (x=0; x> 8) + (lbT[x] & 0x00ff00ff)) & 0x00ff00ff) + + ((((((lbB[x]>>8) & 0x00ff00ff) - ((lbT[x]>>8) & 0x00ff00ff))*X) + (lbT[x] & 0xff00ff00)) & 0xff00ff00); + + } + + dst32 += dp4; + line += vfraq; + } +} +# 11 "stretch_hvx_N.h" 2 +# 33 "stretch_hvx_N.h" +static void stretch_hvx_ARGB_up____DSPF_RGB32 +# 1 "stretch_hvx_32.h" 1 +# 11 "stretch_hvx_32.h" + ( void *dst, + int dpitch, + const void *src, + int spitch, + int width, + int height, + int dst_width, + int dst_height, + const StretchCtx *ctx ) +{ + long x, y = 0; + long cw = ctx->clip.x2 - ctx->clip.x1 + 1; + long ch = ctx->clip.y2 - ctx->clip.y1 + 1; + long hfraq = ((long)(width - 1) << 18) / (long)(dst_width); + long vfraq = ((long)(height - 1) << 18) / (long)(dst_height); + long dp4 = dpitch / 4; + long point0 = 0 + ctx->clip.x1 * hfraq; + long point = point0; + long line = 0 + ctx->clip.y1 * vfraq; + long ratios[cw]; + u32 *dst32; + + + + + + u32 _lbT[cw+8]; + u32 _lbB[cw+8]; + + u32 *lbX; + u32 *lbT = (u32*)((((unsigned long)(&_lbT[0])) + 31) & ~31); + u32 *lbB = (u32*)((((unsigned long)(&_lbB[0])) + 31) & ~31); + + long lineT = -2000; + + for (x=0; x> (18-8) ); + + point += hfraq; + } + + do {} while (0); + + dst = (void*)((char*) dst + ctx->clip.x1 * 4 + ctx->clip.y1 * dpitch); + + dst32 = (u32*) dst; + + + + + for (y=0; y> 18) ); + + D_ASSERT( nlT >= 0 ); + D_ASSERT( nlT < height-1 ); + + + + + if (nlT != lineT) { + u32 L, R; + const u32 *srcT = (const u32 *)((const char*) src + spitch * nlT); + const u32 *srcB = (const u32 *)((const char*) src + spitch * (nlT + 1)); + long diff = nlT - lineT; + + if (diff > 1) { + + + + for (x=0, point=point0; x> 18) ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + + L = ((srcT[pl]) | 0xff000000); + R = ((srcT[pl+1]) | 0xff000000); + + lbT[x]= ((((((R & 0x00ff00ff) - (L & 0x00ff00ff))*ratios[x]) >> 8) + (L & 0x00ff00ff)) & 0x00ff00ff) + + ((((((R>>8) & 0x00ff00ff) - ((L>>8) & 0x00ff00ff))*ratios[x]) + (L & 0xff00ff00)) & 0xff00ff00); + + L = ((srcB[pl]) | 0xff000000); + R = ((srcB[pl+1]) | 0xff000000); + + lbB[x] = ((((((R & 0x00ff00ff) - (L & 0x00ff00ff))*ratios[x]) >> 8) + (L & 0x00ff00ff)) & 0x00ff00ff) + + ((((((R>>8) & 0x00ff00ff) - ((L>>8) & 0x00ff00ff))*ratios[x]) + (L & 0xff00ff00)) & 0xff00ff00); + } + } + else { + + lbX = lbT; + lbT = lbB; + lbB = lbX; + + + + + for (x=0, point=point0; x> 18) ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + + L = ((srcB[pl]) | 0xff000000); + R = ((srcB[pl+1]) | 0xff000000); + + lbB[x] = ((((((R & 0x00ff00ff) - (L & 0x00ff00ff))*ratios[x]) >> 8) + (L & 0x00ff00ff)) & 0x00ff00ff) + + ((((((R>>8) & 0x00ff00ff) - ((L>>8) & 0x00ff00ff))*ratios[x]) + (L & 0xff00ff00)) & 0xff00ff00); + } + } + + lineT = nlT; + } + + + + + X = ( ((line) & 0x3ffff) >> (18-8) ); + + for (x=0; x> 8) + (lbT[x] & 0x00ff00ff)) & 0x00ff00ff) + + ((((((lbB[x]>>8) & 0x00ff00ff) - ((lbT[x]>>8) & 0x00ff00ff))*X) + (lbT[x] & 0xff00ff00)) & 0xff00ff00); + + } + + dst32 += dp4; + line += vfraq; + } +} +# 35 "stretch_hvx_N.h" 2 +# 21 "stretch_up_down_32.h" 2 +# 49 "stretch_up_down_32.h" +# 1 "stretch_hvx_N.h" 1 +# 9 "stretch_hvx_N.h" +static void stretch_hvx_ARGB_down____DSPF_ARGB +# 1 "stretch_hvx_32.h" 1 +# 11 "stretch_hvx_32.h" + ( void *dst, + int dpitch, + const void *src, + int spitch, + int width, + int height, + int dst_width, + int dst_height, + const StretchCtx *ctx ) +{ + long x, y = 0; + long cw = ctx->clip.x2 - ctx->clip.x1 + 1; + long ch = ctx->clip.y2 - ctx->clip.y1 + 1; + long hfraq = ((long)(width - 0) << 18) / (long)(dst_width); + long vfraq = ((long)(height - 0) << 18) / (long)(dst_height); + long dp4 = dpitch / 4; + long point0 = hfraq + ctx->clip.x1 * hfraq; + long point = point0; + long line = vfraq + ctx->clip.y1 * vfraq; + long ratios[cw]; + u32 *dst32; + + + + + + u32 _lbT[cw+8]; + u32 _lbB[cw+8]; + + u32 *lbX; + u32 *lbT = (u32*)((((unsigned long)(&_lbT[0])) + 31) & ~31); + u32 *lbB = (u32*)((((unsigned long)(&_lbB[0])) + 31) & ~31); + + long lineT = -2000; + + for (x=0; xclip.x1 * 4 + ctx->clip.y1 * dpitch); + + dst32 = (u32*) dst; + + + + + for (y=0; y> 18) - 1 ); + + D_ASSERT( nlT >= 0 ); + D_ASSERT( nlT < height-1 ); + + + + + if (nlT != lineT) { + u32 L, R; + const u32 *srcT = (const u32 *)((const char*) src + spitch * nlT); + const u32 *srcB = (const u32 *)((const char*) src + spitch * (nlT + 1)); + long diff = nlT - lineT; + + if (diff > 1) { + + + + for (x=0, point=point0; x> 18) - 1 ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + + L = (srcT[pl]); + R = (srcT[pl+1]); + + lbT[x]= ((((((R & 0x00ff00ff) - (L & 0x00ff00ff))*ratios[x]) >> 8) + (L & 0x00ff00ff)) & 0x00ff00ff) + + ((((((R>>8) & 0x00ff00ff) - ((L>>8) & 0x00ff00ff))*ratios[x]) + (L & 0xff00ff00)) & 0xff00ff00); + + L = (srcB[pl]); + R = (srcB[pl+1]); + + lbB[x] = ((((((R & 0x00ff00ff) - (L & 0x00ff00ff))*ratios[x]) >> 8) + (L & 0x00ff00ff)) & 0x00ff00ff) + + ((((((R>>8) & 0x00ff00ff) - ((L>>8) & 0x00ff00ff))*ratios[x]) + (L & 0xff00ff00)) & 0xff00ff00); + } + } + else { + + lbX = lbT; + lbT = lbB; + lbB = lbX; + + + + + for (x=0, point=point0; x> 18) - 1 ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + + L = (srcB[pl]); + R = (srcB[pl+1]); + + lbB[x] = ((((((R & 0x00ff00ff) - (L & 0x00ff00ff))*ratios[x]) >> 8) + (L & 0x00ff00ff)) & 0x00ff00ff) + + ((((((R>>8) & 0x00ff00ff) - ((L>>8) & 0x00ff00ff))*ratios[x]) + (L & 0xff00ff00)) & 0xff00ff00); + } + } + + lineT = nlT; + } + + + + + X = ( (((((line)) & 0x3ffff) ? : 0x40000) << 8) / (vfraq) ); + + for (x=0; x> 8) + (lbT[x] & 0x00ff00ff)) & 0x00ff00ff) + + ((((((lbB[x]>>8) & 0x00ff00ff) - ((lbT[x]>>8) & 0x00ff00ff))*X) + (lbT[x] & 0xff00ff00)) & 0xff00ff00); + + } + + dst32 += dp4; + line += vfraq; + } +} +# 11 "stretch_hvx_N.h" 2 +# 33 "stretch_hvx_N.h" +static void stretch_hvx_ARGB_down____DSPF_RGB32 +# 1 "stretch_hvx_32.h" 1 +# 11 "stretch_hvx_32.h" + ( void *dst, + int dpitch, + const void *src, + int spitch, + int width, + int height, + int dst_width, + int dst_height, + const StretchCtx *ctx ) +{ + long x, y = 0; + long cw = ctx->clip.x2 - ctx->clip.x1 + 1; + long ch = ctx->clip.y2 - ctx->clip.y1 + 1; + long hfraq = ((long)(width - 0) << 18) / (long)(dst_width); + long vfraq = ((long)(height - 0) << 18) / (long)(dst_height); + long dp4 = dpitch / 4; + long point0 = hfraq + ctx->clip.x1 * hfraq; + long point = point0; + long line = vfraq + ctx->clip.y1 * vfraq; + long ratios[cw]; + u32 *dst32; + + + + + + u32 _lbT[cw+8]; + u32 _lbB[cw+8]; + + u32 *lbX; + u32 *lbT = (u32*)((((unsigned long)(&_lbT[0])) + 31) & ~31); + u32 *lbB = (u32*)((((unsigned long)(&_lbB[0])) + 31) & ~31); + + long lineT = -2000; + + for (x=0; xclip.x1 * 4 + ctx->clip.y1 * dpitch); + + dst32 = (u32*) dst; + + + + + for (y=0; y> 18) - 1 ); + + D_ASSERT( nlT >= 0 ); + D_ASSERT( nlT < height-1 ); + + + + + if (nlT != lineT) { + u32 L, R; + const u32 *srcT = (const u32 *)((const char*) src + spitch * nlT); + const u32 *srcB = (const u32 *)((const char*) src + spitch * (nlT + 1)); + long diff = nlT - lineT; + + if (diff > 1) { + + + + for (x=0, point=point0; x> 18) - 1 ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + + L = ((srcT[pl]) | 0xff000000); + R = ((srcT[pl+1]) | 0xff000000); + + lbT[x]= ((((((R & 0x00ff00ff) - (L & 0x00ff00ff))*ratios[x]) >> 8) + (L & 0x00ff00ff)) & 0x00ff00ff) + + ((((((R>>8) & 0x00ff00ff) - ((L>>8) & 0x00ff00ff))*ratios[x]) + (L & 0xff00ff00)) & 0xff00ff00); + + L = ((srcB[pl]) | 0xff000000); + R = ((srcB[pl+1]) | 0xff000000); + + lbB[x] = ((((((R & 0x00ff00ff) - (L & 0x00ff00ff))*ratios[x]) >> 8) + (L & 0x00ff00ff)) & 0x00ff00ff) + + ((((((R>>8) & 0x00ff00ff) - ((L>>8) & 0x00ff00ff))*ratios[x]) + (L & 0xff00ff00)) & 0xff00ff00); + } + } + else { + + lbX = lbT; + lbT = lbB; + lbB = lbX; + + + + + for (x=0, point=point0; x> 18) - 1 ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + + L = ((srcB[pl]) | 0xff000000); + R = ((srcB[pl+1]) | 0xff000000); + + lbB[x] = ((((((R & 0x00ff00ff) - (L & 0x00ff00ff))*ratios[x]) >> 8) + (L & 0x00ff00ff)) & 0x00ff00ff) + + ((((((R>>8) & 0x00ff00ff) - ((L>>8) & 0x00ff00ff))*ratios[x]) + (L & 0xff00ff00)) & 0xff00ff00); + } + } + + lineT = nlT; + } + + + + + X = ( (((((line)) & 0x3ffff) ? : 0x40000) << 8) / (vfraq) ); + + for (x=0; x> 8) + (lbT[x] & 0x00ff00ff)) & 0x00ff00ff) + + ((((((lbB[x]>>8) & 0x00ff00ff) - ((lbT[x]>>8) & 0x00ff00ff))*X) + (lbT[x] & 0xff00ff00)) & 0xff00ff00); + + } + + dst32 += dp4; + line += vfraq; + } +} +# 35 "stretch_hvx_N.h" 2 +# 50 "stretch_up_down_32.h" 2 +# 74 "Scaler.cxx" 2 +# 99 "Scaler.cxx" +# 1 "stretch_up_down_32.h" 1 +# 20 "stretch_up_down_32.h" +# 1 "stretch_hvx_N.h" 1 +# 9 "stretch_hvx_N.h" +static void stretch_hvx_RGB32_up____DSPF_RGB32 +# 1 "stretch_hvx_32.h" 1 +# 11 "stretch_hvx_32.h" + ( void *dst, + int dpitch, + const void *src, + int spitch, + int width, + int height, + int dst_width, + int dst_height, + const StretchCtx *ctx ) +{ + long x, y = 0; + long cw = ctx->clip.x2 - ctx->clip.x1 + 1; + long ch = ctx->clip.y2 - ctx->clip.y1 + 1; + long hfraq = ((long)(width - 1) << 18) / (long)(dst_width); + long vfraq = ((long)(height - 1) << 18) / (long)(dst_height); + long dp4 = dpitch / 4; + long point0 = 0 + ctx->clip.x1 * hfraq; + long point = point0; + long line = 0 + ctx->clip.y1 * vfraq; + long ratios[cw]; + u32 *dst32; + + + + + + u32 _lbT[cw+8]; + u32 _lbB[cw+8]; + + u32 *lbX; + u32 *lbT = (u32*)((((unsigned long)(&_lbT[0])) + 31) & ~31); + u32 *lbB = (u32*)((((unsigned long)(&_lbB[0])) + 31) & ~31); + + long lineT = -2000; + + for (x=0; x> (18-8) ); + + point += hfraq; + } + + do {} while (0); + + dst = (void*)((char*) dst + ctx->clip.x1 * 4 + ctx->clip.y1 * dpitch); + + dst32 = (u32*) dst; + + + + + for (y=0; y> 18) ); + + D_ASSERT( nlT >= 0 ); + D_ASSERT( nlT < height-1 ); + + + + + if (nlT != lineT) { + u32 L, R; + const u32 *srcT = (const u32 *)((const char*) src + spitch * nlT); + const u32 *srcB = (const u32 *)((const char*) src + spitch * (nlT + 1)); + long diff = nlT - lineT; + + if (diff > 1) { + + + + for (x=0, point=point0; x> 18) ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + + L = (srcT[pl]); + R = (srcT[pl+1]); + + lbT[x]= ((((((R & 0x00ff00ff) - (L & 0x00ff00ff))*ratios[x]) >> 8) + (L & 0x00ff00ff)) & 0x00ff00ff) + + ((((((R>>8) & 0x00ff00ff) - ((L>>8) & 0x00ff00ff))*ratios[x]) + (L & 0x0000ff00)) & 0x0000ff00); + + L = (srcB[pl]); + R = (srcB[pl+1]); + + lbB[x] = ((((((R & 0x00ff00ff) - (L & 0x00ff00ff))*ratios[x]) >> 8) + (L & 0x00ff00ff)) & 0x00ff00ff) + + ((((((R>>8) & 0x00ff00ff) - ((L>>8) & 0x00ff00ff))*ratios[x]) + (L & 0x0000ff00)) & 0x0000ff00); + } + } + else { + + lbX = lbT; + lbT = lbB; + lbB = lbX; + + + + + for (x=0, point=point0; x> 18) ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + + L = (srcB[pl]); + R = (srcB[pl+1]); + + lbB[x] = ((((((R & 0x00ff00ff) - (L & 0x00ff00ff))*ratios[x]) >> 8) + (L & 0x00ff00ff)) & 0x00ff00ff) + + ((((((R>>8) & 0x00ff00ff) - ((L>>8) & 0x00ff00ff))*ratios[x]) + (L & 0x0000ff00)) & 0x0000ff00); + } + } + + lineT = nlT; + } + + + + + X = ( ((line) & 0x3ffff) >> (18-8) ); + + for (x=0; x> 8) + (lbT[x] & 0x00ff00ff)) & 0x00ff00ff) + + ((((((lbB[x]>>8) & 0x00ff00ff) - ((lbT[x]>>8) & 0x00ff00ff))*X) + (lbT[x] & 0x0000ff00)) & 0x0000ff00); + + } + + dst32 += dp4; + line += vfraq; + } +} +# 11 "stretch_hvx_N.h" 2 +# 21 "stretch_up_down_32.h" 2 +# 49 "stretch_up_down_32.h" +# 1 "stretch_hvx_N.h" 1 +# 9 "stretch_hvx_N.h" +static void stretch_hvx_RGB32_down____DSPF_RGB32 +# 1 "stretch_hvx_32.h" 1 +# 11 "stretch_hvx_32.h" + ( void *dst, + int dpitch, + const void *src, + int spitch, + int width, + int height, + int dst_width, + int dst_height, + const StretchCtx *ctx ) +{ + long x, y = 0; + long cw = ctx->clip.x2 - ctx->clip.x1 + 1; + long ch = ctx->clip.y2 - ctx->clip.y1 + 1; + long hfraq = ((long)(width - 0) << 18) / (long)(dst_width); + long vfraq = ((long)(height - 0) << 18) / (long)(dst_height); + long dp4 = dpitch / 4; + long point0 = hfraq + ctx->clip.x1 * hfraq; + long point = point0; + long line = vfraq + ctx->clip.y1 * vfraq; + long ratios[cw]; + u32 *dst32; + + + + + + u32 _lbT[cw+8]; + u32 _lbB[cw+8]; + + u32 *lbX; + u32 *lbT = (u32*)((((unsigned long)(&_lbT[0])) + 31) & ~31); + u32 *lbB = (u32*)((((unsigned long)(&_lbB[0])) + 31) & ~31); + + long lineT = -2000; + + for (x=0; xclip.x1 * 4 + ctx->clip.y1 * dpitch); + + dst32 = (u32*) dst; + + + + + for (y=0; y> 18) - 1 ); + + D_ASSERT( nlT >= 0 ); + D_ASSERT( nlT < height-1 ); + + + + + if (nlT != lineT) { + u32 L, R; + const u32 *srcT = (const u32 *)((const char*) src + spitch * nlT); + const u32 *srcB = (const u32 *)((const char*) src + spitch * (nlT + 1)); + long diff = nlT - lineT; + + if (diff > 1) { + + + + for (x=0, point=point0; x> 18) - 1 ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + + L = (srcT[pl]); + R = (srcT[pl+1]); + + lbT[x]= ((((((R & 0x00ff00ff) - (L & 0x00ff00ff))*ratios[x]) >> 8) + (L & 0x00ff00ff)) & 0x00ff00ff) + + ((((((R>>8) & 0x00ff00ff) - ((L>>8) & 0x00ff00ff))*ratios[x]) + (L & 0x0000ff00)) & 0x0000ff00); + + L = (srcB[pl]); + R = (srcB[pl+1]); + + lbB[x] = ((((((R & 0x00ff00ff) - (L & 0x00ff00ff))*ratios[x]) >> 8) + (L & 0x00ff00ff)) & 0x00ff00ff) + + ((((((R>>8) & 0x00ff00ff) - ((L>>8) & 0x00ff00ff))*ratios[x]) + (L & 0x0000ff00)) & 0x0000ff00); + } + } + else { + + lbX = lbT; + lbT = lbB; + lbB = lbX; + + + + + for (x=0, point=point0; x> 18) - 1 ); + do {} while (0); + + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + + L = (srcB[pl]); + R = (srcB[pl+1]); + + lbB[x] = ((((((R & 0x00ff00ff) - (L & 0x00ff00ff))*ratios[x]) >> 8) + (L & 0x00ff00ff)) & 0x00ff00ff) + + ((((((R>>8) & 0x00ff00ff) - ((L>>8) & 0x00ff00ff))*ratios[x]) + (L & 0x0000ff00)) & 0x0000ff00); + } + } + + lineT = nlT; + } + + + + + X = ( (((((line)) & 0x3ffff) ? : 0x40000) << 8) / (vfraq) ); + + for (x=0; x> 8) + (lbT[x] & 0x00ff00ff)) & 0x00ff00ff) + + ((((((lbB[x]>>8) & 0x00ff00ff) - ((lbT[x]>>8) & 0x00ff00ff))*X) + (lbT[x] & 0x0000ff00)) & 0x0000ff00); + + } + + dst32 += dp4; + line += vfraq; + } +} +# 11 "stretch_hvx_N.h" 2 +# 50 "stretch_up_down_32.h" 2 +# 100 "Scaler.cxx" 2 +# 112 "Scaler.cxx" +class Scaler +{ + + public: Scaler() { + } + + public: void scale( DFBSurfacePixelFormat format, + void *dst, + int dpitch, + const void *src, + int spitch, + int width, + int height, + int dst_width, + int dst_height, + const DFBRegion &clip ) + { + D_DEBUG_AT( PluggIt_Scaler, "%s( %s, %p [%d], %p [%d], %dx%d -> %dx%d, clip %4d,%4d-%4dx%4d )\n", + __FUNCTION__, dfb_pixelformat_name( format ), dst, dpitch, src, spitch, width, height, + dst_width, dst_height, DFB_RECTANGLE_VALS_FROM_REGION( &clip ) ); + + + StretchCtx ctx; + + ctx.clip = clip; + + switch (format) { + case DSPF_RGB16: + if (width <= dst_width || height <= dst_height) + stretch_hvx_RGB16_up____DSPF_RGB32( dst, dpitch, src, spitch, width, height, dst_width, dst_height, &ctx ); + else + stretch_hvx_RGB16_down____DSPF_RGB32( dst, dpitch, src, spitch, width, height, dst_width, dst_height, &ctx ); + break; + + case DSPF_RGB32: + if (width <= dst_width || height <= dst_height) + stretch_hvx_RGB32_up____DSPF_RGB32( dst, dpitch, src, spitch, width, height, dst_width, dst_height, &ctx ); + else + stretch_hvx_RGB32_down____DSPF_RGB32( dst, dpitch, src, spitch, width, height, dst_width, dst_height, &ctx ); + break; + + case DSPF_ARGB: + if (width <= dst_width || height <= dst_height) + stretch_hvx_ARGB_up____DSPF_RGB32( dst, dpitch, src, spitch, width, height, dst_width, dst_height, &ctx ); + else + stretch_hvx_ARGB_down____DSPF_RGB32( dst, dpitch, src, spitch, width, height, dst_width, dst_height, &ctx ); + break; + + default: + D_UNIMPLEMENTED(); + break; + } + } +}; + + + +} +# 1 "View.cxx" +# 1 "" +# 1 "" +# 1 "View.cxx" +namespace PluggIt { + +class View +{ + public: virtual void config( DFBDimension &size ) = 0; + + public: virtual void update( const vector &rects, + void *ptr, + int pitch ) = 0; +}; + +} +# 1 "Source.cxx" +# 1 "" +# 1 "" +# 1 "Source.cxx" +namespace PluggIt { + +class Source +{ + protected: class Config { + protected: Config() {} + }; + + + protected: View *m_view; + protected: const Config &m_config; + + public: Source( View *view, const Config &config ) : m_config(config) { + m_view = view; + } + + + public: virtual int MainLoop() = 0; +}; + +} +# 1 "SourceWin32.cxx" +# 1 "" +# 1 "" +# 1 "SourceWin32.cxx" +namespace PluggIt { + +D_DEBUG_DOMAIN( PluggIt_SourceWin32, "PluggIt/SourceWin32", "PluggIt Source Win32" ); + + +# 1 "ScreenHooks.h" 1 +# 28 "ScreenHooks.h" +extern "C" +{ + __attribute__((dllexport)) bool setHook(HWND targedWinHwnd); + __attribute__((dllexport)) bool unsetHook(); +} +# 7 "SourceWin32.cxx" 2 + +const UINT specIpcCode = RegisterWindowMessage("HOOK.MESSAGE.CODE"); + + +class SourceWin32 :public Source, Runnable +{ + private: HINSTANCE m_hInstance; + + private: HWND m_root; + private: HWND m_window; + + private: DFBPoint m_position; + private: DFBDimension m_size; + + private: HBITMAP m_bitmap; + private: void *m_pixels; + private: int m_pitch; + + private: HBITMAP m_bitmap2; + private: void *m_pixels2; + private: int m_pitch2; + + private: HDC m_window_dc; + private: HDC m_bitmap_dc; + private: HDC m_bitmap_dc2; + + private: Thread *m_thread; + + private: Updates m_updates; + + private: VIDEODRIVER m_driver; + private: bool m_using_driver; + + private: pthread_mutex_t m_lock; + private: pthread_cond_t m_cond; + + + public: class Config :public Source::Config { + friend class SourceWin32; + + public: typedef enum { + WINDOW_SELECTION_NONE, + WINDOW_SELECTION_TITLE, + WINDOW_SELECTION_INTERACTIVE + } WindowSelection; + + private: WindowSelection m_selection; + private: std::string m_title; + private: bool m_updating; + private: bool m_use_driver; + + + public: Config( WindowSelection selection, + const std::string &title = std::string(), + bool updating = false, bool use_driver = true ) + { + m_selection = selection; + m_title = title; + m_updating = updating; + m_use_driver = use_driver; + } + }; + + + public: SourceWin32( View *view, const Config &config ) : Source( view, config ), m_updates(16) { + D_DEBUG_AT( PluggIt_SourceWin32, "%s( %p )\n", __FUNCTION__, view ); + + m_hInstance = GetModuleHandle( NULL ); + + D_DEBUG_AT( PluggIt_SourceWin32, " -> hInstance %p\n", m_hInstance ); + + + m_root = GetDesktopWindow(); + + switch (config.m_selection) { + case Config::WINDOW_SELECTION_NONE: + m_window = m_root; + break; + + case Config::WINDOW_SELECTION_TITLE: + m_window = findWindow( config.m_title ); + if (m_window == 0) + throw new Exception( "Could not find window with title containing '%s'\n", config.m_title.c_str() ); + break; + + case Config::WINDOW_SELECTION_INTERACTIVE: + pickWindow(); + if (m_window == 0) + throw new Exception( "Could not interactively pick a window\n" ); + break; + + default: + throw new Exception( "Invalid window selection method\n" ); + } + + + RECT rect; + + GetClientRect( m_window, &rect ); + + m_position.x = rect.left; + m_position.y = rect.top; + + m_size.w = rect.right - rect.left; + m_size.h = rect.bottom - rect.top; + + queueUpdate( 0, 0, m_size.w - 1, m_size.h - 1 ); + + + std::string t = getWindowTitle( m_window ); + + D_INFO( "Source/Win32: Window %d,%d-%ux%u, name '%s'\n", + m_position.x, m_position.y, m_size.w, m_size.h, t.c_str() ); + + if (config.m_use_driver) + m_driver.VIDEODRIVER_start( m_position.x, m_position.y, m_size.w, m_size.h ); + + m_using_driver = m_driver.mypchangebuf != NULL; + + m_view->config( m_size ); + + + m_window_dc = GetDC( m_window ); + m_bitmap_dc = CreateCompatibleDC( m_window_dc ); + m_bitmap_dc2 = CreateCompatibleDC( m_window_dc ); + + + BITMAPINFO bitmap_info = {{ + biSize: sizeof(BITMAPINFOHEADER), + biWidth: m_size.w, + biHeight: m_size.h, + biPlanes: 1, + biBitCount: 32, + biCompression: BI_RGB, + biSizeImage: 0, + biXPelsPerMeter: 0, + biYPelsPerMeter: 0, + biClrUsed: 0, + biClrImportant: 0, + }}; + + m_bitmap = CreateDIBSection( m_window_dc, &bitmap_info, DIB_RGB_COLORS, &m_pixels, NULL, 0 ); + m_bitmap2 = CreateDIBSection( m_window_dc, &bitmap_info, DIB_RGB_COLORS, &m_pixels2, NULL, 0 ); + + + BITMAP bitmap; + + GetObject( m_bitmap, sizeof(BITMAP), &bitmap ); + + m_pitch = bitmap.bmWidthBytes; + + GetObject( m_bitmap2, sizeof(BITMAP), &bitmap ); + + m_pitch2 = bitmap.bmWidthBytes; + + + SelectObject( m_bitmap_dc, m_bitmap ); + SelectObject( m_bitmap_dc2, m_bitmap2 ); + + + pthread_mutex_init( &m_lock, NULL ); + pthread_cond_init( &m_cond, NULL ); + + + if (!m_using_driver) { + HWND w; + + WNDCLASSEX wndClass; + + ZeroMemory( &wndClass, sizeof(wndClass) ); + + wndClass.cbSize = sizeof(wndClass); + wndClass.style = CS_HREDRAW | CS_VREDRAW; + wndClass.lpfnWndProc = MsgWndProc; + wndClass.cbClsExtra = 0; + wndClass.cbWndExtra = 0; + wndClass.hInstance = GetModuleHandle(NULL); + wndClass.hIcon = NULL; + wndClass.hIconSm = NULL; + wndClass.hCursor = LoadCursor( NULL, IDC_UPARROW ); + wndClass.hbrBackground = (HBRUSH) GetStockObject( NULL_BRUSH ); + wndClass.lpszMenuName = NULL; + wndClass.lpszClassName = "MsgWindow"; + + if (!RegisterClassEx( &wndClass )) + throw new Exception( "RegisterClassEx() failed!" ); + + + w = CreateWindowEx( 0, + "MsgWindow", + "MsgWindow", + WS_POPUP, + CW_USEDEFAULT, + CW_USEDEFAULT, + 1, + 1, + NULL, + NULL, + GetModuleHandle(NULL), + this ); + + if (!setHook( w )) + throw new Exception( "Failed to set hooks!" ); + } + + + + m_thread = new Thread( this, "SourceWin32" ); + + m_thread->start(); + } + + virtual ~SourceWin32() { + m_thread->interrupt(); + m_thread->join(); + delete m_thread; + + pthread_mutex_destroy( &m_lock ); + pthread_cond_destroy( &m_cond ); + + DeleteDC( m_window_dc ); + DeleteDC( m_bitmap_dc ); + DeleteDC( m_bitmap_dc2 ); + + DeleteObject( m_bitmap ); + DeleteObject( m_bitmap2 ); + } + + private: void addRect( const RECT &rect ) { + if (rect.left >= rect.right) + return; + + if (rect.top >= rect.bottom) + return; + + DFBRegion region( rect.left, + rect.top, + rect.right - 1, + rect.bottom - 1 ); + + m_updates.addRegion( region ); + } + + private: void run() { + if (m_using_driver) { + D_ASSERT( m_driver.mypchangebuf != NULL ); + + unsigned int counter = m_driver.mypchangebuf->counter; + unsigned int i; + + long long last_time = direct_clock_get_abs_millis(); + + D_DEBUG_AT( PluggIt_SourceWin32, "%s()\n", __FUNCTION__ ); + + while (!m_thread->isInterrupted()) { + if (m_driver.mypchangebuf->counter < 1 || + m_driver.mypchangebuf->counter >= MAXCHANGES_BUF || + counter == m_driver.mypchangebuf->counter) + usleep( 10000 ); + + if (counter != m_driver.mypchangebuf->counter) { + D_DEBUG_AT( PluggIt_SourceWin32, " -> counter: %d -> %d\n", counter, m_driver.mypchangebuf->counter ); + + if (counter < m_driver.mypchangebuf->counter) { + for (i=counter+1; i<=m_driver.mypchangebuf->counter; i++) { + addRect( m_driver.mypchangebuf->pointrect[i].rect ); + } + } + else if (counter > m_driver.mypchangebuf->counter) { + for (i=counter+1; ipointrect[i].rect ); + } + for (i=1; i<=m_driver.mypchangebuf->counter; i++) { + addRect( m_driver.mypchangebuf->pointrect[i].rect ); + } + } + + counter = m_driver.mypchangebuf->counter; + } + + if (direct_clock_get_abs_millis() - last_time > 2000) { + DFBRegion region( 0, + 0, + m_size.w - 1, + m_size.h - 1 ); + + m_updates.addRegion( region ); + + last_time = direct_clock_get_abs_millis(); + } + + if (m_updates.num_regions() > 0) { + vector rects; + + m_updates.GetRectangles( rects ); + + + const DFBRegion &bounding = m_updates.bounding(); + + D_DEBUG_AT( PluggIt_SourceWin32, " -> %4d,%4d-%4dx%4d (%d regions, %d rectangles)\n", + DFB_RECTANGLE_VALS_FROM_REGION( &bounding ), m_updates.num_regions(), rects.size() ); + + m_updates.reset(); + + flushUpdates( rects ); + } + } + } + else { + D_DEBUG_AT( PluggIt_SourceWin32, "%s()\n", __FUNCTION__ ); + + long long last_time = direct_clock_get_abs_millis(); + + while (!m_thread->isInterrupted()) { + if (((const Config&)m_config).m_updating) { + usleep( 100000 ); + + queueUpdate( 0, 0, m_size.w - 1, m_size.h - 1 ); + + pthread_mutex_lock( &m_lock ); + } + else { + pthread_mutex_lock( &m_lock ); + + if (m_updates.num_regions() == 0) + usleep( 10000 ); + + } + + if (direct_clock_get_abs_millis() - last_time > 2000) { + DFBRegion region( 0, + 0, + m_size.w - 1, + m_size.h - 1 ); + + m_updates.addRegion( region ); + + last_time = direct_clock_get_abs_millis(); + } + + + vector rects; + + if (m_updates.num_regions() > 0) { + m_updates.GetRectangles( rects ); + + + const DFBRegion &bounding = m_updates.bounding(); + + D_DEBUG_AT( PluggIt_SourceWin32, " -> %4d,%4d-%4dx%4d (%d regions, %d rectangles)\n", + DFB_RECTANGLE_VALS_FROM_REGION( &bounding ), m_updates.num_regions(), rects.size() ); + + m_updates.reset(); + } + + pthread_mutex_unlock( &m_lock ); + + if (!rects.empty()) + flushUpdates( rects ); + } + } + } + + + + private: void queueUpdate( int x1, int y1, int x2, int y2 ) { + D_DEBUG_AT( PluggIt_SourceWin32, "%s( %d,%d-%dx%d )\n", __FUNCTION__, x1, y1, x2 - x1 + 1, y2 - y1 + 1 ); + + pthread_mutex_lock( &m_lock ); + + DFBRegion damage( x1, y1, x2, y2 ); + + m_updates.addRegion( damage ); + + pthread_mutex_unlock( &m_lock ); + + pthread_cond_signal( &m_cond ); + } + + private: bool flushUpdates( vector &rects ) { + D_DEBUG_AT( PluggIt_SourceWin32, "%s()\n", __FUNCTION__ ); + + if (m_using_driver) { + m_view->update( rects, m_driver.myframebuffer, m_pitch ); + } + else { + for (unsigned int i=0; iupdate( rects, (void*)((char*) m_pixels + m_pitch * (m_size.h - 1)), - m_pitch ); + } + + D_DEBUG_AT( PluggIt_SourceWin32, " -> flush done\n" ); + + return true; + } + + + + + + private: static std::string getWindowTitle( HWND window ) { + char buf[1024] = { 0 }; + + GetWindowText( window, buf, sizeof(buf) ); + + D_DEBUG_AT( PluggIt_SourceWin32, "%s( %p ) -> '%s'\n", __FUNCTION__, window, buf ); + + return buf; + } + + + + + class EnumContext { + public: const std::string &title; + public: HWND window; + + public: EnumContext( const std::string &title ) : title(title), window(0) {} + }; + + private: static BOOL CALLBACK enumWindowsProc( HWND hwnd, + LPARAM lParam ) + { + EnumContext *ctx = reinterpret_cast( lParam ); + + D_DEBUG_AT( PluggIt_SourceWin32, "%s( %p )\n", __FUNCTION__, hwnd ); + + std::string title = getWindowTitle( hwnd ); + + if (title == ctx->title || title.find( ctx->title ) < title.size()) + ctx->window = hwnd; + + return ctx->window == NULL; + } + + private: HWND findWindow( const std::string &title ) { + D_DEBUG_AT( PluggIt_SourceWin32, "%s( %s )\n", __FUNCTION__, title.c_str() ); + + EnumContext ctx( title ); + + EnumWindows( enumWindowsProc, reinterpret_cast( &ctx ) ); + + return ctx.window; + } + + + + + static LRESULT CALLBACK WndProc( HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam ) + { + static SourceWin32 *thiz; + POINT point; + CREATESTRUCT *create; + + switch (uMsg) { + case WM_CREATE: + create = reinterpret_cast( lParam ); + thiz = reinterpret_cast( create->lpCreateParams ); + + SetCursor( LoadCursor( NULL, IDC_CROSS ) ); + break; + + case WM_LBUTTONDOWN: + ShowWindow( hwnd, SW_HIDE ); + + + GetCursorPos( &point ); + + D_DEBUG_AT( PluggIt_SourceWin32, " -> Cursor position is %ld,%ld\n", point.x, point.y ); + + + thiz->m_window = WindowFromPoint( point ); + if (thiz->m_window) { + HWND parent; + + while ((parent = GetParent( thiz->m_window )) != NULL) + thiz->m_window = parent; + } + + D_DEBUG_AT( PluggIt_SourceWin32, " -> Window at cursor is %p: %s\n", + thiz->m_window, getWindowTitle( thiz->m_window ).c_str() ); + + DestroyWindow( hwnd ); + break; + + case WM_TIMER: + if (wParam == 666) + DestroyWindow( hwnd ); + break; + + case WM_DESTROY: + KillTimer( hwnd, 666 ); + PostQuitMessage( 0 ); + break; + + default: + SetTimer( hwnd, 666, 5000, NULL ); + + return DefWindowProc( hwnd, uMsg, wParam, lParam ); + } + + return 0; + } + + private: void pickWindow() { + D_DEBUG_AT( PluggIt_SourceWin32, "%s()\n", __FUNCTION__ ); + + HDC hdc; + + hdc = GetDC( NULL ); + if (!hdc) + throw new Exception( "GetDC() returned NULL" ); + + RECT rect; + + GetClipBox( hdc, &rect ); + + D_DEBUG_AT( PluggIt_SourceWin32, " -> Desktop size: %ldx%ld\n", + rect.right - rect.left, rect.bottom - rect.top ); + + ReleaseDC( NULL, hdc ); + + + + WNDCLASSEX wndClass; + + ZeroMemory( &wndClass, sizeof(wndClass) ); + + wndClass.cbSize = sizeof(wndClass); + wndClass.style = CS_HREDRAW | CS_VREDRAW; + wndClass.lpfnWndProc = WndProc; + wndClass.cbClsExtra = 0; + wndClass.cbWndExtra = 0; + wndClass.hInstance = m_hInstance; + wndClass.hIcon = NULL; + wndClass.hIconSm = NULL; + wndClass.hCursor = LoadCursor( NULL, IDC_UPARROW ); + wndClass.hbrBackground = (HBRUSH) GetStockObject( NULL_BRUSH ); + wndClass.lpszMenuName = NULL; + wndClass.lpszClassName = "GrabWindow"; + + if (!RegisterClassEx( &wndClass )) + throw new Exception( "RegisterClassEx() failed!\n" ); + + + AdjustWindowRect( &rect, WS_CAPTION, FALSE ); + + + HWND grabwin; + + grabwin = CreateWindowEx( 0, + "GrabWindow", + "GrabWindow", + WS_POPUP, + CW_USEDEFAULT, + CW_USEDEFAULT, + rect.right - rect.left, + rect.bottom - rect.top, + NULL, + NULL, + m_hInstance, + this ); + + SetWindowLong( grabwin, GWL_EXSTYLE, + GetWindowLong( grabwin, GWL_EXSTYLE ) | WS_EX_TRANSPARENT | WS_EX_TOPMOST ); + + ShowWindow( grabwin, SW_SHOW ); + + + + MSG msg; + + while (GetMessage( &msg, 0, 0, 0 )) { + TranslateMessage( &msg ); + + D_DEBUG_AT( PluggIt_SourceWin32, " -> Dispatching event (id %u)...\n", msg.message ); + + DispatchMessage( &msg ); + } + } + + + + static LRESULT CALLBACK MsgWndProc( HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam ) + { + static SourceWin32 *thiz; + CREATESTRUCT *create; + + switch (uMsg) { + case WM_CREATE: + create = reinterpret_cast( lParam ); + thiz = reinterpret_cast( create->lpCreateParams ); + break; + + case WM_DESTROY: + PostQuitMessage( 0 ); + break; + + default: + if (uMsg == specIpcCode) { + int x1 = wParam >> 16; + int y1 = wParam & 0xffff; + int x2 = lParam >> 16; + int y2 = lParam & 0xffff; + + if (x1 < x2 && y1 < y2) + thiz->queueUpdate( x1, y1, x2 - 1, y2 - 1 ); + + break; + } + + return DefWindowProc( hwnd, uMsg, wParam, lParam ); + } + + return 0; + } + + public: virtual int MainLoop() { + MSG msg; + + while (GetMessage( &msg, 0, 0, 0 )) { + TranslateMessage( &msg ); + DispatchMessage( &msg ); + } + + return 0; + } +}; + +} +# 1 "Main.cxx" +# 1 "" +# 1 "" +# 1 "Main.cxx" +namespace PluggIt { + +D_DEBUG_DOMAIN( PluggIt_Main, "PluggIt/Main", "PluggIt Main" ); +D_DEBUG_DOMAIN( PluggIt_View, "PluggIt/View", "PluggIt View" ); + +class Main :public 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 { + + 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__ ); + + + 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__ ); + + + 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 ); +# 122 "Main.cxx" + } + + 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 ); + + + if (m_source_resolution == source_resolution) { + D_DEBUG_AT( PluggIt_View, " -> unchanged source size\n" ); + return; + } + + m_source_resolution = source_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 ); + + + + 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 { + + 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 ); + + + + 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); + + + 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 ); + + } + } + + 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); + + + 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 ); + + } + } + } + } + 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); + + + 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 ) ); + + + 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 ); + + } + } + + free( tmp ); + } + + m_surface.Flip( &flip ); + + if (!m_view_visible) { + m_window.SetOpacity( 0xff ); + + m_view_visible = true; + } + } +}; + +} +extern "C" { +# 1 "main.c" +# 1 "" +# 1 "" +# 1 "main.c" + +int +main( int argc, char *argv[] ) +{ + PluggIt::Main *main = new PluggIt::Main(); + + main->main( argc, argv ); + + delete main; +} +} diff --git a/src/classes.h b/src/classes.h new file mode 100644 index 0000000..4809afb --- /dev/null +++ b/src/classes.h @@ -0,0 +1,64 @@ +#define DIRECT_ENABLE_DEBUG + + +#include +#include + +using namespace std; + + +/* + * ++DFB + */ +#include <++dfb.h> + + + +/* + * Direct + */ +extern "C" { +#include + +#include +#include +#include +#include +#include +#include + +#include +} + + +/* + * Win32 + */ +#ifdef __WIN32__ +#define CreateWindow CreateWindowWin32 +#include +#include +#include +#include "videodriver.h" +#undef CreateWindow + +#else + +/* + * X11 + */ +extern "C" { +#include /* fundamentals X datas structures */ +#include /* datas definitions for various functions */ +#include /* for a perfect use of keyboard events */ +#include +#include + +#include +#include +#include +#include +} + +#endif + diff --git a/src/gen_classes.sh b/src/gen_classes.sh new file mode 100755 index 0000000..dc5847d --- /dev/null +++ b/src/gen_classes.sh @@ -0,0 +1,33 @@ +#!/bin/sh -e + +CLASSES= +SOURCES= + +while test -n "$1"; do + SOURCES="$SOURCES $1" + CLASSES="$CLASSES `echo "$1" | sed 's/\.cxx//'`" + shift +done + +echo '# 1 "classes.h"' +cat classes.h + + +for i in $CLASSES; do + echo "class $i;" +done + +for i in $SOURCES; do + cpp $CPPFLAGS $i | + sed 's/public/public:/' | + sed 's/protected/protected:/' | + sed 's/private/private:/' | + sed 's/extends/:public/' +done + + +echo 'extern "C" {' + +cpp main.c + +echo '}' diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..c9fa208 --- /dev/null +++ b/src/main.c @@ -0,0 +1,11 @@ + +int +main( int argc, char *argv[] ) +{ + PluggIt::Main *main = new PluggIt::Main(); + + main->main( argc, argv ); + + delete main; +} + diff --git a/src/stretch_hvx_16.h b/src/stretch_hvx_16.h new file mode 100644 index 0000000..a661648 --- /dev/null +++ b/src/stretch_hvx_16.h @@ -0,0 +1,469 @@ +#ifndef SOURCE_LOOKUP +#define SOURCE_LOOKUP(x) (x) +#define SOURCE_LOOKUP_AUTO +#endif + +#ifndef SOURCE_TYPE +#define SOURCE_TYPE u16 +#define SOURCE_TYPE_AUTO +#endif + + +#define SHIFT_L5 SHIFT_R5 +#define SHIFT_L6 SHIFT_R6 +#define SHIFT_L10 (16-SHIFT_L6) + +#define X_003F (X_07E0>>SHIFT_R5) + +#define X_003E07C0 (X_F81F<>SHIFT_R5) + +#if 0 +#define HVX_DEBUG(x...) direct_log_printf( NULL, x ) +#else +#define HVX_DEBUG(x...) do {} while (0) +#endif + +/* stretch_hvx_up/down_16_KPI */( void *dst, + int dpitch, + const void *src, + int spitch, + int width, + int height, + int dst_width, + int dst_height, + const StretchCtx *ctx ) +{ + long x, y, r = 0; + long head = ((((unsigned long) dst) & 2) >> 1) ^ (ctx->clip.x1 & 1); + long cw = ctx->clip.x2 - ctx->clip.x1 + 1; + long ch = ctx->clip.y2 - ctx->clip.y1 + 1; + long tail = (cw - head) & 1; + long w2 = (cw - head) / 2; + long hfraq = ((long)(width - MINUS_1) << 18) / (long)(dst_width); + long vfraq = ((long)(height - MINUS_1) << 18) / (long)(dst_height); + long dp4 = dpitch / 4; + long point0 = POINT_0 + ctx->clip.x1 * hfraq; + long point = point0; + long line = LINE_0 + ctx->clip.y1 * vfraq; + long ratios[cw]; + u32 *dst32; + +#if defined (COLOR_KEY) || defined (KEY_PROTECT) + u32 dt; + u16 l_, h_; +#endif + + u32 _lbT[w2+8]; + u32 _lbB[w2+8]; + + u32 *lbX; + u32 *lbT = (u32*)((((unsigned long)(&_lbT[0])) + 31) & ~31); + u32 *lbB = (u32*)((((unsigned long)(&_lbB[0])) + 31) & ~31); + + long lineT = -2000; + + for (x=0; x %dx%d (0x%lx, 0x%lx) prot %lx, key %lx\n", + __FUNCTION__, width, height, dst_width, dst_height, hfraq, vfraq, ctx->protect, ctx->key ); + + dst = (void*)((char*) dst + ctx->clip.x1 * 2 + ctx->clip.y1 * dpitch); + + dst32 = (u32*) dst; + + if (head) { + u32 dpT, dpB, L, R; + + u16 *dst16 = (u16*) dst; + + point = point0; + + for (y=0; y= 0 ); + D_ASSERT( pl < width-1 ); + L = SOURCE_LOOKUP(srcT[pl]); + R = SOURCE_LOOKUP(srcT[pl+1]); + + dpT = (((((R & X_F81F)-(L & X_F81F))*ratios[r] + ((L & X_F81F)<> SHIFT_R6; + + L = SOURCE_LOOKUP(srcB[pl]); + R = SOURCE_LOOKUP(srcB[pl+1]); + + dpB = (((((R & X_F81F)-(L & X_F81F))*ratios[r] + ((L & X_F81F)<> SHIFT_R6; + + /* + * Vertical interpolation + */ +#if defined (COLOR_KEY) || defined (KEY_PROTECT) + l_ = ((((((dpB & X_F81F) - (dpT & X_F81F))*X) >> SHIFT_R5) + (dpT & X_F81F)) & X_F81F) + + ((((((dpB>>SHIFT_R5) & X_003F) - ((dpT>>SHIFT_R5) & X_003F))*X) + (dpT & X_07E0)) & X_07E0); +#ifdef COLOR_KEY + if ((l_ & MASK_RGB) != (COLOR_KEY)) +#endif +#ifdef KEY_PROTECT + /* Write to destination with color key protection */ + dst16[0] = ((l_ & MASK_RGB) == KEY_PROTECT) ? l_^1 : l_; +#else + /* Write to destination without color key protection */ + dst16[0] = l_; +#endif +#else + /* Write to destination without color key protection */ + dst16[0] = ((((((dpB & X_F81F) - (dpT & X_F81F))*X) >> SHIFT_R5) + (dpT & X_F81F)) & X_F81F) + + ((((((dpB>>SHIFT_R5) & X_003F) - ((dpT>>SHIFT_R5) & X_003F))*X) + (dpT & X_07E0)) & X_07E0); +#endif + + dst16 += dpitch / 2; + line += vfraq; + } + + /* Adjust */ + point0 += hfraq; + dst32 = (u32*)((char*) dst + 2); + + /* Reset */ + line = LINE_0 + ctx->clip.y1 * vfraq; + } + + /* + * Scale line by line. + */ + for (y=0; y= 0 ); + D_ASSERT( nlT < height-1 ); + + /* + * Fill line buffer(s) ? + */ + if (nlT != lineT) { + u32 L, R, dpT, dpB; + const SOURCE_TYPE *srcT = (const SOURCE_TYPE *)((char*) src + spitch * nlT); + const SOURCE_TYPE *srcB = (const SOURCE_TYPE *)((char*) src + spitch * (nlT + 1)); + long diff = nlT - lineT; + + if (diff > 1) { + /* + * Two output pixels per step. + */ + for (x=0, r=head, point=point0; x= 0 ); + D_ASSERT( pl < width-1 ); + L = SOURCE_LOOKUP(srcT[pl]); + R = SOURCE_LOOKUP(srcT[pl+1]); + + dpT = (((((R & X_F81F)-(L & X_F81F))*ratios[r] + ((L & X_F81F)<> SHIFT_R6; +#endif + + L = SOURCE_LOOKUP(srcB[pl]); + R = SOURCE_LOOKUP(srcB[pl+1]); + + dpB = (((((R & X_F81F)-(L & X_F81F))*ratios[r] + ((L & X_F81F)<> SHIFT_R6; +#endif + + point += hfraq; + r++; + + + pl = POINT_L( point, hfraq ); + HVX_DEBUG("%ld,%ld %lu (%lu/%lu) 0x%x 0x%x\n", x, y, pl, + POINT_L( point, hfraq ), POINT_R( point, hfraq ), point, ratios[r] ); + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + + L = SOURCE_LOOKUP(srcT[pl]); + R = SOURCE_LOOKUP(srcT[pl+1]); + + dpT |= (((((R & X_F81F)-(L & X_F81F))*ratios[r] + ((L & X_F81F)<> SHIFT_R6; +#else + << SHIFT_L10; +#endif + + L = SOURCE_LOOKUP(srcB[pl]); + R = SOURCE_LOOKUP(srcB[pl+1]); + + dpB |= (((((R & X_F81F)-(L & X_F81F))*ratios[r] + ((L & X_F81F)<> SHIFT_R6; +#else + << SHIFT_L10; +#endif + + point += hfraq; + r++; + + /* Store */ + lbT[x] = dpT; + lbB[x] = dpB; + } + } + else { + /* Swap */ + lbX = lbT; + lbT = lbB; + lbB = lbX; + + /* + * Two output pixels per step. + */ + for (x=0, r=head, point=point0; x= 0 ); + D_ASSERT( pl < width-1 ); + L = SOURCE_LOOKUP(srcB[pl]); + R = SOURCE_LOOKUP(srcB[pl+1]); + + dpB = (((((R & X_F81F)-(L & X_F81F))*ratios[r] + ((L & X_F81F)<> SHIFT_R6; +#endif + + point += hfraq; + r++; + + + pl = POINT_L( point, hfraq ); + HVX_DEBUG("%ld,%ld %lu (%lu/%lu) 0x%x 0x%x\n", x, y, pl, + POINT_L( point, hfraq ), POINT_R( point, hfraq ), point, ratios[r] ); + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + + L = SOURCE_LOOKUP(srcB[pl]); + R = SOURCE_LOOKUP(srcB[pl+1]); + + dpB |= (((((R & X_F81F)-(L & X_F81F))*ratios[r] + ((L & X_F81F)<> SHIFT_R6; +#else + << SHIFT_L10; +#endif + + point += hfraq; + r++; + + /* Store */ + lbB[x] = dpB; + } + } + + lineT = nlT; + } + + /* + * Vertical interpolation + */ + X = LINE_TO_RATIO( line, vfraq ); + + for (x=0; x> SHIFT_R5) + (lbT[x] & X_F81FF81F)) & X_F81FF81F) + + ((((((lbB[x]>>SHIFT_R5) & X_F81FF81F) - ((lbT[x]>>SHIFT_R5) & X_F81FF81F))*X) + (lbT[x] & X_07E007E0)) & X_07E007E0); +#else + dt = ((((((lbB[x] & X_07E0F81F) - (lbT[x] & X_07E0F81F))*X) >> SHIFT_R5) + (lbT[x] & X_07E0F81F)) & X_07E0F81F) + + ((((((lbB[x]>>SHIFT_R5) & X_07C0F83F) - ((lbT[x]>>SHIFT_R5) & X_07C0F83F))*X) + (lbT[x] & X_F81F07E0)) & X_F81F07E0); +#endif + + /* Get two new pixels. */ + l_ = dt; + h_ = dt >> 16; + +#ifdef COLOR_KEY + if ((l_ & MASK_RGB) != (COLOR_KEY)) { + if ((h_ & MASK_RGB) != (COLOR_KEY)) { +#ifdef KEY_PROTECT + /* Write to destination with color key protection */ + dst32[x] = ((((h_ & MASK_RGB) == KEY_PROTECT) ? h_^1 : h_) << 16) | (((l_ & MASK_RGB) == KEY_PROTECT) ? l_^1 : l_); +#else + /* Write to destination without color key protection */ + dst32[x] = dt; +#endif + } + else { + u16 *_dst16 = (u16*) &dst32[x]; + +#ifdef KEY_PROTECT + /* Write to destination with color key protection */ + *_dst16 = (((l_ & MASK_RGB) == KEY_PROTECT) ? l_^1 : l_); +#else + /* Write to destination without color key protection */ + *_dst16 = l_; +#endif + } + } + else if ((h_ & MASK_RGB) != (COLOR_KEY)) { + u16 *_dst16 = ((u16*) &dst32[x]) + 1; + +#ifdef KEY_PROTECT + /* Write to destination with color key protection */ + *_dst16 = (((h_ & MASK_RGB) == KEY_PROTECT) ? h_^1 : h_); +#else + /* Write to destination without color key protection */ + *_dst16 = h_; +#endif + } +#else + /* Write to destination with color key protection */ + dst32[x] = ((((h_ & MASK_RGB) == KEY_PROTECT) ? h_^1 : h_) << 16) | (((l_ & MASK_RGB) == KEY_PROTECT) ? l_^1 : l_); +#endif +#else +#ifdef HAS_ALPHA + dst32[x] = ((((((lbB[x] & X_F81FF81F) - (lbT[x] & X_F81FF81F))*X) >> SHIFT_R5) + (lbT[x] & X_F81FF81F)) & X_F81FF81F) + + ((((((lbB[x]>>SHIFT_R5) & X_F81FF81F) - ((lbT[x]>>SHIFT_R5) & X_F81FF81F))*X) + (lbT[x] & X_07E007E0)) & X_07E007E0); +#else + dst32[x] = ((((((lbB[x] & X_07E0F81F) - (lbT[x] & X_07E0F81F))*X) >> SHIFT_R5) + (lbT[x] & X_07E0F81F)) & X_07E0F81F) + + ((((((lbB[x]>>SHIFT_R5) & X_07C0F83F) - ((lbT[x]>>SHIFT_R5) & X_07C0F83F))*X) + (lbT[x] & X_F81F07E0)) & X_F81F07E0); +#endif +#endif + } + + dst32 += dp4; + line += vfraq; + } + + if (tail) { + u32 dpT, dpB, L, R; + + u16 *dst16 = (u16*)((char*) dst + cw * 2 - 2); + + /* Reset */ + line = LINE_0 + ctx->clip.y1 * vfraq; + + for (y=0; y= 0 ); + D_ASSERT( pl < width-1 ); + L = SOURCE_LOOKUP(srcT[pl]); + R = SOURCE_LOOKUP(srcT[pl+1]); + + dpT = (((((R & X_F81F)-(L & X_F81F))*ratios[r] + ((L & X_F81F)<> SHIFT_R6; + + L = SOURCE_LOOKUP(srcB[pl]); + R = SOURCE_LOOKUP(srcB[pl+1]); + + dpB = (((((R & X_F81F)-(L & X_F81F))*ratios[r] + ((L & X_F81F)<> SHIFT_R6; + + /* + * Vertical interpolation + */ +#if defined (COLOR_KEY) || defined (KEY_PROTECT) + l_ = ((((((dpB & X_F81F) - (dpT & X_F81F))*X) >> SHIFT_R5) + (dpT & X_F81F)) & X_F81F) + + ((((((dpB>>SHIFT_R5) & X_003F) - ((dpT>>SHIFT_R5) & X_003F))*X) + (dpT & X_07E0)) & X_07E0); + +#ifdef COLOR_KEY + if ((l_ & MASK_RGB) != (COLOR_KEY)) +#endif +#ifdef KEY_PROTECT + /* Write to destination with color key protection */ + dst16[0] = ((l_ & MASK_RGB) == KEY_PROTECT) ? l_^1 : l_; +#else + /* Write to destination without color key protection */ + dst16[0] = l_; +#endif +#else + /* Write to destination without color key protection */ + dst16[0] = ((((((dpB & X_F81F) - (dpT & X_F81F))*X) >> SHIFT_R5) + (dpT & X_F81F)) & X_F81F) + + ((((((dpB>>SHIFT_R5) & X_003F) - ((dpT>>SHIFT_R5) & X_003F))*X) + (dpT & X_07E0)) & X_07E0); +#endif + + dst16 += dpitch / 2; + line += vfraq; + } + } +} + + +#undef SHIFT_L6 +#undef SHIFT_L10 + +#undef X_003F + +#undef X_003E07C0 +#undef X_0001F800 + +#undef X_07E0F81F +#undef X_F81F07E0 + +#undef X_07C0F83F + + + +#ifdef SOURCE_LOOKUP_AUTO +#undef SOURCE_LOOKUP_AUTO +#undef SOURCE_LOOKUP +#endif + +#ifdef SOURCE_TYPE_AUTO +#undef SOURCE_TYPE_AUTO +#undef SOURCE_TYPE +#endif + diff --git a/src/stretch_hvx_32.h b/src/stretch_hvx_32.h new file mode 100644 index 0000000..7a86403 --- /dev/null +++ b/src/stretch_hvx_32.h @@ -0,0 +1,168 @@ +#ifndef SOURCE_LOOKUP +#define SOURCE_LOOKUP(x) (x) +#define SOURCE_LOOKUP_AUTO +#endif + +#ifndef SOURCE_TYPE +#define SOURCE_TYPE u32 +#define SOURCE_TYPE_AUTO +#endif + +/* stretch_hvx_up/down_32_KPI */( void *dst, + int dpitch, + const void *src, + int spitch, + int width, + int height, + int dst_width, + int dst_height, + const StretchCtx *ctx ) +{ + long x, y = 0; + long cw = ctx->clip.x2 - ctx->clip.x1 + 1; + long ch = ctx->clip.y2 - ctx->clip.y1 + 1; + long hfraq = ((long)(width - MINUS_1) << 18) / (long)(dst_width); + long vfraq = ((long)(height - MINUS_1) << 18) / (long)(dst_height); + long dp4 = dpitch / 4; + long point0 = POINT_0 + ctx->clip.x1 * hfraq; + long point = point0; + long line = LINE_0 + ctx->clip.y1 * vfraq; + long ratios[cw]; + u32 *dst32; + +#if defined (COLOR_KEY) || defined (KEY_PROTECT) + u32 dt; +#endif + + u32 _lbT[cw+8]; + u32 _lbB[cw+8]; + + u32 *lbX; + u32 *lbT = (u32*)((((unsigned long)(&_lbT[0])) + 31) & ~31); + u32 *lbB = (u32*)((((unsigned long)(&_lbB[0])) + 31) & ~31); + + long lineT = -2000; + + for (x=0; x %dx%d (0x%x, 0x%x)\n", width, height, dst_width, dst_height, hfraq, vfraq ); + + dst = (void*)((char*) dst + ctx->clip.x1 * 4 + ctx->clip.y1 * dpitch); + + dst32 = (u32*) dst; + + /* + * Scale line by line. + */ + for (y=0; y= 0 ); + D_ASSERT( nlT < height-1 ); + + /* + * Fill line buffer(s) ? + */ + if (nlT != lineT) { + u32 L, R; + const SOURCE_TYPE *srcT = (const SOURCE_TYPE *)((const char*) src + spitch * nlT); + const SOURCE_TYPE *srcB = (const SOURCE_TYPE *)((const char*) src + spitch * (nlT + 1)); + long diff = nlT - lineT; + + if (diff > 1) { + /* + * Horizontal interpolation + */ + for (x=0, point=point0; x= 0 ); + D_ASSERT( pl < width-1 ); + + L = SOURCE_LOOKUP(srcT[pl]); + R = SOURCE_LOOKUP(srcT[pl+1]); + + lbT[x]= ((((((R & X_00FF00FF) - (L & X_00FF00FF))*ratios[x]) >> SHIFT_R8) + (L & X_00FF00FF)) & X_00FF00FF) + + ((((((R>>SHIFT_R8) & X_00FF00FF) - ((L>>SHIFT_R8) & X_00FF00FF))*ratios[x]) + (L & X_FF00FF00)) & X_FF00FF00); + + L = SOURCE_LOOKUP(srcB[pl]); + R = SOURCE_LOOKUP(srcB[pl+1]); + + lbB[x] = ((((((R & X_00FF00FF) - (L & X_00FF00FF))*ratios[x]) >> SHIFT_R8) + (L & X_00FF00FF)) & X_00FF00FF) + + ((((((R>>SHIFT_R8) & X_00FF00FF) - ((L>>SHIFT_R8) & X_00FF00FF))*ratios[x]) + (L & X_FF00FF00)) & X_FF00FF00); + } + } + else { + /* Swap */ + lbX = lbT; + lbT = lbB; + lbB = lbX; + + /* + * Horizontal interpolation + */ + for (x=0, point=point0; x= 0 ); + D_ASSERT( pl < width-1 ); + + L = SOURCE_LOOKUP(srcB[pl]); + R = SOURCE_LOOKUP(srcB[pl+1]); + + lbB[x] = ((((((R & X_00FF00FF) - (L & X_00FF00FF))*ratios[x]) >> SHIFT_R8) + (L & X_00FF00FF)) & X_00FF00FF) + + ((((((R>>SHIFT_R8) & X_00FF00FF) - ((L>>SHIFT_R8) & X_00FF00FF))*ratios[x]) + (L & X_FF00FF00)) & X_FF00FF00); + } + } + + lineT = nlT; + } + + /* + * Vertical interpolation + */ + X = LINE_TO_RATIO( line, vfraq ); + + for (x=0; x> SHIFT_R8) + (lbT[x] & X_00FF00FF)) & X_00FF00FF) + + ((((((lbB[x]>>SHIFT_R8) & X_00FF00FF) - ((lbT[x]>>SHIFT_R8) & X_00FF00FF))*X) + (lbT[x] & X_FF00FF00)) & X_FF00FF00); +#ifdef COLOR_KEY + if (dt != (COLOR_KEY)) +#endif +#ifdef KEY_PROTECT + /* Write to destination with color key protection */ + dst32[x] = ((dt & MASK_RGB) == KEY_PROTECT) ? dt^1 : dt; +#else + /* Write to destination without color key protection */ + dst32[x] = dt; +#endif +#else + /* Write to destination without color key protection */ + dst32[x] = ((((((lbB[x] & X_00FF00FF) - (lbT[x] & X_00FF00FF))*X) >> SHIFT_R8) + (lbT[x] & X_00FF00FF)) & X_00FF00FF) + + ((((((lbB[x]>>SHIFT_R8) & X_00FF00FF) - ((lbT[x]>>SHIFT_R8) & X_00FF00FF))*X) + (lbT[x] & X_FF00FF00)) & X_FF00FF00); +#endif + } + + dst32 += dp4; + line += vfraq; + } +} + +#ifdef SOURCE_LOOKUP_AUTO +#undef SOURCE_LOOKUP_AUTO +#undef SOURCE_LOOKUP +#endif + +#ifdef SOURCE_TYPE_AUTO +#undef SOURCE_TYPE_AUTO +#undef SOURCE_TYPE +#endif + diff --git a/src/stretch_hvx_N.h b/src/stretch_hvx_N.h new file mode 100644 index 0000000..168f4e0 --- /dev/null +++ b/src/stretch_hvx_N.h @@ -0,0 +1,42 @@ +#if UPDOWN == 1 +#define FUNC_NAME_(K,P,F) FUNC_NAME(up,K,P,F) +#else +#define FUNC_NAME_(K,P,F) FUNC_NAME(down,K,P,F) +#endif + + +/* NONE */ +static void FUNC_NAME_(_,_,DST_FORMAT) +#include STRETCH_HVX_N_H + + +/* FIXME: DST_FORMAT == DSPF_RGB16 doesn't work */ +#ifdef FORMAT_RGB16 +/* RGB16 <- RGB32 */ +#define SOURCE_TYPE u32 +#define SOURCE_LOOKUP(x) PIXEL_RGB16( ((x) & 0xff0000) >> 16, \ + ((x) & 0x00ff00) >> 8, \ + ((x) & 0x0000ff) ) +static void FUNC_NAME_(_,_,DSPF_RGB32) +#include STRETCH_HVX_N_H + +#undef SOURCE_LOOKUP +#undef SOURCE_TYPE +#endif + + +/* FIXME: DST_FORMAT == DSPF_ARGB doesn't work */ +#ifdef FORMAT_ARGB +/* ARGB <- RGB32 */ +#define SOURCE_TYPE u32 +#define SOURCE_LOOKUP(x) ((x) | 0xff000000) +static void FUNC_NAME_(_,_,DSPF_RGB32) +#include STRETCH_HVX_N_H + +#undef SOURCE_LOOKUP +#undef SOURCE_TYPE +#endif + + +#undef FUNC_NAME_ + diff --git a/src/stretch_up_down_16.h b/src/stretch_up_down_16.h new file mode 100644 index 0000000..103dfc3 --- /dev/null +++ b/src/stretch_up_down_16.h @@ -0,0 +1,68 @@ +#define STRETCH_HVX_N_H "stretch_hvx_16.h" +#define uN u16 + +/**********************************************************************************************************************/ +/* Upscaling */ + +#define POINT_0 0 +#define LINE_0 0 +#define MINUS_1 1 +#define POINT_TO_RATIO(p,ps) ( ((p) & 0x3ffff) >> (18-SHIFT_L6) ) +#define LINE_TO_RATIO(l,ls) ( ((l) & 0x3ffff) >> (18-SHIFT_L5) ) + +#define POINT_L(p,ps) ( (((p)) >> 18) ) +#define POINT_R(p,ps) ( (((p)) >> 18) + 1 ) + +#define LINE_T(l,ls) ( (((l)) >> 18) ) +#define LINE_B(l,ls) ( (((l)) >> 18) + 1 ) + +#define UPDOWN 1 +#include "stretch_hvx_N.h" +#undef UPDOWN + +#undef POINT_0 +#undef LINE_0 +#undef MINUS_1 +#undef POINT_TO_RATIO +#undef LINE_TO_RATIO +#undef POINT_L +#undef POINT_R +#undef LINE_T +#undef LINE_B + +/**********************************************************************************************************************/ +/* Downscaling */ + +#define POINT_0 hfraq +#define LINE_0 vfraq +#define MINUS_1 0 +#define POINT_TO_RATIO(p,ps) ( (((((p)) & 0x3ffff) ? : 0x40000) << SHIFT_L6) / (ps) ) +#define LINE_TO_RATIO(l,ls) ( (((((l)) & 0x3ffff) ? : 0x40000) << SHIFT_L5) / (ls) ) + +#define POINT_L(p,ps) ( (((p)-1) >> 18) - 1 ) +#define POINT_R(p,ps) ( (((p)-1) >> 18) ) + +#define LINE_T(l,ls) ( (((l)-1) >> 18) - 1 ) +#define LINE_B(l,ls) ( (((l)-1) >> 18) ) + +#define UPDOWN 0 +#include "stretch_hvx_N.h" +#undef UPDOWN + +#undef POINT_0 +#undef LINE_0 +#undef MINUS_1 +#undef POINT_TO_RATIO +#undef LINE_TO_RATIO +#undef POINT_L +#undef POINT_R +#undef LINE_T +#undef LINE_B + +/**********************************************************************************************************************/ + +#undef STRETCH_HVX_N_H +#undef uN + +//#include "stretch_up_down_table.h" + diff --git a/src/stretch_up_down_32.h b/src/stretch_up_down_32.h new file mode 100644 index 0000000..7f2aacc --- /dev/null +++ b/src/stretch_up_down_32.h @@ -0,0 +1,68 @@ +#define STRETCH_HVX_N_H "stretch_hvx_32.h" +#define uN u32 + +/**********************************************************************************************************************/ +/* Upscaling */ + +#define POINT_0 0 +#define LINE_0 0 +#define MINUS_1 1 +#define POINT_TO_RATIO(p,ps) ( ((p) & 0x3ffff) >> (18-SHIFT_L8) ) +#define LINE_TO_RATIO(l,ls) ( ((l) & 0x3ffff) >> (18-SHIFT_L8) ) + +#define POINT_L(p,ps) ( (((p)) >> 18) ) +#define POINT_R(p,ps) ( (((p)) >> 18) + 1 ) + +#define LINE_T(l,ls) ( (((l)) >> 18) ) +#define LINE_B(l,ls) ( (((l)) >> 18) + 1 ) + +#define UPDOWN 1 +#include "stretch_hvx_N.h" +#undef UPDOWN + +#undef POINT_0 +#undef LINE_0 +#undef MINUS_1 +#undef POINT_TO_RATIO +#undef LINE_TO_RATIO +#undef POINT_L +#undef POINT_R +#undef LINE_T +#undef LINE_B + +/**********************************************************************************************************************/ +/* Downscaling */ + +#define POINT_0 hfraq +#define LINE_0 vfraq +#define MINUS_1 0 +#define POINT_TO_RATIO(p,ps) ( (((((p)) & 0x3ffff) ? : 0x40000) << SHIFT_L8) / (ps) ) +#define LINE_TO_RATIO(l,ls) ( (((((l)) & 0x3ffff) ? : 0x40000) << SHIFT_L8) / (ls) ) + +#define POINT_L(p,ps) ( (((p)-1) >> 18) - 1 ) +#define POINT_R(p,ps) ( (((p)-1) >> 18) ) + +#define LINE_T(l,ls) ( (((l)-1) >> 18) - 1 ) +#define LINE_B(l,ls) ( (((l)-1) >> 18) ) + +#define UPDOWN 0 +#include "stretch_hvx_N.h" +#undef UPDOWN + +#undef POINT_0 +#undef LINE_0 +#undef MINUS_1 +#undef POINT_TO_RATIO +#undef LINE_TO_RATIO +#undef POINT_L +#undef POINT_R +#undef LINE_T +#undef LINE_B + +/**********************************************************************************************************************/ + +#undef STRETCH_HVX_N_H +#undef uN + +//#include "stretch_up_down_table.h" + diff --git a/src/stretch_up_down_table.h b/src/stretch_up_down_table.h new file mode 100644 index 0000000..32f208b --- /dev/null +++ b/src/stretch_up_down_table.h @@ -0,0 +1,59 @@ +/**********************************************************************************************************************/ +/* Function table */ + +static const StretchFunctionTable TABLE_NAME = { +#define FUNC_NAME_(K,P,F) FUNC_NAME(up,K,P,F) + .f[DFB_PIXELFORMAT_INDEX(DST_FORMAT)].up[STRETCH_NONE] = FUNC_NAME_(_,_,DST_FORMAT), + .f[DFB_PIXELFORMAT_INDEX(DST_FORMAT)].up[STRETCH_PROTECT] = FUNC_NAME_(_,P,DST_FORMAT), + .f[DFB_PIXELFORMAT_INDEX(DST_FORMAT)].up[STRETCH_SRCKEY] = FUNC_NAME_(K,_,DST_FORMAT), + .f[DFB_PIXELFORMAT_INDEX(DST_FORMAT)].up[STRETCH_SRCKEY_PROTECT] = FUNC_NAME_(K,P,DST_FORMAT), + .f[DFB_PIXELFORMAT_INDEX(DSPF_LUT8)].up[STRETCH_NONE] = FUNC_NAME_(_,_,DSPF_LUT8), + .f[DFB_PIXELFORMAT_INDEX(DSPF_LUT8)].up[STRETCH_PROTECT] = FUNC_NAME_(_,P,DSPF_LUT8), + .f[DFB_PIXELFORMAT_INDEX(DSPF_LUT8)].up[STRETCH_SRCKEY] = FUNC_NAME_(K,_,DSPF_LUT8), + .f[DFB_PIXELFORMAT_INDEX(DSPF_LUT8)].up[STRETCH_SRCKEY_PROTECT] = FUNC_NAME_(K,P,DSPF_LUT8), +#undef FUNC_NAME_ + +#define FUNC_NAME_(K,P,F) FUNC_NAME(down,K,P,F) + .f[DFB_PIXELFORMAT_INDEX(DST_FORMAT)].down[STRETCH_NONE] = FUNC_NAME_(_,_,DST_FORMAT), + .f[DFB_PIXELFORMAT_INDEX(DST_FORMAT)].down[STRETCH_PROTECT] = FUNC_NAME_(_,P,DST_FORMAT), + .f[DFB_PIXELFORMAT_INDEX(DST_FORMAT)].down[STRETCH_SRCKEY] = FUNC_NAME_(K,_,DST_FORMAT), + .f[DFB_PIXELFORMAT_INDEX(DST_FORMAT)].down[STRETCH_SRCKEY_PROTECT] = FUNC_NAME_(K,P,DST_FORMAT), + .f[DFB_PIXELFORMAT_INDEX(DSPF_LUT8)].down[STRETCH_NONE] = FUNC_NAME_(_,_,DSPF_LUT8), + .f[DFB_PIXELFORMAT_INDEX(DSPF_LUT8)].down[STRETCH_PROTECT] = FUNC_NAME_(_,P,DSPF_LUT8), + .f[DFB_PIXELFORMAT_INDEX(DSPF_LUT8)].down[STRETCH_SRCKEY] = FUNC_NAME_(K,_,DSPF_LUT8), + .f[DFB_PIXELFORMAT_INDEX(DSPF_LUT8)].down[STRETCH_SRCKEY_PROTECT] = FUNC_NAME_(K,P,DSPF_LUT8), +#undef FUNC_NAME_ + +/* FIXME: DST_FORMAT == DSPF_RGB16 doesn't work */ +#ifdef FORMAT_RGB16 +#define FUNC_NAME_(K,P,F) FUNC_NAME(up,K,P,F) + .f[DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)].up[STRETCH_NONE] = FUNC_NAME_(_,_,DSPF_ARGB4444), + .f[DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)].up[STRETCH_PROTECT] = FUNC_NAME_(_,P,DSPF_ARGB4444), + .f[DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)].up[STRETCH_SRCKEY] = FUNC_NAME_(K,_,DSPF_ARGB4444), + .f[DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)].up[STRETCH_SRCKEY_PROTECT] = FUNC_NAME_(K,P,DSPF_ARGB4444), +#undef FUNC_NAME_ +#define FUNC_NAME_(K,P,F) FUNC_NAME(down,K,P,F) + .f[DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)].down[STRETCH_NONE] = FUNC_NAME_(_,_,DSPF_ARGB4444), + .f[DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)].down[STRETCH_PROTECT] = FUNC_NAME_(_,P,DSPF_ARGB4444), + .f[DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)].down[STRETCH_SRCKEY] = FUNC_NAME_(K,_,DSPF_ARGB4444), + .f[DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)].down[STRETCH_SRCKEY_PROTECT] = FUNC_NAME_(K,P,DSPF_ARGB4444), +#undef FUNC_NAME_ +#endif + +/* FIXME: DST_FORMAT == DSPF_ARGB4444 doesn't work */ +#ifdef FORMAT_ARGB4444 +#define FUNC_NAME_(K,P,F) FUNC_NAME(up,K,P,F) + .f[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)].up[STRETCH_NONE] = FUNC_NAME_(_,_,DSPF_RGB16), + .f[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)].up[STRETCH_PROTECT] = FUNC_NAME_(_,P,DSPF_RGB16), + .f[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)].up[STRETCH_SRCKEY] = FUNC_NAME_(K,_,DSPF_RGB16), + .f[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)].up[STRETCH_SRCKEY_PROTECT] = FUNC_NAME_(K,P,DSPF_RGB16), +#undef FUNC_NAME_ +#define FUNC_NAME_(K,P,F) FUNC_NAME(down,K,P,F) + .f[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)].down[STRETCH_NONE] = FUNC_NAME_(_,_,DSPF_RGB16), + .f[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)].down[STRETCH_PROTECT] = FUNC_NAME_(_,P,DSPF_RGB16), + .f[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)].down[STRETCH_SRCKEY] = FUNC_NAME_(K,_,DSPF_RGB16), + .f[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)].down[STRETCH_SRCKEY_PROTECT] = FUNC_NAME_(K,P,DSPF_RGB16), +#undef FUNC_NAME_ +#endif +}; + diff --git a/src/videodriver.cpp b/src/videodriver.cpp new file mode 100644 index 0000000..644fa9e --- /dev/null +++ b/src/videodriver.cpp @@ -0,0 +1,905 @@ +#define VC_EXTRALEAN + +#include +#include +#include +#include +//#include +#include +#include +//#include +#include +#include + +extern "C" { +#include +} + +#include "Exception.h" + +#include "videodriver.h" + +//#include +static const char* driverName = "mv video hook driver2"; + +#define MAP1 1030 +#define UNMAP1 1031 +#define CURSOREN 1060 +#define CURSORDIS 1061 + +#define _T(x) (x) + +VIDEODRIVER::VIDEODRIVER() +{ + mypVideoMemory=NULL; + mypchangebuf=NULL; + myframebuffer=NULL; + shared_buffer_size=0; +} + +void +VIDEODRIVER::VIDEODRIVER_start(int x,int y,int w,int h) +{ + blocked=true; + oldaantal=1; + mypVideoMemory=NULL; + OSVER=OSVersion(); + if (OSVER==OSWIN2000||OSVER==OSWIN2003||OSVER==OSWINXP||OSVER==OSWINXP64) { + if (Mirror_driver_attach_XP(x,y,w,h)) { + if (GetDcMirror()!=NULL) { + mypVideoMemory=VideoMemory_GetSharedMemory(); + mypchangebuf=(PCHANGES_BUF)mypVideoMemory; + myframebuffer=mypVideoMemory+sizeof(CHANGES_BUF); + } + else { + mypVideoMemory=NULL; + } + } + else { + mypVideoMemory=NULL; + } + } + if (OSVER==OSVISTA) { + if (Mirror_driver_Vista(1,x,y,w,h)) { + if (GetDcMirror()!=NULL) { + mypVideoMemory=VideoMemory_GetSharedMemory(); + mypchangebuf=(PCHANGES_BUF)mypVideoMemory; + myframebuffer=mypVideoMemory+sizeof(CHANGES_BUF); + //if (mypVideoMemory==NULL) MessageBox(NULL,"MVideo driver failed", NULL, MB_OK); + } + else { + // MessageBox(NULL,"Video driver failed", NULL, MB_OK); +//////////////////////////////////////////////////////////////////////////////// + if (Mirror_driver_attach_XP(x,y,w,h)) { + if (GetDcMirror()!=NULL) { + mypVideoMemory=VideoMemory_GetSharedMemory(); + mypchangebuf=(PCHANGES_BUF)mypVideoMemory; + myframebuffer=mypVideoMemory+sizeof(CHANGES_BUF); + } + else { + mypVideoMemory=NULL; + } + } + else { + mypVideoMemory=NULL; + } +//////////////////////////////////////////////////////////////////////////////// + //mypVideoMemory=NULL; + } + } + else { + mypVideoMemory=NULL; + } + } + blocked=false; +} + +void +VIDEODRIVER::VIDEODRIVER_Stop() +{ + OSVER=OSVersion(); + if (OSVER==OSWIN2000||OSVER==OSWIN2003||OSVER==OSWINXP||OSVER==OSWINXP64) { + Mirror_driver_detach_XP(); + if (mypVideoMemory!=NULL) VideoMemory_ReleaseSharedMemory(mypVideoMemory); + } + if (OSVER==OSVISTA) { + Mirror_driver_Vista(0,0,0,0,0); + if (mypVideoMemory!=NULL) VideoMemory_ReleaseSharedMemory(mypVideoMemory); + } + mypVideoMemory=NULL; + mypchangebuf=NULL; + myframebuffer=NULL; + + +} + + +VIDEODRIVER::~VIDEODRIVER() +{ + //mypVideoMemory=NULL; + OSVER=OSVersion(); + if (OSVER==OSWIN2000||OSVER==OSWIN2003||OSVER==OSWINXP||OSVER==OSWINXP64) { + Mirror_driver_detach_XP(); + if (mypVideoMemory!=NULL) VideoMemory_ReleaseSharedMemory(mypVideoMemory); + } + if (OSVER==OSVISTA) { + Mirror_driver_Vista(0,0,0,0,0); + if (mypVideoMemory!=NULL) VideoMemory_ReleaseSharedMemory(mypVideoMemory); + } + +} + +void VIDEODRIVER::VideoMemory_ReleaseSharedMemory(PCHAR pVideoMemory) +{ + UnmapViewOfFile(pVideoMemory); +} + +PCHAR VIDEODRIVER::VideoMemory_GetSharedMemory(void) +{ + PCHAR pVideoMemory=NULL; + HANDLE hMapFile, hFile, hFile0,hFile1; + hFile=NULL; + + hFile0 = CreateFile("c:\\video0.dat", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + hFile1 = CreateFile("c:\\video1.dat", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if ((hFile0 && hFile0 != INVALID_HANDLE_VALUE) && !(hFile1 && hFile1 != INVALID_HANDLE_VALUE)) hFile=hFile0; + if ((hFile1 && hFile1 != INVALID_HANDLE_VALUE) && !(hFile0 && hFile0 != INVALID_HANDLE_VALUE)) hFile=hFile1; + if ((hFile0 && hFile0 != INVALID_HANDLE_VALUE) && (hFile1 && hFile1 != INVALID_HANDLE_VALUE)) { + DWORD size0=GetFileSize(hFile0,NULL); + DWORD size1=GetFileSize(hFile1,NULL); + if (size0==shared_buffer_size) hFile=hFile0; + if (size1==shared_buffer_size) hFile=hFile1; + if (size1==shared_buffer_size && size0==shared_buffer_size) { + //find last modification time + FILETIME createt0, lastWriteTime0, lastAccessTime0; + GetFileTime( hFile0, &createt0, &lastAccessTime0, &lastWriteTime0); + FILETIME createt1, lastWriteTime1, lastAccessTime1; + GetFileTime( hFile0, &createt1, &lastAccessTime1, &lastWriteTime1); + LONG result=CompareFileTime(&lastWriteTime0,&lastWriteTime1); + if (result==0 || result== 1) hFile=hFile0; + else hFile=hFile1; + + } + + } + + + if (hFile && hFile != INVALID_HANDLE_VALUE) { + hMapFile = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL); + + if (hMapFile && hMapFile != INVALID_HANDLE_VALUE) { + pVideoMemory = (char *) MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0); + + CloseHandle(hMapFile); + } + + CloseHandle(hFile); + } + else { + throw new PluggIt::Exception( "Error video.dat \n" ); + } + + return pVideoMemory; +} + +bool +VIDEODRIVER::Mirror_driver_Vista(DWORD dwAttach,int x,int y,int w,int h) +{ + HDESK hdeskInput; + HDESK hdeskCurrent; + pEnumDisplayDevices pd; + HMODULE hUser32=LoadLibrary("USER32"); + pd = (pEnumDisplayDevices)GetProcAddress( hUser32, "EnumDisplayDevicesA"); + + BOOL bED = TRUE; + DEVMODE devmode; + + FillMemory(&devmode, sizeof(DEVMODE), 0); + devmode.dmSize = sizeof(DEVMODE); + devmode.dmDriverExtra = 0; + + // Make sure we have a display on this thread. + BOOL change = EnumDisplaySettings(NULL, + ENUM_CURRENT_SETTINGS, + &devmode); + + devmode.dmFields = DM_BITSPERPEL | + DM_PELSWIDTH | + DM_PELSHEIGHT | + DM_POSITION ; + + if (change) { + // query all display devices in the system until we hit a primary + // display device. Using it get the width and height of the primary + // so we can use that for the mirror driver. Also enumerate the + // display devices installed on this machine untill we hit + // our favourate mirrored driver, then extract the device name string + // of the format '\\.\DISPLAY#' +// MessageBox(NULL, "change ok", NULL, MB_OK); + + DISPLAY_DEVICE dispDevice; + + FillMemory(&dispDevice, sizeof(DISPLAY_DEVICE), 0); + + dispDevice.cb = sizeof(DISPLAY_DEVICE); + + LPSTR deviceName = NULL; + + devmode.dmDeviceName[0] = '\0'; + + INT devNum = 0; + BOOL result; + DWORD cxPrimary = 0xFFFFFFFF; + DWORD cyPrimary = 0xFFFFFFFF; + + // First enumerate for Primary display device: + while (result = (*pd)(NULL, + devNum, + &dispDevice, + 0)) { +// MessageBox(NULL, &dispDevice.DeviceString[0], NULL, MB_OK); + if (dispDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) { + // Primary device. Find out its dmPelsWidht and dmPelsHeight. + EnumDisplaySettings(dispDevice.DeviceName, + ENUM_CURRENT_SETTINGS, + &devmode); + + cxPrimary = devmode.dmPelsWidth; + cyPrimary = devmode.dmPelsHeight; + break; + } + devNum++; + } +#if defined(MIRROR_24) + if (devmode.dmBitsPerPel == 24) + devmode.dmBitsPerPel = 32; +#endif + if (devmode.dmBitsPerPel!=8 && devmode.dmBitsPerPel!=16 && devmode.dmBitsPerPel!=32) { + if (hUser32) FreeLibrary(hUser32); + return false; + } + shared_buffer_size=devmode.dmBitsPerPel/8*w*h+sizeof(CHANGES_BUF); + + // error check + if (!result) { +// MessageBox(NULL, driverName, NULL, MB_OK); + if (hUser32) FreeLibrary(hUser32); + return false; + } + + if (cxPrimary == 0xffffffff || cyPrimary == 0xffffffff) { +// MessageBox(NULL,"cxPrimary or cyPrimary not valid", NULL, MB_OK); + if (hUser32) FreeLibrary(hUser32); + return false; + } + + // Enumerate again for the mirror driver: + devNum = 0; + while (result = (*pd)(NULL, + devNum, + &dispDevice, + 0)) { + if (strcmp(&dispDevice.DeviceString[0], driverName) == 0) + break; + + devNum++; + } + + // error check + if (!result) { +// MessageBox(NULL,driverName, NULL, MB_OK); + if (hUser32) FreeLibrary(hUser32); + return false; + } + +// printf("DevNum:%d\nName:%s\nString:%s\nID:%s\nKey:%s\n\n", +// devNum, +// &dispDevice.DeviceName[0], +// &dispDevice.DeviceString[0], +// &dispDevice.DeviceID[0], +// &dispDevice.DeviceKey[0]); + + CHAR deviceNum[MAX_PATH]; + LPSTR deviceSub; + + // Simply extract 'DEVICE#' from registry key. This will depend + // on how many mirrored devices your driver has and which ones + // you intend to use. + + strupr(&dispDevice.DeviceKey[0]); + + deviceSub = strstr(&dispDevice.DeviceKey[0], + "\\DEVICE"); + + if (!deviceSub) + direct_snputs(&deviceNum[0], "DEVICE0", sizeof(deviceNum)); + else + direct_snputs(&deviceNum[0], ++deviceSub, sizeof(deviceNum)); + + // Reset the devmode for mirror driver use: + int depth=devmode.dmBitsPerPel; + FillMemory(&devmode, sizeof(DEVMODE), 0); + devmode.dmSize = sizeof(DEVMODE); + devmode.dmDriverExtra = 0; + devmode.dmBitsPerPel=depth; + + devmode.dmFields = DM_BITSPERPEL | + DM_PELSWIDTH | + DM_PELSHEIGHT | + DM_POSITION; + + direct_snputs((LPSTR)&devmode.dmDeviceName[0], "mv2", sizeof(devmode.dmDeviceName)); + deviceName = (LPSTR)&dispDevice.DeviceName[0]; + + if (bED) { + // Attach and detach information is sent via the dmPelsWidth/Height + // of the devmode. + // +// MessageBox(NULL,"bED", NULL, MB_OK); + if (dwAttach == 0) { + devmode.dmPelsWidth = 0; + devmode.dmPelsHeight = 0; + } + else { + devmode.dmPelsWidth=w; + devmode.dmPelsHeight=h; + devmode.dmPosition.x=x; + devmode.dmPosition.y=y; + } + // Update the mirror device's registry data with the devmode. Dont + // do a mode change. + +///////////////////////// + hdeskCurrent = GetThreadDesktop(GetCurrentThreadId()); + if (hdeskCurrent != NULL) { + hdeskInput = OpenInputDesktop(0, FALSE, MAXIMUM_ALLOWED); + if (hdeskInput != NULL) { + SetThreadDesktop(hdeskInput); + } + } + + + INT code = + ChangeDisplaySettingsEx(deviceName, + &devmode, + NULL, + (CDS_UPDATEREGISTRY | CDS_RESET|CDS_GLOBAL), + NULL + ); +// GetDispCode(code); + if (code!=0) { + if (hUser32) FreeLibrary(hUser32); + return false; + } + // Now do the real mode change to take mirror driver changes into + // effect. + code = ChangeDisplaySettingsEx(NULL, + NULL, + NULL, + 0, + NULL); + + SetThreadDesktop(hdeskCurrent); + CloseDesktop(hdeskInput); + + if (code!=0) { + if (hUser32) FreeLibrary(hUser32); + return false; + } + if (hUser32) FreeLibrary(hUser32); + return true; + } + if (hUser32) FreeLibrary(hUser32); + return false; + } + if (hUser32) FreeLibrary(hUser32); + return false; +} + + + +void +VIDEODRIVER::Mirror_driver_detach_XP() +{ + HDESK hdeskInput; + HDESK hdeskCurrent; + pEnumDisplayDevices pd; + HMODULE hUser32=LoadLibrary("USER32"); + pd = (pEnumDisplayDevices)GetProcAddress( hUser32, "EnumDisplayDevicesA"); + + DEVMODE devmode; + + FillMemory(&devmode, sizeof(DEVMODE), 0); + + devmode.dmSize = sizeof(DEVMODE); + devmode.dmDriverExtra = 0; + + BOOL change = EnumDisplaySettings(NULL, + ENUM_CURRENT_SETTINGS, + &devmode); + + devmode.dmFields = DM_BITSPERPEL | + DM_PELSWIDTH | + DM_PELSHEIGHT; + + if (change) { + // query all display devices in the system until we hit + // our favourate mirrored driver, then extract the device name string + // of the format '\\.\DISPLAY#' + + DISPLAY_DEVICE dispDevice; + + FillMemory(&dispDevice, sizeof(DISPLAY_DEVICE), 0); + + dispDevice.cb = sizeof(DISPLAY_DEVICE); + + LPSTR deviceName = NULL; + + devmode.dmDeviceName[0] = '\0'; + + INT devNum = 0; + BOOL result; + + while (result = (*pd)(NULL, + devNum, + &dispDevice, + 0)) { + printf("Driver '%s' found.\n", &dispDevice.DeviceString[0]); + if (strcmp(&dispDevice.DeviceString[0], driverName) == 0) + break; + + devNum++; + } + + if (!result) { + printf("No '%s' found.\n", driverName); + if (hUser32) FreeLibrary(hUser32); + return; + } + + printf("DevNum:%d\nName:%s\nString:%s\nID:%s\nKey:%s\n\n", + devNum, + &dispDevice.DeviceName[0], + &dispDevice.DeviceString[0], + &dispDevice.DeviceID[0], + &dispDevice.DeviceKey[0]); + + CHAR deviceNum[MAX_PATH]; + LPSTR deviceSub; + + // Simply extract 'DEVICE#' from registry key. This will depend + // on how many mirrored devices your driver has and which ones + // you intend to use. + + strupr(&dispDevice.DeviceKey[0]); + + deviceSub = strstr(&dispDevice.DeviceKey[0], + "\\DEVICE"); + + if (!deviceSub) + direct_snputs(&deviceNum[0], "DEVICE0", sizeof(deviceNum)); + else + direct_snputs(&deviceNum[0], ++deviceSub, sizeof(deviceNum)); + + // Add 'Attach.ToDesktop' setting. + // + { + HKEY hKeyProfileMirror = (HKEY)0; + if (RegCreateKey(HKEY_LOCAL_MACHINE, + _T("SYSTEM\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet\\Services\\mv2"), + &hKeyProfileMirror) != ERROR_SUCCESS) { + if (hUser32) FreeLibrary(hUser32); + return; + } + + HKEY hKeyDevice = (HKEY)0; + if (RegCreateKey(hKeyProfileMirror, + _T(&deviceNum[0]), + &hKeyDevice) != ERROR_SUCCESS) { + if (hUser32) FreeLibrary(hUser32); + return; + } + + DWORD one = 0; + if (RegSetValueEx(hKeyDevice, + _T("Attach.ToDesktop"), + 0, + REG_DWORD, + (unsigned char *)&one, + 4) != ERROR_SUCCESS) { + if (hUser32) FreeLibrary(hUser32); + return; + } + RegCloseKey(hKeyProfileMirror); + RegCloseKey(hKeyDevice); + } + { + deviceSub = strstr(&dispDevice.DeviceKey[0], + "SYSTEM"); + + HKEY hKeyProfileMirror = (HKEY)0; + if (RegCreateKey(HKEY_LOCAL_MACHINE, + _T("SYSTEM\\CurrentControlSet\\Hardware Profiles\\Current"), + &hKeyProfileMirror) != ERROR_SUCCESS) { + if (hUser32) FreeLibrary(hUser32); + return; + } + + HKEY hKeyDevice = (HKEY)0; + if (RegCreateKey(hKeyProfileMirror, + _T(deviceSub), + &hKeyDevice) != ERROR_SUCCESS) { + if (hUser32) FreeLibrary(hUser32); + return; + } + + DWORD one = 0; + if (RegSetValueEx(hKeyDevice, + _T("Attach.ToDesktop"), + 0, + REG_DWORD, + (unsigned char *)&one, + 4) != ERROR_SUCCESS) { + if (hUser32) FreeLibrary(hUser32); + return; + } + RegCloseKey(hKeyProfileMirror); + RegCloseKey(hKeyDevice); + } + + + FillMemory(&devmode, sizeof(DEVMODE), 0); + + devmode.dmSize = sizeof(DEVMODE); + devmode.dmDriverExtra = 0; + + direct_snputs((LPSTR)&devmode.dmDeviceName[0], "mv2", sizeof(devmode.dmDeviceName)); + deviceName = (LPSTR)&dispDevice.DeviceName[0]; + devmode.dmBitsPerPel=32; + // add 'Default.*' settings to the registry under above hKeyProfile\mirror\device + hdeskCurrent = GetThreadDesktop(GetCurrentThreadId()); + if (hdeskCurrent != NULL) { + hdeskInput = OpenInputDesktop(0, FALSE, MAXIMUM_ALLOWED); + if (hdeskInput != NULL) { + SetThreadDesktop(hdeskInput); + } + } + + INT code = + ChangeDisplaySettingsEx(deviceName, + &devmode, + NULL, + CDS_UPDATEREGISTRY, + NULL + ); + +// GetDispCode(code); + + code = ChangeDisplaySettingsEx(deviceName, + &devmode, + NULL, + 0, + NULL + ); + + SetThreadDesktop(hdeskCurrent); + CloseDesktop(hdeskInput); + + } + if (hUser32) FreeLibrary(hUser32); +} + +//BOOL +//Activate_video_driver(); + +bool +VIDEODRIVER::Mirror_driver_attach_XP(int x,int y,int w,int h) +{ + HDESK hdeskInput; + HDESK hdeskCurrent; + + pEnumDisplayDevices pd; + HMODULE hUser32=LoadLibrary("USER32"); + pd = (pEnumDisplayDevices)GetProcAddress( hUser32, "EnumDisplayDevicesA"); + + DEVMODE devmode; + + FillMemory(&devmode, sizeof(DEVMODE), 0); + + devmode.dmSize = sizeof(DEVMODE); + devmode.dmDriverExtra = 0; + + BOOL change = EnumDisplaySettings(NULL, + ENUM_CURRENT_SETTINGS, + &devmode); + + devmode.dmFields = DM_BITSPERPEL | + DM_PELSWIDTH | + DM_POSITION | + DM_PELSHEIGHT; + +#if defined(MIRROR_24) + // for 24 bit mode, have the mirror driver use 32 bit. + if (devmode.dmBitsPerPel == 24) + devmode.dmBitsPerPel = 32; +#endif + if (devmode.dmBitsPerPel!=8 && devmode.dmBitsPerPel!=16 && devmode.dmBitsPerPel!=32) { + if (hUser32) FreeLibrary(hUser32); + return false; + } + + shared_buffer_size=devmode.dmBitsPerPel/8*w*h+sizeof(CHANGES_BUF); + + if (change) { + // query all display devices in the system until we hit + // our favourate mirrored driver, then extract the device name string + // of the format '\\.\DISPLAY#' + + DISPLAY_DEVICE dispDevice; + + FillMemory(&dispDevice, sizeof(DISPLAY_DEVICE), 0); + + dispDevice.cb = sizeof(DISPLAY_DEVICE); + + LPSTR deviceName = NULL; + + devmode.dmDeviceName[0] = '\0'; + + INT devNum = 0; + BOOL result; + + while (result = (*pd)(NULL, + devNum, + &dispDevice, + 0)) { + if (strcmp(&dispDevice.DeviceString[0], driverName) == 0) + break; + + devNum++; + } + + if (!result) { + printf("No '%s' found.\n", driverName); + if (hUser32) FreeLibrary(hUser32); + return false; + } + + printf("DevNum:%d\nName:%s\nString:%s\nID:%s\nKey:%s\n\n", + devNum, + &dispDevice.DeviceName[0], + &dispDevice.DeviceString[0], + &dispDevice.DeviceID[0], + &dispDevice.DeviceKey[0]); + + CHAR deviceNum[MAX_PATH]; + LPSTR deviceSub; + + // Simply extract 'DEVICE#' from registry key. This will depend + // on how many mirrored devices your driver has and which ones + // you intend to use. + + strupr(&dispDevice.DeviceKey[0]); + + deviceSub = strstr(&dispDevice.DeviceKey[0], + "\\DEVICE"); + + if (!deviceSub) + direct_snputs(&deviceNum[0], "DEVICE0", MAX_PATH); + else + direct_snputs(&deviceNum[0], ++deviceSub, MAX_PATH); + + // Add 'Attach.ToDesktop' setting. + // + + HKEY hKeyProfileMirror = (HKEY)0; + if (RegCreateKey(HKEY_LOCAL_MACHINE, + _T("SYSTEM\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet\\Services\\mv2"), + &hKeyProfileMirror) != ERROR_SUCCESS) { + if (hUser32) FreeLibrary(hUser32); + return false; + } + + HKEY hKeyDevice = (HKEY)0; + if (RegCreateKey(hKeyProfileMirror, + _T(&deviceNum[0]), + &hKeyDevice) != ERROR_SUCCESS) { + if (hUser32) FreeLibrary(hUser32); + return false; + } + + DWORD one = 1; + if (RegSetValueEx(hKeyDevice, + _T("Attach.ToDesktop"), + 0, + REG_DWORD, + (unsigned char *)&one, + 4) != ERROR_SUCCESS) { + if (hUser32) FreeLibrary(hUser32); + return false; + } + int depth=devmode.dmBitsPerPel; + + FillMemory(&devmode, sizeof(DEVMODE), 0); + + devmode.dmSize = sizeof(DEVMODE); + devmode.dmDriverExtra = 0; + + direct_snputs((LPSTR)&devmode.dmDeviceName[0], "mv2", 32); + + devmode.dmFields = DM_BITSPERPEL | + DM_PELSWIDTH | + DM_POSITION | + DM_PELSHEIGHT; + deviceName = (LPSTR)&dispDevice.DeviceName[0]; + devmode.dmPelsWidth=w; + devmode.dmPelsHeight=h; + devmode.dmPosition.x=x; + devmode.dmPosition.y=y; + devmode.dmBitsPerPel=depth; + + hdeskCurrent = GetThreadDesktop(GetCurrentThreadId()); + if (hdeskCurrent != NULL) { + hdeskInput = OpenInputDesktop(0, FALSE, MAXIMUM_ALLOWED); + if (hdeskInput != NULL) { + SetThreadDesktop(hdeskInput); + } + } + + // add 'Default.*' settings to the registry under above hKeyProfile\mirror\device + INT code = + ChangeDisplaySettingsEx(deviceName, + &devmode, + NULL, + CDS_UPDATEREGISTRY, + NULL + ); + +// GetDispCode(code); + if (code!=0) { + if (hUser32) FreeLibrary(hUser32); + return false; + } + code = ChangeDisplaySettingsEx(deviceName, + &devmode, + NULL, + 0, + NULL + ); + + SetThreadDesktop(hdeskCurrent); + CloseDesktop(hdeskInput); + + RegCloseKey(hKeyProfileMirror); + RegCloseKey(hKeyDevice); + if (code!=0) { + if (hUser32) FreeLibrary(hUser32); + return false; + } + if (hUser32) FreeLibrary(hUser32); + return true; + } + if (hUser32) FreeLibrary(hUser32); + return false; +} + +int +VIDEODRIVER::OSVersion() +{ + OSVERSIONINFOEX osvi; + SYSTEM_INFO si; + PGNSI pGNSI; + BOOL bOsVersionInfoEx; + + ZeroMemory(&si, sizeof(SYSTEM_INFO)); + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + if ( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) ) { + osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); + if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) ) + return FALSE; + } + pGNSI = (PGNSI) GetProcAddress( + GetModuleHandle(TEXT("kernel32.dll")), + "GetNativeSystemInfo"); + if (NULL != pGNSI) + pGNSI(&si); + else GetSystemInfo(&si); + + switch (osvi.dwPlatformId) { + case VER_PLATFORM_WIN32_NT: + + // Test for the specific product. + + if ( osvi.dwMajorVersion == 6) { + return OSVISTA; + } + + if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 ) { + if ( osvi.wProductType == VER_NT_WORKSTATION && + si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64) { + return OSWINXP64; + } + else return OSWIN2003; + } + + if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 ) + return OSWINXP; + + if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 ) + return OSWIN2000; + + if ( osvi.dwMajorVersion <= 4 ) + return OSOLD; + + } + return OSOLD; +} + + +HDC +VIDEODRIVER::GetDcMirror() +{ + typedef BOOL (WINAPI* pEnumDisplayDevices)(PVOID,DWORD,PVOID,DWORD); + HDC m_hrootdc=NULL; + pEnumDisplayDevices pd; + static const char* driverName = "mv video hook driver2"; + BOOL DriverFound; + DEVMODE devmode; + FillMemory(&devmode, sizeof(DEVMODE), 0); + devmode.dmSize = sizeof(DEVMODE); + devmode.dmDriverExtra = 0; + BOOL change = EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS,&devmode); + devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; + HMODULE hUser32=LoadLibrary("USER32"); + pd = (pEnumDisplayDevices)GetProcAddress( hUser32, "EnumDisplayDevicesA"); + if (pd) { + LPSTR deviceName=NULL; + DISPLAY_DEVICE dd; + ZeroMemory(&dd, sizeof(dd)); + dd.cb = sizeof(dd); + devmode.dmDeviceName[0] = '\0'; + INT devNum = 0; + BOOL result; + DriverFound=false; + while (result = (*pd)(NULL,devNum, &dd,0)) { + if (strcmp((const char *)&dd.DeviceString[0], driverName) == 0) { + DriverFound=true; + break; + } + devNum++; + } + if (DriverFound) { + deviceName = (LPSTR)&dd.DeviceName[0]; + m_hrootdc = CreateDC("DISPLAY",deviceName,NULL,NULL); + if (m_hrootdc) DeleteDC(m_hrootdc); + } + } + if (hUser32) FreeLibrary(hUser32); + + return m_hrootdc; +} + +BOOL +VIDEODRIVER:: HardwareCursor() +{ + HDC gdc; + int returnvalue; + gdc = GetDC(NULL); + returnvalue= ExtEscape(gdc, MAP1, 0, NULL, NULL, NULL); + returnvalue= ExtEscape(gdc, CURSOREN, 0, NULL, NULL, NULL); + ReleaseDC(NULL,gdc); + return true; +} + +BOOL +VIDEODRIVER:: NoHardwareCursor() +{ + HDC gdc; + int returnvalue; + gdc = GetDC(NULL); + returnvalue= ExtEscape(gdc, CURSORDIS, 0, NULL, NULL, NULL); + ReleaseDC(NULL,gdc); + return true; +} + diff --git a/src/videodriver.h b/src/videodriver.h new file mode 100644 index 0000000..fefa489 --- /dev/null +++ b/src/videodriver.h @@ -0,0 +1,76 @@ +#ifndef _VIDEOD_H +#define _VIDEOD_H + +#include +#include +#include +#include + +//#include +#include +#include +//#include + +#define MAXCHANGES_BUF 2000 + +#define OSVISTA 6 +#define OSWINXP 5 +#define OSWIN2000 5 +#define OSWIN2003 5 +#define OSOLD 4 +#define OSWINXP64 7 + +#define SCREEN_SCREEN 11 +#define BLIT 12 +#define SOLIDFILL 13 +#define BLEND 14 +#define TRANS 15 +#define PLG 17 +#define TEXTOUT 18 + +typedef BOOL (WINAPI* pEnumDisplayDevices)(PVOID,DWORD,PVOID,DWORD); +typedef LONG (WINAPI* pChangeDisplaySettingsExA)(LPCSTR,LPDEVMODEA,HWND,DWORD,LPVOID); +typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO); +typedef struct _CHANGES_RECORD { + ULONG type; //screen_to_screen, blit, newcache,oldcache + RECT rect; + POINT point; +}CHANGES_RECORD; +typedef CHANGES_RECORD *PCHANGES_RECORD; +typedef struct _CHANGES_BUF { + ULONG counter; + CHANGES_RECORD pointrect[MAXCHANGES_BUF]; +}CHANGES_BUF; +typedef CHANGES_BUF *PCHANGES_BUF; + +class VIDEODRIVER { +public: + VIDEODRIVER(); + void VIDEODRIVER_start(int x,int y,int w,int h); + void VIDEODRIVER_Stop(); + virtual ~VIDEODRIVER(); + BOOL HardwareCursor(); + BOOL NoHardwareCursor(); + + ULONG oldaantal; + PCHAR mypVideoMemory; + PCHAR myframebuffer; + PCHANGES_BUF mypchangebuf; + BOOL blocked; + DWORD shared_buffer_size; + + +protected: + int OSVersion(); + bool Mirror_driver_attach_XP(int x,int y,int w,int h); + void Mirror_driver_detach_XP(); + bool Mirror_driver_Vista(DWORD dwAttach,int x,int y,int w,int h); + PCHAR VideoMemory_GetSharedMemory(void); + void VideoMemory_ReleaseSharedMemory(PCHAR pVideoMemory); + HDC GetDcMirror(); + + int OSVER; + +}; + +#endif diff --git a/src/videodrivercheck.cpp b/src/videodrivercheck.cpp new file mode 100644 index 0000000..93a407f --- /dev/null +++ b/src/videodrivercheck.cpp @@ -0,0 +1,154 @@ +#include +#include +//#include "vncOSVersion.h" + +typedef BOOL (WINAPI* pEnumDisplayDevices)(PVOID,DWORD,PVOID,DWORD); + +/*bool CheckDriver2(void) +{ + SC_HANDLE schMaster; + SC_HANDLE schSlave; + + schMaster = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); + + schSlave = OpenService (schMaster, "vnccom", SERVICE_ALL_ACCESS); + + if (schSlave == NULL) + { + CloseServiceHandle(schMaster); + return false; + } + else + { + CloseServiceHandle (schSlave); + CloseServiceHandle(schMaster); + return true; + } +}*/ + + +/////////////////////////////////////////////////////////////////// +BOOL GetDllProductVersion(char* dllName, char *vBuffer, int size) +{ + char *versionInfo; + void *lpBuffer; + unsigned int cBytes; + DWORD rBuffer; + + if( !dllName || !vBuffer ) + return(FALSE); + +// DWORD sName = GetModuleFileName(NULL, fileName, sizeof(fileName)); +// FYI only + DWORD sVersion = GetFileVersionInfoSize(dllName, &rBuffer); + if (sVersion==0) return (FALSE); + versionInfo = new char[sVersion]; + + BOOL resultVersion = GetFileVersionInfo(dllName, + NULL, + sVersion, + versionInfo); + + BOOL resultValue = VerQueryValue(versionInfo, + +TEXT("\\StringFileInfo\\040904b0\\ProductVersion"), + &lpBuffer, + &cBytes); + + if( !resultValue ) + { + resultValue = VerQueryValue(versionInfo,TEXT("\\StringFileInfo\\000004b0\\ProductVersion"), + &lpBuffer, + &cBytes); + + } + + if( resultValue ) + { + strncpy(vBuffer, (char *) lpBuffer, size); + delete versionInfo; + return(TRUE); + } + else + { + *vBuffer = '\0'; + delete versionInfo; + return(FALSE); + } +} + +/////////////////////////////////////////////////////////////////// + +bool +CheckVideoDriver(bool Box) +{ + typedef BOOL (WINAPI* pEnumDisplayDevices)(PVOID,DWORD,PVOID,DWORD); + HDC m_hrootdc=NULL; + pEnumDisplayDevices pd; + static const char* driverName = "mv video hook driver2"; + BOOL DriverFound; + DEVMODE devmode; + FillMemory(&devmode, sizeof(DEVMODE), 0); + devmode.dmSize = sizeof(DEVMODE); + devmode.dmDriverExtra = 0; + BOOL change = EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS,&devmode); + devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; + HMODULE hUser32=LoadLibrary("USER32"); + pd = (pEnumDisplayDevices)GetProcAddress( hUser32, "EnumDisplayDevicesA"); + if (pd) + { + LPSTR deviceName=NULL; + DISPLAY_DEVICE dd; + ZeroMemory(&dd, sizeof(dd)); + dd.cb = sizeof(dd); + devmode.dmDeviceName[0] = '\0'; + INT devNum = 0; + BOOL result; + DriverFound=false; + while (result = (*pd)(NULL,devNum, &dd,0)) + { + if (strcmp((const char *)&dd.DeviceString[0], driverName) == 0) + { + DriverFound=true; + break; + } + devNum++; + } + if (DriverFound) + { + if (hUser32) FreeLibrary(hUser32); + if(Box) + { + char buf[512]; + GetDllProductVersion((char*)"mv2.dll",buf,512); + if (dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) + { + strcat(buf," driver Active"); + HDC testdc=NULL; + deviceName = (LPSTR)&dd.DeviceName[0]; + testdc = CreateDC("DISPLAY",deviceName,NULL,NULL); + if (testdc) + { + DeleteDC(testdc); + strcat(buf," access ok"); + } + else + { + strcat(buf," access denied, permission problem"); + } + } + else + strcat(buf," driver Not Active"); + + MessageBox(NULL,buf,"driver info: required version 1.22",0); + } + return true; + //deviceName = (LPSTR)&dd.DeviceName[0]; + //m_hrootdc = CreateDC("DISPLAY",deviceName,NULL,NULL); + //if (m_hrootdc) DeleteDC(m_hrootdc); + } + else if(Box) MessageBox(NULL,"Driver not found: Perhaps you need to reboot after install","driver info: required version 1.22",0); + } + if (hUser32) FreeLibrary(hUser32); + return false; +} -- cgit