--- src/vdrivers/vd_win32.c.orig	Tue Aug 28 22:55:26 2007
+++ src/vdrivers/vd_win32.c	Fri Dec 12 15:23:39 2008
@@ -78,6 +78,19 @@
  **     1 - revert the previous change: was saturating GrMouseInfo->queue
  **         for fast paintings
  **     2 - GetUpdateRect() gave wrong UpdateRect !!!
+ **
+ ** Changes by Peter Schauer <peterschauer@gmx.net> 12/05/2008
+ **   - vdrivers/vd_win32.c has a race condition with the loadcolor
+ **     SetDIBColorTable function call, which happens sometimes on
+ **     fast multiprocessor machines. This affects only 8 bpp modes,
+ **     as loadcolor is not called in 32 bpp modes.
+ **     If the WndThread is currently executing its BitBlt during WM_PAINT
+ **     processing and the GRX user thread is calling GrAllocColor, the
+ **     SetDIBColorTable function call fails, as the DC is locked by the BitBlt.
+ **     This results in the color not being set, which could also happen
+ **     during the initial setting of the VGA colors in _GrResetColors.
+ **     My proposed fix delays the SetDIBColorTable call and moves it to
+ **     the WM_PAINT processing, making it synchronous with the BitBlt call.
  **/
 
 #include "libwin32.h"
@@ -111,6 +124,13 @@
 static volatile int isWindowThreadRunning = 0;
 static volatile int isMainWaitingTermination = 0;
 
+struct _GR_modifiedColors {
+    int modified;
+    RGBQUAD color;
+};
+static struct _GR_modifiedColors modifiedColors[256];
+static volatile int isColorModified = 0;
+
 static DWORD WINAPI WndThread(void *param);
 static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam,
 				LPARAM lParam);
@@ -122,8 +142,12 @@
     color.rgbGreen = g;
     color.rgbRed = r;
     color.rgbReserved = 0;
-    SetDIBColorTable(hDCMem, c, 1, &color);
-    InvalidateRect(hGRXWnd, NULL, FALSE);        
+    if (c >= 0 && c <= 256) {
+	modifiedColors[c].color = color;
+	modifiedColors[c].modified = 1;
+	isColorModified = 1;
+	InvalidateRect(hGRXWnd, NULL, FALSE);        
+    }
 }
 
 static HBITMAP CreateDIB8(HDC hdc, int w, int h, char **pBits)
@@ -598,6 +622,21 @@
     case WM_PAINT:
 	{
 	    PAINTSTRUCT ps;
+
+	    if (isColorModified) {
+		int c;
+
+		isColorModified = 0;
+		for (c = 0; c < 256; c++) {
+		    if (modifiedColors[c].modified) {
+			int res;
+
+			modifiedColors[c].modified = 0;
+    			if ((res = SetDIBColorTable(hDCMem, c, 1, &modifiedColors[c].color)) != 1)
+			    DBGPRINTF(DBG_DRIVER,("SetDIBColorTable returned %d (%ld) color %d\n", res, GetLastError(), c));
+		    }
+		}
+	    }
 
 	    if (BeginPaint(hWnd, &ps)){
 		BitBlt(ps.hdc,

