[Sumover-dev] [svn commit] r3994 - vic/branches/mpeg4/render

sumover-dev at cs.ucl.ac.uk sumover-dev at cs.ucl.ac.uk
Wed May 2 14:47:44 BST 2007


Author: piers
Date: Wed May  2 14:48:11 2007
New Revision: 3994

Modified:
   vic/branches/mpeg4/render/color-hi.cpp
   vic/branches/mpeg4/render/vw.cpp
   vic/branches/mpeg4/render/vw.h

Log:
DDRAW updates from AG-vic

Modified: vic/branches/mpeg4/render/color-hi.cpp
==============================================================================
--- vic/branches/mpeg4/render/color-hi.cpp	(original)
+++ vic/branches/mpeg4/render/color-hi.cpp	Wed May  2 14:48:11 2007
@@ -115,9 +115,21 @@
 	u_int gmask = visual_->green_mask;
 	u_int bmask = visual_->blue_mask;
 #else /* WIN32: tcl/tk uses a different bit mask in images and visuals */
+#ifndef USE_DDRAW
 	u_int rmask   = 0x7c00;
 	u_int gmask   = 0x03e0;
 	u_int bmask   = 0x001f; 
+#else
+	u_int rmask   = 0xf800;
+	u_int gmask   = 0x07e0;
+	u_int bmask   = 0x001f; 
+//#else
+//	u_int rmask = visual_->red_mask;
+//	u_int gmask = visual_->green_mask;
+//	u_int bmask = visual_->blue_mask;
+
+
+#endif
 #endif /* WIN32 */
 	/* XXX
 	 * we would expect the masks we get back from the server to

Modified: vic/branches/mpeg4/render/vw.cpp
==============================================================================
--- vic/branches/mpeg4/render/vw.cpp	(original)
+++ vic/branches/mpeg4/render/vw.cpp	Wed May  2 14:48:11 2007
@@ -92,6 +92,24 @@
 #endif
 #endif
 }
+#ifdef USE_DDRAW
+
+//  #define DDRAW_USE_BLTFAST
+
+#include <windows.h>
+#include <ddraw.h>
+#include <tkWin.h>
+#include <dvp.h>
+
+char *ddrawErrorString(HRESULT rc);
+
+static totalPixelsDrawn = 0.0;
+
+DDrawVideoImage::MonitorList DDrawVideoImage::monitors_;
+HWND DDrawVideoImage::appMainWindow_;
+
+
+#endif
 
 static class VideoCommand : public TclObject {
 public:
@@ -153,6 +171,33 @@
 		delete p;
 	}
 #endif
+#ifdef USE_DDRAW
+	extern int use_ddraw;
+	Tcl tcl = Tcl::instance();
+	if (use_ddraw)
+	{
+		const char *minWS, *minHS;
+		int minW, minH;
+
+		if ((minWS = tcl.attr("ddraw_min_width")) != NULL)
+			minW = atoi(minWS);
+		else
+			minW = 10;
+
+		if ((minHS = tcl.attr("ddraw_min_height")) != NULL)
+			minH = atoi(minHS);
+		else
+			minH = 10;
+
+
+		if (w > minW && h > minH)
+		{
+			DDrawVideoImage *p = new DDrawVideoImage(tk, w, h);
+			return p;
+		}
+	}
+#endif
+
 	return (new SlowVideoImage(tk, w, h));
 }
 
@@ -320,6 +365,957 @@
 }
 #endif
 
+#ifdef USE_DDRAW
+DDrawVideoImage::DDrawVideoImage(Tk_Window tk, int w, int h)
+	: StandardVideoImage(tk, w, h)
+{
+	init(tk, w, h);
+}
+
+DDrawVideoImage::DDrawVideoImage(Tk_Window tk, int w, int h, int bpp)
+	: StandardVideoImage(tk, w, h)
+{
+	bpp_ = bpp;
+	init(tk, w, h);
+}
+
+
+
+DDrawVideoImage::~DDrawVideoImage()
+{
+    Tk_DeleteEventHandler(toplevelTkWindow_, StructureNotifyMask, windowConfigureEvent_s, this);
+    Tk_DeleteEventHandler(tk_, StructureNotifyMask, videoWindowConfigureEvent_s, this);
+
+    ImageMonitorList::iterator it;
+    for (it = imageMonitors_.begin(); it != imageMonitors_.end(); it++)
+    {
+	DDrawImageMonitor *im = *it;
+
+	delete im;
+    }
+
+    delete image_->data;
+    image_->data = 0;
+}
+
+void DDrawVideoImage::init(Tk_Window tk, int w, int h)
+{
+    int size = w * h;
+
+    if (bpp_ > 8)
+	size *= bpp_ / 8;
+    image_->data = new char[size];
+
+    window_ = 0;
+    needRecalculate_ = true;
+    
+    /*
+    * Find the toplevel window for this video window
+    */
+    
+    for (toplevelTkWindow_ = tk; !Tk_IsTopLevel(toplevelTkWindow_); )
+	toplevelTkWindow_ = Tk_Parent(toplevelTkWindow_);
+//    debug_msg("got toplevel=%d\n", toplevelTkWindow_);
+     
+    /*
+    * Register for configure events, so that we can recalculate
+    * the monitor/surface drawing stuff.
+    */
+    tk_ = tk;
+    Tk_CreateEventHandler(toplevelTkWindow_, StructureNotifyMask, windowConfigureEvent_s, this);
+    Tk_CreateEventHandler(tk, StructureNotifyMask, videoWindowConfigureEvent_s, this);
+
+    /*
+     * Set up the ImageMonitor objects
+     */
+
+    MonitorList::iterator it;
+    for (it = monitors_.begin(); it != monitors_.end(); it++)
+    {
+	DDrawMonitor *m = (*it);
+
+	DDrawImageMonitor *im = new DDrawImageMonitor(image_, m);
+
+	imageMonitors_.push_back(im);
+    }
+    
+}
+
+/*
+ * Determine which monitors should display this image by 
+ * passing the video window to each ImageMonitor object. If
+ * the ImageMonitor should draw the window, it enables itself.
+ */
+void DDrawVideoImage::calculateCoverage(HWND hwnd)
+{
+    window_ = hwnd;
+//    debug_msg("calculate coverage this=%x window_=%x\n", this, window_);
+    ImageMonitorList::iterator it;
+
+    for (it = imageMonitors_.begin(); it != imageMonitors_.end(); it++)
+    {
+	(*it)->setEnabled(false);
+    }
+
+    RECT win;
+    POINT points[4];
+    int i;
+
+    GetClientRect(window_, &win);
+
+    points[0].x = win.left;
+    points[0].y = win.top;
+
+    points[1].x = win.right;
+    points[1].y = win.top;
+
+    points[2].x = win.left;
+    points[2].y = win.bottom;
+
+    points[3].x = win.right;
+    points[3].y = win.bottom;
+
+    for (i = 0; i < 4; i++)
+	ClientToScreen(window_, &(points[i]));
+
+    for (it = imageMonitors_.begin(); it != imageMonitors_.end(); it++)
+    {
+	DDrawImageMonitor *m = *it;
+	//debug_msg("About to calculate coverage for monitor %x\n", m);
+	CHECK_SENTINELS(m)
+	//debug_msg("Monitor name is %s\n", m->monitor()->driverDescription_);
+	for (i = 0; i < 4; i++)
+	{
+	    CHECK_SENTINELS(m)
+	    //debug_msg("calculate coverage for %d\n", i);
+	    m->calculateCoverage(points[i]);
+	    //debug_msg("done with %d\n", i);
+	    CHECK_SENTINELS(m)
+	}
+
+	m->configureSurface();
+    }
+
+#if 0
+    debug_msg("After calculate, enabled status is:\n");
+    for (it = imageMonitors_.begin(); it != imageMonitors_.end(); it++)
+    {
+	DDrawImageMonitor *m = (*it);
+	debug_msg("%s: %s\n", m->enabled() ? "ENABLED " : "DISABLED",
+	    m->monitor()->driverDescription_);
+   }
+#endif
+}
+
+void DDrawVideoImage::windowConfigureEvent_s(ClientData data, XEvent *eventPtr)
+{
+    DDrawVideoImage *img = (DDrawVideoImage *) data;
+    // debug_msg("got event type=%d\n", eventPtr->type);
+    if (eventPtr->type == ConfigureNotify)
+	img->windowConfigureEvent(&(eventPtr->xconfigure));
+}
+
+void DDrawVideoImage::windowConfigureEvent(XConfigureEvent *event)
+{
+//    debug_msg("Got window configure event for img pos=%d %d\n",
+//	event->x, event->y);
+
+    forceRecalculate();
+
+    std::list<WindowMotionCallback *>::iterator it;
+    for (it = windowMotionCallbacks_.begin(); it != windowMotionCallbacks_.end(); it++)
+    {
+	(*it)->windowMoved();
+    }
+}
+void DDrawVideoImage::videoWindowConfigureEvent_s(ClientData data, XEvent *eventPtr)
+{
+    DDrawVideoImage *img = (DDrawVideoImage *) data;
+    // debug_msg("got video window event type=%d\n", eventPtr->type);
+    if (eventPtr->type == MapNotify)
+	img->videoWindowConfigureEvent(&(eventPtr->xmap));
+}
+
+void DDrawVideoImage::videoWindowConfigureEvent(XMapEvent *event)
+{
+//    debug_msg("Got window map event window=%x \n", event->window);
+
+    forceRecalculate();
+
+    std::list<WindowMotionCallback *>::iterator it;
+    for (it = windowMotionCallbacks_.begin(); it != windowMotionCallbacks_.end(); it++)
+    {
+	(*it)->windowMoved();
+    }
+	
+}
+
+//
+// Find the first enabled monitor.
+//
+DDrawImageMonitor * DDrawVideoImage::currentMonitor()
+{
+
+    DDrawImageMonitor *mon = 0;
+    ImageMonitorList::iterator it;
+    for (it = imageMonitors_.begin(); it != imageMonitors_.end(); it++)
+    {
+	DDrawImageMonitor *m = (*it);
+	if (m->enabled())
+	{
+	    mon = m;
+	    break;
+	}
+    }
+
+    return mon;
+    
+}
+
+void DDrawVideoImage::lockSurface(int sx, int sy, int x, int y, int w, int h,
+				    LockedRegion &lock)
+{
+    DDrawImageMonitor *mon = currentMonitor();
+
+    if (mon == 0)
+	return;
+
+    mon->lockSurface(window_, sx, sy, x, y, w, h, lock);
+}
+
+void DDrawMonitor::init(GUID *g, char *desc, char *name, HMONITOR mon)
+{
+    static int nextIndex = 0;
+
+    myIndex_ = nextIndex++;
+    nPixelsDrawn_ = 0.0;
+
+    if (g != 0)
+    {
+	guid_ = new GUID;
+	memcpy(guid_, g, sizeof(GUID));
+    }
+    else
+	guid_ = 0;
+    if (desc != 0)
+    {
+	driverDescription_ = new char[strlen(desc) + 1];
+	strcpy(driverDescription_, desc);
+    }
+    else
+	driverDescription_ = "none";
+    
+    if (name != 0)
+    {
+	driverName_ = new char[strlen(name) + 1];
+	strcpy(driverName_, name);
+    }
+    else
+	driverName_ = "none";
+    
+    if (guid_ != 0)
+    {
+	WCHAR s[1024];
+	int n = StringFromGUID2(*guid_, s, sizeof(s));
+	if (n > 0)
+	{
+	    WideCharToMultiByte(CP_UTF8, 0, s, n, guidString_, sizeof(guidString_), 0, 0);
+	}
+	else
+	    guidString_[0] = 0;
+    }
+    else
+	guidString_[0] = 0;
+    
+    monitorInfo_.cbSize = sizeof(monitorInfo_);
+    HRESULT rc = GetMonitorInfo(mon, &monitorInfo_);
+    if (rc == 0)
+	debug_msg("getmonitorinfo failed\n");
+    
+    handle_ = mon;
+};
+
+void DDrawMonitor::updatePixelCount(int pixels, int depth)
+{
+    nPixelsDrawn_ += (double) pixels;
+}
+
+void DDrawMonitor::updateRate()
+{
+    Tcl& tcl = Tcl::instance();
+    tcl.evalf("set pixrate(%d) %f", myIndex_, nPixelsDrawn_ / 1000.0);
+}
+
+void DDrawMonitor::allocateDirectDraw(HWND hwnd)
+{
+	HRESULT ddrval;
+
+//	debug_msg("ddraw create for monitor %s\n", driverName_);
+
+	// ddrval = DirectDrawCreate(NULL, &lpDD, NULL);
+
+	ddrval = DirectDrawCreateEx(guid_, (VOID**)&directDraw_, IID_IDirectDraw7, NULL);
+
+//	debug_msg("dd create returns %d\n", ddrval);
+
+	if (ddrval != DD_OK)
+	{
+		debug_msg("ddcreate failed\n");
+		return;
+	}
+
+	ddrval = directDraw_->SetCooperativeLevel(hwnd, DDSCL_NORMAL);
+
+	if (ddrval != DD_OK)
+	{
+		debug_msg("setcoop failed\n");
+		return;
+	}
+
+	DDCAPS caps;
+	ZeroMemory(&caps, sizeof(caps));
+	caps.dwSize = sizeof(caps);
+	ddrval = directDraw_->GetCaps(&caps, NULL);
+
+	if (ddrval != DD_OK)
+	{
+		debug_msg("getcaps failed with %s\n", ddrawErrorString(ddrval));
+		return;
+	}
+
+	debug_msg("got caps: max overlays=%d currently visible overlays=%d\n",
+		caps.dwMaxVisibleOverlays, caps.dwCurrVisibleOverlays);
+}
+
+static HRESULT WINAPI enumPortsCallback(
+  LPDDVIDEOPORTCAPS lpDDVideoPortCaps,  
+  LPVOID lpContext                      
+)
+{
+    debug_msg("Enum ports: \n");
+    return DDENUMRET_OK;
+}
+ 
+
+void DDrawMonitor::createSurface(HWND hwnd)
+{
+    /* Now create the primary surface */
+    
+    HRESULT		        hRet;
+    DDSURFACEDESC2      ddsd;
+    
+    // Create the primary surface
+    ZeroMemory(&ddsd,sizeof(ddsd));
+    ddsd.dwSize = sizeof(ddsd);
+    ddsd.dwFlags = DDSD_CAPS; // | DDSD_PIXELFORMAT;
+    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+    ddsd.ddpfPixelFormat.dwFourCC = 0 ;
+    hRet = directDraw_->CreateSurface(&ddsd, &primarySurface_, NULL);
+    if (hRet != DD_OK)
+    {
+	debug_msg("primary surface creation failed\n");
+	return;
+    }
+
+    // What's the pixel format here?
+
+    DDPIXELFORMAT pfmt;
+
+    ZeroMemory(&pfmt, sizeof(DDPIXELFORMAT));
+    pfmt.dwSize = sizeof(pfmt);
+    hRet = primarySurface_->GetPixelFormat(&pfmt);
+    if (hRet == DD_OK)
+    {
+	debug_msg("Pixel format:\n");
+    }
+    else
+	debug_msg("GetPixelFormat failed: %s\n", ddrawErrorString(hRet));
+
+    //
+    // Check out video ports
+    //
+
+    LPDDVIDEOPORTCONTAINER portContainer;
+    hRet = directDraw_->QueryInterface(IID_IDDVideoPortContainer, (void **) &portContainer);
+    if (hRet == S_OK)
+    {
+	debug_msg("Got port container!\n");
+	portContainer->EnumVideoPorts(0, 0, 0, enumPortsCallback);
+    }
+    //
+    // What color codes does this surface support?
+    //
+    DWORD codes[32];
+    DWORD nCodes = 32;
+    hRet = directDraw_->GetFourCCCodes(&nCodes, codes);
+    if (hRet == DD_OK)
+    {
+	unsigned char *c;
+	for (int i= 0; i < nCodes; i++)
+	{
+	    c = (unsigned char *) (&codes[i]);
+	    debug_msg("Code %d: %x %c%c%c%c\n", i, codes[i], c[0], c[1], c[2], c[3]);
+	}
+    }
+
+    
+//    debug_msg("created surface\n");
+    
+#ifndef DDRAW_USE_BLTFAST
+    // Create a clipper object since this is for a Windowed render
+    
+    hRet = directDraw_->CreateClipper(0, &clipper_, NULL);
+    if (hRet != DD_OK)
+    {
+	debug_msg("CreateClipper FAILED");
+	return;
+	
+    }
+    
+//   debug_msg("created clipper\n");
+    
+    primarySurface_->SetClipper(clipper_);
+#endif  
+}
+
+BOOL CALLBACK DDrawVideoImage::enumProc(HMONITOR hMonitor, HDC hdcMon, 
+					LPRECT lprcMon, LPARAM dwData)
+{
+    debug_msg("other enum proc\n");
+    DDrawMonitor *m;
+    
+    m = new DDrawMonitor(0, "primary", "primary", hMonitor);
+    m->print();
+    m->allocateDirectDraw(appMainWindow_);
+    m->createSurface(appMainWindow_);
+    
+    monitors_.push_back(m);
+    return TRUE;
+}
+
+void DDrawVideoImage::initMonitors()
+{
+    HRESULT rc;
+    
+    rc = DirectDrawEnumerateEx(findMonitorsCallback, 0,
+	DDENUM_ATTACHEDSECONDARYDEVICES);
+    
+    if (rc != DD_OK)
+    {
+	debug_msg("device enumeration failed");
+    }
+
+    if (monitors_.size() == 0)
+    {
+	debug_msg("single monitor");
+
+	HDC hdc;
+	RECT rclip;
+
+	hdc = GetDC(NULL);
+	rclip.bottom = 10;
+	rclip.top = 0;
+	rclip.left = 0;
+	rclip.right = 10;
+	EnumDisplayMonitors(hdc, &rclip, enumProc, 0);
+	ReleaseDC(NULL, hdc);
+
+#if 0
+	DDrawMonitor *m;
+	m = new DDrawMonitor();
+	m->print();
+	m->allocateDirectDraw(appMainWindow_);
+	m->createSurface(appMainWindow_);
+	monitors_.push_back(m);
+#endif
+    }
+}
+
+
+BOOL WINAPI DDrawVideoImage::findMonitorsCallback(GUID FAR *lpGUID,    
+						  LPSTR     lpDriverDescription, 
+						  LPSTR     lpDriverName,        
+						  LPVOID    lpContext,           
+						  HMONITOR  hm)
+{
+    debug_msg("monitor enumeration: %x %s %s %x\n",
+	lpGUID, lpDriverDescription, lpDriverName, hm);
+    if (lpGUID != 0)
+    {
+	DDrawMonitor *m;
+	
+	m = new DDrawMonitor(lpGUID, lpDriverDescription, lpDriverName, hm);
+	m->print();
+	m->allocateDirectDraw(appMainWindow_);
+	m->createSurface(appMainWindow_);
+	
+	monitors_.push_back(m);
+    }		
+    return TRUE;
+}
+
+void DDrawVideoImage::initDirectDraw()
+{
+    Tcl& t = Tcl::instance();
+    Tk_Window tkMain = t.tkmain();
+    appMainWindow_ = Tk_GetHWND(Tk_WindowId(tkMain));
+    
+    initMonitors();
+}
+
+void DDrawVideoImage::getTclMonitorList(char *buf)
+{
+    MonitorList::iterator it;
+
+    strcpy(buf, "");
+    for (it = monitors_.begin(); it != monitors_.end(); it++)
+    {
+	char moninfo[60];
+	DDrawMonitor *m = (*it);
+
+	RECT *r = &m->monitorInfo_.rcWork;
+	sprintf(moninfo, "{ %d %d %d %d %d %d } ", 
+	    r->left, r->top, r->right, r->bottom, 
+	   m->myIndex_, m->myIndex_);
+	strcat(buf, moninfo);
+    }
+}
+
+static HRESULT bindImageToSurface(XImage *image, LPDIRECTDRAWSURFACE7 *lpDDS,
+								  LPDIRECTDRAW7 lpDD)
+{ 
+    HRESULT hr;
+    LPVOID  lpSurface  = NULL;
+    HLOCAL  hMemHandle = NULL;
+    DDSURFACEDESC2 ddsd2;
+ 
+ 
+    // Initialize the surface description.
+    ZeroMemory(&ddsd2, sizeof(DDSURFACEDESC2));
+    ZeroMemory(&ddsd2.ddpfPixelFormat, sizeof(DDPIXELFORMAT));
+    ddsd2.dwSize = sizeof(ddsd2);
+    ddsd2.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_LPSURFACE |
+                    DDSD_PITCH | DDSD_PIXELFORMAT | DDSD_CAPS;
+    ddsd2.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN |
+                           DDSCAPS_SYSTEMMEMORY;
+    ddsd2.dwWidth = image->width;
+    ddsd2.dwHeight= image->height;
+    ddsd2.lPitch  = image->bytes_per_line;
+    ddsd2.lpSurface = image->data;
+ 
+    // Set up the pixel format for 24-bit RGB (8-8-8).
+    ddsd2.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
+    ddsd2.ddpfPixelFormat.dwFlags= DDPF_RGB;
+    ddsd2.ddpfPixelFormat.dwRGBBitCount = (DWORD) image->depth;
+
+    if (image->depth == 16)
+    {
+#if 0
+    	ddsd2.ddpfPixelFormat.dwRBitMask = 0x7c00;
+	ddsd2.ddpfPixelFormat.dwGBitMask = 0x03e0;
+	ddsd2.ddpfPixelFormat.dwBBitMask = 0x001f; 
+#else
+    	ddsd2.ddpfPixelFormat.dwRBitMask = 0xf800;
+	ddsd2.ddpfPixelFormat.dwGBitMask = 0x07e0;
+	ddsd2.ddpfPixelFormat.dwBBitMask = 0x001f; 
+#endif
+    }
+    else
+    {
+	ddsd2.ddpfPixelFormat.dwRBitMask    = 0x00FF0000;
+	ddsd2.ddpfPixelFormat.dwGBitMask    = 0x0000FF00;
+	ddsd2.ddpfPixelFormat.dwBBitMask    = 0x000000FF;
+    }
+ 
+    // Create the surface
+    hr = lpDD->CreateSurface(&ddsd2, lpDDS, NULL);
+    return hr;
+}
+
+
+
+DDrawImageMonitor::DDrawImageMonitor(XImage *image, DDrawMonitor *mon) :
+image_(image),
+monitor_(mon),
+enabled_(1)
+{
+    SETUP_SENTINELS()
+
+    imageSurface_ = 0;
+    /*
+     * Delay this until configureSurface() is called.
+     *
+    rc = bindImageToSurface(image_, &imageSurface_, monitor_->directDraw_);
+    if (rc != DD_OK)
+    {
+	debug_msg("monitor image bind failed with %s\n", ddrawErrorString(rc));
+	return;
+    }
+    */
+//    debug_msg("bound monitor ximage to surface\n");
+}
+
+DDrawImageMonitor::~DDrawImageMonitor()
+{
+//    debug_msg("delete DDRawImageMonitor %x\n", this);
+    CHECK_SENTINELS(this);
+
+    
+    if (imageSurface_ != 0)
+    {
+	releaseSurface();
+    }
+}
+
+static DWORD exceptionFilter(LPEXCEPTION_POINTERS p)
+{
+//    LPEXCEPTION_POINTERS p;
+    
+    debug_msg("Exception on surface release!\n");
+//    p = GetExceptionInformation();
+    
+    LPEXCEPTION_RECORD e = p->ExceptionRecord;
+    debug_msg("Code=%d\n", e->ExceptionCode);
+    if (e->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
+    {
+	debug_msg("access type = %s, address=%x\n",
+	    e->ExceptionInformation[0] == 0 ? "read" : "write",
+	    e->ExceptionInformation[1]);
+    }
+    
+    return EXCEPTION_EXECUTE_HANDLER;
+}
+
+void DDrawImageMonitor::releaseSurface()
+{
+    __try {
+	ULONG oldRefCount = imageSurface_->Release();
+//	debug_msg("oldRefCount=%d\n", oldRefCount);
+    } 
+    __except(exceptionFilter(GetExceptionInformation())) {
+    }
+    imageSurface_ = 0;
+}
+
+
+/*
+ * Determine if this monitor should be enabled by testing
+ * if the given point is in the monitor's coverage.
+ */
+void DDrawImageMonitor::calculateCoverage(POINT pt)
+{
+    if (PtInRect(&monitor_->monitorInfo_.rcWork, pt))
+	enabled_ = true;
+}
+
+/*
+ * If this monitor is enabled, create the surface if one doesn't
+ * yet exist.
+ *
+ * If this monitor is not enabled, release the surface if one
+ * already exists.
+ */
+
+void DDrawImageMonitor::configureSurface()
+{
+    if (enabled_)
+    {
+	if (imageSurface_ == 0)
+	{
+	    int rc;
+	    rc = bindImageToSurface(image_, &imageSurface_, monitor_->directDraw_);
+	    if (rc != DD_OK)
+	    {
+		debug_msg("monitor image bind failed with %s\n", ddrawErrorString(rc));
+		return;
+	    }
+	}
+    }
+    else
+    {
+	if (imageSurface_ != 0)
+	{
+    
+	    releaseSurface();
+	}
+    }
+ }
+
+void DDrawImageMonitor::putimage(HWND hWnd, int sx, int sy, int x, int y, int w, int h)
+{
+    if (!enabled_)
+	return;
+    
+    int dx, dy;
+    
+    // Adjust for display in non-primary monitor
+    
+    dx = x - monitor_->monitorInfo_.rcMonitor.left;
+    dy = y - monitor_->monitorInfo_.rcMonitor.top;
+    
+//    debug_msg("putimage mon %s image %x\n", 
+//	monitor_->driverDescription_, image_);
+    
+#ifdef USE_PROFILING
+    startCounter(STATE_PUTIMAGE_DDRAW);
+#endif
+    RECT srcRect, dstRect;
+    
+#ifndef DDRAW_USE_BLTFAST
+    // Associate the clipper with the window
+    
+    monitor_->clipper_->SetHWnd(0, hWnd);
+#endif		
+
+    GetClientRect(hWnd, &dstRect);
+        
+    ClientToScreen(hWnd, (POINT*)&dstRect.left);
+    ClientToScreen(hWnd, (POINT*)&dstRect.right);
+    
+    dstRect.left += dx;
+    dstRect.right = dstRect.left + w;
+    dstRect.top += dy;
+    dstRect.bottom = dstRect.top + h;
+    
+    SetRect(&srcRect, sx, sy, sx + w, sy + h);
+#ifdef USE_PROFILING
+    startCounter(STATE_BITBLT);
+#endif
+#ifdef DDRAW_USE_BLTFAST
+    HRESULT res = monitor_->primarySurface_->BltFast(dstRect.left, dstRect.top,
+	imageSurface_, 
+	&srcRect, DDBLTFAST_NOCOLORKEY );
+#else
+    HRESULT res = monitor_->primarySurface_->Blt(&dstRect, imageSurface_, 
+	&srcRect, DDBLT_WAIT, 0);
+#endif
+#ifdef USE_PROFILING
+    LARGE_INTEGER elap;
+    stopCounter(STATE_BITBLT, &elap);
+    addBlitEntry(w,h,&elap);
+#endif
+    if (res != DD_OK)
+    {
+	debug_msg("blit failed with %s\n", ddrawErrorString(res));
+	return;
+    }
+    monitor_->updatePixelCount(w * h, image_->depth);
+
+#ifdef USE_PROFILING
+    stopCounter(STATE_PUTIMAGE_DDRAW);
+#endif
+}
+
+bool DDrawImageMonitor::supportsOverlay(int &maxOverlays, int &visibleOverlays)
+{
+    DDCAPS caps;
+    HRESULT rc;
+
+    maxOverlays = visibleOverlays = -1;
+
+    ZeroMemory(&caps, sizeof(caps));
+    caps.dwSize = sizeof(caps);
+
+    rc = monitor()->directDraw_->GetCaps(&caps, 0);
+
+    if (FAILED(rc))
+	return false;
+
+    if (caps.dwCaps & DDCAPS_OVERLAY)
+    {
+	maxOverlays = caps.dwMaxVisibleOverlays;
+	visibleOverlays = caps.dwCurrVisibleOverlays;
+	return true;
+    }
+    else
+	return false;
+}
+
+void DDrawImageMonitor::getDisplayRect(HWND hWnd, int x, int y, int w, int h,
+				    RECT &dstRect)
+{
+    if (!enabled_)
+	return;
+    
+    int dx, dy;
+    
+    // Adjust for display in non-primary monitor
+    
+    dx = x - monitor_->monitorInfo_.rcMonitor.left;
+    dy = y - monitor_->monitorInfo_.rcMonitor.top;
+    
+    GetClientRect(hWnd, &dstRect);
+        
+    ClientToScreen(hWnd, (POINT*)&dstRect.left);
+    ClientToScreen(hWnd, (POINT*)&dstRect.right);
+    
+    dstRect.left += dx;
+    dstRect.right = dstRect.left + w;
+    dstRect.top += dy;
+    dstRect.bottom = dstRect.top + h;
+    
+}
+void DDrawImageMonitor::lockSurface(HWND hWnd, int sx, int sy, int x, int y, int w, int h,
+				    DDrawVideoImage::LockedRegion &lock)
+{
+    if (!enabled_)
+	return;
+    
+    int dx, dy;
+    
+    // Adjust for display in non-primary monitor
+    
+    dx = x - monitor_->monitorInfo_.rcMonitor.left;
+    dy = y - monitor_->monitorInfo_.rcMonitor.top;
+    
+//    debug_msg("putimage mon %s image %x\n", 
+//	monitor_->driverDescription_, image_);
+    
+#ifdef USE_PROFILING
+    startCounter(STATE_PUTIMAGE_DDRAW);
+#endif
+    RECT srcRect, dstRect;
+    
+    GetClientRect(hWnd, &dstRect);
+        
+    ClientToScreen(hWnd, (POINT*)&dstRect.left);
+    ClientToScreen(hWnd, (POINT*)&dstRect.right);
+    
+    dstRect.left += dx;
+    dstRect.right = dstRect.left + w;
+    dstRect.top += dy;
+    dstRect.bottom = dstRect.top + h;
+    
+    SetRect(&srcRect, sx, sy, sx + w, sy + h);
+
+    HRESULT res = monitor_->primarySurface_->Lock(&dstRect, lock.surfaceDesc(), 
+	DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0);
+    
+    if (res != DD_OK)
+    {
+	debug_msg("lock failed with %s\n", ddrawErrorString(res));
+	return;
+    }
+
+    lock.setLockParams(monitor_->primarySurface_, dstRect);
+//    debug_msg("Lock succeeded! size=%d %d pitch=%d ptr=%x\n",
+//	surfp->dwWidth, surfp->dwHeight, surfp->lPitch, surfp->lpSurface);
+//    ZeroMemory(surfp->lpSurface, 8192);
+
+//    monitor_->primarySurface_->Unlock(&dstRect);
+}
+
+DDrawVideoImage::LockedRegion::LockedRegion() :
+    locked_(0), surface_(0)
+{
+    ZeroMemory(&surfaceDesc_, sizeof(surfaceDesc_));
+    surfaceDesc_.dwSize = sizeof(surfaceDesc_);
+}
+
+DDrawVideoImage::LockedRegion::~LockedRegion()
+{
+    release();
+}
+
+void  DDrawVideoImage::LockedRegion::release()
+{
+    if (!locked_)
+	return;
+    surface_->Unlock(&lockedRect_);
+    locked_ = 0;
+}
+
+void DDrawVideoImage::LockedRegion::setLockParams(LPDIRECTDRAWSURFACE7 surface, RECT &rect)
+{
+    surface_ = surface;
+    lockedRect_ = rect;
+    locked_ = 1;
+}
+
+int DDrawVideoImage::LockedRegion::width()
+{
+    return surfaceDesc_.dwWidth;
+}
+
+int DDrawVideoImage::LockedRegion::height()
+{
+    return surfaceDesc_.dwWidth;
+}
+
+int DDrawVideoImage::LockedRegion::locked()
+{
+    return locked_;
+}
+
+long DDrawVideoImage::LockedRegion::pitch()
+{
+    return surfaceDesc_.lPitch;
+}
+
+void * DDrawVideoImage::LockedRegion::address()
+{
+    return surfaceDesc_.lpSurface;
+}
+
+/*
+     XPutImage(display, d, gc, image, src_x, src_y, dest_x,
+     dest_y, width, height)
+             Display *display;
+             Drawable d;
+             GC gc;
+             XImage *image;
+             int src_x, src_y;
+             int dest_x, dest_y;
+             unsigned int width, height;
+*/
+
+void DDrawVideoImage::doPutImage(LPDIRECTDRAWSURFACE7 surface,
+				 LPDIRECTDRAWSURFACE7 imageSurface,
+				 LPDIRECTDRAWCLIPPER clipper,
+				 HWND hWnd,
+				 int sx, int sy, int x, int y,
+				 int w, int h) const
+{
+    
+}		
+
+void DDrawVideoImage::checkRecalculate(Window window) 
+{
+    HWND hWnd = Tk_GetHWND(window);
+
+    if (needRecalculate_)
+    {
+	calculateCoverage(hWnd);
+	needRecalculate_ = false;
+    }
+}
+
+void DDrawVideoImage::putimage(Display* dpy, Window window, GC gc,
+			       int sx, int sy, int x, int y,
+			       int w, int h) const
+{
+    HWND hWnd = Tk_GetHWND(window);
+
+
+    ((DDrawVideoImage *) this)->checkRecalculate(window);
+    totalPixelsDrawn += (double) w * h;
+
+    ImageMonitorList::const_iterator it;
+    for (it = imageMonitors_.begin(); it != imageMonitors_.end(); it++)
+    {
+	DDrawImageMonitor *m = *it;
+
+	__try {
+	    
+	    m->putimage(hWnd, sx, sy, x, y, w, h);
+	} 
+	__except(exceptionFilter(GetExceptionInformation())) {
+	}	    
+    }
+}
+
+#endif
+
 BareWindow::BareWindow(const char* name, XVisualInfo* vinfo)
 	: TclObject(name), width_(0), height_(0)
 {
@@ -668,3 +1664,321 @@
 				    width_, height_, frm);
 	}
 }
