winedos / Console cleanups

Jukka Heinonen jhei at iki.fi
Sun Feb 9 03:18:03 CST 2003


This patch simplifies VGA console handling and also
makes it somewhat faster. Since the patch also
reduces number of code in vga.c and improves comments,
I kind of like it.




Changelog:
    Add locking to VGA_SetWindowStart.
    Move console updates to update thread instead
    of immediately writing to console.




Index: dlls/winedos/vga.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/vga.c,v
retrieving revision 1.29
diff -u -r1.29 vga.c
--- dlls/winedos/vga.c	28 Jan 2003 00:16:15 -0000	1.29
+++ dlls/winedos/vga.c	9 Feb 2003 09:02:59 -0000
@@ -120,6 +120,17 @@
 static BYTE vga_index_3d4;
 static BOOL vga_address_3c0 = TRUE;
 
+/*
+ * This mutex is used to protect VGA state during asynchronous
+ * screen updates (see VGA_Poll). It makes sure that VGA state changes
+ * are atomic and the user interface is protected from flicker and
+ * corruption.
+ *
+ * The mutex actually serializes VGA operations and the screen update. 
+ * Which means that whenever VGA_Poll occurs, application stalls if it 
+ * tries to modify VGA state. This is not how real VGA adapters work,
+ * but it makes timing and correctness issues much easier to deal with.
+ */
 static CRITICAL_SECTION vga_lock = CRITICAL_SECTION_INIT("VGA");
 
 typedef HRESULT (WINAPI *DirectDrawCreateProc)(LPGUID,LPDIRECTDRAW *,LPUNKNOWN);
@@ -549,6 +560,8 @@
     if(start == vga_fb_window)
         return;
 
+    EnterCriticalSection(&vga_lock);
+
     if(vga_fb_window == -1)
         FIXME("Remove VGA memory emulation.\n");
     else
@@ -560,6 +573,8 @@
         FIXME("Install VGA memory emulation.\n");
     else
         memmove( (char *)0xa0000, vga_fb_data + vga_fb_window, 64 * 1024);
+
+    LeaveCriticalSection(&vga_lock);
 }
 
 /*
@@ -689,13 +704,6 @@
 {
     vga_text_x = X;
     vga_text_y = Y;
-
-    if (vga_text_console) {
-        COORD pos;
-        pos.X = X;
-        pos.Y = Y;
-        SetConsoleCursorPosition(VGA_AlphaConsole(),pos);
-    }
 }
 
 void VGA_GetCursorPos(unsigned*X,unsigned*Y)
@@ -704,54 +712,20 @@
     if (Y) *Y = vga_text_y;
 }
 
-static void VGA_PutCharAt(unsigned x, unsigned y, BYTE ascii, BYTE attr)
+static void VGA_PutCharAt(unsigned x, unsigned y, BYTE ascii, int attr)
 {
-    char *dat;
-
-    dat = VGA_AlphaBuffer() + ((vga_text_width * y + x) * 2);
-    dat[0] = ascii;
-    dat[1] = attr;
-    
-    dat = vga_text_old + ((vga_text_width * y + x) * 2);
+    char *dat = VGA_AlphaBuffer() + ((vga_text_width * y + x) * 2);
     dat[0] = ascii;
-    dat[1] = attr;
+    if (attr>=0)
+        dat[1] = attr;
 }
 
 void VGA_WriteChars(unsigned X,unsigned Y,unsigned ch,int attr,int count)
 {
-    CHAR_INFO info;
-    COORD siz, off;
-    SMALL_RECT dest;
-
     EnterCriticalSection(&vga_lock);
 
-    info.Char.AsciiChar = ch;
-    info.Attributes = (WORD)attr;
-    siz.X = 1;
-    siz.Y = 1;
-    off.X = 0;
-    off.Y = 0;
-    dest.Top=Y;
-    dest.Bottom=Y;
-
-    while (count--) {
-        BYTE realattr;
-
-        if (attr < 0) {
-            char *dat = VGA_AlphaBuffer() + ((vga_text_width * Y + X + count) * 2);
-            realattr = dat[1];
-        } else
-            realattr = attr;
-
-        VGA_PutCharAt(X + count, Y, ch, realattr);
-
-        if (vga_text_console) {
-            dest.Left = X + count;
-            dest.Right = X + count;
-            info.Attributes= realattr;
-            WriteConsoleOutputA(VGA_AlphaConsole(), &info, siz, off, &dest);
-        }
-    }
+    while (count--) 
+        VGA_PutCharAt(X + count, Y, ch, attr);
 
     LeaveCriticalSection(&vga_lock);
 }
@@ -791,19 +765,11 @@
      * FIXME: add line wrapping and scrolling
      */
 
