aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaroslav Hensl <jara@hensl.cz>2023-07-12 17:11:08 +0200
committerJaroslav Hensl <jara@hensl.cz>2023-07-12 17:11:08 +0200
commit030cb4e96b4f77231454c3209ae04c1f42ca837c (patch)
tree0716a5232e390831dc67a91754ab83fd60982c1e
parent47b0c297d5719a9a3e72c4199f99ba6d0c793b68 (diff)
downloadvmdisp9x-1.2023.0.11.tar.gz
Fix: race condition - FIFO access, clear screenv1.2023.0.11
-rw-r--r--README.md65
-rw-r--r--control.c141
-rw-r--r--drvlib.c50
-rw-r--r--drvlib.h1
-rw-r--r--init.c16
-rw-r--r--init_svga.c2
-rw-r--r--makefile11
-rw-r--r--minidrv.h6
-rw-r--r--modes.c267
-rw-r--r--version.h2
-rw-r--r--vmdisp9x.inf30
11 files changed, 459 insertions, 132 deletions
diff --git a/README.md b/README.md
index cd4405a..462d7a4 100644
--- a/README.md
+++ b/README.md
@@ -52,6 +52,71 @@ QEMU is supported since **v1.2023.0.10**. Supported adapters are `-vga std` whic
`*.dll` = 32bit user library runs in 32-bit protected mode in RING 3
+### Adapters
+
+Default inf file is supporting these 4 adapter:
+
+`[VBox]` Default adapter to VirtualBox (VBoxVGA) (until version 6.0 only one adapter) - using 16 bit `boxvmini.drv` driver. Device identification is `PCI\VEN_80EE&DEV_BEEF&SUBSYS_00000000`.
+
+`[Qemu]` QEMUs `-vga std` (or `-device VGA`) device - using 16 bit `qemumini.drv` driver. Device identification is `PCI\VEN_1234&DEV_1111`.
+
+`[VMSvga]` VMware adapter, VirtualBox VMSVGA and QEMU `-vga vmware`. Using 16 bit `vmwsmini.drv` driver and 32 bit `vmwsmini.vxd` driver. Device identification is `PCI\VEN_15AD&DEV_0405&SUBSYS_040515AD`.
+
+`[VBoxSvga]` VirtualBox VBoxSVGA, using 16 bit `vmwsmini.drv` driver and 32 bit `vmwsmini.vxd` driver. Device identification is `PCI\VEN_80EE&DEV_BEEF&SUBSYS_040515AD`.
+
+## Resolutions support
+With default `*.inf` file, default maximum resolution is 1920 x 1200. Maximum wired resolution is 5120 x 4096. For compatibility reasons maximum of VRAM is limited to 128 MB (If you set to adapter more, it'll report only first 128 MB).
+
+However it is possible increase the limit to 256 MB (Windows 9x maximum), if code is compiled with defined `VRAM256MB` (edit `makefile` to set this and recompile project) maximum resolution for this settings is 8192 x 5120.
+
+### QXGA, WQHD, 4K and 5K
+Resolutions sets larger than FullHD, are present in inf file, but needs to be *enabled* if you wish use them. They're split to 4 individual section:
+
+- `[VM.QXGA]` - QXGA, QWXGA and some others bit larger then FullHD
+- `[VM.WQHD]` - 1440p resolutions set
+- `[VM.UHD]` - 4K resolutions set
+- `[VM.R5K]` - 5K resolutions set
+
+To enable one of them just append section name to `AddReg=` parameter to corresponding adapter. For example to add 4K to **VMware adapter** change:
+
+```
+[VMSvga]
+CopyFiles=VMSvga.Copy,Dx.Copy,DX.CopyBackup,Voodoo.Copy
+DelReg=VM.DelReg
+AddReg=VMSvga.AddReg,VM.AddReg,DX.addReg
+```
+
+to:
+
+```
+[VMSvga]
+CopyFiles=VMSvga.Copy,Dx.Copy,DX.CopyBackup,Voodoo.Copy
+DelReg=VM.DelReg
+AddReg=VMSvga.AddReg,VM.AddReg,DX.addReg,VM.UHD
+```
+
+### Custom resolutions
+
+To add custom resolution just append line to `[VM.AddReg]` section with following format:
+
+```
+HKR,"MODES\{BPP}\{WIDTH},{HEIGHT}"
+```
+
+For example adding 1366x768 for all color modes can look like:
+
+```
+HKR,"MODES\8\1366,768"
+HKR,"MODES\16\1366,768"
+HKR,"MODES\24\1366,768"
+HKR,"MODES\32\1366,768"
+```
+
+### VRAM size
+
+In current state the driver using VRAM as framebuffer only. For example if you're using 1920 x 1080 x 32 bpp, driver consume only 8 MB of VRAM and rest of is unutilized. Even if you using HW accelerated graphics with this driver all textures, surface and even backbuffers (implemented as surfaces) are stored in virtual machine's RAM.
+
+
## Security
In 2D mode any application could read and write guest frame buffer and rest of video ram. If 3D is enabled and works (on hypervisor site) is possible by any application to write virtual GPU FIFO which could leads to read memory of different process (in same guest) or crash the guest. These risks are noted but needs to be mentioned that these old systems haven't or has only minimal security management. For example, Microsoft Windows 9x system hasn't no file system rights, all process has mapped system memory (in last 1 GB of 32bit memory space) and any user could run 16bit application where have access to everything including I/O because of compatibility.
diff --git a/control.c b/control.c
index a2fa102..040fd04 100644
--- a/control.c
+++ b/control.c
@@ -178,6 +178,8 @@ typedef struct _svga_hda_t
#define ULF_HEIGHT 2
#define ULF_BPP 3
#define ULF_PITCH 4
+#define ULF_LOCK_UL 5
+#define ULF_LOCK_FIFO 6
static svga_hda_t SVGAHDA;
@@ -315,8 +317,8 @@ void SVGAHDA_init()
{
_fmemset(&SVGAHDA, 0, sizeof(svga_hda_t));
- SVGAHDA.ul_flags_index = 0; // dirty, width, height, bpp, pitch
- SVGAHDA.ul_fence_index = SVGAHDA.ul_flags_index + 5;
+ SVGAHDA.ul_flags_index = 0; // dirty, width, height, bpp, pitch, fifo_lock, ul_lock, fb_lock
+ SVGAHDA.ul_fence_index = SVGAHDA.ul_flags_index + 8;
SVGAHDA.ul_gmr_start = SVGAHDA.ul_fence_index + 1;
SVGAHDA.ul_gmr_count = SVGA_ReadReg(SVGA_REG_GMR_MAX_IDS);
SVGAHDA.ul_ctx_start = SVGAHDA.ul_gmr_start + SVGAHDA.ul_gmr_count*4;
@@ -332,11 +334,23 @@ void SVGAHDA_init()
SVGAHDA.userlist_pm16[ULF_DIRTY] = 0xFFFFFFFFUL;
/* zero the memory, because is large than 64k, is much easier do it in PM32 */
- if(VXD_load())
- {
- VXD_zeromem(SVGAHDA.userlist_linear, SVGAHDA.userlist_length * sizeof(uint32_t));
- }
+ VXD_zeromem(SVGAHDA.userlist_linear, SVGAHDA.userlist_length * sizeof(uint32_t));
+ SVGAHDA.userlist_pm16[ULF_LOCK_UL] = 0;
+ SVGAHDA.userlist_pm16[ULF_LOCK_FIFO] = 0;
+ }
+
+ dbg_printf("SVGAHDA_init\n");
+}
+
+/**
+ * update frame buffer and fifo addresses in SVGAHDA from gSVGA
+ *
+ **/
+void SVGAHDA_setmode()
+{
+ if(SVGAHDA.userlist_pm16)
+ {
SVGAHDA.vram_linear = gSVGA.fbLinear;
SVGAHDA.vram_pm16 = gSVGA.fbMem;
SVGAHDA.vram_physical = gSVGA.fbPhy;
@@ -350,6 +364,109 @@ void SVGAHDA_init()
}
/**
+ * Lock resource
+ *
+ * Note: this is simple spinlock implementation because multitasking isn't
+ * preemptive in Win9x this can lead to deadlock. Please use SVGAHDA_trylock
+ * instead.
+ *
+ * Note: please call SVGAHDA_unlock every time after this function
+ *
+ **/
+BOOL SVGAHDA_lock(uint32_t lockid)
+{
+ volatile uint32_t __far * ptr_lock = SVGAHDA.userlist_pm16 + lockid;
+
+ if(SVGAHDA.userlist_pm16)
+ {
+ _asm
+ {
+ .386
+ push eax
+ push ebx
+
+ spin_lock:
+ mov eax, 1
+ les bx, ptr_lock
+ lock xchg eax, es:[bx]
+ test eax, eax
+ jnz spin_lock
+
+ pop ebx
+ pop eax
+
+ };
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ * Try to lock resource and return TRUE is success.
+ *
+ * Note: if is function successfull you must call SVGAHDA_unlock!
+ *
+ **/
+BOOL SVGAHDA_trylock(uint32_t lockid)
+{
+ volatile uint32_t __far * ptr_lock = SVGAHDA.userlist_pm16 + lockid;
+ BOOL locked = FALSE;
+
+ if(SVGAHDA.userlist_pm16)
+ {
+ _asm
+ {
+ .386
+ push eax
+ push ebx
+
+ mov eax, 1
+ les bx, ptr_lock
+ lock xchg eax, es:[bx]
+ test eax, eax
+ jnz lock_false
+ mov locked, 1
+ lock_false:
+
+ pop ebx
+ pop eax
+
+ };
+ }
+
+ return locked;
+}
+
+/**
+ * Unlock resource
+ *
+ **/
+void SVGAHDA_unlock(uint32_t lockid)
+{
+ volatile uint32_t __far * ptr_lock = SVGAHDA.userlist_pm16 + lockid;
+
+ if(SVGAHDA.userlist_pm16)
+ {
+ _asm
+ {
+ .386
+ push eax
+ push ebx
+
+ xor eax, eax
+ les bx, ptr_lock
+ lock xchg eax, es:[bx]
+
+ pop ebx
+ pop eax
+
+ };
+ }
+}
+
+/**
* This is called after every screen change
**/
void SVGAHDA_update(DWORD width, DWORD height, DWORD bpp, DWORD pitch)
@@ -597,8 +714,6 @@ LONG WINAPI __loadds Control(LPVOID lpDevice, UINT function,
uint32_t ppn;
uint32_t pgblk;
- VXD_load();
-
if(VXD_CreateRegion(lpIn[1], &lAddr, &ppn, &pgblk)) /* allocate physical memory */
{
dbg_printf("Region address = %lX, PPN = %lX, GMRBLK = %lX\n", lAddr, ppn, pgblk);
@@ -640,7 +755,6 @@ LONG WINAPI __loadds Control(LPVOID lpDevice, UINT function,
SVGA_Flush();
/* region physical delete */
- VXD_load();
VXD_FreeRegion(linear, pgblk);
rc = 1;
@@ -739,14 +853,7 @@ LONG WINAPI __loadds Control(LPVOID lpDevice, UINT function,
lpver[0] = DRV_API_LEVEL;
- if(VXD_load())
- {
- lpver[1] = VXD_apiver();
- }
- else
- {
- lpver[1] = 0;
- }
+ lpver[1] = VXD_apiver();
rc = 1;
}
diff --git a/drvlib.c b/drvlib.c
index f25db8a..33997be 100644
--- a/drvlib.c
+++ b/drvlib.c
@@ -31,7 +31,6 @@ void __far *drv_malloc(DWORD dwSize, DWORD __far *lpLinear)
if(!wSel)
return NULL;
- /* Map the framebuffer physical memory. */
dwLin = DPMI_AllocMemBlk(dwSize);
if(dwLin)
@@ -46,3 +45,52 @@ void __far *drv_malloc(DWORD dwSize, DWORD __far *lpLinear)
return NULL;
}
+
+/**
+ * MEMSET for area larger than one segment. This function is not very effective,
+ * I assume it will be called only in few speed non critical situation
+ * (driver/screen inicialization or reset).
+ *
+ * @param dwLinearBase: linear address
+ * @param dwOffset: offset to linear address
+ * @param value: value to set (same bahaviour as C memset)
+ * @param dwNum: number of bytes to set;
+ *
+ **/
+void drv_memset_large(DWORD dwLinearBase, DWORD dwOffset, UINT value, DWORD dwNum)
+{
+ WORD wSel;
+ DWORD dwLinPtr;
+ DWORD dwLinPtrMax;
+ WORD wAddr;
+ BYTE __far *lpPM16Ptr;
+
+ wSel = DPMI_AllocLDTDesc(1);
+ if(!wSel) return;
+
+ dwLinPtr = dwLinearBase + dwOffset;
+ dwLinPtrMax = dwLinPtr + dwNum;
+
+ /* overflow or nothing to do */
+ if(dwLinPtrMax <= dwLinPtr) return;
+
+ DPMI_SetSegBase(wSel, dwLinPtr);
+ DPMI_SetSegLimit(wSel, 0xFFFF);
+
+ for(; dwLinPtr < dwLinPtrMax; dwLinPtr++)
+ {
+ wAddr = dwLinPtr & 0xFFFF;
+
+ /* move to new segment */
+ if(wAddr == 0x0000)
+ {
+ DPMI_SetSegBase(wSel, dwLinPtr);
+ }
+
+ lpPM16Ptr = (BYTE __far *)(wSel :> wAddr);
+
+ *lpPM16Ptr = value;
+ }
+
+ DPMI_FreeLDTDesc(wSel);
+}
diff --git a/drvlib.h b/drvlib.h
index 5755bf5..aaf0146 100644
--- a/drvlib.h
+++ b/drvlib.h
@@ -3,5 +3,6 @@
void drv_memcpy(void __far *dst, void __far *src, long size);
void __far *drv_malloc(DWORD dwSize, DWORD __far *lpLinear);
+void drv_memset_large(DWORD dwLinearBase, DWORD dwOffset, UINT value, DWORD dwNum);
#endif /* __DRVLIB_H__INCLUDED__ */
diff --git a/init.c b/init.c
index 562f734..de29398 100644
--- a/init.c
+++ b/init.c
@@ -32,6 +32,11 @@ THE SOFTWARE.
#include "minidrv.h"
#include <configmg.h>
+#ifdef SVGA
+#include <stdint.h>
+#include "control_vxd.h"
+#endif
+
/* GlobalSmartPageLock is a semi-undocumented function. Not officially
* documented but described in KB Article Q180586. */
UINT WINAPI GlobalSmartPageLock( HGLOBAL hglb );
@@ -330,6 +335,17 @@ UINT FAR DriverInit( UINT cbHeap, UINT hModule, LPSTR lpCmdLine )
/* Read the display configuration before doing anything else. */
ReadDisplayConfig();
+#ifdef SVGA
+ /* connect to 32bit RING-0 driver */
+ if(!VXD_load())
+ {
+ dbg_printf("VXD load failure!\n");
+ return 0;
+ }
+
+ dbg_printf("VXD load success\n");
+#endif
+
return( 1 ); /* Success. */
}
#endif
diff --git a/init_svga.c b/init_svga.c
new file mode 100644
index 0000000..2c6640f
--- /dev/null
+++ b/init_svga.c
@@ -0,0 +1,2 @@
+#define SVGA
+#include "init.c"
diff --git a/makefile b/makefile
index 666a793..826ca92 100644
--- a/makefile
+++ b/makefile
@@ -4,11 +4,11 @@ OBJS = dibthunk.obj dibcall.obj enable.obj init.obj palette.obj &
scrsw_svga.obj control_svga.obj modes_svga.obj palette_svga.obj &
pci.obj svga.obj svga3d.obj svga32.obj pci32.obj dddrv.obj &
enable_svga.obj dibcall_svga.obj boxv_qemu.obj modes_qemu.obj &
- init_qemu.obj
+ init_qemu.obj init_svga.obj
INCS = -I$(%WATCOM)\h\win -Iddk -Ivmware
-VER_BUILD = 10
+VER_BUILD = 11
FLAGS = -DDRV_VER_BUILD=$(VER_BUILD) -DCAP_R5G6B5_ALWAYS_WRONG
@@ -16,6 +16,8 @@ FLAGS = -DDRV_VER_BUILD=$(VER_BUILD) -DCAP_R5G6B5_ALWAYS_WRONG
#FLAGS += -DHWBLT
# Define HWCURSOR if you want accelerate cursor (SVGA only)
#FLAGS += -DHWCURSOR
+# Define VRAM256MB if you want set VRAM limit to 256MB (default is 128MB)
+#FLAGS += -DVRAM256MB
# Set DBGPRINT to add debug printf logging.
#DBGPRINT = 1
@@ -93,6 +95,9 @@ init.obj : init.c .autodepend
init_qemu.obj : init_qemu.c .autodepend
$(CC) $(CFLAGS) -zW $(INCS) $(FLAGS) $<
+
+init_svga.obj : init_svga.c .autodepend
+ $(CC) $(CFLAGS) -zW $(INCS) $(FLAGS) $<
control.obj : control.c .autodepend
$(CC) $(CFLAGS) -zW $(INCS) $(FLAGS) $<
@@ -243,7 +248,7 @@ file dibthunk.obj
file dibcall_svga.obj
file drvlib.obj
file enable_svga.obj
-file init.obj
+file init_svga.obj
file palette_svga.obj
file scrsw_svga.obj
file sswhook.obj
diff --git a/minidrv.h b/minidrv.h
index 75365c4..9946718 100644
--- a/minidrv.h
+++ b/minidrv.h
@@ -143,7 +143,11 @@ extern void CallVDD( unsigned Function );
BOOL DDCreateDriverObject(int bReset);
/* 9x VRAM limit */
-#define MAX_VRAM 0x8000000UL /* 128 MB */
+#ifdef VRAM256MB
+# define MAX_VRAM 0x10000000UL /* 256 MB */
+#else
+# define MAX_VRAM 0x08000000UL /* 128 MB */
+#endif
#ifdef SVGA
#define SVGA_PARTIAL_UPDATE_MAX 16
diff --git a/modes.c b/modes.c
index f88a3a8..b5403ef 100644
--- a/modes.c
+++ b/modes.c
@@ -46,11 +46,16 @@ THE SOFTWARE.
#include <stdlib.h> /* abs */
/* Somewhat arbitrary max resolution. */
-//#define RES_MAX_X (5 * 1024)
-//#define RES_MAX_Y (5 * 768)
+#ifdef VRAM256MB
+/* (max) 256MB VRAM: max 8K in 16:10 */
+#define RES_MAX_X 8192
+#define RES_MAX_Y 5120
+#else
+/* (max) 128MB VRAM: max 5K in 5:4 */
#define RES_MAX_X 5120
#define RES_MAX_Y 4096
-/* ^ JH: 5K in 5:4 */
+#endif
+
WORD wScreenX = 0;
WORD wScreenY = 0;
@@ -108,8 +113,15 @@ extern DWORD CallVDDRegister( WORD Function, WORD wPitch, WORD wHeight, void _fa
/* from control.c */
#ifdef SVGA
void SVGAHDA_init();
+void SVGAHDA_setmode();
WORD SVGA_3DSupport();
void SVGAHDA_update(DWORD width, DWORD height, DWORD bpp, DWORD pitch);
+BOOL SVGAHDA_lock(DWORD lockid);
+BOOL SVGAHDA_trylock(DWORD lockid);
+void SVGAHDA_unlock(DWORD lockid);
+
+#define LOCK_FIFO 6
+
#endif
#pragma code_seg( _INIT );
@@ -199,7 +211,7 @@ static int IsModeOK( WORD wXRes, WORD wYRes, WORD wBpp )
/* some implementations not support 8 and 16 bpp */
if(gSVGA.only32bit && wBpp != 32)
{
- return 0;
+ return 0;
}
#endif
@@ -223,12 +235,12 @@ static int IsModeOK( WORD wXRes, WORD wYRes, WORD wBpp )
/* Clear the visible screen by setting it to all black (zeros).
- * NB: Assumes there is no off-screen region to the right of
- * the visible area.
+ * JH: off-screen region to the right is not affected
*/
static void ClearVisibleScreen( void )
{
- LPDWORD lpScr;
+#if 0
+ LPDWORD lpScr;
WORD wLines = wScreenY;
WORD i;
@@ -240,6 +252,17 @@ static void ClearVisibleScreen( void )
}
lpScr += wScreenPitchBytes; // Scanline pitch.
}
+#endif
+ DWORD dwLinestart = 0;
+ WORD wLines = wScreenY;
+ WORD wPS = ((wBpp+7) >> 3);
+
+ while(wLines--)
+ {
+ drv_memset_large(dwScreenFlatAddr, dwLinestart, 0, (DWORD)wScreenX*wPS);
+
+ dwLinestart += (DWORD)wScreenPitchBytes;
+ }
}
/* Map physical memory to memory space, lpLinAddress is option pointer to store
@@ -263,7 +286,7 @@ static DWORD AllocLinearSelector(DWORD dwPhysAddr, DWORD dwSize, DWORD __far * l
if(lpLinAddress != NULL)
{
- *lpLinAddress = dwLinear;
+ *lpLinAddress = dwLinear;
}
return( wSel );
@@ -283,20 +306,20 @@ static void SVGA_defineScreen(unsigned wXRes, unsigned wYRes, unsigned wBpp)
if(screen)
{
- _fmemset(screen, 0, sizeof(SVGAFifoCmdDefineScreen));
- screen->screen.structSize = sizeof(SVGAScreenObject);
- screen->screen.id = 0;
- screen->screen.flags = SVGA_SCREEN_MUST_BE_SET | SVGA_SCREEN_IS_PRIMARY;
- screen->screen.size.width = wXRes;
- screen->screen.size.height = wYRes;
- screen->screen.root.x = 0;
- screen->screen.root.y = 0;
- screen->screen.cloneCount = 0;
-
- screen->screen.backingStore.pitch = CalcPitch(wXRes, wBpp);
-
- SVGA_FIFOCommitAll();
- }
+ _fmemset(screen, 0, sizeof(SVGAFifoCmdDefineScreen));
+ screen->screen.structSize = sizeof(SVGAScreenObject);
+ screen->screen.id = 0;
+ screen->screen.flags = SVGA_SCREEN_MUST_BE_SET | SVGA_SCREEN_IS_PRIMARY;
+ screen->screen.size.width = wXRes;
+ screen->screen.size.height = wYRes;
+ screen->screen.root.x = 0;
+ screen->screen.root.y = 0;
+ screen->screen.cloneCount = 0;
+
+ screen->screen.backingStore.pitch = CalcPitch(wXRes, wBpp);
+
+ SVGA_FIFOCommitAll();
+ }
}
/* Check if screen acceleration is available */
@@ -315,34 +338,48 @@ static DWORD SVGA_partial_update_cnt = 0;
/* Update screen rect if its relevant */
extern void __loadds SVGA_UpdateRect(LONG x, LONG y, LONG w, LONG h)
{
- /* SVGA commands works only for 32 bpp surfaces */
- if(wBpp != 32)
- {
- return;
- }
-
- if(SVGA_partial_update_cnt++ > SVGA_PARTIAL_UPDATE_MAX)
- {
- SVGA_Update(0, 0, wScreenX, wScreenY);
- SVGA_partial_update_cnt = 0;
- return;
- }
-
- if(x < 0) x = 0;
- if(y < 0) y = 0;
- if(x+w > wScreenX) w = wScreenX - x;
- if(y+h > wScreenY) y = wScreenY - h;
-
- if(w > 0 && h > 0)
- {
- SVGA_Update(x, y, w, h);
- }
-
- /* test if it's full update */
- if(x == 0 && y == 0 && w == wScreenX && h == wScreenY)
- {
- SVGA_partial_update_cnt = 0;
- }
+ /* SVGA commands works only for 32 bpp surfaces */
+ if(wBpp != 32)
+ {
+ return;
+ }
+
+ if(SVGA_partial_update_cnt++ > SVGA_PARTIAL_UPDATE_MAX)
+ {
+ if(SVGAHDA_trylock(LOCK_FIFO))
+ {
+ SVGA_Update(0, 0, wScreenX, wScreenY);
+ SVGAHDA_unlock(LOCK_FIFO);
+ SVGA_partial_update_cnt = 0;
+ }
+ return;
+ }
+
+ if(x < 0) x = 0;
+ if(y < 0) y = 0;
+ if(x+w > wScreenX) w = wScreenX - x;
+ if(y+h > wScreenY) y = wScreenY - h;
+
+ if(w > 0 && h > 0)
+ {
+ if(SVGAHDA_trylock(LOCK_FIFO))
+ {
+ SVGA_Update(x, y, w, h);
+ SVGAHDA_unlock(LOCK_FIFO);
+ }
+ else
+ {
+ /* update full screen next time! */
+ SVGA_partial_update_cnt = SVGA_PARTIAL_UPDATE_MAX+1;
+ return;
+ }
+ }
+
+ /* test if it's full update */
+ if(x == 0 && y == 0 && w == wScreenX && h == wScreenY)
+ {
+ SVGA_partial_update_cnt = 0;
+ }
}
/* Initialize SVGA structure and map FIFO to memory */
@@ -376,11 +413,11 @@ static int __loadds SVGA_full_init()
gSVGA.fifoSel = DPMI_AllocLDTDesc(1);
if(gSVGA.fifoSel)
{
- DPMI_SetSegLimit(gSVGA.fifoSel, 0xFFFF);
-
- gSVGA.fifoAct = 0;
- DPMI_SetSegBase(gSVGA.fifoSel, gSVGA.fifoLinear);
- }
+ DPMI_SetSegLimit(gSVGA.fifoSel, 0xFFFF);
+
+ gSVGA.fifoAct = 0;
+ DPMI_SetSegBase(gSVGA.fifoSel, gSVGA.fifoLinear);
+ }
/* sets FIFO */
SVGA_Enable();
@@ -403,43 +440,49 @@ static int SetDisplayMode( WORD wXRes, WORD wYRes, int bFullSet )
CallVDD( VDD_PRE_MODE_CHANGE );
#ifdef SVGA
- /* Make sure, that we drain full FIFO */
- SVGA_Flush();
-
- SVGA_SetMode(wXRes, wYRes, wBpp); /* setup by legacy registry */
- wMesa3DEnabled = 0;
- if(SVGA3D_Init())
+ /* lock FIFO to make sure, no one is filling it during mode change */
+ if(SVGAHDA_trylock(LOCK_FIFO))
{
- wMesa3DEnabled = SVGA_3DSupport();
+ /* Make sure, that we drain full FIFO */
+ SVGA_Flush();
+
+ SVGA_SetMode(wXRes, wYRes, wBpp); /* setup by legacy registry */
+ wMesa3DEnabled = 0;
+ if(SVGA3D_Init())
+ {
+ wMesa3DEnabled = SVGA_3DSupport();
+ }
+
+ /* setting screen by fifo, this method is required in VB 6.1 */
+ if(SVGA_hasAccelScreen())
+ {
+ SVGA_defineScreen(wXRes, wYRes, wBpp);
+ }
+
+ /*
+ * JH: this is a bit stupid = all SVGA command cannot work with non 32 bpp.
+ * SVGA_CMD_UPDATE included. So if we're working in 32 bpp, we'll disable
+ * traces and updating framebuffer changes with SVGA_CMD_UPDATE.
+ * On non 32 bpp we just enable SVGA_REG_TRACES.
+ *
+ * QEMU hasn't SVGA_REG_TRACES register and framebuffer cannot be se to
+ * 16 or 8 bpp = we supporting only 32 bpp moders if we're running under it.
+ */
+ if(wBpp == 32)
+ {
+ SVGA_WriteReg(SVGA_REG_TRACES, FALSE);
+ }
+ else
+ {
+ SVGA_WriteReg(SVGA_REG_TRACES, TRUE);
+ }
+
+ SVGA_WriteReg(SVGA_REG_ENABLE, TRUE);
+ SVGA_Flush();
+
+ SVGAHDA_unlock(LOCK_FIFO);
}
- /* setting screen by fifo, this method is required in VB 6.1 */
- if(SVGA_hasAccelScreen())
- {
- SVGA_defineScreen(wXRes, wYRes, wBpp);
- }
-
- /*
- * JH: this is a bit stupid = all SVGA command cannot work with non 32 bpp.
- * SVGA_CMD_UPDATE included. So if we're working in 32 bpp, we'll disable
- * traces and updating framebuffer changes with SVGA_CMD_UPDATE.
- * On non 32 bpp we just enable SVGA_REG_TRACES.
- *
- * QEMU hasn't SVGA_REG_TRACES register and framebuffer cannot be se to
- * 16 or 8 bpp = we supporting only 32 bpp moders if we're running under it.
- */
- if(wBpp == 32)
- {
- SVGA_WriteReg(SVGA_REG_TRACES, FALSE);
- }
- else
- {
- SVGA_WriteReg(SVGA_REG_TRACES, TRUE);
- }
-
- SVGA_WriteReg(SVGA_REG_ENABLE, TRUE);
- SVGA_Flush();
-
dbg_printf("Pitch: %lu\n", SVGA_ReadReg(SVGA_REG_BYTES_PER_LINE));
SVGAHDA_update(wScrX, wScrY, wBpp, SVGA_ReadReg(SVGA_REG_BYTES_PER_LINE));
@@ -526,10 +569,16 @@ int PhysicalEnable( void )
/* limit vram size */
if(dwVideoMemorySize > MAX_VRAM)
{
- dwVideoMemorySize = MAX_VRAM;
+ dwVideoMemorySize = MAX_VRAM;
}
dbg_printf( "PhysicalEnable: Hardware detected, dwVideoMemorySize=%lX dwPhysVRAM=%lX\n", dwVideoMemorySize, dwPhysVRAM );
+
+
+#ifdef SVGA
+ /* init here, there are locks for FIFO commands! */
+ SVGAHDA_init();
+#endif
}
dbg_printf("PhysicalEnable: continue with %ux%u\n", wScrX, wScrY);
@@ -547,7 +596,7 @@ int PhysicalEnable( void )
/* Allocate an LDT selector for the screen. */
if( !ScreenSelector ) {
- //ScreenSelector = AllocLinearSelector( dwPhysVRAM, dwVideoMemorySize );
+ //ScreenSelector = AllocLinearSelector( dwPhysVRAM, dwVideoMemorySize );
ScreenSelector = AllocLinearSelector(dwPhysVRAM, dwVideoMemorySize, &dwScreenFlatAddr);
if( !ScreenSelector ) {
dbg_printf( "PhysicalEnable: AllocScreenSelector failed!\n" );
@@ -558,9 +607,9 @@ int PhysicalEnable( void )
gSVGA.fbLinear = dwScreenFlatAddr;
gSVGA.fbPhy = dwPhysVRAM;
gSVGA.fbMem = ScreenSelector :> 0;
-
- /* init userspace hardware access */
- SVGAHDA_init();
+
+ /* update userspace hardware access */
+ SVGAHDA_setmode();
#endif
}
@@ -578,21 +627,21 @@ int PhysicalEnable( void )
/* allocate and fill FBHDA */
if(FBHDA_ptr == NULL)
{
- FBHDA_ptr = drv_malloc(sizeof(FBHDA), &FBHDA_linear);
- if(FBHDA_ptr)
- {
- FBHDA_ptr->width = wScrX;
- FBHDA_ptr->height = wScrY;
- FBHDA_ptr->bpp = wBpp;
- FBHDA_ptr->pitch = wScreenPitchBytes;
-
- FBHDA_ptr->fb_pm32 = dwScreenFlatAddr;
- FBHDA_ptr->fb_pm16 = ScreenSelector :> 0;
- }
- else
- {
- dbg_printf( "FBHDA_ptr = drv_malloc FAIL\n" );
- }
+ FBHDA_ptr = drv_malloc(sizeof(FBHDA), &FBHDA_linear);
+ if(FBHDA_ptr)
+ {
+ FBHDA_ptr->width = wScrX;
+ FBHDA_ptr->height = wScrY;
+ FBHDA_ptr->bpp = wBpp;
+ FBHDA_ptr->pitch = wScreenPitchBytes;
+
+ FBHDA_ptr->fb_pm32 = dwScreenFlatAddr;
+ FBHDA_ptr->fb_pm16 = ScreenSelector :> 0;
+ }
+ else
+ {
+ dbg_printf( "FBHDA_ptr = drv_malloc FAIL\n" );
+ }
}
#ifdef SVGA
diff --git a/version.h b/version.h
index 270964f..2311c4b 100644
--- a/version.h
+++ b/version.h
@@ -5,7 +5,7 @@
#define DRV_STR(x) DRV_STR_(x)
/* DRV, VXD and DLL have to have the same */
-#define DRV_API_LEVEL 20230707UL
+#define DRV_API_LEVEL 20230710UL
/* on binaries equals 1 and for INF is 1 = separate driver, 2 = softgpu pack */
#define DRV_VER_MAJOR 1
diff --git a/vmdisp9x.inf b/vmdisp9x.inf
index 5274eb5..41e8906 100644
--- a/vmdisp9x.inf
+++ b/vmdisp9x.inf
@@ -211,99 +211,129 @@ HKR,"MODES\32\1920,1200"
[VM.QXGA]
HKR,"MODES\8\2048,1080"
+HKR,"MODES\16\2048,1080"
HKR,"MODES\24\2048,1080"
HKR,"MODES\32\2048,1080"
HKR,"MODES\8\2048,1536"
+HKR,"MODES\16\2048,1536"
HKR,"MODES\24\2048,1536"
HKR,"MODES\32\2048,1536"
HKR,"MODES\8\2048,1152"
+HKR,"MODES\16\2048,1152"
HKR,"MODES\24\2048,1152"
HKR,"MODES\32\2048,1152"
[VM.WQHD]
HKR,"MODES\8\1920,1440"
+HKR,"MODES\16\1920,1440"
HKR,"MODES\24\1920,1440"
HKR,"MODES\32\1920,1440"
HKR,"MODES\8\2160,1440"
+HKR,"MODES\16\2160,1440"
HKR,"MODES\24\2160,1440"
HKR,"MODES\32\2160,1440"
HKR,"MODES\8\2304,1440"
+HKR,"MODES\16\2304,1440"
HKR,"MODES\24\2304,1440"
HKR,"MODES\32\2304,1440"
HKR,"MODES\8\2560,1440"
+HKR,"MODES\16\2560,1440"
HKR,"MODES\24\2560,1440"
HKR,"MODES\32\2560,1440"
HKR,"MODES\8\2880,1440"
+HKR,"MODES\16\2880,1440"
HKR,"MODES\24\2880,1440"
HKR,"MODES\32\2880,1440"
HKR,"MODES\8\2960,1440"
+HKR,"MODES\16\2960,1440"
HKR,"MODES\24\2960,1440"
HKR,"MODES\32\2960,1440"
HKR,"MODES\8\3040,1440"
+HKR,"MODES\16\3040,1440"
HKR,"MODES\24\3040,1440"
HKR,"MODES\32\3040,1440"
HKR,"MODES\8\3120,1440"
+HKR,"MODES\16\3120,1440"
HKR,"MODES\24\3120,1440"
HKR,"MODES\32\3120,1440"
HKR,"MODES\8\3200,1440"
+HKR,"MODES\16\3200,1440"
HKR,"MODES\24\3200,1440"
HKR,"MODES\32\3200,1440"
HKR,"MODES\8\3440,1440"
+HKR,"MODES\16\3440,1440"
HKR,"MODES\24\3440,1440"
HKR,"MODES\32\3440,1440"
HKR,"MODES\8\5120,1440"
+HKR,"MODES\16\5120,1440"
HKR,"MODES\24\5120,1440"
HKR,"MODES\32\5120,1440"
[VM.UHD]
HKR,"MODES\8\3840,2160"
+HKR,"MODES\16\3840,2160"
HKR,"MODES\24\3840,2160"
HKR,"MODES\32\3840,2160"
HKR,"MODES\8\4096,2560"
+HKR,"MODES\16\3840,2160"
HKR,"MODES\24\4096,2560"
HKR,"MODES\32\4096,2560"
HKR,"MODES\8\4096,2304"
+HKR,"MODES\16\4096,2304"
HKR,"MODES\24\4096,2304"
HKR,"MODES\32\4096,2304"
HKR,"MODES\8\3840,2400"
+HKR,"MODES\16\3840,2400"
HKR,"MODES\24\3840,2400"
HKR,"MODES\32\3840,2400"
HKR,"MODES\8\3840,1920"
+HKR,"MODES\16\3840,1920"
HKR,"MODES\24\3840,1920"
HKR,"MODES\32\3840,1920"
HKR,"MODES\8\3840,1600"
+HKR,"MODES\16\3840,1600"
HKR,"MODES\24\3840,1600"
HKR,"MODES\32\3840,1600"
HKR,"MODES\8\3840,1080"
+HKR,"MODES\16\3840,1080"
HKR,"MODES\24\3840,1080"
HKR,"MODES\32\3840,1080"
[VM.R5K]
HKR,"MODES\8\5120,1440"
+HKR,"MODES\16\5120,1440"
HKR,"MODES\24\5120,1440"
HKR,"MODES\32\5120,1440"
HKR,"MODES\8\5120,2160"
+HKR,"MODES\16\5120,2160"
HKR,"MODES\24\5120,2160"
HKR,"MODES\32\5120,2160"
HKR,"MODES\8\5120,2560"
+HKR,"MODES\16\5120,2560"
HKR,"MODES\24\5120,2560"
HKR,"MODES\32\5120,2560"
HKR,"MODES\8\4800,2700"
+HKR,"MODES\16\4800,2700"
HKR,"MODES\24\4800,2700"
HKR,"MODES\32\4800,2700"
HKR,"MODES\8\5120,2700"
+HKR,"MODES\16\5120,2700"
HKR,"MODES\24\5120,2700"
HKR,"MODES\32\5120,2700"
HKR,"MODES\8\5120,2880"
+HKR,"MODES\16\5120,2880"
HKR,"MODES\24\5120,2880"
HKR,"MODES\32\5120,2880"
HKR,"MODES\8\5120,3200"
+HKR,"MODES\16\5120,3200"
HKR,"MODES\24\5120,3200"
HKR,"MODES\32\5120,3200"
HKR,"MODES\8\5120,3840"
+HKR,"MODES\16\5120,3840"
HKR,"MODES\24\5120,3840"
HKR,"MODES\32\5120,3840"
HKR,"MODES\8\5120,4096"
+HKR,"MODES\16\5120,4096"
HKR,"MODES\24\5120,4096"
HKR,"MODES\32\5120,4096"