+
+#ifdef USE_DDRAW
+
+char *ddrawErrorString(HRESULT rc)
+{
+	char *mesg;
+	switch (rc)
+	{
+    case DD_OK:
+        mesg = "DD_OK";
+        break;
+    case DDERR_ALREADYINITIALIZED:
+        mesg = "DDERR_ALREADYINITIALIZED";
+        break;
+    case DDERR_BLTFASTCANTCLIP:
+        mesg = "DDERR_BLTFASTCANTCLIP";
+        break;
+    case DDERR_CANNOTATTACHSURFACE:
+        mesg = "DDERR_CANNOTATTACHSURFACE";
+        break;
+    case DDERR_CANNOTDETACHSURFACE:
+        mesg = "DDERR_CANNOTDETACHSURFACE";
+        break;
+    case DDERR_CANTCREATEDC:
+        mesg = "DDERR_CANTCREATEDC";
+        break;
+    case DDERR_CANTDUPLICATE:
+        mesg = "DDERR_CANTDUPLICATE";
+        break;
+    case DDERR_CANTLOCKSURFACE:
+        mesg = "DDERR_CANTLOCKSURFACE";
+        break;
+    case DDERR_CANTPAGELOCK:
+        mesg = "DDERR_CANTPAGELOCK";
+        break;
+    case DDERR_CANTPAGEUNLOCK:
+        mesg = "DDERR_CANTPAGEUNLOCK";
+        break;
+    case DDERR_CLIPPERISUSINGHWND:
+        mesg = "DDERR_CLIPPERISUSINGHWND";
+        break;
+    case DDERR_COLORKEYNOTSET:
+        mesg = "DDERR_COLORKEYNOTSET";
+        break;
+    case DDERR_CURRENTLYNOTAVAIL:
+        mesg = "DDERR_CURRENTLYNOTAVAIL";
+        break;
+    case DDERR_DCALREADYCREATED:
+        mesg = "DDERR_DCALREADYCREATED";
+        break;
+    case DDERR_DEVICEDOESNTOWNSURFACE:
+        mesg = "DDERR_DEVICEDOESNTOWNSURFACE";
+        break;
+    case DDERR_DIRECTDRAWALREADYCREATED:
+        mesg = "DDERR_DIRECTDRAWALREADYCREATED";
+        break;
+    case DDERR_EXCEPTION:
+        mesg = "DDERR_EXCEPTION";
+        break;
+    case DDERR_EXCLUSIVEMODEALREADYSET:
+        mesg = "DDERR_EXCLUSIVEMODEALREADYSET";
+        break;
+    case DDERR_EXPIRED:
+        mesg = "DDERR_EXPIRED";
+        break;
+    case DDERR_GENERIC:
+        mesg = "DDERR_GENERIC";
+        break;
+    case DDERR_HEIGHTALIGN:
+        mesg = "DDERR_HEIGHTALIGN";
+        break;
+    case DDERR_HWNDALREADYSET:
+        mesg = "DDERR_HWNDALREADYSET";
+        break;
+    case DDERR_HWNDSUBCLASSED:
+        mesg = "DDERR_HWNDSUBCLASSED";
+        break;
+    case DDERR_IMPLICITLYCREATED:
+        mesg = "DDERR_IMPLICITLYCREATED";
+        break;
+    case DDERR_INCOMPATIBLEPRIMARY:
+        mesg = "DDERR_INCOMPATIBLEPRIMARY";
+        break;
+    case DDERR_INVALIDCAPS:
+        mesg = "DDERR_INVALIDCAPS";
+        break;
+    case DDERR_INVALIDCLIPLIST:
+        mesg = "DDERR_INVALIDCLIPLIST";
+        break;
+    case DDERR_INVALIDDIRECTDRAWGUID:
+        mesg = "DDERR_INVALIDDIRECTDRAWGUID";
+        break;
+    case DDERR_INVALIDMODE:
+        mesg = "DDERR_INVALIDMODE";
+        break;
+    case DDERR_INVALIDOBJECT:
+        mesg = "DDERR_INVALIDOBJECT";
+        break;
+    case DDERR_INVALIDPARAMS:
+        mesg = "DDERR_INVALIDPARAMS";
+        break;
+    case DDERR_INVALIDPIXELFORMAT:
+        mesg = "DDERR_INVALIDPIXELFORMAT";
+        break;
+    case DDERR_INVALIDPOSITION:
+        mesg = "DDERR_INVALIDPOSITION";
+        break;
+    case DDERR_INVALIDRECT:
+        mesg = "DDERR_INVALIDRECT";
+        break;
+    case DDERR_INVALIDSTREAM:
+        mesg = "DDERR_INVALIDSTREAM";
+        break;
+    case DDERR_INVALIDSURFACETYPE:
+        mesg = "DDERR_INVALIDSURFACETYPE";
+        break;
+    case DDERR_LOCKEDSURFACES:
+        mesg = "DDERR_LOCKEDSURFACES";
+        break;
+    case DDERR_MOREDATA:
+        mesg = "DDERR_MOREDATA";
+        break;
+    case DDERR_NO3D:
+        mesg = "DDERR_NO3D";
+        break;
+    case DDERR_NOALPHAHW:
+        mesg = "DDERR_NOALPHAHW";
+        break;
+    case DDERR_NOBLTHW:
+        mesg = "DDERR_NOBLTHW";
+        break;
+    case DDERR_NOCLIPLIST:
+        mesg = "DDERR_NOCLIPLIST";
+        break;
+    case DDERR_NOCLIPPERATTACHED:
+        mesg = "DDERR_NOCLIPPERATTACHED";
+        break;
+    case DDERR_NOCOLORCONVHW:
+        mesg = "DDERR_NOCOLORCONVHW";
+        break;
+    case DDERR_NOCOLORKEY:
+        mesg = "DDERR_NOCOLORKEY";
+        break;
+    case DDERR_NOCOLORKEYHW:
+        mesg = "DDERR_NOCOLORKEYHW";
+        break;
+    case DDERR_NOCOOPERATIVELEVELSET:
+        mesg = "DDERR_NOCOOPERATIVELEVELSET";
+        break;
+    case DDERR_NODC:
+        mesg = "DDERR_NODC";
+        break;
+    case DDERR_NODDROPSHW:
+        mesg = "DDERR_NODDROPSHW";
+        break;
+    case DDERR_NODIRECTDRAWHW:
+        mesg = "DDERR_NODIRECTDRAWHW";
+        break;
+    case DDERR_NODIRECTDRAWSUPPORT:
+        mesg = "DDERR_NODIRECTDRAWSUPPORT";
+        break;
+    case DDERR_NOEMULATION:
+        mesg = "DDERR_NOEMULATION";
+        break;
+    case DDERR_NOEXCLUSIVEMODE:
+        mesg = "DDERR_NOEXCLUSIVEMODE";
+        break;
+    case DDERR_NOFLIPHW:
+        mesg = "DDERR_NOFLIPHW";
+        break;
+    case DDERR_NOFOCUSWINDOW:
+        mesg = "DDERR_NOFOCUSWINDOW";
+        break;
+    case DDERR_NOGDI:
+        mesg = "DDERR_NOGDI";
+        break;
+    case DDERR_NOHWND:
+        mesg = "DDERR_NOHWND";
+        break;
+    case DDERR_NOMIPMAPHW:
+        mesg = "DDERR_NOMIPMAPHW";
+        break;
+    case DDERR_NOMIRRORHW:
+        mesg = "DDERR_NOMIRRORHW";
+        break;
+    case DDERR_NONONLOCALVIDMEM:
+        mesg = "DDERR_NONONLOCALVIDMEM";
+        break;
+    case DDERR_NOOPTIMIZEHW:
+        mesg = "DDERR_NOOPTIMIZEHW";
+        break;
+    case DDERR_NOOVERLAYHW:
+        mesg = "DDERR_NOOVERLAYHW";
+        break;
+    case DDERR_NOPALETTEATTACHED:
+        mesg = "DDERR_NOPALETTEATTACHED";
+        break;
+    case DDERR_NOPALETTEHW:
+        mesg = "DDERR_NOPALETTEHW";
+        break;
+    case DDERR_NORASTEROPHW:
+        mesg = "DDERR_NORASTEROPHW";
+        break;
+    case DDERR_NOROTATIONHW:
+        mesg = "DDERR_NOROTATIONHW";
+        break;
+    case DDERR_NOSTEREOHARDWARE:
+        mesg = "DDERR_NOSTEREOHARDWARE";
+        break;
+    case DDERR_NOSTRETCHHW:
+        mesg = "DDERR_NOSTRETCHHW";
+        break;
+    case DDERR_NOSURFACELEFT:
+        mesg = "DDERR_NOSURFACELEFT";
+        break;
+    case DDERR_NOT4BITCOLOR:
+        mesg = "DDERR_NOT4BITCOLOR";
+        break;
+    case DDERR_NOT4BITCOLORINDEX:
+        mesg = "DDERR_NOT4BITCOLORINDEX";
+        break;
+    case DDERR_NOT8BITCOLOR:
+        mesg = "DDERR_NOT8BITCOLOR";
+        break;
+    case DDERR_NOTAOVERLAYSURFACE:
+        mesg = "DDERR_NOTAOVERLAYSURFACE";
+        break;
+    case DDERR_NOTEXTUREHW:
+        mesg = "DDERR_NOTEXTUREHW";
+        break;
+    case DDERR_NOTFLIPPABLE:
+        mesg = "DDERR_NOTFLIPPABLE";
+        break;
+    case DDERR_NOTFOUND:
+        mesg = "DDERR_NOTFOUND";
+        break;
+    case DDERR_NOTINITIALIZED:
+        mesg = "DDERR_NOTINITIALIZED";
+        break;
+	default:
+		mesg = "??";
+	}
+	return mesg;
+}
+#endif
+
+static class MonitorCommand : public TclObject {
+public:
+	MonitorCommand(const char* name) : TclObject(name) { }
+protected:
+	int command(int argc, const char*const* argv);
+} get_monitors_command("get_monitors");
+
+/*
+ * get_monitors
+ */
+int MonitorCommand::command(int argc, const char*const* argv)
+{
+	Tcl& tcl = Tcl::instance();
+	if (argc != 1) {
+		tcl.result("get_monitors arg mismatch");
+		return (TCL_ERROR);
+	}
+
+#ifdef USE_DDRAW
+
+	char * buf = new char[4096];
+	// char buf[1024];
+	DDrawVideoImage::getTclMonitorList(buf);
+	tcl.result(buf);
+	
+#else
+
+	tcl.result("");
+#endif
+
+	return (TCL_OK);
+}
+
+static class UpdateRatesCommand : public TclObject {
+public:
+	UpdateRatesCommand(const char* name) : TclObject(name) { }
+protected:
+	int command(int argc, const char*const* argv);
+} update_rates_command("update_pixrates_vars");
+
+/*
+ * get_monitors
+ */
+int UpdateRatesCommand::command(int argc, const char*const* argv)
+{
+	Tcl& tcl = Tcl::instance();
+	if (argc != 1) {
+		tcl.result("update_pixrates arg mismatch");
+		return (TCL_ERROR);
+	}
+
+	debug_msg("Here in update rates...\n");
+#ifdef USE_DDRAW
+    DDrawVideoImage::MonitorList::iterator it;
+
+    for (it = DDrawVideoImage::monitors_.begin(); it != DDrawVideoImage::monitors_.end(); it++)
+    {
+	DDrawMonitor *im = *it;
+
+	im->updateRate();
+    }
+
+    debug_msg("total %d\n", totalPixelsDrawn);
+    tcl.evalf("set pixrate(total) %f", totalPixelsDrawn / 1000.0);
+
+
+#else
+
+#endif
+
+	return (TCL_OK);
+}