-    WriteFile(VGA_AlphaConsole(), &ascii, 1, NULL, NULL);
-
     /*
-     * The following is just a sanity check.
+     * If we don't have a console, write directly to standard output.
      */
-    if(vga_text_console) {
-        CONSOLE_SCREEN_BUFFER_INFO info;
-        GetConsoleScreenBufferInfo( VGA_AlphaConsole(), &info );
-
-        if( info.dwCursorPosition.X != vga_text_x || 
-            info.dwCursorPosition.Y != vga_text_y)
-            WARN("VGA emulator and text console have become unsynchronized.\n");
-    }
+    if(!vga_text_console)
+        WriteFile(VGA_AlphaConsole(), &ascii, 1, NULL, NULL);
 
     LeaveCriticalSection(&vga_lock);
 }
@@ -811,32 +777,19 @@
 void VGA_SetTextAttribute(BYTE attr)
 {
     vga_text_attr = attr;
-    if(vga_text_console)
-        SetConsoleTextAttribute(VGA_AlphaConsole(), attr);
 }
 
 void VGA_ClearText(unsigned row1, unsigned col1,
-                  unsigned row2, unsigned col2,
-                  BYTE attr)
+                   unsigned row2, unsigned col2,
+                   BYTE attr)
 {
     unsigned x, y;
 
     EnterCriticalSection(&vga_lock);
 
-    for(y=row1; y<=row2; y++) {
-        if(vga_text_console) {
-            HANDLE con = VGA_AlphaConsole();
-            COORD off;
-
-            off.X = col1;
-            off.Y = y;        
-            FillConsoleOutputCharacterA(con, ' ', col2-col1+1, off, NULL);
-            FillConsoleOutputAttribute(con, attr, col2-col1+1, off, NULL);
-        }
-
+    for(y=row1; y<=row2; y++)
         for(x=col1; x<=col2; x++)
             VGA_PutCharAt(x, y, ' ', attr);
-    }
 
     LeaveCriticalSection(&vga_lock);
 }
@@ -913,12 +866,18 @@
     COORD siz, off;
     SMALL_RECT dest;
     HANDLE con = VGA_AlphaConsole();
-    BOOL linechanged = FALSE; /* video memory area differs from stored copy ? */
+    BOOL linechanged = FALSE; /* video memory area differs from stored copy? */
+
+    /* Synchronize cursor position. */
+    off.X = vga_text_x;
+    off.Y = vga_text_y;
+    SetConsoleCursorPosition(con,off);
 
     dat = VGA_AlphaBuffer();
     old = vga_text_old; /* pointer to stored video mem copy */
     siz.X = vga_text_width; siz.Y = 1;
     off.X = 0; off.Y = 0;
+
     /* copy from virtual VGA frame buffer to console */
     for (Y=0; Y<vga_text_height; Y++) {
 	linechanged = memcmp(dat, old, vga_text_width*2);
@@ -946,19 +905,18 @@
 
 static void CALLBACK VGA_Poll( LPVOID arg, DWORD low, DWORD high )
 {
-    if(!TryEnterCriticalSection(&vga_lock))
-        return;
+    EnterCriticalSection(&vga_lock);
 
-    if (lpddraw) {
+    if (lpddraw)
         VGA_Poll_Graphics();
-    } else {
+    else
         VGA_Poll_Text();
-    }
 
     /*
      * Fake start of retrace.
      */
     vga_retrace_vertical = TRUE;
+
     LeaveCriticalSection(&vga_lock);
 }
 



-- 
Jukka Heinonen <http://www.iki.fi/jhei/>



More information about the wine-patches mailing list