Modified: vic/branches/mpeg4/render/vw.h
==============================================================================
--- vic/branches/mpeg4/render/vw.h	(original)
+++ vic/branches/mpeg4/render/vw.h	Wed May  2 14:48:11 2007
@@ -135,6 +135,270 @@
 };
 #endif
 
+#ifdef USE_DDRAW
+
+#define FRONT_SENTINEL 0xdabbfeed
+#define BACK_SENTINEL 0xbaddbeef
+
+#define SETUP_SENTINELS() { \
+    frontSentinel_ = FRONT_SENTINEL; \
+backSentinel_ = BACK_SENTINEL; }
+
+#define CHECK_SENTINELS(obj) {			    \
+if (obj == 0) {					    \
+    debug_msg("Null object in sentinel check\n");   \
+}	\
+    else {					    \
+    if (obj->frontSentinel_ != FRONT_SENTINEL)			    \
+	debug_msg("Front sentinel on object %x bad: %x != %x\n",    \
+	    obj->frontSentinel_, FRONT_SENTINEL);		    \
+    if (obj->backSentinel_ != BACK_SENTINEL)			   \
+	debug_msg("Back sentinel on object %x bad: %x != %x\n",	\
+	    obj->backSentinel_, BACK_SENTINEL)	;		\
+} \
+}
+
+#pragma warning( disable : 4786)
+
+#include <windows.h>
+#include <winuser.h>
+#include <ddraw.h>
+#include <list>
+#include <map>
+
+class DDrawMonitor
+{
+public:
+    int frontSentinel_;
+    GUID *guid_;
+    char guidString_[1024];
+    char *driverDescription_;
+    char *driverName_;
+    int myIndex_;
+    HMONITOR handle_;
+    LPDIRECTDRAW7 directDraw_;
+    LPDIRECTDRAWSURFACE7 primarySurface_;
+    LPDIRECTDRAWCLIPPER clipper_;
+    
+    MONITORINFO monitorInfo_;
+
+    double nPixelsDrawn_;
+
+    int backSentinel_;
+    
+    DDrawMonitor(GUID *g, char *desc, char *name, HMONITOR mon)
+    {
+	SETUP_SENTINELS();
+	init(g, desc, name, mon);
+    }
+    
+    DDrawMonitor()
+    {
+	SETUP_SENTINELS();
+	init(0, 0, 0, 0);
+    }
+    
+    ~DDrawMonitor()
+    {
+	delete driverDescription_;
+	delete driverName_;
+    }
+    
+    void allocateDirectDraw(HWND);
+    void createSurface(HWND);
+
+    LPDIRECTDRAW7 getDirectDraw() { return directDraw_; }
+    
+    void print()
+    {
+	debug_msg("Monitor: index=%d guid=%s desc=%s name=%s handle=%x\n",
+	    myIndex_, guidString_, driverDescription_, driverName_, handle_);
+#if 1
+	debug_msg("         disp origin=%d %d work origin=%d %d \n",
+	    monitorInfo_.rcMonitor.left, monitorInfo_.rcMonitor.top,
+	    monitorInfo_.rcWork.left, monitorInfo_.rcWork.top);
+#endif
+    }
+
+    void updatePixelCount(int pixels, int depth);
+    void updateRate();
+    
+private:
+    void init(GUID *g, char *desc, char *name, HMONITOR mon);
+       
+};
+
+class DDrawImageMonitor;
+
+/*
+ * A class for DirectDraw based video images. 
+ */
+class DDrawVideoImage : public StandardVideoImage {
+    public:
+	DDrawVideoImage(Tk_Window, int width, int height);
+	DDrawVideoImage(Tk_Window, int width, int height, int bpp);
+	virtual ~DDrawVideoImage();
+	void checkRecalculate(Window window);
+	void putimage(Display* dpy, Window window, GC gc,
+		      int sx, int sy, int x, int y,
+		      int w, int h) const;
+
+	static void initDirectDraw();
+	static void getTclMonitorList(char *);
+
+	class LockedRegion;
+
+	void lockSurface(int sx, int sy, int x, int y, int w, int h,
+				    DDrawVideoImage::LockedRegion &lock);
+
+	void forceRecalculate() { needRecalculate_ = true; }
+
+	DDrawImageMonitor *currentMonitor();
+
+	class WindowMotionCallback
+	{
+	public:
+	    virtual void windowMoved() = 0;
+	};
+
+	void addWindowMotionCallback(WindowMotionCallback *c)
+	{
+	    windowMotionCallbacks_.push_back(c);
+	}
+
+	class LockedRegion
+	{
+	public:
+	    LockedRegion();
+	    ~LockedRegion();
+
+	    void setLockParams(LPDIRECTDRAWSURFACE7 surface, RECT &rect);
+
+	    LPDDSURFACEDESC2 surfaceDesc() {
+		return &surfaceDesc_;
+	    }
+	    void *address();
+	    int width();
+	    int height();
+	    long pitch();
+	    int locked();
+
+	    void release();
+	private:
+	    int locked_;
+	    DDSURFACEDESC2 surfaceDesc_;
+	    RECT lockedRect_;
+	    LPDIRECTDRAWSURFACE7 surface_;
+	};
+    protected:
+	void init(Tk_Window tk, int w, int h);
+
+	static void initMonitors();
+	static BOOL WINAPI findMonitorsCallback(									  
+		GUID FAR *lpGUID,    
+		LPSTR     lpDriverDescription, 
+		  LPSTR     lpDriverName,        
+		  LPVOID    lpContext,           
+		  HMONITOR  hm);
+	static BOOL CALLBACK enumProc(HMONITOR hMonitor, HDC hdcMon, LPRECT lprcMon,
+			      LPARAM dwData);
+
+	void doPutImage(LPDIRECTDRAWSURFACE7 surface,
+		LPDIRECTDRAWSURFACE7 imageSurface,
+		 LPDIRECTDRAWCLIPPER clipper,
+		 HWND hWnd,
+		 int sx, int sy, int x, int y,
+		 int w, int h) const;
+
+	std::list<WindowMotionCallback *> windowMotionCallbacks_;
+
+	bool needRecalculate_;
+	void calculateCoverage(HWND);
+	/*
+	 * Windows handle for the video window
+	 */
+	HWND window_;
+
+	/* 
+	 * Toplevel Tk window
+	 */
+	Tk_Window toplevelTkWindow_;
+	Tk_Window tk_;
+	 
+	/*
+	 * Application main window
+	 */
+	static HWND appMainWindow_;
+
+	/*
+	 * Static list of monitors that are available
+	 */
+	typedef std::list<DDrawMonitor *> MonitorList;
+	static MonitorList monitors_;
+
+	/* 
+	 * List of ImageMonitor mapping objects for this window
+	 */
+	typedef std::list<DDrawImageMonitor *> ImageMonitorList;
+	ImageMonitorList imageMonitors_;
+
+
+	/*
+	 * Tk event stuff to detect window moves
+	 */
+	static void windowConfigureEvent_s(ClientData data, XEvent *eventPtr);
+	void windowConfigureEvent(XConfigureEvent *eventPtr);
+	static void videoWindowConfigureEvent_s(ClientData data, XEvent *eventPtr);
+	void videoWindowConfigureEvent(XMapEvent *eventPtr);
+
+	friend class UpdateRatesCommand;
+};
+	
+/*
+ * A DDrawImageMonitor maps an image surface to a monitor.
+ * The DDrawVideoImage keeps a list of these for displaying
+ * its XImage onto each of the attached monitors.
+ * An imagemonitor can be disabled when the video image is not
+ * visible on that monitor.
+ */
+
+class DDrawImageMonitor
+{
+public:
+    int frontSentinel_;
+    DDrawImageMonitor(XImage *image, DDrawMonitor *mon);
+    ~DDrawImageMonitor();
+    void setEnabled(bool enabled) { enabled_ = enabled; }
+    void putimage(HWND hwnd, int sx, int sy, int x, int y, int w, int h);
+
+    void calculateCoverage(POINT);
+
+    void configureSurface();
+    void releaseSurface();
+
+    void lockSurface(HWND hWnd, int sx, int sy, int x, int y, int w, int h,
+				    DDrawVideoImage::LockedRegion &lock);
+
+    bool enabled() { return enabled_; }
+    DDrawMonitor *monitor() { return monitor_; }
+
+    bool supportsOverlay(int &maxOverlays, int &visibleOverlays);
+    LPDIRECTDRAWSURFACE7 getSurface() { return imageSurface_; }
+
+    void getDisplayRect(HWND hWnd, int x, int y, int w, int h,
+				    RECT &dstRect);
+private:
+
+    XImage *image_;
+    LPDIRECTDRAWSURFACE7 imageSurface_;
+    DDrawMonitor *monitor_;
+
+    bool enabled_;
+public:
+    int backSentinel_;
+};
+#endif
+
 class BareWindow : public TclObject {
     public:
 	BareWindow(const char* name, XVisualInfo* vinfo = 0);



More information about the Sumover-dev mailing list