From 095ab8c8dd5f4fc4a2c6cd955fbe0e7b7295287f Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sat, 10 Jan 2004 14:39:21 +0000 Subject: [PATCH] Moved video drivers to a separate directory and added initial version of VBE miniport driver. svn path=/trunk/; revision=7548 --- reactos/Makefile | 39 +- reactos/drivers/video/displays/vga/.cvsignore | 7 + .../video/displays/vga/main/.cvsignore | 3 + .../drivers/video/displays/vga/main/enable.c | 608 ++++++++++ reactos/drivers/video/displays/vga/makefile | 47 + .../video/displays/vga/objects/.cvsignore | 3 + .../video/displays/vga/objects/bitblt.c | 475 ++++++++ .../video/displays/vga/objects/bitblt.h | 22 + .../video/displays/vga/objects/brush.h | 58 + .../video/displays/vga/objects/copybits.c | 40 + .../video/displays/vga/objects/lineto.c | 413 +++++++ .../video/displays/vga/objects/offscreen.c | 193 +++ .../video/displays/vga/objects/paint.c | 245 ++++ .../video/displays/vga/objects/pointer.c | 382 ++++++ .../video/displays/vga/objects/screen.c | 168 +++ .../video/displays/vga/objects/transblt.c | 34 + reactos/drivers/video/displays/vga/vgaddi.def | 11 + reactos/drivers/video/displays/vga/vgaddi.edf | 11 + reactos/drivers/video/displays/vga/vgaddi.h | 246 ++++ reactos/drivers/video/displays/vga/vgaddi.rc | 38 + .../video/displays/vga/vgavideo/.cvsignore | 3 + .../video/displays/vga/vgavideo/vgavideo.c | 1042 +++++++++++++++++ .../video/displays/vga/vgavideo/vgavideo.h | 75 ++ reactos/drivers/video/makefile | 57 + reactos/drivers/video/miniport/vbe/.cvsignore | 8 + reactos/drivers/video/miniport/vbe/makefile | 16 + reactos/drivers/video/miniport/vbe/vbemp.c | 699 +++++++++++ reactos/drivers/video/miniport/vbe/vbemp.h | 208 ++++ reactos/drivers/video/miniport/vbe/vbemp.rc | 38 + reactos/drivers/video/miniport/vga/.cvsignore | 8 + reactos/drivers/video/miniport/vga/initvga.c | 129 ++ reactos/drivers/video/miniport/vga/makefile | 20 + reactos/drivers/video/miniport/vga/vgamp.c | 486 ++++++++ reactos/drivers/video/miniport/vga/vgamp.rc | 38 + reactos/drivers/video/miniport/vga/vgavideo.c | 94 ++ reactos/drivers/video/miniport/vga/vgavideo.h | 41 + 36 files changed, 5995 insertions(+), 10 deletions(-) create mode 100644 reactos/drivers/video/displays/vga/.cvsignore create mode 100644 reactos/drivers/video/displays/vga/main/.cvsignore create mode 100644 reactos/drivers/video/displays/vga/main/enable.c create mode 100644 reactos/drivers/video/displays/vga/makefile create mode 100644 reactos/drivers/video/displays/vga/objects/.cvsignore create mode 100644 reactos/drivers/video/displays/vga/objects/bitblt.c create mode 100644 reactos/drivers/video/displays/vga/objects/bitblt.h create mode 100644 reactos/drivers/video/displays/vga/objects/brush.h create mode 100644 reactos/drivers/video/displays/vga/objects/copybits.c create mode 100644 reactos/drivers/video/displays/vga/objects/lineto.c create mode 100644 reactos/drivers/video/displays/vga/objects/offscreen.c create mode 100644 reactos/drivers/video/displays/vga/objects/paint.c create mode 100644 reactos/drivers/video/displays/vga/objects/pointer.c create mode 100644 reactos/drivers/video/displays/vga/objects/screen.c create mode 100644 reactos/drivers/video/displays/vga/objects/transblt.c create mode 100644 reactos/drivers/video/displays/vga/vgaddi.def create mode 100644 reactos/drivers/video/displays/vga/vgaddi.edf create mode 100644 reactos/drivers/video/displays/vga/vgaddi.h create mode 100644 reactos/drivers/video/displays/vga/vgaddi.rc create mode 100644 reactos/drivers/video/displays/vga/vgavideo/.cvsignore create mode 100644 reactos/drivers/video/displays/vga/vgavideo/vgavideo.c create mode 100644 reactos/drivers/video/displays/vga/vgavideo/vgavideo.h create mode 100644 reactos/drivers/video/makefile create mode 100644 reactos/drivers/video/miniport/vbe/.cvsignore create mode 100644 reactos/drivers/video/miniport/vbe/makefile create mode 100644 reactos/drivers/video/miniport/vbe/vbemp.c create mode 100644 reactos/drivers/video/miniport/vbe/vbemp.h create mode 100644 reactos/drivers/video/miniport/vbe/vbemp.rc create mode 100644 reactos/drivers/video/miniport/vga/.cvsignore create mode 100644 reactos/drivers/video/miniport/vga/initvga.c create mode 100644 reactos/drivers/video/miniport/vga/makefile create mode 100644 reactos/drivers/video/miniport/vga/vgamp.c create mode 100644 reactos/drivers/video/miniport/vga/vgamp.rc create mode 100644 reactos/drivers/video/miniport/vga/vgavideo.c create mode 100644 reactos/drivers/video/miniport/vga/vgavideo.h diff --git a/reactos/Makefile b/reactos/Makefile index 38e4ee44bf2..7e2d469fca2 100644 --- a/reactos/Makefile +++ b/reactos/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.200 2004/01/09 19:55:29 ekohl Exp $ +# $Id: Makefile,v 1.201 2004/01/10 14:39:20 navaraf Exp $ # # Global makefile # @@ -46,9 +46,6 @@ DLLS = libwine advapi32 cards crtdll fmifs freetype gdi32 kernel32 packet lzexpa syssetup twain unicode user32 userenv version winspool ws2help ws2_32 wsock32 \ wshirda iphlpapi msgina mswsock msimg32 d3d8thk winmm comctl32 $(DLLS_KBD) -# Uncomment this after the update W32API headers will be released. -# DLLS += ole32 shlwapi - SUBSYS = smss win32k csrss ntvdm # @@ -67,8 +64,8 @@ DRIVERS_LIB = bzip2 # Kernel mode device drivers # Obsolete: ide -# beep blue floppy null parallel ramdrv serenum serial vga videoprt -DEVICE_DRIVERS = beep blue debugout floppy null serial vga videoprt bootvid +# beep blue floppy null parallel ramdrv serenum serial videoprt +DEVICE_DRIVERS = beep blue debugout floppy null serial videoprt bootvid # Kernel mode input drivers INPUT_DRIVERS = keyboard mouclass psaux sermouse @@ -111,7 +108,7 @@ EXT_MODULES = endif KERNEL_DRIVERS = $(DRIVERS_LIB) $(DEVICE_DRIVERS) $(INPUT_DRIVERS) $(FS_DRIVERS) \ - $(NET_DRIVERS) $(NET_DEVICE_DRIVERS) $(STORAGE_DRIVERS) + $(NET_DRIVERS) $(NET_DEVICE_DRIVERS) $(STORAGE_DRIVERS) VIDEO_DRIVERS # Regression tests REGTESTS = regtests @@ -258,8 +255,9 @@ $(SYS_SVC:%=%_install): %_install: $(APPS): %: $(MAKE) -C apps/$* -$(APPS:%=%_implib): %_implib: - $(MAKE) -C apps/$* implib +# Not needed +# $(APPS:%=%_implib): %_implib: +# $(MAKE) -C apps/$* implib $(APPS:%=%_clean): %_clean: $(MAKE) -C apps/$* clean @@ -444,6 +442,28 @@ $(DEVICE_DRIVERS:%=%_bootcd): %_bootcd: $(DEVICE_DRIVERS:%=%_install) $(DEVICE_DRIVERS:%=%_bootcd) +# +# Video device driver rules +# +VIDEO_DRIVERS: + $(MAKE) -C drivers/video + +VIDEO_DRIVERS_implib: + $(MAKE) -C drivers/video implib + +VIDEO_DRIVERS_clean: + $(MAKE) -C drivers/video clean + +VIDEO_DRIVERS_install: + $(MAKE) -C drivers/video install + +VIDEO_DRIVERS_bootcd: + $(MAKE) -C drivers/video bootcd + +.PHONY: VIDEO_DRIVERS VIDEO_DRIVERS_implib VIDEO_DRIVERS_clean \ + VIDEO_DRIVERS_install VIDEO_DRIVERS_bootcd + + # # Input driver rules # @@ -465,7 +485,6 @@ $(INPUT_DRIVERS:%=%_bootcd): %_bootcd: .PHONY: $(INPUT_DRIVERS) $(INPUT_DRIVERS:%=%_implib) $(INPUT_DRIVERS:%=%_clean)\ $(INPUT_DRIVERS:%=%_install) $(INPUT_DRIVERS:%=%_bootcd) - # # Filesystem driver rules # diff --git a/reactos/drivers/video/displays/vga/.cvsignore b/reactos/drivers/video/displays/vga/.cvsignore new file mode 100644 index 00000000000..36574fe6c63 --- /dev/null +++ b/reactos/drivers/video/displays/vga/.cvsignore @@ -0,0 +1,7 @@ +vgaddi.coff +*.sym +*.o +*.dll +*.map +*.tmp +.*.d diff --git a/reactos/drivers/video/displays/vga/main/.cvsignore b/reactos/drivers/video/displays/vga/main/.cvsignore new file mode 100644 index 00000000000..0abd2c98ac8 --- /dev/null +++ b/reactos/drivers/video/displays/vga/main/.cvsignore @@ -0,0 +1,3 @@ +*.o +*.map +.*.d diff --git a/reactos/drivers/video/displays/vga/main/enable.c b/reactos/drivers/video/displays/vga/main/enable.c new file mode 100644 index 00000000000..f3e353f53be --- /dev/null +++ b/reactos/drivers/video/displays/vga/main/enable.c @@ -0,0 +1,608 @@ +/* + * entry.c + * + * $Revision: 1.1 $ + * $Author: navaraf $ + * $Date: 2004/01/10 14:39:20 $ + * + */ + +#include "../vgaddi.h" +#include "../vgavideo/vgavideo.h" +#define NDEBUG +#include + +#define DBG_PREFIX "VGADDI: " + +static BOOL VGAInitialized = FALSE; + +DRVFN FuncList[] = +{ + /* Required Display driver fuctions */ + {INDEX_DrvAssertMode, (PFN) DrvAssertMode}, + {INDEX_DrvCompletePDEV, (PFN) DrvCompletePDEV}, + {INDEX_DrvCopyBits, (PFN) DrvCopyBits}, + {INDEX_DrvDisablePDEV, (PFN) DrvDisablePDEV}, + {INDEX_DrvDisableSurface, (PFN) DrvDisableSurface}, + {INDEX_DrvEnablePDEV, (PFN) DrvEnablePDEV}, + {INDEX_DrvEnableSurface, (PFN) DrvEnableSurface}, + {INDEX_DrvGetModes, (PFN) DrvGetModes}, + {INDEX_DrvLineTo, (PFN) DrvLineTo}, + {INDEX_DrvPaint, (PFN) DrvPaint}, + {INDEX_DrvBitBlt, (PFN) DrvBitBlt}, + {INDEX_DrvTransparentBlt, (PFN) DrvTransparentBlt}, + {INDEX_DrvMovePointer, (PFN) DrvMovePointer}, + {INDEX_DrvSetPointerShape, (PFN) DrvSetPointerShape}, + +#if 0 + /* Optional Display driver functions */ + {INDEX_, (PFN) }, + {INDEX_DescribePixelFormat, (PFN) VGADDIDescribePixelFormat}, + {INDEX_DrvDitherColor, (PFN) VGADDIDitherColor}, + {INDEX_DrvFillPath, (PFN) VGADDIFillPath}, + {INDEX_DrvGetTrueTypeFile, (PFN) VGADDIGetTrueTypeFile}, + {INDEX_DrvLoadFontFile, (PFN) VGADDILoadFontFile}, + {INDEX_DrvQueryFont, (PFN) VGADDIQueryFont}, + {INDEX_DrvQueryFontCaps, (PFN) VGADDIQueryFontCaps}, + {INDEX_DrvQueryFontData, (PFN) VGADDIQueryFontData}, + {INDEX_DrvQueryFontFile, (PFN) VGADDIQueryFontFile}, + {INDEX_DrvQueryFontTree, (PFN) VGADDIQueryFontTree}, + {INDEX_DrvQueryTrueTypeOutline, (PFN) VGADDIQueryTrueTypeOutline}, + {INDEX_DrvQueryTrueTypeTable, (PFN) VGADDIQueryTrueTypeTable}, + {INDEX_DrvRealizeBrush, (PFN) VGADDIRealizeBrush}, + {INDEX_DrvResetPDEV, (PFN) VGADDIResetPDEV}, + {INDEX_DrvSetPalette, (PFN) VGADDISetPalette}, + {INDEX_DrvSetPixelFormat, (PFN) VGADDISetPixelFormat}, + {INDEX_DrvStretchBlt, (PFN) VGADDIStretchBlt}, + {INDEX_DrvStrokePath, (PFN) VGADDIStrokePath}, + {INDEX_DrvSwapBuffers, (PFN) VGADDISwapBuffers}, + {INDEX_DrvTextOut, (PFN) VGADDITextOut}, + {INDEX_DrvUnloadFontFile, (PFN) VGADDIUnloadFontFile}, +#endif +}; + +GDIINFO gaulCap = { + GDI_DRIVER_VERSION, + DT_RASDISPLAY, // ulTechnology + 0, // ulHorzSize + 0, // ulVertSize + 0, // ulHorzRes (filled in at initialization) + 0, // ulVertRes (filled in at initialization) + 4, // cBitsPixel + 1, // cPlanes + 16, // ulNumColors + 0, // flRaster (DDI reserved field) + + 96, // ulLogPixelsX (must be set to 96 according to MSDN) + 96, // ulLogPixelsY (must be set to 96 according to MSDN) + + TC_RA_ABLE | TC_SCROLLBLT, // flTextCaps + + 6, // ulDACRed + 6, // ulDACGree + 6, // ulDACBlue + + 0x0024, // ulAspectX (one-to-one aspect ratio) + 0x0024, // ulAspectY + 0x0033, // ulAspectXY + + 1, // xStyleStep + 1, // yStyleSte; + 3, // denStyleStep + + { 0, 0 }, // ptlPhysOffset + { 0, 0 }, // szlPhysSize + + 0, // ulNumPalReg (win3.1 16 color drivers say 0 too) + +// These fields are for halftone initialization. + + { // ciDevice, ColorInfo + { 6700, 3300, 0 }, // Red + { 2100, 7100, 0 }, // Green + { 1400, 800, 0 }, // Blue + { 1750, 3950, 0 }, // Cyan + { 4050, 2050, 0 }, // Magenta + { 4400, 5200, 0 }, // Yellow + { 3127, 3290, 0 }, // AlignmentWhite + 20000, // RedGamma + 20000, // GreenGamma + 20000, // BlueGamma + 0, 0, 0, 0, 0, 0 + }, + + 0, // ulDevicePelsDPI + PRIMARY_ORDER_CBA, // ulPrimaryOrder + HT_PATSIZE_4x4_M, // ulHTPatternSize + HT_FORMAT_4BPP_IRGB, // ulHTOutputFormat + HT_FLAG_ADDITIVE_PRIMS, // flHTFlags + + 0, // ulVRefresh + 8, // ulBltAlignment + 0, // ulPanningHorzRes + 0, // ulPanningVertRes +}; + +// Palette for VGA + +typedef struct _VGALOGPALETTE +{ + USHORT ident; + USHORT NumEntries; + PALETTEENTRY PaletteEntry[16]; +} VGALOGPALETTE; + +const VGALOGPALETTE VGApalette = +{ + +0x400, // driver version +16, // num entries +{ + { 0x00, 0x00, 0x00, 0x00 }, // 0 + { 0x80, 0x00, 0x00, 0x00 }, // 1 + { 0x00, 0x80, 0x00, 0x00 }, // 2 + { 0x80, 0x80, 0x00, 0x00 }, // 3 + { 0x00, 0x00, 0x80, 0x00 }, // 4 + { 0x80, 0x00, 0x80, 0x00 }, // 5 + { 0x00, 0x80, 0x80, 0x00 }, // 6 + { 0x80, 0x80, 0x80, 0x00 }, // 7 + { 0xc0, 0xc0, 0xc0, 0x00 }, // 8 + { 0xff, 0x00, 0x00, 0x00 }, // 9 + { 0x00, 0xff, 0x00, 0x00 }, // 10 + { 0xff, 0xff, 0x00, 0x00 }, // 11 + { 0x00, 0x00, 0xff, 0x00 }, // 12 + { 0xff, 0x00, 0xff, 0x00 }, // 13 + { 0x00, 0xff, 0xff, 0x00 }, // 14 + { 0xff, 0xff, 0xff, 0x00 } // 15 +} +}; + +// Devinfo structure passed back to the engine in DrvEnablePDEV + +#define SYSTM_LOGFONT {16,7,0,0,700,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,VARIABLE_PITCH | FF_DONTCARE, L"System"} +#define HELVE_LOGFONT {12,9,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_STROKE_PRECIS,PROOF_QUALITY,VARIABLE_PITCH | FF_DONTCARE, L"MS Sans Serif"} +#define COURI_LOGFONT {12,9,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_STROKE_PRECIS,PROOF_QUALITY,FIXED_PITCH | FF_DONTCARE, L"Courier"} + +DEVINFO devinfoVGA = +{ + (GCAPS_OPAQUERECT | GCAPS_HORIZSTRIKE | GCAPS_ALTERNATEFILL | GCAPS_MONO_DITHER | GCAPS_COLOR_DITHER | + GCAPS_WINDINGFILL | GCAPS_DITHERONREALIZE + ), // Graphics capabilities + + SYSTM_LOGFONT, // Default font description + HELVE_LOGFONT, // ANSI variable font description + COURI_LOGFONT, // ANSI fixed font description + 0, // Count of device fonts + BMF_4BPP, // preferred DIB format + 8, // Width of color dither + 8, // Height of color dither + 0 // Default palette to use for this device +}; + + +BOOL STDCALL +DrvEnableDriver(IN ULONG EngineVersion, + IN ULONG SizeOfDED, + OUT PDRVENABLEDATA DriveEnableData) +{ +/* EngDebugPrint("VGADDI", "DrvEnableDriver called...\n", 0); */ + + vgaPreCalc(); + + // FIXME: Use Vidport to map the memory properly + vidmem = (char *)(0xd0000000 + 0xa0000); + + VGADDI_InitializeOffScreenMem((640 * 480) >> 3, 65536 - ((640 * 480) >> 3)); + + DriveEnableData->pdrvfn = FuncList; + DriveEnableData->c = sizeof(FuncList) / sizeof(DRVFN); + DriveEnableData->iDriverVersion = DDI_DRIVER_VERSION_NT4; + + return TRUE; +} + +// DrvDisableDriver +// DESCRIPTION: +// This function is called by the KMGDI at exit. It should cleanup. +// ARGUMENTS: +// NONE +// RETURNS: +// NONE + +VOID STDCALL +DrvDisableDriver(VOID) +{ + return; +} + +// ----------------------------------------------- Driver Implementation + + +// DrvEnablePDEV +// DESCRIPTION: +// This function is called after DrvEnableDriver to get information +// about the mode that is to be used. This function just returns +// information, and should not yet initialize the mode. +// ARGUMENTS: +// IN DEVMODEW * DM Describes the mode requested +// IN LPWSTR LogAddress +// IN ULONG PatternCount number of patterns expected +// OUT HSURF * SurfPatterns array to contain pattern handles +// IN ULONG GDIInfoSize the size of the GDIInfo object passed in +// OUT ULONG * GDIInfo GDI Info object +// IN ULONG DevInfoSize the size of the DevInfo object passed in +// OUT ULONG * DevInfo Device Info object +// IN LPWSTR DevDataFile ignore +// IN LPWSTR DeviceName Device name +// IN HANDLE Driver handle to KM driver +// RETURNS: +// DHPDEV a handle to a DPev object + +DHPDEV STDCALL +DrvEnablePDEV(IN DEVMODEW *DM, + IN LPWSTR LogAddress, + IN ULONG PatternCount, + OUT HSURF *SurfPatterns, + IN ULONG GDIInfoSize, + OUT ULONG *GDIInfo, + IN ULONG DevInfoSize, + OUT DEVINFO *DevInfo, + IN HDEV Dev, + IN LPWSTR DeviceName, + IN HANDLE Driver) +{ + PPDEV PDev; + + PDev = EngAllocMem(FL_ZERO_MEMORY, sizeof(PDEV), ALLOC_TAG); + if (PDev == NULL) + { + EngDebugPrint(DBG_PREFIX, "EngAllocMem failed for PDEV\n", 0); + return(NULL); + } + PDev->KMDriver = Driver; + DPRINT( "PDev: %x, Driver: %x\n", PDev, PDev->KMDriver ); + PDev->xyCursor.x = 320; + PDev->xyCursor.y = 240; + PDev->ptlExtent.x = 0; + PDev->ptlExtent.y = 0; + PDev->cExtent = 0; + PDev->flCursor = CURSOR_DOWN; + + gaulCap.ulHorzRes = 640; + gaulCap.ulVertRes = 480; + if (sizeof(GDIINFO) < GDIInfoSize) + { + GDIInfoSize = sizeof(GDIINFO); + } + memcpy(GDIInfo, &gaulCap, GDIInfoSize); + + devinfoVGA.hpalDefault = EngCreatePalette(PAL_INDEXED, 16, (ULONG *) VGApalette.PaletteEntry, 0, 0, 0); + if (sizeof(DEVINFO) < DevInfoSize) + { + DevInfoSize = sizeof(DEVINFO); + } + memcpy(DevInfo, &devinfoVGA, DevInfoSize); + + return (DHPDEV) PDev; +} + + +// DrvCompletePDEV +// DESCRIPTION +// Called after initialization of PDEV is complete. Supplies +// a reference to the GDI handle for the PDEV. + +VOID STDCALL +DrvCompletePDEV(IN DHPDEV PDev, + IN HDEV Dev) +{ + ((PPDEV) PDev)->GDIDevHandle = Dev; // Handle to the DC +} + + +BOOL STDCALL +DrvAssertMode(IN DHPDEV DPev, + IN BOOL Enable) +{ + PPDEV ppdev = (PPDEV)DPev; + ULONG returnedDataLength; + + if(Enable==TRUE) + { + // Reenable our graphics mode + + if (!InitPointer(ppdev)) + { + // Failed to set pointer + return FALSE; + } + + if (!VGAInitialized) + { + if (!InitVGA(ppdev, FALSE)) + { + // Failed to initialize the VGA + return FALSE; + } + VGAInitialized = TRUE; + } + } else { + // Go back to last known mode + DPRINT( "ppdev: %x, KMDriver: %x", ppdev, ppdev->KMDriver ); + if (EngDeviceIoControl(ppdev->KMDriver, IOCTL_VIDEO_RESET_DEVICE, NULL, 0, NULL, 0, &returnedDataLength)) + { + // Failed to go back to mode + return FALSE; + } + VGAInitialized = FALSE; + } + return TRUE; +} + + +VOID STDCALL +DrvDisablePDEV(IN DHPDEV PDev) +{ + PPDEV ppdev = (PPDEV)PDev; + + // EngDeletePalette(devinfoVGA.hpalDefault); + if (ppdev->pjPreallocSSBBuffer != NULL) + { + EngFreeMem(ppdev->pjPreallocSSBBuffer); + } + + if (ppdev->pucDIB4ToVGAConvBuffer != NULL) + { + EngFreeMem(ppdev->pucDIB4ToVGAConvBuffer); + } + DPRINT( "Freeing PDEV\n" ); + EngFreeMem(PDev); +} + + +VOID STDCALL +DrvDisableSurface(IN DHPDEV PDev) +{ + PPDEV ppdev = (PPDEV)PDev; + PDEVSURF pdsurf = ppdev->AssociatedSurf; + CHECKPOINT; + DPRINT( "KMDriver: %x\n", ppdev->KMDriver ); + // EngFreeMem(pdsurf->BankSelectInfo); + CHECKPOINT; + if (pdsurf->BankInfo != NULL) { + EngFreeMem(pdsurf->BankInfo); + } + CHECKPOINT; + if (pdsurf->BankInfo2RW != NULL) { + EngFreeMem(pdsurf->BankInfo2RW); + } + CHECKPOINT; + if (pdsurf->BankBufferPlane0 != NULL) { + EngFreeMem(pdsurf->BankBufferPlane0); + } + CHECKPOINT; + if (ppdev->pPointerAttributes != NULL) { + EngFreeMem(ppdev->pPointerAttributes); + } + CHECKPOINT; + // free any pending saved screen bit blocks +#if 0 + pSSB = pdsurf->ssbList; + while (pSSB != (PSAVED_SCREEN_BITS) NULL) { + + // Point to the next saved screen bits block + pSSBNext = (PSAVED_SCREEN_BITS) pSSB->pvNextSSB; + + // Free the current block + EngFreeMem(pSSB); + pSSB = pSSBNext; + } +#endif + EngDeleteSurface((HSURF) ppdev->SurfHandle); + // EngFreeMem(pdsurf); // free the surface +} + + +static VOID +InitSavedBits(PPDEV ppdev) +{ + if (!(ppdev->fl & DRIVER_OFFSCREEN_REFRESHED)) + { + return; + } + + // set up rect to right of visible screen + ppdev->SavedBitsRight.left = ppdev->sizeSurf.cx; + ppdev->SavedBitsRight.top = 0; + ppdev->SavedBitsRight.right = ppdev->sizeMem.cx-PLANAR_PELS_PER_CPU_ADDRESS; + ppdev->SavedBitsRight.bottom = ppdev->sizeSurf.cy; + + if ((ppdev->SavedBitsRight.right <= ppdev->SavedBitsRight.left) || + (ppdev->SavedBitsRight.bottom <= ppdev->SavedBitsRight.top)) + { + ppdev->SavedBitsRight.left = 0; + ppdev->SavedBitsRight.top = 0; + ppdev->SavedBitsRight.right = 0; + ppdev->SavedBitsRight.bottom = 0; + } + + // set up rect below visible screen + ppdev->SavedBitsBottom.left = 0; + ppdev->SavedBitsBottom.top = ppdev->sizeSurf.cy; + ppdev->SavedBitsBottom.right = ppdev->sizeMem.cx-PLANAR_PELS_PER_CPU_ADDRESS; + ppdev->SavedBitsBottom.bottom = ppdev->sizeMem.cy - ppdev->NumScansUsedByPointer; + + if ((ppdev->SavedBitsBottom.right <= ppdev->SavedBitsBottom.left) || + (ppdev->SavedBitsBottom.bottom <= ppdev->SavedBitsBottom.top)) + { + ppdev->SavedBitsBottom.left = 0; + ppdev->SavedBitsBottom.top = 0; + ppdev->SavedBitsBottom.right = 0; + ppdev->SavedBitsBottom.bottom = 0; + } + + ppdev->BitsSaved = FALSE; + + return; +} + + +HSURF STDCALL +DrvEnableSurface(IN DHPDEV PDev) +{ + PPDEV ppdev = (PPDEV)PDev; + PDEVSURF pdsurf; + DHSURF dhsurf; + HSURF hsurf; + + DPRINT("DrvEnableSurface() called\n"); + + // Initialize the VGA + if (!VGAInitialized) + { + if (!InitVGA(ppdev, TRUE)) + { + goto error_done; + } + VGAInitialized = TRUE; + } + + // dhsurf is of type DEVSURF, which is the drivers specialized surface type + dhsurf = (DHSURF)EngAllocMem(0, sizeof(DEVSURF), ALLOC_TAG); + if (dhsurf == (DHSURF) 0) + { + goto error_done; + } + + pdsurf = (PDEVSURF) dhsurf; + pdsurf->ident = DEVSURF_IDENT; + pdsurf->flSurf = 0; + pdsurf->Format = BMF_PHYSDEVICE; + pdsurf->jReserved1 = 0; + pdsurf->jReserved2 = 0; + pdsurf->ppdev = ppdev; + pdsurf->sizeSurf.cx = ppdev->sizeSurf.cx; + pdsurf->sizeSurf.cy = ppdev->sizeSurf.cy; + pdsurf->NextPlane = 0; + pdsurf->Scan0 = ppdev->fbScreen; + pdsurf->BitmapStart = ppdev->fbScreen; + pdsurf->StartBmp = ppdev->fbScreen; + +/* pdsurf->Conv = &ConvertBuffer[0]; */ + + if (!InitPointer(ppdev)) { + DbgPrint("DrvEnablePDEV failed bInitPointer\n"); + goto error_clean; + } + +/* if (!SetUpBanking(pdsurf, ppdev)) { + DISPDBG((0, "DrvEnablePDEV failed SetUpBanking\n")); + goto error_clean; + } BANKING CODE UNIMPLEMENTED */ + + if ((hsurf = EngCreateDeviceSurface(dhsurf, ppdev->sizeSurf, BMF_4BPP)) == + (HSURF)0) + { + // Call to EngCreateDeviceSurface failed + EngDebugPrint("VGADDI:", "EngCreateDeviceSurface call failed\n", 0); + goto error_clean; + } + + InitSavedBits(ppdev); + + if (EngAssociateSurface(hsurf, ppdev->GDIDevHandle, HOOK_BITBLT | HOOK_PAINT | HOOK_LINETO | HOOK_COPYBITS | + HOOK_TRANSPARENTBLT)) + { +/* EngDebugPrint("VGADDI:", "Successfully associated surface\n", 0); */ + ppdev->SurfHandle = hsurf; + ppdev->AssociatedSurf = pdsurf; + + // Set up an empty saved screen block list + pdsurf->ssbList = NULL; + + return(hsurf); + } + DPRINT( "EngAssociateSurface() failed\n" ); + EngDeleteSurface(hsurf); + +error_clean: + EngFreeMem(dhsurf); + +error_done: + return((HSURF)0); +} + + +ULONG STDCALL +DrvGetModes(IN HANDLE Driver, + IN ULONG DataSize, + OUT PDEVMODEW DM) +{ + DWORD NumModes; + DWORD ModeSize; + DWORD OutputSize; + DWORD OutputModes = DataSize / (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE); + PVIDEO_MODE_INFORMATION VideoModeInformation, VideoTemp; + + NumModes = getAvailableModes(Driver, + (PVIDEO_MODE_INFORMATION *) &VideoModeInformation, + &ModeSize); + + if (NumModes == 0) + { + return 0; + } + + if (DM == NULL) + { + OutputSize = NumModes * (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE); + } else { + + OutputSize=0; + VideoTemp = VideoModeInformation; + + do + { + if (VideoTemp->Length != 0) + { + if (OutputModes == 0) + { + break; + } + + memset(DM, 0, sizeof(DEVMODEW)); + memcpy(DM->dmDeviceName, DLL_NAME, sizeof(DLL_NAME)); + + DM->dmSpecVersion = DM_SPECVERSION; + DM->dmDriverVersion = DM_SPECVERSION; + DM->dmSize = sizeof(DEVMODEW); + DM->dmDriverExtra = DRIVER_EXTRA_SIZE; + DM->dmBitsPerPel = VideoTemp->NumberOfPlanes * + VideoTemp->BitsPerPlane; + DM->dmPelsWidth = VideoTemp->VisScreenWidth; + DM->dmPelsHeight = VideoTemp->VisScreenHeight; + DM->dmDisplayFrequency = VideoTemp->Frequency; + DM->dmDisplayFlags = 0; + + DM->dmFields = DM_BITSPERPEL | + DM_PELSWIDTH | + DM_PELSHEIGHT | + DM_DISPLAYFREQUENCY | + DM_DISPLAYFLAGS ; + + // next DEVMODE entry + OutputModes--; + + DM = (PDEVMODEW) ( ((ULONG)DM) + sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE); + + OutputSize += (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE); + } + + VideoTemp = (PVIDEO_MODE_INFORMATION)(((PUCHAR)VideoTemp) + ModeSize); + + } while (--NumModes); + } + return OutputSize; +} + +/* EOF */ diff --git a/reactos/drivers/video/displays/vga/makefile b/reactos/drivers/video/displays/vga/makefile new file mode 100644 index 00000000000..71bb62480a3 --- /dev/null +++ b/reactos/drivers/video/displays/vga/makefile @@ -0,0 +1,47 @@ +# $Id: makefile,v 1.1 2004/01/10 14:39:20 navaraf Exp $ + +PATH_TO_TOP = ../../../.. + +TARGET_BASE = 0x70000000 + +TARGET_TYPE = gdi_driver + +TARGET_NAME = vgaddi + +TARGET_CFLAGS = -Wall -Werror + +MAIN_OBJECTS = \ + main/enable.o + +OTHER_OBJECTS = \ + objects/screen.o \ + objects/pointer.o \ + objects/lineto.o \ + objects/paint.o \ + objects/bitblt.o \ + objects/transblt.o \ + objects/offscreen.o \ + objects/copybits.o + +VGAVIDEO_OBJECTS = \ + vgavideo/vgavideo.o + +TARGET_OBJECTS = \ + $(MAIN_OBJECTS) \ + $(OTHER_OBJECTS) \ + $(VGAVIDEO_OBJECTS) + +TARGET_CLEAN = \ + main/*.o \ + objects/*.o \ + vgavideo/*.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# Automatic dependency tracking +DEP_OBJECTS := $(TARGET_OBJECTS) +include $(PATH_TO_TOP)/tools/depend.mk + +# EOF diff --git a/reactos/drivers/video/displays/vga/objects/.cvsignore b/reactos/drivers/video/displays/vga/objects/.cvsignore new file mode 100644 index 00000000000..0abd2c98ac8 --- /dev/null +++ b/reactos/drivers/video/displays/vga/objects/.cvsignore @@ -0,0 +1,3 @@ +*.o +*.map +.*.d diff --git a/reactos/drivers/video/displays/vga/objects/bitblt.c b/reactos/drivers/video/displays/vga/objects/bitblt.c new file mode 100644 index 00000000000..1a97f14c705 --- /dev/null +++ b/reactos/drivers/video/displays/vga/objects/bitblt.c @@ -0,0 +1,475 @@ +#include +#define NDEBUG +#include +#include "../vgaddi.h" +#include "../vgavideo/vgavideo.h" +#include "brush.h" +#include "bitblt.h" + +typedef BOOL (*PFN_VGABlt)(SURFOBJ*, SURFOBJ*, XLATEOBJ*, RECTL*, POINTL*); +typedef BOOL STDCALL (*PBLTRECTFUNC)(SURFOBJ* OutputObj, + SURFOBJ* InputObj, + SURFOBJ* Mask, + XLATEOBJ* ColorTranslation, + RECTL* OutputRect, + POINTL* InputPoint, + POINTL* MaskOrigin, + BRUSHOBJ* Brush, + POINTL* BrushOrigin, + ROP4 Rop4); + +static BOOL FASTCALL VGADDI_IntersectRect(RECTL* prcDst, RECTL* prcSrc1, RECTL* prcSrc2) +{ + static const RECTL rclEmpty = { 0, 0, 0, 0 }; + + prcDst->left = max(prcSrc1->left, prcSrc2->left); + prcDst->right = min(prcSrc1->right, prcSrc2->right); + + if (prcDst->left < prcDst->right) + { + prcDst->top = max(prcSrc1->top, prcSrc2->top); + prcDst->bottom = min(prcSrc1->bottom, prcSrc2->bottom); + + if (prcDst->top < prcDst->bottom) return(TRUE); + } + + *prcDst = rclEmpty; + + return(FALSE); +} + +void DIB_BltToVGA_Fixed(int x, int y, int w, int h, void *b, int Source_lDelta, int mod); + +BOOL +DIBtoVGA(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation, + RECTL *DestRect, POINTL *SourcePoint) +{ + LONG dx, dy; + + dx = DestRect->right - DestRect->left; + dy = DestRect->bottom - DestRect->top; + + if (NULL == ColorTranslation || 0 != (ColorTranslation->flXlate & XO_TRIVIAL)) + { + DIB_BltToVGA(DestRect->left, DestRect->top, dx, dy, + Source->pvScan0 + SourcePoint->y * Source->lDelta + (SourcePoint->x >> 1), + Source->lDelta, SourcePoint->x % 2); + } + else + { + /* Perform color translation */ + DIB_BltToVGAWithXlate(DestRect->left, DestRect->top, dx, dy, + Source->pvScan0 + SourcePoint->y * Source->lDelta + (SourcePoint->x >> 1), + Source->lDelta, ColorTranslation); + } + return FALSE; +} + +BOOL +VGAtoDIB(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation, + RECTL *DestRect, POINTL *SourcePoint) +{ + LONG i, j, dx, dy; + BYTE *GDIpos, *initial; + + // Used by the temporary DFB + DEVSURF DestDevSurf; + + // FIXME: Optimize to retrieve entire bytes at a time (see /display/vgavideo/vgavideo.c:vgaGetByte) + + GDIpos = Dest->pvBits /* + (DestRect->top * Dest->lDelta) + (DestRect->left >> 1) */ ; + dx = DestRect->right - DestRect->left; + dy = DestRect->bottom - DestRect->top; + + if(ColorTranslation == NULL) + { + // Prepare a Dest Dev Target and copy from the DFB to the DIB + DestDevSurf.NextScan = Dest->lDelta; + DestDevSurf.StartBmp = Dest->pvScan0; + + DIB_BltFromVGA(SourcePoint->x, SourcePoint->y, dx, dy, Dest->pvBits, Dest->lDelta); + + } else { + // Color translation + for(j=SourcePoint->y; jy+dy; j++) + { + initial = GDIpos; + for(i=SourcePoint->x; ix+dx; i++) + { + *GDIpos = XLATEOBJ_iXlate(ColorTranslation, vgaGetPixel(i, j)); + GDIpos+=1; + } + GDIpos = initial + Dest->lDelta; + } + } + return FALSE; +} + +BOOL +DFBtoVGA(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation, + RECTL *DestRect, POINTL *SourcePoint) +{ + return FALSE; + // Do DFBs need color translation?? +} + +BOOL +VGAtoDFB(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation, + RECTL *DestRect, POINTL *SourcePoint) +{ + return FALSE; + // Do DFBs need color translation?? +} + +BOOL +VGAtoVGA(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation, + RECTL *DestRect, POINTL *SourcePoint) +{ + LONG i, i2, j, dx, dy, alterx, altery; + //LARGE_INTEGER Start, End; // for performance measurement only + static char buf[640]; + + // Calculate deltas + + dx = DestRect->right - DestRect->left; + dy = DestRect->bottom - DestRect->top; + + alterx = DestRect->left - SourcePoint->x; + altery = DestRect->top - SourcePoint->y; + + //KeQueryTickCount ( &Start ); + + i = SourcePoint->x; + i2 = i + alterx; + + if (SourcePoint->y >= DestRect->top) + { + for(j=SourcePoint->y; jy+dy; j++) + { + LONG j2 = j + altery; + vgaReadScan ( i, j, dx, buf ); + vgaWriteScan ( i2, j2, dx, buf ); + } + } + else + { + for(j=(SourcePoint->y+dy-1); j>=SourcePoint->y; j--) + { + LONG j2 = j + altery; + vgaReadScan ( i, j, dx, buf ); + vgaWriteScan ( i2, j2, dx, buf ); + } + } + + //KeQueryTickCount ( &End ); + //DbgPrint ( "VgaBitBlt timing: %lu\n", (ULONG)(End.QuadPart-Start.QuadPart) ); + + return TRUE; +} + +BOOL STDCALL +VGADDI_BltBrush(SURFOBJ* Dest, SURFOBJ* Source, SURFOBJ* MaskSurf, + XLATEOBJ* ColorTranslation, RECTL* DestRect, + POINTL* SourcePoint, POINTL* MaskPoint, + BRUSHOBJ* Brush, POINTL* BrushPoint, ROP4 Rop4) +{ + UCHAR SolidColor = 0; + ULONG Left; + ULONG Length; + PUCHAR Video; + UCHAR Mask; + ULONG i, j; + ULONG RasterOp = VGA_NORMAL; + + /* Punt brush blts to non-device surfaces. */ + if (Dest->iType != STYPE_DEVICE) + { + return(FALSE); + } + + /* Punt pattern fills. */ + if ((Rop4 == PATCOPY || Rop4 == PATINVERT) && + Brush->iSolidColor == 0xFFFFFFFF) + { + return(FALSE); + } + + /* Get the brush colour. */ + switch (Rop4) + { + case PATCOPY: SolidColor = Brush->iSolidColor; break; + case PATINVERT: SolidColor = Brush->iSolidColor; RasterOp = VGA_XOR; break; + case WHITENESS: SolidColor = 0xF; break; + case BLACKNESS: SolidColor = 0x0; break; + case DSTINVERT: SolidColor = 0xF; RasterOp = VGA_XOR; break; + } + + /* Select write mode 3. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x03); + + /* Setup set/reset register. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x00); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, (UCHAR)SolidColor); + + /* Enable writes to all pixels. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0xFF); + + /* Set up data rotate. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, RasterOp); + + /* Fill any pixels on the left which don't fall into a full row of eight. */ + if ((DestRect->left % 8) != 0) + { + /* Disable writes to pixels outside of the destination rectangle. */ + Mask = (1 << (8 - (DestRect->left % 8))) - 1; + if ((DestRect->right - DestRect->left) < (8 - (DestRect->left % 8))) + { + Mask &= ~((1 << (8 - (DestRect->right % 8))) - 1); + } + + /* Write the same color to each pixel. */ + Video = (PUCHAR)vidmem + DestRect->top * 80 + (DestRect->left >> 3); + for (i = DestRect->top; i < DestRect->bottom; i++, Video+=80) + { + (VOID)READ_REGISTER_UCHAR(Video); + WRITE_REGISTER_UCHAR(Video, Mask); + } + + /* Have we finished. */ + if ((DestRect->right - DestRect->left) < (8 - (DestRect->left % 8))) + { + /* Restore write mode 2. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02); + + /* Set up data rotate. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00); + + return TRUE; + } + } + + /* Fill any whole rows of eight pixels. */ + Left = (DestRect->left + 7) & ~0x7; + Length = (DestRect->right >> 3) - (Left >> 3); + for (i = DestRect->top; i < DestRect->bottom; i++) + { + Video = (PUCHAR)vidmem + i * 80 + (Left >> 3); + for (j = 0; j < Length; j++, Video++) + { + (VOID)READ_REGISTER_UCHAR(Video); + WRITE_REGISTER_UCHAR(Video, 0xFF); + } + } + + /* Fill any pixels on the right which don't fall into a complete row. */ + if ((DestRect->right % 8) != 0) + { + /* Disable writes to pixels outside the destination rectangle. */ + Mask = ~((1 << (8 - (DestRect->right % 8))) - 1); + + Video = (PUCHAR)vidmem + DestRect->top * 80 + (DestRect->right >> 3); + for (i = DestRect->top; i < DestRect->bottom; i++, Video+=80) + { + (VOID)READ_REGISTER_UCHAR(Video); + WRITE_REGISTER_UCHAR(Video, Mask); + } + } + + /* Restore write mode 2. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02); + + /* Set up data rotate. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00); + + return TRUE; +} + +BOOL STDCALL +VGADDI_BltSrc(SURFOBJ* Dest, SURFOBJ* Source, SURFOBJ* Mask, + XLATEOBJ* ColorTranslation, RECTL* DestRect, POINTL* SourcePoint, + POINTL* MaskOrigin, BRUSHOBJ* Brush, POINTL* BrushOrigin, ROP4 Rop4) +{ + PFN_VGABlt BltOperation; + ULONG SourceType; + + SourceType = Source->iType; + + if (SourceType == STYPE_BITMAP && Dest->iType == STYPE_DEVICE) + { + BltOperation = DIBtoVGA; + } + else if (SourceType == STYPE_DEVICE && Dest->iType == STYPE_BITMAP) + { + BltOperation = VGAtoDIB; + } + else if (SourceType == STYPE_DEVICE && Dest->iType == STYPE_DEVICE) + { + BltOperation = VGAtoVGA; + } + else if (SourceType == STYPE_DEVBITMAP && Dest->iType == STYPE_DEVICE) + { + BltOperation = DFBtoVGA; + } + else if (SourceType == STYPE_DEVICE && Dest->iType == STYPE_DEVBITMAP) + { + BltOperation = VGAtoDFB; + } + else + { + /* Punt blts not involving a device or a device-bitmap. */ + return(FALSE); + } + + BltOperation(Dest, Source, ColorTranslation, DestRect, SourcePoint); + return(TRUE); +} + +BOOL STDCALL +VGADDI_BltMask(SURFOBJ* Dest, SURFOBJ* Source, SURFOBJ* Mask, + XLATEOBJ* ColorTranslation, RECTL* DestRect, + POINTL* SourcePoint, POINTL* MaskPoint, BRUSHOBJ* Brush, + POINTL* BrushPoint, ROP4 Rop4) +{ + LONG i, j, dx, dy, c8; + BYTE *tMask, *lMask; + + dx = DestRect->right - DestRect->left; + dy = DestRect->bottom - DestRect->top; + + if (ColorTranslation == NULL) + { + if (Mask != NULL) + { + tMask = Mask->pvBits; + for (j=0; jleft + i, DestRect->top + j, Brush->iSolidColor); + } + c8++; + if(c8 == 8) { lMask++; c8=0; } + } + tMask += Mask->lDelta; + } + } + } + return TRUE; +} + +BOOL STDCALL +DrvBitBlt(SURFOBJ *Dest, + SURFOBJ *Source, + SURFOBJ *Mask, + CLIPOBJ *Clip, + XLATEOBJ *ColorTranslation, + RECTL *DestRect, + POINTL *SourcePoint, + POINTL *MaskPoint, + BRUSHOBJ *Brush, + POINTL *BrushPoint, + ROP4 rop4) +{ + PBLTRECTFUNC BltRectFunc; + RECTL CombinedRect; + BOOL Ret; + RECT_ENUM RectEnum; + BOOL EnumMore; + unsigned i; + POINTL Pt; + ULONG Direction; + + switch (rop4) + { + case BLACKNESS: + case PATCOPY: + case WHITENESS: + case PATINVERT: + case DSTINVERT: + BltRectFunc = VGADDI_BltBrush; + break; + + case SRCCOPY: + if (BMF_4BPP == Source->iBitmapFormat && BMF_4BPP == Dest->iBitmapFormat) + { + BltRectFunc = VGADDI_BltSrc; + } + else + { + return FALSE; + } + break; + + case 0xAACC: + BltRectFunc = VGADDI_BltMask; + break; + + default: + return FALSE; + } + + switch(NULL == Clip ? DC_TRIVIAL : Clip->iDComplexity) + { + case DC_TRIVIAL: + Ret = (*BltRectFunc)(Dest, Source, Mask, ColorTranslation, DestRect, + SourcePoint, MaskPoint, Brush, BrushPoint, + rop4); + break; + case DC_RECT: + // Clip the blt to the clip rectangle + VGADDI_IntersectRect(&CombinedRect, DestRect, &(Clip->rclBounds)); + Pt.x = SourcePoint->x + CombinedRect.left - DestRect->left; + Pt.y = SourcePoint->y + CombinedRect.top - DestRect->top; + Ret = (*BltRectFunc)(Dest, Source, Mask, ColorTranslation, &CombinedRect, + &Pt, MaskPoint, Brush, BrushPoint, + rop4); + break; + case DC_COMPLEX: + Ret = TRUE; + if (Dest == Source) + { + if (DestRect->top <= SourcePoint->y) + { + Direction = DestRect->left < SourcePoint->x ? CD_RIGHTDOWN : CD_LEFTDOWN; + } + else + { + Direction = DestRect->left < SourcePoint->x ? CD_RIGHTUP : CD_LEFTUP; + } + } + else + { + Direction = CD_ANY; + } + CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, Direction, 0); + do + { + EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); + + for (i = 0; i < RectEnum.c; i++) + { + VGADDI_IntersectRect(&CombinedRect, DestRect, RectEnum.arcl + i); + Pt.x = SourcePoint->x + CombinedRect.left - DestRect->left; + Pt.y = SourcePoint->y + CombinedRect.top - DestRect->top; + Ret = (*BltRectFunc)(Dest, Source, Mask, ColorTranslation, &CombinedRect, + &Pt, MaskPoint, Brush, BrushPoint, rop4) && + Ret; + } + } + while (EnumMore); + break; + } + + return Ret; +} diff --git a/reactos/drivers/video/displays/vga/objects/bitblt.h b/reactos/drivers/video/displays/vga/objects/bitblt.h new file mode 100644 index 00000000000..2f5d359eb81 --- /dev/null +++ b/reactos/drivers/video/displays/vga/objects/bitblt.h @@ -0,0 +1,22 @@ +/// Define the A vector polynomial bits +// Each bit corresponds to one of the terms in the polynomial +// +// Rop(D,S,P) = a + a D + a S + a P + a DS + a DP + a SP + a DSP +// 0 d s p ds dp sp dsp + +#define AVEC_NOT 0x01 +#define AVEC_D 0x02 +#define AVEC_S 0x04 +#define AVEC_P 0x08 +#define AVEC_DS 0x10 +#define AVEC_DP 0x20 +#define AVEC_SP 0x40 +#define AVEC_DSP 0x80 + +#define AVEC_NEED_SOURCE (AVEC_S | AVEC_DS | AVEC_SP | AVEC_DSP) +#define AVEC_NEED_PATTERN (AVEC_P | AVEC_DP | AVEC_SP | AVEC_DSP) + +#define BB_TARGET_SCREEN 0x0001 +#define BB_TARGET_ONLY 0x0002 +#define BB_SOURCE_COPY 0x0004 +#define BB_PATTERN_COPY 0x0008 diff --git a/reactos/drivers/video/displays/vga/objects/brush.h b/reactos/drivers/video/displays/vga/objects/brush.h new file mode 100644 index 00000000000..bbcc82611c5 --- /dev/null +++ b/reactos/drivers/video/displays/vga/objects/brush.h @@ -0,0 +1,58 @@ +typedef struct _BRUSHINST +{ + // We need to removed ajC0-3 when color pattern code is complete!!! + // + BYTE ajC0[8]; // Color bits for plane 0 + BYTE ajC1[8]; // Color bits for plane 1 + BYTE ajC2[8]; // Color bits for plane 2 + BYTE ajC3[8]; // Color bits for plane 3 + + BYTE ajPattern[32]; // Color bits for the mask + USHORT usStyle; // Brush style + BYTE fjAccel; // Accelerator flags + BYTE jFgColor; // Current foreground color + BYTE jBkColor; // Current background color + BYTE RealWidth; // + BYTE YShiftValue; // + BYTE jOldBrushRealized; // + DWORD Width; // Width of brush + DWORD Height; + BYTE *pPattern; //Pointer to realized mono pattern +} BRUSHINST; + +#define BRI_SOLID 0 +#define BRI_HOLLOW 1 +#define BRI_HATCHED 2 +#define BRI_PATTERN 3 +#define BRI_MONO_PATTERN 4 +#define BRI_COLOR_PATTERN 5 + +// Definitions for the pcol_C3 byte of the physical color +// +// Some of these definitions have limitations as to when they +// are valid. They are as follows: +// +// C0_BIT color device, phys color, solid brushes if SOLID_COLOR +// C1_BIT color device, phys color, solid brushes if SOLID_COLOR +// C2_BIT color device, phys color, solid brushes if SOLID_COLOR +// C3_BIT color device, phys color, solid brushes if SOLID_COLOR +// MONO_BIT mono device, phys color +// ONES_OR_ZEROS color device, phys color, solid brushes if SOLID_COLOR +// GREY_SCALE color device, dithered solid and hatched brushes +// SOLID_BRUSH color device, solid brush qualifier +// +// There may be brushes where the accelerators could have been set, +// but wasn't. That's life. + +#define C0_BIT 0x01 // C0 color +#define C1_BIT 0x02 // C1 color +#define C2_BIT 0x04 // C2 color +#define C3_BIT 0x08 // C3 color +#define COLOR_BITS 0x0f // All the color bits +#define MONO_BIT 0x10 // Monochrome bit +#define ONES_OR_ZEROS 0x20 // Color is really all 1's or all 0's +#define GREY_SCALE 0x40 // Indicates a real grey scale brush +#define SOLID_BRUSH 0x80 // Indicates a solid color brush + +#define PTRI_INVERT 0x0001 +#define PTRI_ANIMATE 0x0002 diff --git a/reactos/drivers/video/displays/vga/objects/copybits.c b/reactos/drivers/video/displays/vga/objects/copybits.c new file mode 100644 index 00000000000..dd072b2ef47 --- /dev/null +++ b/reactos/drivers/video/displays/vga/objects/copybits.c @@ -0,0 +1,40 @@ +#include "../vgaddi.h" +#include "../vgavideo/vgavideo.h" + +#define DBG +#include + +BOOL STDCALL +DrvCopyBits(OUT SURFOBJ* DestObj, + IN SURFOBJ* SourceObj, + IN CLIPOBJ* ClipObj, + IN XLATEOBJ* XLateObj, + IN RECTL* DestRectL, + IN POINTL* SrcPointL) +{ + BOOL Done = FALSE; + + if (STYPE_BITMAP == DestObj->iType && BMF_4BPP == DestObj->iBitmapFormat && + STYPE_DEVICE == SourceObj->iType) + { + /* Screen to 4 BPP DIB */ + DIB_BltFromVGA(SrcPointL->x, SrcPointL->y, + DestRectL->right - DestRectL->left, + DestRectL->bottom - DestRectL->top, + DestObj->pvScan0, DestObj->lDelta); + Done = TRUE; + } + else if (STYPE_DEVICE == DestObj->iType && + STYPE_BITMAP == SourceObj->iType && BMF_4BPP == SourceObj->iBitmapFormat) + { + /* 4 BPP DIB to Screen */ + DIB_BltToVGA(DestRectL->left, DestRectL->top, + DestRectL->right - DestRectL->left, + DestRectL->bottom - DestRectL->top, + SourceObj->pvScan0, SourceObj->lDelta, + 0); + Done = TRUE; + } + + return Done; +} diff --git a/reactos/drivers/video/displays/vga/objects/lineto.c b/reactos/drivers/video/displays/vga/objects/lineto.c new file mode 100644 index 00000000000..80d8a11caac --- /dev/null +++ b/reactos/drivers/video/displays/vga/objects/lineto.c @@ -0,0 +1,413 @@ +/* + * ReactOS VGA driver + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id: lineto.c,v 1.1 2004/01/10 14:39:20 navaraf Exp $ + */ + +#include "../vgaddi.h" +#include "../vgavideo/vgavideo.h" + +/* + * Draw a line from top-left to bottom-right + */ +static void FASTCALL +vgaNWtoSE(CLIPOBJ* Clip, BRUSHOBJ* Brush, LONG x, LONG y, LONG deltax, LONG deltay) +{ + int i; + int error; + BOOLEAN EnumMore; + PRECTL ClipRect; + RECT_ENUM RectEnum; + ULONG Pixel = Brush->iSolidColor; + LONG delta; + + CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0); + EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); + ClipRect = RectEnum.arcl; + delta = max(deltax, deltay); + i = 0; + error = delta/2; + while (i < delta && (ClipRect < RectEnum.arcl + RectEnum.c || EnumMore)) + { + while ((ClipRect < RectEnum.arcl + RectEnum.c /* there's still a current clip rect */ + && (ClipRect->bottom <= y /* but it's above us */ + || (ClipRect->top <= y && ClipRect->right <= x))) /* or to the left of us */ + || EnumMore) /* no current clip rect, but rects left */ + { + /* Skip to the next clip rect */ + if (RectEnum.arcl + RectEnum.c <= ClipRect) + { + EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); + ClipRect = RectEnum.arcl; + } + else + { + ClipRect++; + } + } + if ( ClipRect < RectEnum.arcl + RectEnum.c ) /* If there's no current clip rect we're done */ + { + if (ClipRect->left <= x && ClipRect->top <= y) + { + vgaPutPixel ( x, y, Pixel ); + } + if ( deltax < deltay ) + { + y++; + error += deltax; + if ( error >= deltay ) + { + x++; + error -= deltay; + } + } + else + { + x++; + error += deltay; + if ( error >= deltax ) + { + y++; + error -= deltax; + } + } + i++; + } + } +} + +static void FASTCALL +vgaSWtoNE(CLIPOBJ* Clip, BRUSHOBJ* Brush, LONG x, LONG y, LONG deltax, LONG deltay) +{ + int i; + int error; + BOOLEAN EnumMore; + PRECTL ClipRect; + RECT_ENUM RectEnum; + ULONG Pixel = Brush->iSolidColor; + LONG delta; + + CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTUP, 0); + EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); + ClipRect = RectEnum.arcl; + delta = max(deltax, deltay); + i = 0; + error = delta/2; + while (i < delta && (ClipRect < RectEnum.arcl + RectEnum.c || EnumMore)) + { + while ((ClipRect < RectEnum.arcl + RectEnum.c + && (y < ClipRect->top + || (y < ClipRect->bottom && ClipRect->right <= x))) + || EnumMore) + { + if (RectEnum.arcl + RectEnum.c <= ClipRect) + { + EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); + ClipRect = RectEnum.arcl; + } + else + { + ClipRect++; + } + } + if (ClipRect < RectEnum.arcl + RectEnum.c) + { + if (ClipRect->left <= x && y < ClipRect->bottom) + { + vgaPutPixel(x, y, Pixel); + } + if (deltax < deltay) + { + y--; + error = error + deltax; + if (deltay <= error) + { + x++; + error = error - deltay; + } + } + else + { + x++; + error = error + deltay; + if (deltax <= error) + { + y--; + error = error - deltax; + } + } + i++; + } + } +} + +static void FASTCALL +vgaNEtoSW(CLIPOBJ* Clip, BRUSHOBJ* Brush, LONG x, LONG y, LONG deltax, LONG deltay) +{ + int i; + int error; + BOOLEAN EnumMore; + PRECTL ClipRect; + RECT_ENUM RectEnum; + ULONG Pixel = Brush->iSolidColor; + LONG delta; + + CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_LEFTDOWN, 0); + EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); + ClipRect = RectEnum.arcl; + delta = max(deltax, deltay); + i = 0; + error = delta/2; + while (i < delta && (ClipRect < RectEnum.arcl + RectEnum.c || EnumMore)) + { + while ((ClipRect < RectEnum.arcl + RectEnum.c + && (ClipRect->bottom <= y + || (ClipRect->top <= y && x < ClipRect->left))) + || EnumMore) + { + if (RectEnum.arcl + RectEnum.c <= ClipRect) + { + EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); + ClipRect = RectEnum.arcl; + } + else + { + ClipRect++; + } + } + if (ClipRect < RectEnum.arcl + RectEnum.c) + { + if (x < ClipRect->right && ClipRect->top <= y) + { + vgaPutPixel(x, y, Pixel); + } + if (deltax < deltay) + { + y++; + error = error + deltax; + if (deltay <= error) + { + x--; + error = error - deltay; + } + } + else + { + x--; + error = error + deltay; + if (deltax <= error) + { + y++; + error = error - deltax; + } + } + i++; + } + } +} + +static void FASTCALL +vgaSEtoNW(CLIPOBJ* Clip, BRUSHOBJ* Brush, LONG x, LONG y, LONG deltax, LONG deltay) +{ + int i; + int error; + BOOLEAN EnumMore; + PRECTL ClipRect; + RECT_ENUM RectEnum; + ULONG Pixel = Brush->iSolidColor; + LONG delta; + + CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_LEFTUP, 0); + EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); + ClipRect = RectEnum.arcl; + delta = max(deltax, deltay); + i = 0; + error = delta/2; + while (i < delta && (ClipRect < RectEnum.arcl + RectEnum.c || EnumMore)) + { + while ((ClipRect < RectEnum.arcl + RectEnum.c + && (y < ClipRect->top + || (y < ClipRect->bottom && x < ClipRect->left))) + || EnumMore) + { + if (RectEnum.arcl + RectEnum.c <= ClipRect) + { + EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); + ClipRect = RectEnum.arcl; + } + else + { + ClipRect++; + } + } + if (ClipRect < RectEnum.arcl + RectEnum.c) + { + if (x < ClipRect->right && y < ClipRect->bottom) + { + vgaPutPixel(x, y, Pixel); + } + if (deltax < deltay) + { + y--; + error = error + deltax; + if (deltay <= error) + { + x--; + error = error - deltay; + } + } + else + { + x--; + error = error + deltay; + if (deltax <= error) + { + y--; + error = error - deltax; + } + } + i++; + } + } +} + +/* + * FIXME: Use Mix to perform ROPs + * FIXME: Non-solid Brush + */ +BOOL STDCALL +DrvLineTo(SURFOBJ *DestObj, + CLIPOBJ *Clip, + BRUSHOBJ *Brush, + LONG x1, + LONG y1, + LONG x2, + LONG y2, + RECTL *RectBounds, + MIX mix) +{ + LONG x, y, deltax, deltay, i, xchange, ychange, hx, vy; + ULONG Pixel = Brush->iSolidColor; + RECT_ENUM RectEnum; + BOOL EnumMore; + + x = x1; + y = y1; + deltax = x2 - x1; + deltay = y2 - y1; + + if (deltax < 0) + { + xchange = -1; + deltax = - deltax; + hx = x2+1; + //x--; + } + else + { + xchange = 1; + hx = x1; + } + + if (deltay < 0) + { + ychange = -1; + deltay = - deltay; + vy = y2+1; + //y--; + } + else + { + ychange = 1; + vy = y1; + } + + if (y1 == y2) + { + CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0); + do + { + EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); + for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= y1; i++) + { + if (y1 < RectEnum.arcl[i].bottom && + RectEnum.arcl[i].left <= hx + deltax && + hx < RectEnum.arcl[i].right) + { + + vgaHLine(max(hx, RectEnum.arcl[i].left), y1, + min(hx + deltax, RectEnum.arcl[i].right) + -max(hx, RectEnum.arcl[i].left), Pixel); + } + } + } + while (EnumMore); + } + else if (x1 == x2) + { + CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0); + do + { + EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); + for (i = 0; i < RectEnum.c; i++) + { + if (RectEnum.arcl[i].left <= x1 && + x1 < RectEnum.arcl[i].right && + RectEnum.arcl[i].top <= vy + deltay && + vy < RectEnum.arcl[i].bottom) + { + vgaVLine(x1, + max(vy, RectEnum.arcl[i].top), + min(vy + deltay, RectEnum.arcl[i].bottom) + - max(vy, RectEnum.arcl[i].top), + Pixel); + } + } + } + while (EnumMore); + } + else + { + if (0 < xchange) + { + if (0 < ychange) + { + vgaNWtoSE(Clip, Brush, x, y, deltax, deltay); + } + else + { + vgaSWtoNE(Clip, Brush, x, y, deltax, deltay); + } + } + else + { + if (0 < ychange) + { + vgaNEtoSW(Clip, Brush, x, y, deltax, deltay); + } + else + { + vgaSEtoNW(Clip, Brush, x, y, deltax, deltay); + } + } + } + + return TRUE; +} + +/* EOF */ diff --git a/reactos/drivers/video/displays/vga/objects/offscreen.c b/reactos/drivers/video/displays/vga/objects/offscreen.c new file mode 100644 index 00000000000..92f8e854f4e --- /dev/null +++ b/reactos/drivers/video/displays/vga/objects/offscreen.c @@ -0,0 +1,193 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id: offscreen.c,v 1.1 2004/01/10 14:39:20 navaraf Exp $ + * + * PROJECT: ReactOS VGA16 display driver + * FILE: drivers/dd/vga/display/objects/offscreen.c + * PURPOSE: Manages off-screen video memory. + */ + +/* INCLUDES ******************************************************************/ + +#include "../vgaddi.h" +#include "../vgavideo/vgavideo.h" +#include + +/* GLOBALS *******************************************************************/ + +static LIST_ENTRY SavedBitsList; + +/* FUNCTIONS *****************************************************************/ + +VOID +VGADDI_BltFromSavedScreenBits(ULONG DestX, + ULONG DestY, + PSAVED_SCREEN_BITS Src, + ULONG SizeX, + ULONG SizeY) +{ + PUCHAR DestOffset; + PUCHAR SrcOffset; + ULONG i, j; + + /* Select write mode 1. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 1); + + SrcOffset = (PUCHAR)vidmem + Src->Offset; + for (i = 0; i < SizeY; i++) + { + DestOffset = (PUCHAR)vidmem + (i + DestY) * 80 + (DestX >> 3); + //FIXME: in the loop below we should treat the case when SizeX is not divisible by 8, i.e. partial bytes + for (j = 0; j < SizeX>>3; j++, SrcOffset++, DestOffset++) + { + (VOID)READ_REGISTER_UCHAR(SrcOffset); + WRITE_REGISTER_UCHAR(DestOffset, 0); + } + } + + /* Select write mode 2. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 2); +} + +VOID +VGADDI_BltToSavedScreenBits(PSAVED_SCREEN_BITS Dest, + ULONG SourceX, + ULONG SourceY, + ULONG SizeX, + ULONG SizeY) +{ + PUCHAR DestOffset; + PUCHAR SrcOffset; + ULONG i, j; + + /* Select write mode 1. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 1); + + DestOffset = (PUCHAR)vidmem + Dest->Offset; + + for (i = 0; i < SizeY; i++) + { + SrcOffset = (PUCHAR)vidmem + (SourceY + i) * 80 + (SourceX >> 3); + //FIXME: in the loop below we should treat the case when SizeX is not divisible by 8, i.e. partial bytes + for (j = 0; j < SizeX>>3; j++, SrcOffset++, DestOffset++) + { + (VOID)READ_REGISTER_UCHAR(SrcOffset); + WRITE_REGISTER_UCHAR(DestOffset, 0); + } + } + + /* Select write mode 2. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 2); +} + +VOID +VGADDI_FreeSavedScreenBits(PSAVED_SCREEN_BITS SavedBits) +{ + SavedBits->Free = TRUE; + + if (SavedBits->ListEntry.Blink != &SavedBitsList) + { + PSAVED_SCREEN_BITS Previous; + + Previous = CONTAINING_RECORD(SavedBits->ListEntry.Blink, + SAVED_SCREEN_BITS, ListEntry); + if (Previous->Free) + { + Previous->Size += SavedBits->Size; + RemoveEntryList(&SavedBits->ListEntry); + EngFreeMem(SavedBits); + SavedBits = Previous; + } + } + if (SavedBits->ListEntry.Flink != &SavedBitsList) + { + PSAVED_SCREEN_BITS Next; + + Next = CONTAINING_RECORD(SavedBits->ListEntry.Flink, SAVED_SCREEN_BITS, + ListEntry); + if (Next->Free) + { + SavedBits->Size += Next->Size; + RemoveEntryList(&SavedBits->ListEntry); + EngFreeMem(SavedBits); + } + } +} + +PSAVED_SCREEN_BITS +VGADDI_AllocSavedScreenBits(ULONG Size) +{ + PSAVED_SCREEN_BITS Current; + PLIST_ENTRY CurrentEntry; + PSAVED_SCREEN_BITS Best; + PSAVED_SCREEN_BITS New; + + Best = NULL; + CurrentEntry = SavedBitsList.Flink; + while (CurrentEntry != &SavedBitsList) + { + Current = CONTAINING_RECORD(CurrentEntry, SAVED_SCREEN_BITS, ListEntry); + + if (Current->Free && Current->Size >= Size && + (Best == NULL || (Current->Size - Size) < (Best->Size - Size))) + { + Best = Current; + } + + CurrentEntry = CurrentEntry->Flink; + } + + if (Best == NULL) + { + return(NULL); + } + if (Best->Size == Size) + { + Best->Free = FALSE; + return(Best); + } + else + { + New = EngAllocMem(0, sizeof(SAVED_SCREEN_BITS), ALLOC_TAG); + New->Free = FALSE; + New->Offset = Best->Offset + Size; + New->Size = Size; + Best->Size -= Size; + InsertHeadList(&Best->ListEntry, &New->ListEntry); + return(New); + } +} + +VOID +VGADDI_InitializeOffScreenMem(ULONG Start, ULONG Length) +{ + PSAVED_SCREEN_BITS FreeBits; + + InitializeListHead(&SavedBitsList); + + FreeBits = EngAllocMem(0, sizeof(SAVED_SCREEN_BITS), ALLOC_TAG); + FreeBits->Free = TRUE; + FreeBits->Offset = Start; + FreeBits->Size = Length; + InsertHeadList(&SavedBitsList, &FreeBits->ListEntry); +} diff --git a/reactos/drivers/video/displays/vga/objects/paint.c b/reactos/drivers/video/displays/vga/objects/paint.c new file mode 100644 index 00000000000..af95f60c065 --- /dev/null +++ b/reactos/drivers/video/displays/vga/objects/paint.c @@ -0,0 +1,245 @@ + +#include "../vgaddi.h" +#include "../vgavideo/vgavideo.h" +#include "brush.h" + +#include + +BOOL VGADDIFillSolid(SURFOBJ *Surface, RECTL Dimensions, ULONG iColor) +{ + int x, y, x2, y2, w, h; + ULONG offset, j, pre1; + ULONG orgpre1, orgx, midpre1, tmppre1; + ULONG ileftpix, imidpix, irightpix; + double leftpix, midpix, rightpix; + UCHAR a; + + DPRINT("VGADDIFillSolid: x:%d, y:%d, w:%d, h:%d\n", x, y, w, h); + + // Swap dimensions so that x, y are at topmost left + if ( Dimensions.right < Dimensions.left ) + { + x = Dimensions.right; + x2 = Dimensions.left; + } + else + { + x2 = Dimensions.right; + x = Dimensions.left; + } + if ( Dimensions.bottom < Dimensions.top ) + { + y = Dimensions.bottom; + y2 = Dimensions.top; + } + else + { + y2 = Dimensions.bottom; + y = Dimensions.top; + } + + // Calculate the width and height + w = x2 - x; + h = y2 - y; + + // Calculate the starting offset + offset = xconv[x]+y80[y]; + + // Make a note of original x + orgx = x; + + // Calculate the left mask pixels, middle bytes and right mask pixel + ileftpix = 7 - mod8(x-1); + rightpix = mod8(x+w); + midpix = (w-leftpix-rightpix) / 8; + + ileftpix = leftpix; + irightpix = rightpix; + imidpix = midpix; + + pre1 = xconv[(x-1)&~7] + y80[y]; + orgpre1=pre1; + + // check for overlap ( very horizontally skinny rect ) + if ( (ileftpix+irightpix) > w ) + { + int mask = startmasks[ileftpix] & endmasks[irightpix]; + + WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08); // set the mask + WRITE_PORT_UCHAR((PUCHAR)GRA_D,mask); + + tmppre1 = pre1; + for ( j = y; j < y+h; j++ ) + { + a = READ_REGISTER_UCHAR ( vidmem+tmppre1 ); + WRITE_REGISTER_UCHAR ( vidmem+tmppre1, iColor ); + tmppre1 += 80; + } + return TRUE; + } + + if ( ileftpix > 0 ) + { + // Write left pixels + WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08); // set the mask + WRITE_PORT_UCHAR((PUCHAR)GRA_D,startmasks[ileftpix]); + + tmppre1 = pre1; + for ( j = y; j < y+h; j++ ) + { + a = READ_REGISTER_UCHAR(vidmem + tmppre1); + WRITE_REGISTER_UCHAR(vidmem + tmppre1, iColor); + tmppre1 += 80; + } + + // Prepare new x for the middle + x = orgx + 8; + } + + if ( imidpix > 0 ) + { + midpre1=xconv[x] + y80[y]; + + // Set mask to all pixels in byte + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08); + + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0xff); + + for ( j = y; j < y+h; j++ ) + { + memset(vidmem+midpre1, iColor, imidpix); // write middle pixels, no need to read in latch because of the width + midpre1 += 80; + } + } + + x = orgx + w - irightpix; + pre1 = xconv[x] + y80[y]; + + // Write right pixels + WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08); // set the mask bits + WRITE_PORT_UCHAR((PUCHAR)GRA_D,endmasks[irightpix]); + + for ( j = y; j < y+h; j++ ) + { + a = READ_REGISTER_UCHAR(vidmem + pre1); + WRITE_REGISTER_UCHAR(vidmem + pre1, iColor); + pre1 += 80; + } + + return TRUE; +} + +BOOL VGADDIPaintRgn(SURFOBJ *Surface, CLIPOBJ *ClipRegion, ULONG iColor, MIX Mix, + BRUSHINST *BrushInst, POINTL *BrushPoint) +{ + RECT_ENUM RectEnum; + BOOL EnumMore; + + DPRINT("VGADDIPaintRgn: iMode: %d, iDComplexity: %d\n Color:%d\n", ClipRegion->iMode, ClipRegion->iDComplexity, iColor); + switch(ClipRegion->iMode) { + + case TC_RECTANGLES: + + /* Rectangular clipping can be handled without enumeration. + Note that trivial clipping is not possible, since the clipping + region defines the area to fill */ + + if (ClipRegion->iDComplexity == DC_RECT) + { + DPRINT("VGADDIPaintRgn Rect:%d %d %d %d\n", ClipRegion->rclBounds.left, ClipRegion->rclBounds.top, ClipRegion->rclBounds.right, ClipRegion->rclBounds.bottom); + VGADDIFillSolid(Surface, ClipRegion->rclBounds, iColor); + } else { + /* Enumerate all the rectangles and draw them */ + + CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, CD_ANY, 0); + + do { + int i; + EnumMore = CLIPOBJ_bEnum(ClipRegion, sizeof(RectEnum), (PVOID) &RectEnum); + DPRINT("EnumMore: %d, count: %d\n", EnumMore, RectEnum.c); + for( i=0; iiSolidColor; // FIXME: Realizations and the like + + // If the foreground and background Mixes are the same, + // (LATER or if there's no brush mask) + // then see if we can use the solid brush accelerators + + // FIXME: Put in the mix switch below + // Brush color parameter doesn't matter for these rops + return(VGADDIPaintRgn(Surface, ClipRegion, iSolidColor, Mix, NULL, BrushOrigin)); + + if ((Mix & 0xFF) == ((Mix >> 8) & 0xFF)) + { + switch (Mix & 0xFF) + { + case 0: + break; + + // FIXME: Implement all these millions of ROPs + // For now we don't support brushes -- everything is solid + + case R2_MASKNOTPEN: + case R2_NOTCOPYPEN: + case R2_XORPEN: + case R2_MASKPEN: + case R2_NOTXORPEN: + case R2_MERGENOTPEN: + case R2_COPYPEN: + case R2_MERGEPEN: + case R2_NOTMERGEPEN: + case R2_MASKPENNOT: + case R2_NOTMASKPEN: + case R2_MERGEPENNOT: + + // Rops that are implicit solid colors + case R2_NOT: + case R2_WHITE: + case R2_BLACK: + + + // FIXME: The Paint region belongs HERE + + case R2_NOP: + return(TRUE); + + default: + break; + } + } + +/* +doBitBlt: + + // If VGADDIPaint can't do it, VGADDIBitBlt can.. or it might just loop back + // here and we have a nice infinite loop + + return( VGADDIBitBlt(Surface, (SURFOBJ *)NULL, (SURFOBJ *)NULL, ClipRegion, + (XLATEOBJ *)NULL, &ClipRegion->rclBounds, + NULL, (POINTL *)NULL, Brush, BrushOrigin, + NULL) ); UNIMPLEMENTED */ +} diff --git a/reactos/drivers/video/displays/vga/objects/pointer.c b/reactos/drivers/video/displays/vga/objects/pointer.c new file mode 100644 index 00000000000..91f340810ff --- /dev/null +++ b/reactos/drivers/video/displays/vga/objects/pointer.c @@ -0,0 +1,382 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id: pointer.c,v 1.1 2004/01/10 14:39:20 navaraf Exp $ + * + * PROJECT: ReactOS VGA16 display driver + * FILE: drivers/dd/vga/display/objects/pointer.c + * PURPOSE: Draws the mouse pointer. + */ + +/* INCLUDES ******************************************************************/ + +#include "../vgaddi.h" +#include "../vgavideo/vgavideo.h" + +/* GLOBALS *******************************************************************/ + +static LONG oldx, oldy; +static PSAVED_SCREEN_BITS ImageBehindCursor = NULL; +VOID VGADDI_HideCursor(PPDEV ppdev); +VOID VGADDI_ShowCursor(PPDEV ppdev); + +/* FUNCTIONS *****************************************************************/ + +VOID +VGADDI_BltPointerToVGA(LONG StartX, LONG StartY, ULONG SizeX, + ULONG SizeY, PUCHAR MaskBits, ULONG MaskPitch, ULONG MaskOp) +{ + ULONG DestX, EndX, DestY, EndY; + UCHAR Mask; + PUCHAR Video; + PUCHAR Src; + UCHAR SrcValue; + ULONG i, j; + ULONG Left; + ULONG Length; + LONG Bits; + + DestX = StartX < 0 ? 0 : StartX; + DestY = StartY < 0 ? 0 : StartY; + EndX = StartX + SizeX; + EndY = StartY + SizeY; + + /* Set write mode zero. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0); + + /* Select raster op. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 3); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, MaskOp); + + if ((DestX % 8) != 0) + { + /* Disable writes to pixels outside of the destination rectangle. */ + Mask = (1 << (8 - (DestX % 8))) - 1; + if ((EndX - DestX) < (8 - (DestX % 8))) + { + Mask &= ~((1 << (8 - (EndX % 8))) - 1); + } + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x8); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, Mask); + + /* Write the mask. */ + Video = (PUCHAR)vidmem + DestY * 80 + (DestX >> 3); + Src = MaskBits + (SizeY - (DestY - StartY)) * MaskPitch; + for (i = DestY; i < EndY; i++, Video += 80) + { + Src -= MaskPitch; + SrcValue = (*Src) >> (DestX % 8); + (VOID)READ_REGISTER_UCHAR(Video); + WRITE_REGISTER_UCHAR(Video, SrcValue); + } + } + + /* Enable writes to all pixels. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x8); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0xFF); + + /* Have we finished. */ + if ((EndX - DestX) < (8 - (DestX % 8))) + { + return; + } + + /* Fill any whole rows of eight pixels. */ + Left = (DestX + 7) & ~0x7; + Length = (EndX >> 3) - (Left >> 3); + Bits = StartX; + while (Bits < 0) + { + Bits += 8; + } + Bits = Bits % 8; + for (i = DestY; i < EndY; i++) + { + Video = (PUCHAR)vidmem + i * 80 + (Left >> 3); + Src = MaskBits + (EndY - i - 1) * MaskPitch + ((DestX - StartX) >> 3); + for (j = 0; j < Length; j++, Video++, Src++) + { + if (Bits != 0) + { + SrcValue = (Src[0] << (8 - Bits)); + SrcValue |= (Src[1] >> Bits); + } + else + { + SrcValue = Src[0]; + } + (VOID)READ_REGISTER_UCHAR(Video); + WRITE_REGISTER_UCHAR(Video, SrcValue); + } + } + + /* Fill any pixels on the right which don't fall into a complete row. */ + if ((EndX % 8) != 0) + { + /* Disable writes to pixels outside the destination rectangle. */ + Mask = ~((1 << (8 - (EndX % 8))) - 1); + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x8); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, Mask); + + Video = (PUCHAR)vidmem + DestY * 80 + (EndX >> 3); + Src = MaskBits + (SizeY - (DestY - StartY)) * MaskPitch + (SizeX >> 3) - 1; + for (i = DestY; i < EndY; i++, Video+=80) + { + Src -= MaskPitch; + SrcValue = (Src[0] << (8 - Bits)); + (VOID)READ_REGISTER_UCHAR(Video); + WRITE_REGISTER_UCHAR(Video, SrcValue); + } + + /* Restore the default write masks. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x8); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0xFF); + } + + /* Set write mode two. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 2); + + /* Select raster op replace. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 3); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0); +} + +BOOL InitPointer(PPDEV ppdev) +{ + ULONG CursorWidth = 32, CursorHeight = 32; + ULONG PointerAttributesSize; + ULONG SavedMemSize; + + /* Determine the size of the pointer attributes */ + PointerAttributesSize = sizeof(VIDEO_POINTER_ATTRIBUTES) + + ((CursorWidth * CursorHeight * 2) >> 3); + + /* Allocate memory for pointer attributes */ + ppdev->pPointerAttributes = EngAllocMem(0, PointerAttributesSize, ALLOC_TAG); + + ppdev->pPointerAttributes->Flags = 0; /* FIXME: Do this right */ + ppdev->pPointerAttributes->Width = CursorWidth; + ppdev->pPointerAttributes->Height = CursorHeight; + ppdev->pPointerAttributes->WidthInBytes = CursorWidth >> 3; + ppdev->pPointerAttributes->Enable = 0; + ppdev->pPointerAttributes->Column = 0; + ppdev->pPointerAttributes->Row = 0; + + /* Allocate memory for the pixels behind the cursor */ + SavedMemSize = ((((CursorWidth + 7) & ~0x7) + 16) * CursorHeight) >> 3; + ImageBehindCursor = VGADDI_AllocSavedScreenBits(SavedMemSize); + + return(TRUE); +} + +VOID STDCALL +DrvMovePointer(IN SURFOBJ* pso, + IN LONG x, + IN LONG y, + IN PRECTL prcl) +{ + PPDEV ppdev = (PPDEV)pso->dhpdev; + + + if (x < 0 && 0 == (ppdev->flCursor & CURSOR_DOWN)) + { + /* x < 0 and y < 0 indicates we must hide the cursor */ + VGADDI_HideCursor(ppdev); + return; + } + + ppdev->xyCursor.x = x; + ppdev->xyCursor.y = y; + + if (0 == (ppdev->flCursor & CURSOR_DOWN)) + { + VGADDI_ShowCursor(ppdev); + } + + /* Give feedback on the new cursor rectangle */ + /*if (prcl != NULL) ComputePointerRect(ppdev, prcl);*/ +} + + +ULONG STDCALL +DrvSetPointerShape(SURFOBJ* pso, + SURFOBJ* psoMask, + SURFOBJ* psoColor, + XLATEOBJ* pxlo, + LONG xHot, + LONG yHot, + LONG x, + LONG y, + PRECTL prcl, + ULONG fl) +{ + PPDEV ppdev = (PPDEV)pso->dhpdev; + ULONG NewWidth, NewHeight; + PUCHAR Src, Dest; + ULONG i; + + /* Hide the cursor */ + if (ppdev->pPointerAttributes->Enable != 0 + && 0 == (ppdev->flCursor & CURSOR_DOWN)) + { + VGADDI_HideCursor(ppdev); + } + + if (! psoMask) + { + ppdev->flCursor = CURSOR_DOWN; + return SPS_ACCEPT_EXCLUDE; + } + ppdev->flCursor = ppdev->flCursor & (~ CURSOR_DOWN); + + NewWidth = psoMask->lDelta << 3; + NewHeight = (psoMask->cjBits / psoMask->lDelta) / 2; + + /* Reallocate the space for the cursor if necessary. */ + if (ppdev->pPointerAttributes->Width != NewWidth || + ppdev->pPointerAttributes->Height != NewHeight) + { + ULONG PointerAttributesSize; + PVIDEO_POINTER_ATTRIBUTES NewPointerAttributes; + ULONG SavedMemSize; + + /* Determine the size of the pointer attributes */ + PointerAttributesSize = sizeof(VIDEO_POINTER_ATTRIBUTES) + + ((NewWidth * NewHeight * 2) >> 3); + + /* Allocate memory for pointer attributes */ + NewPointerAttributes = EngAllocMem(0, PointerAttributesSize, ALLOC_TAG); + *NewPointerAttributes = *ppdev->pPointerAttributes; + NewPointerAttributes->Width = NewWidth; + NewPointerAttributes->Height = NewHeight; + NewPointerAttributes->WidthInBytes = NewWidth >> 3; + EngFreeMem(ppdev->pPointerAttributes); + ppdev->pPointerAttributes = NewPointerAttributes; + + /* Reallocate the space for the saved bits. */ + VGADDI_FreeSavedScreenBits(ImageBehindCursor); + SavedMemSize = ((((NewWidth + 7) & ~0x7) + 16) * NewHeight) >> 3; + ImageBehindCursor = VGADDI_AllocSavedScreenBits(SavedMemSize); + } + + /* Copy the new cursor in. */ + for (i = 0; i < (NewHeight * 2); i++) + { + Src = (PUCHAR)psoMask->pvBits; + Src += (i * (NewWidth >> 3)); + Dest = (PUCHAR)ppdev->pPointerAttributes->Pixels; + if (i >= NewHeight) + { + Dest += (((NewHeight * 3) - i - 1) * (NewWidth >> 3)); + } + else + { + Dest += ((NewHeight - i - 1) * (NewWidth >> 3)); + } + memcpy(Dest, Src, NewWidth >> 3); + } + + /* Set the new cursor position */ + ppdev->xyCursor.x = x; + ppdev->xyCursor.y = y; + ppdev->xyHotSpot.x = xHot; + ppdev->xyHotSpot.y = yHot; + + /* Show the cursor */ + VGADDI_ShowCursor(ppdev); + + return SPS_ACCEPT_EXCLUDE; +} + +VOID +VGADDI_HideCursor(PPDEV ppdev) +{ + ULONG SizeX, SizeY; + + /* Display what was behind cursor */ + SizeX = min(((oldx + ppdev->pPointerAttributes->Width) + 7) & ~0x7, ppdev->sizeSurf.cx); + SizeX -= (oldx & ~0x7); + SizeY = min(ppdev->pPointerAttributes->Height, ppdev->sizeSurf.cy - oldy); + VGADDI_BltFromSavedScreenBits(max(oldx, 0) & ~0x7, + max(oldy, 0), + ImageBehindCursor, + SizeX, + SizeY); + + ppdev->pPointerAttributes->Enable = 0; +} + +VOID +VGADDI_ShowCursor(PPDEV ppdev) +{ + LONG cx, cy; + PUCHAR AndMask, XorMask; + ULONG SizeX, SizeY; + + if (ppdev->pPointerAttributes->Enable != 0) + { + VGADDI_HideCursor(ppdev); + } + + /* Capture pixels behind the cursor */ + cx = ppdev->xyCursor.x - ppdev->xyHotSpot.x; + cy = ppdev->xyCursor.y - ppdev->xyHotSpot.y; + + /* Used to repaint background */ + SizeX = min(((cx + ppdev->pPointerAttributes->Width) + 7) & ~0x7, ppdev->sizeSurf.cx); + SizeX -= (cx & ~0x7); + SizeY = min(ppdev->pPointerAttributes->Height, ppdev->sizeSurf.cy - cy); + + VGADDI_BltToSavedScreenBits(ImageBehindCursor, + max(cx, 0) & ~0x7, + max(cy, 0), + SizeX, + SizeY); + + /* Display the cursor. */ + SizeX = min(ppdev->pPointerAttributes->Width, ppdev->sizeSurf.cx - cx); + SizeY = min(ppdev->pPointerAttributes->Height, ppdev->sizeSurf.cy - cy); + AndMask = ppdev->pPointerAttributes->Pixels + + (ppdev->pPointerAttributes->Height - SizeY) * ppdev->pPointerAttributes->WidthInBytes; + VGADDI_BltPointerToVGA(cx, + cy, + SizeX, + SizeY, + AndMask, + ppdev->pPointerAttributes->WidthInBytes, + VGA_AND); + XorMask = AndMask + + ppdev->pPointerAttributes->WidthInBytes * + ppdev->pPointerAttributes->Height; + VGADDI_BltPointerToVGA(cx, + cy, + SizeX, + SizeY, + XorMask, + ppdev->pPointerAttributes->WidthInBytes, + VGA_XOR); + + /* Save the new cursor location. */ + oldx = cx; + oldy = cy; + + /* Mark the cursor as currently displayed. */ + ppdev->pPointerAttributes->Enable = 1; +} diff --git a/reactos/drivers/video/displays/vga/objects/screen.c b/reactos/drivers/video/displays/vga/objects/screen.c new file mode 100644 index 00000000000..7008ee162c0 --- /dev/null +++ b/reactos/drivers/video/displays/vga/objects/screen.c @@ -0,0 +1,168 @@ +#include "../vgaddi.h" + +static WORD PaletteBuffer[] = { + 16, 0, // 16 entries, start with 0 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +}; + +static BYTE ColorBuffer[] = { + 16, // 16 entries + 0, 0, + 0, // start with 0 + 0x00, 0x00, 0x00, 0x00, // black + 0x2A, 0x00, 0x15, 0x00, // red + 0x00, 0x2A, 0x15, 0x00, // green + 0x2A, 0x2A, 0x15, 0x00, // brown + 0x00, 0x00, 0x2A, 0x00, // blue + 0x2A, 0x15, 0x2A, 0x00, // magenta + 0x15, 0x2A, 0x2A, 0x00, // cyan + 0x21, 0x22, 0x23, 0x00, // dark gray + 0x30, 0x31, 0x32, 0x00, // light gray + 0x3F, 0x00, 0x00, 0x00, // bright red + 0x00, 0x3F, 0x00, 0x00, // bright green + 0x3F, 0x3F, 0x00, 0x00, // bright yellow + 0x00, 0x00, 0x3F, 0x00, // bright blue + 0x3F, 0x00, 0x3F, 0x00, // bright magenta + 0x00, 0x3F, 0x3F, 0x00, // bright cyan + 0x3F, 0x3F, 0x3F, 0x00 // bright white +}; + +DWORD getAvailableModes(HANDLE Driver, + PVIDEO_MODE_INFORMATION *modeInformation, + DWORD *ModeSize) +{ + ULONG Temp; + VIDEO_NUM_MODES modes; + PVIDEO_MODE_INFORMATION VideoTemp; + + // get number of modes supported + if (EngDeviceIoControl(Driver, + IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES, + NULL, + 0, + &modes, + sizeof(VIDEO_NUM_MODES), + &Temp)) + { + // get modes failed + return(0); + } + + *ModeSize = modes.ModeInformationLength; + + // allocate buffer for the mini-port to write the modes in + *modeInformation = (PVIDEO_MODE_INFORMATION) + EngAllocMem(0, modes.NumModes * + modes.ModeInformationLength, ALLOC_TAG); + + if (*modeInformation == (PVIDEO_MODE_INFORMATION) NULL) + { + // couldn't allocate buffer + return 0; + } + + // Ask the mini-port to fill in the available modes. + if (EngDeviceIoControl(Driver, + IOCTL_VIDEO_QUERY_AVAIL_MODES, + NULL, + 0, + *modeInformation, + modes.NumModes * modes.ModeInformationLength, + &Temp)) + { + // failed to query modes + EngFreeMem(*modeInformation); + *modeInformation = (PVIDEO_MODE_INFORMATION) NULL; + + return(0); + } + + // Which modes supported by miniport driver are also suppoted by us, the + // display driver + + Temp = modes.NumModes; + VideoTemp = *modeInformation; + + // Reject mode if it's not 4 planes or not graphic or not 1 bits per pel + while (Temp--) + { + if ((VideoTemp->NumberOfPlanes != 4 ) || + !(VideoTemp->AttributeFlags & VIDEO_MODE_GRAPHICS) || + (VideoTemp->BitsPerPlane != 1) || + BROKEN_RASTERS(VideoTemp->ScreenStride, VideoTemp->VisScreenHeight)) + + { + VideoTemp->Length = 0; + } + + VideoTemp = (PVIDEO_MODE_INFORMATION)(((PUCHAR)VideoTemp) + modes.ModeInformationLength); + } + + return modes.NumModes; +} + +BOOL InitVGA(PPDEV ppdev, BOOL bFirst) +{ + ULONG ReturnedDataLength; + + ppdev->sizeSurf.cx = 640; + ppdev->sizeSurf.cy = 480; + ppdev->ModeNum = 12; + + // Set the mode that was requested + if (EngDeviceIoControl(ppdev->KMDriver, + IOCTL_VIDEO_SET_CURRENT_MODE, + &ppdev->ModeNum, + sizeof(VIDEO_MODE), + NULL, + 0, + &ReturnedDataLength)) { + return(FALSE); + } + + // set up internal palette + if (EngDeviceIoControl(ppdev->KMDriver, + IOCTL_VIDEO_SET_PALETTE_REGISTERS, + (PVOID) PaletteBuffer, + sizeof (PaletteBuffer), + NULL, + 0, + &ReturnedDataLength)) { + return(FALSE); + } + + // set up the DAC + if (EngDeviceIoControl(ppdev->KMDriver, + IOCTL_VIDEO_SET_COLOR_REGISTERS, + (PVOID) ColorBuffer, + sizeof (ColorBuffer), + NULL, + 0, + &ReturnedDataLength)) { + return(FALSE); + } + +/* + +gotta fix this up.. it prevents drawing to vidmem right now + + if (bFirst) { + // map video memory into virtual memory + VideoMemory.RequestedVirtualAddress = NULL; + + if (EngDeviceIoControl(ppdev->KMDriver, + IOCTL_VIDEO_MAP_VIDEO_MEMORY, + (PVOID) &VideoMemory, + sizeof (VIDEO_MEMORY), + (PVOID) &VideoMemoryInfo, + sizeof (VideoMemoryInfo), + &ReturnedDataLength)) { + // Failed to map to virtual memory + return (FALSE); + } + + ppdev->fbScreen = VideoMemoryInfo.FrameBufferBase; + } +*/ + return TRUE; +} diff --git a/reactos/drivers/video/displays/vga/objects/transblt.c b/reactos/drivers/video/displays/vga/objects/transblt.c new file mode 100644 index 00000000000..25eb5fc0c2b --- /dev/null +++ b/reactos/drivers/video/displays/vga/objects/transblt.c @@ -0,0 +1,34 @@ +#include +#define NDEBUG +#include +#include "../vgaddi.h" +#include "../vgavideo/vgavideo.h" +#include "brush.h" +#include "bitblt.h" + +BOOL STDCALL +DrvTransparentBlt(SURFOBJ* Dest, + SURFOBJ* Source, + CLIPOBJ* Clip, + XLATEOBJ* ColorTranslation, + RECTL* DestRect, + RECTL* SourceRect, + ULONG TransparentColor, + ULONG Reserved) +{ + LONG dx, dy, sx, sy; + + dx = abs(DestRect->right - DestRect->left); + dy = abs(DestRect->bottom - DestRect->top); + + sx = abs(SourceRect->right - SourceRect->left); + sy = abs(SourceRect->bottom - SourceRect->top); + + if(sxleft, DestRect->top, dx, dy, Source->pvBits, Source->lDelta, TransparentColor); + + return TRUE; +} diff --git a/reactos/drivers/video/displays/vga/vgaddi.def b/reactos/drivers/video/displays/vga/vgaddi.def new file mode 100644 index 00000000000..8be4f57c69d --- /dev/null +++ b/reactos/drivers/video/displays/vga/vgaddi.def @@ -0,0 +1,11 @@ +; $Id: vgaddi.def,v 1.1 2004/01/10 14:39:20 navaraf Exp $ +; +; vgaddi.def +; +; ReactOS Operating System +; +; From Anders Norlander's w32api-0.1.5 vgaddi.def. +; +LIBRARY vgaddi.dll +EXPORTS +DrvEnableDriver@12 diff --git a/reactos/drivers/video/displays/vga/vgaddi.edf b/reactos/drivers/video/displays/vga/vgaddi.edf new file mode 100644 index 00000000000..4f87b2bfceb --- /dev/null +++ b/reactos/drivers/video/displays/vga/vgaddi.edf @@ -0,0 +1,11 @@ +; $Id: vgaddi.edf,v 1.1 2004/01/10 14:39:20 navaraf Exp $ +; +; vgaddi.def +; +; ReactOS Operating System +; +; From Anders Norlander's w32api-0.1.5 vgaddi.def. +; +LIBRARY vgaddi.dll +EXPORTS +DrvEnableDriver=DrvEnableDriver@12 diff --git a/reactos/drivers/video/displays/vga/vgaddi.h b/reactos/drivers/video/displays/vga/vgaddi.h new file mode 100644 index 00000000000..1a00de0b7a1 --- /dev/null +++ b/reactos/drivers/video/displays/vga/vgaddi.h @@ -0,0 +1,246 @@ +#include +#include +#include + +#define DS_SOLIDBRUSH 0x00000001 +#define DS_GREYBRUSH 0x00000002 +#define DS_BRUSH 0x00000004 +#define DS_DIB 0x00000008 + +#define POW2(stride) (!((stride) & ((stride)-1))) // TRUE if stride is power of 2 +#define BROKEN_RASTERS(stride,cy) ((!(POW2(stride))) && ((stride*cy) > 0x10000)) + +#define ENUM_RECT_LIMIT 50 + +typedef struct _RECT_ENUM +{ + ULONG c; + RECTL arcl[ENUM_RECT_LIMIT]; +} RECT_ENUM; + +// Cursor coordinates +typedef struct _XYPAIR +{ + USHORT x; + USHORT y; +} XYPAIR; + +// Cursor states +#define CURSOR_DOWN 0x00000001 +#define CURSOR_COLOR 0x00000004 +#define CURSOR_HW 0x00000010 +#define CURSOR_HW_ACTIVE 0x00000020 +#define CURSOR_ANIMATE 0x00000040 + +typedef struct _PDEV +{ + ULONG fl; // driver flags + + // Handles + HANDLE KMDriver; + HDEV GDIDevHandle; // engine's handle to PDEV + HSURF SurfHandle; // engine's handle to surface + PVOID AssociatedSurf; // associated surface + + // Cursor + XYPAIR xyCursor; // cursor position + XYPAIR xyHotSpot; // cursor hotspot + POINTL ptlExtent; // cursor extent + ULONG cExtent; // effective cursor extent + ULONG flCursor; // cursor status + + // Pointer + PVIDEO_POINTER_ATTRIBUTES pPointerAttributes; // HW Pointer Attributes + ULONG XorMaskStartOffset; // Start offset of hardware pointer + // XOR mask relative to AND mask for + // passing to HW pointer + DWORD PointerAttributes; // Size of buffer allocated + DWORD flPreallocSSBBufferInUse; // True if preallocated saved screen + // bits buffer is in use + PUCHAR pjPreallocSSBBuffer; // Pointer to preallocated saved screen + // bits buffer, if there is one + ULONG ulPreallocSSBSize; // Size of preallocated saved screen + // bits buffer + VIDEO_POINTER_CAPABILITIES PointerCapabilities; // HW pointer abilities + PUCHAR pucDIB4ToVGAConvBuffer; // DIB4->VGA conversion table buffer + PUCHAR pucDIB4ToVGAConvTables; // Pointer to DIB4->VGA conversion + + // Misc + ULONG ModeNum; // mode index for current VGA mode + + SIZEL sizeSurf; // displayed size of the surface + PBYTE fbScreen; // pointer to the frame buffer + RECTL SavedBitsRight; // invisible part right of screen + RECTL SavedBitsBottom; // invisible part at the bottom of the screen + BOOL BitsSaved; // TRUE if bits are currently saved + SIZEL sizeMem; // actual size (in pixels) of video memory + LONG NumScansUsedByPointer; // # scans of offscreen memory used by + +} PDEV, *PPDEV; + +typedef struct { + RECTL BankBounds; // Pixels addressable in this bank + ULONG BankOffset; // Offset of bank start from bitmap start if linearly addressable +} BANK_INFO, *PBANK_INFO; + +typedef enum { + JustifyTop = 0, + JustifyBottom, +} BANK_JUST; + +// bank control function vector +//typedef VOID (*PFN_BankControl)(PDEVSURF, ULONG, BANK_JUST); +typedef VOID (*PFN_BankControl)(PVOID, ULONG, BANK_JUST); + +#if 0 +// descriptor for a saved screen bits block + +typedef struct _SAVED_SCREEN_BITS +{ + BOOL bFlags; + PBYTE pjBuffer; // pointer to save buffer start + ULONG ulSize; // size of save buffer (per plane; display memory only) + ULONG ulSaveWidthInBytes; // # of bytes across save area (including + // partial edge bytes, if any) + ULONG ulDelta; // # of bytes from end of one saved scan's saved bits to + // start of next (system memory only) + PVOID pvNextSSB; // pointer to next saved screen bits block + // for system memory blocks, saved bits start immediately + // after this structure +} SAVED_SCREEN_BITS, *PSAVED_SCREEN_BITS; +#else +typedef struct _SAVED_SCREEN_BITS +{ + BOOL Free; + DWORD Offset; + ULONG Size; + LIST_ENTRY ListEntry; +} SAVED_SCREEN_BITS, *PSAVED_SCREEN_BITS; +#endif + +// DEVSURF -- definition of a surface as seen and used by the various VGA +// drivers + +typedef struct _DEVSURF +{ + IDENT ident; // Identifier for debugging ease + ULONG flSurf; // DS_ flags as defined below + BYTE Color; // Solid color surface if DS_SOLIDBRUSH + +// If DS_SOLIDBRUSH, the following fields are undefined and not guaranteed to +// have been allocated! + + BYTE Format; // BMF_*, BMF_PHYSDEVICE + BYTE jReserved1; // Reserved + BYTE jReserved2; // Reserved + PPDEV ppdev; // Pointer to associated PDEV + SIZEL sizeSurf; // Size of the surface + ULONG NextScan; // Offset from scan "n" to "n+1" + ULONG NextPlane; // Offset from plane "n" to "n+1" + PVOID Scan0; // Pointer to scan 0 of bitmap + // (actual address of start of bank, for banked VGA surface) + PVOID StartBmp; // Pointer to start of bitmap + PVOID Conv; // Pointer to DIB/Planer conversion buffer + +// Banking variables; used only for banked VGA surfaces + + PVIDEO_BANK_SELECT BankSelectInfo; + ULONG Bank2RWSkip; // Offset from one bank index to next to make two 32K banks appear to be + // one seamless 64K bank + PFN pfnBankSwitchCode; + VIDEO_BANK_TYPE BankingType; + ULONG BitmapSize; // Length of bitmap if there were no banking, in CPU addressable bytes + ULONG PtrBankScan; // Last scan line in pointer work bank + RECTL WindowClip1; // Single-window banking clip rect + RECTL WindowClip2[2]; // Double-window banking clip rects for + // windows 0 & 1 + ULONG WindowBank[2]; // Current banks mapped into windows + // 0 & 1 (used in 2 window mode only) + PBANK_INFO BankInfo; // Pointer to array of bank clip info + ULONG BankInfoLength; // Length of pbiBankInfo, in entries + PBANK_INFO BankInfo2RW; // Same as above, but for 2RW window + ULONG BankInfo2RWLength; // case + PFN_BankControl pfnBankControl; // Pointer to bank control function + PFN_BankControl pfnBankControl2Window; // Pointer to double-window bank + // control function + PVOID BitmapStart; // Single-window bitmap start pointer (adjusted as + // necessary to make window map in at proper offset) + PVOID BitmapStart2Window[2]; // Double-window window 0 and 1 bitmap start + PVOID BankBufferPlane0; // Pointer to temp buffer capable of + // storing one full bank for plane 0 for 1 + // R/W case; capable of storing one full + // bank height of edge bytes for all four + // planes for the 1R/1W case. Also used to + // point to text building buffer in all + // cases. This is the pointer used to + // dealloc bank working storage for all + // four planes + + // The following 3 pointers used by 1 R/W banked devices + PVOID BankBufferPlane1; // Like above, but for plane 1 + PVOID BankBufferPlane2; // Like above, but for plane 2 + PVOID BankBufferPlane3; // Like above, but for plane 3 + ULONG TempBufferSize; // Full size of temp buffer pointed to + // by pvBankBufferPlane0 + + ULONG ajBits[1]; // Bits will start here for device bitmaps + PSAVED_SCREEN_BITS ssbList; // Pointer to start of linked list of + // saved screen bit blocks +} DEVSURF, *PDEVSURF; + +typedef VOID (*PFN_ScreenToScreenBlt)(PDEVSURF, PRECTL, PPOINTL, INT); + +// BMF_PHYSDEVICE format type + +#define BMF_PHYSDEVICE 0xFF +#define BMF_DFB 0xFE + +// Identifiers used in debugging (DEVSURF.ident) + +#define PDEV_IDENT ('V' + ('P' << 8) + ('D' << 16) + ('V' << 24)) +#define DEVSURF_IDENT ('V' + ('S' << 8) + ('R' << 16) + ('F' << 24)) + +BOOL InitVGA(PPDEV ppdev, BOOL bFirst); // screen.c: initialize VGA mode + +#define DRIVER_EXTRA_SIZE 0 +#define ALLOC_TAG TAG('D', 'v', 'g', 'a') // Dvga tag +#define DLL_NAME L"vga" // DLL name in Unicode + +#define MAX_SCAN_WIDTH 2048 // pixels +#define DRIVER_OFFSCREEN_REFRESHED 0x04L // if not set, don't use offscreen memory +#define PLANAR_PELS_PER_CPU_ADDRESS 8 +#define PACKED_PELS_PER_CPU_ADDRESS 2 + +BOOL VGAtoGDI( + SURFOBJ *Dest, SURFOBJ *Source, SURFOBJ *Mask, XLATEOBJ *ColorTranslation, + RECTL *DestRect, POINTL *SourcePoint); + +VOID +VGADDI_BltFromSavedScreenBits(ULONG DestX, + ULONG DestY, + PSAVED_SCREEN_BITS Src, + ULONG SizeX, + ULONG SizeY); +VOID +VGADDI_BltToSavedScreenBits(PSAVED_SCREEN_BITS Dest, + ULONG SourceX, + ULONG SourceY, + ULONG SizeX, + ULONG SizeY); +VOID +VGADDI_FreeSavedScreenBits(PSAVED_SCREEN_BITS SavedBits); +PSAVED_SCREEN_BITS +VGADDI_AllocSavedScreenBits(ULONG Size); +VOID +VGADDI_InitializeOffScreenMem(ULONG Start, ULONG Length); + +BOOL InitPointer(PPDEV ppdev); +DWORD getAvailableModes(HANDLE Driver, + PVIDEO_MODE_INFORMATION *modeInformation, + DWORD *ModeSize); + +void FASTCALL +vgaReadScan ( int x, int y, int w, void *b ); + +void FASTCALL +vgaWriteScan ( int x, int y, int w, void *b ); diff --git a/reactos/drivers/video/displays/vga/vgaddi.rc b/reactos/drivers/video/displays/vga/vgaddi.rc new file mode 100644 index 00000000000..8a3dd7c3415 --- /dev/null +++ b/reactos/drivers/video/displays/vga/vgaddi.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "VGA Display Driver\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "vgaddi\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "vgaddi.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/reactos/drivers/video/displays/vga/vgavideo/.cvsignore b/reactos/drivers/video/displays/vga/vgavideo/.cvsignore new file mode 100644 index 00000000000..0abd2c98ac8 --- /dev/null +++ b/reactos/drivers/video/displays/vga/vgavideo/.cvsignore @@ -0,0 +1,3 @@ +*.o +*.map +.*.d diff --git a/reactos/drivers/video/displays/vga/vgavideo/vgavideo.c b/reactos/drivers/video/displays/vga/vgavideo/vgavideo.c new file mode 100644 index 00000000000..eb11205c2a7 --- /dev/null +++ b/reactos/drivers/video/displays/vga/vgavideo/vgavideo.c @@ -0,0 +1,1042 @@ +#include +#include +#include +#include +#include +#include "vgavideo.h" + +UCHAR PreCalcReverseByte[256]; +int maskbit[640]; +int y80[480]; +int xconv[640]; +int bit8[640]; +int startmasks[8]; +int endmasks[8]; +char* vidmem; +static ULONG UnpackPixel[256]; + +static unsigned char leftMask; +static int byteCounter; +static unsigned char rightMask; + +#define READ_REGISTER_UCHAR(p) (*((PUCHAR)(p))) +#define WRITE_REGISTER_UCHAR(p,c) (*((PCHAR)(p))) = (c) + +INT abs(INT nm) +{ + if(nm<0) + { + return nm * -1; + } else + { + return nm; + } +} + +div_t div(int num, int denom) +{ + div_t r; + if (num > 0 && denom < 0) { + num = -num; + denom = -denom; + } + r.quot = num / denom; + r.rem = num % denom; + if (num < 0 && denom > 0) + { + if (r.rem > 0) + { + r.quot++; + r.rem -= denom; + } + } + return r; +} + +/*int mod(int num, int denom) +{ + div_t dvt = div(num, denom); + return dvt.rem; +}*/ + +BYTE bytesPerPixel(ULONG Format) +{ + // This function is taken from /subsys/win32k/eng/surface.c + // FIXME: GDI bitmaps are supposed to be pixel-packed. Right now if the + // pixel size if < 1 byte we expand it to 1 byte for simplicities sake + + switch ( Format ) + { + case BMF_1BPP: + return 1; + + case BMF_4BPP: + case BMF_4RLE: + return 1; + + case BMF_8BPP: + case BMF_8RLE: + return 1; + + case BMF_16BPP: + return 2; + + case BMF_24BPP: + return 3; + + case BMF_32BPP: + return 4; + + default: + return 0; + } +} + +VOID vgaPreCalc() +{ + ULONG j; + + startmasks[0] = 255; + startmasks[1] = 1; + startmasks[2] = 3; + startmasks[3] = 7; + startmasks[4] = 15; + startmasks[5] = 31; + startmasks[6] = 63; + startmasks[7] = 127; + + endmasks[0] = 0; + endmasks[1] = 128; + endmasks[2] = 192; + endmasks[3] = 224; + endmasks[4] = 240; + endmasks[5] = 248; + endmasks[6] = 252; + endmasks[7] = 254; + + for(j=0; j<80; j++) + { + maskbit[j*8] = 128; + maskbit[j*8+1] = 64; + maskbit[j*8+2] = 32; + maskbit[j*8+3] = 16; + maskbit[j*8+4] = 8; + maskbit[j*8+5] = 4; + maskbit[j*8+6] = 2; + maskbit[j*8+7] = 1; + + bit8[j*8] = 7; + bit8[j*8+1] = 6; + bit8[j*8+2] = 5; + bit8[j*8+3] = 4; + bit8[j*8+4] = 3; + bit8[j*8+5] = 2; + bit8[j*8+6] = 1; + bit8[j*8+7] = 0; + } + for(j=0; j<480; j++) + { + y80[j] = j*80; + } + for(j=0; j<640; j++) + { + xconv[j] = j >> 3; + } + + for (j = 0; j < 256; j++) + { + PreCalcReverseByte[j] = + (((j >> 0) & 0x1) << 7) | + (((j >> 1) & 0x1) << 6) | + (((j >> 2) & 0x1) << 5) | + (((j >> 3) & 0x1) << 4) | + (((j >> 4) & 0x1) << 3) | + (((j >> 5) & 0x1) << 2) | + (((j >> 6) & 0x1) << 1) | + (((j >> 7) & 0x1) << 0); + } + + for (j = 0; j < 256; j++) + { + UnpackPixel[j] = + (((j >> 0) & 0x1) << 4) | + (((j >> 1) & 0x1) << 0) | + (((j >> 2) & 0x1) << 12) | + (((j >> 3) & 0x1) << 8) | + (((j >> 4) & 0x1) << 20) | + (((j >> 5) & 0x1) << 16) | + (((j >> 6) & 0x1) << 28) | + (((j >> 7) & 0x1) << 24); + } +} + +void +get_masks(int x, int w) +{ + register int tmp; + + leftMask = rightMask = 0; + byteCounter = w; + /* right margin */ + tmp = (x+w) & 7; + if (tmp) { + byteCounter -= tmp; + rightMask = (unsigned char)(0xff00 >> tmp); + } + /* left margin */ + tmp = x & 7; + if (tmp) { + byteCounter -= (8 - tmp); + leftMask = (0xff >> tmp); + } + /* too small ? */ + if (byteCounter < 0) { + leftMask &= rightMask; + rightMask = 0; + byteCounter = 0; + } + byteCounter /= 8; +} + +VOID vgaPutPixel(INT x, INT y, UCHAR c) +{ + ULONG offset; + UCHAR a; + + offset = xconv[x]+y80[y]; + + WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08); + WRITE_PORT_UCHAR((PUCHAR)GRA_D,maskbit[x]); + + a = READ_REGISTER_UCHAR(vidmem + offset); + WRITE_REGISTER_UCHAR(vidmem + offset, c); +} + +VOID vgaPutByte(INT x, INT y, UCHAR c) +{ + ULONG offset; + + offset = xconv[x]+y80[y]; + + // Set the write mode + WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08); + WRITE_PORT_UCHAR((PUCHAR)GRA_D,0xff); + + WRITE_REGISTER_UCHAR(vidmem + offset, c); +} + +VOID vgaGetByte(ULONG offset, + UCHAR *b, UCHAR *g, + UCHAR *r, UCHAR *i) +{ + WRITE_PORT_USHORT((PUSHORT)GRA_I, 0x0304); + *i = READ_REGISTER_UCHAR(vidmem + offset); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02); + *r = READ_REGISTER_UCHAR(vidmem + offset); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x01); + *g = READ_REGISTER_UCHAR(vidmem + offset); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00); + *b = READ_REGISTER_UCHAR(vidmem + offset); +} + +INT vgaGetPixel(INT x, INT y) +{ + UCHAR mask, b, g, r, i; + ULONG offset; + + offset = xconv[x]+y80[y]; + vgaGetByte(offset, &b, &g, &r, &i); + + mask=maskbit[x]; + b=b&mask; + g=g&mask; + r=r&mask; + i=i&mask; + + mask=bit8[x]; + g=g>>mask; + b=b>>mask; + r=r>>mask; + i=i>>mask; + + return(b+2*g+4*r+8*i); +} + +BOOL vgaHLine(INT x, INT y, INT len, UCHAR c) +{ + UCHAR a; + ULONG pre1; + ULONG orgpre1, orgx, midpre1; + ULONG ileftpix, imidpix, irightpix; + + orgx = x; + + /*if ( len < 8 ) + { + for (i = x; i < x+len; i++ ) + vgaPutPixel ( i, y, c ); + + return TRUE; + }*/ + + // Calculate the left mask pixels, middle bytes and right mask pixel + ileftpix = 7 - mod8(x-1); + irightpix = mod8(x+len); + imidpix = (len-ileftpix-irightpix) / 8; + + pre1 = xconv[(x-1)&~7] + y80[y]; + orgpre1=pre1; + + // check for overlap ( very short line ) + if ( (ileftpix+irightpix) > len ) + { + int mask = startmasks[ileftpix] & endmasks[irightpix]; + // Write left pixels + WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08); // set the mask + WRITE_PORT_UCHAR((PUCHAR)GRA_D,mask); + + a = READ_REGISTER_UCHAR(vidmem + pre1); + WRITE_REGISTER_UCHAR(vidmem + pre1, c); + + return TRUE; + } + + // Left + if ( ileftpix > 0 ) + { + // Write left pixels + WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08); // set the mask + WRITE_PORT_UCHAR((PUCHAR)GRA_D,startmasks[ileftpix]); + + a = READ_REGISTER_UCHAR(vidmem + pre1); + WRITE_REGISTER_UCHAR(vidmem + pre1, c); + + // Prepare new x for the middle + x = orgx + 8; + } + + if ( imidpix > 0 ) + { + midpre1 = xconv[x] + y80[y]; + + // Set mask to all pixels in byte + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0xff); + memset(vidmem+midpre1, c, imidpix); // write middle pixels, no need to read in latch because of the width + } + + if ( irightpix > 0 ) + { + x = orgx + len - irightpix; + pre1 = xconv[x] + y80[y]; + + // Write right pixels + WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08); // set the mask bits + WRITE_PORT_UCHAR((PUCHAR)GRA_D, endmasks[irightpix]); + a = READ_REGISTER_UCHAR(vidmem + pre1); + WRITE_REGISTER_UCHAR(vidmem + pre1, c); + } + + return TRUE; +} + +BOOL vgaVLine(INT x, INT y, INT len, UCHAR c) +{ + ULONG offset, i; + UCHAR a; + + offset = xconv[x]+y80[y]; + +#ifdef VGA_PERF + vgaSetBitMaskRegister ( maskbit[x] ); +#else + WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08); // set the mask + WRITE_PORT_UCHAR((PUCHAR)GRA_D,maskbit[x]); +#endif + + for(i=y; ileft = max(prcSrc1->left, prcSrc2->left); + prcDst->right = min(prcSrc1->right, prcSrc2->right); + + if (prcDst->left < prcDst->right) { + prcDst->top = max(prcSrc1->top, prcSrc2->top); + prcDst->bottom = min(prcSrc1->bottom, prcSrc2->bottom); + + if (prcDst->top < prcDst->bottom) + { + return TRUE; + } + } + + *prcDst = rclEmpty; + + return FALSE; +} + +void DIB_BltFromVGA(int x, int y, int w, int h, void *b, int Dest_lDelta) +{ + ULONG plane; + ULONG left = x >> 3; + ULONG shift = x - (x & ~0x7); + UCHAR pixel, nextpixel; + ULONG rightcount; + ULONG i, j; + ULONG stride = w >> 3; + + /* Calculate the number of rightmost bytes not in a dword block. */ + if (w >= 8) + { + rightcount = w % 8; + } + else + { + stride = 0; + rightcount = w; + } + + /* Reset the destination. */ + memset(b, 0, h * Dest_lDelta); + + for (plane = 0; plane < 4; plane++) + { + PUCHAR dest = b; + + /* Select the plane we are reading in this iteration. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x04); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, plane); + + for (j = 0; j < h; j++) + { + PULONG destline = (PULONG)dest; + PUCHAR src = vidmem + (y + j) * SCREEN_STRIDE + left; + /* Read the data for one plane for an eight aligned pixel block. */ + nextpixel = PreCalcReverseByte[READ_REGISTER_UCHAR(src)]; + for (i = 0; i < stride; i++, src++, destline++) + { + /* Form the data for one plane for an aligned block in the destination. */ + pixel = nextpixel; + pixel >>= shift; + + nextpixel = PreCalcReverseByte[READ_REGISTER_UCHAR(src + 1)]; + pixel |= (nextpixel << (8 - shift)); + + /* Expand the plane data to 'chunky' format and store. */ + *destline |= (UnpackPixel[pixel] << plane); + } + /* Handle any pixels not falling into a full block. */ + if (rightcount != 0) + { + ULONG row; + + /* Form the data for a complete block. */ + pixel = nextpixel; + pixel >>= shift; + + nextpixel = PreCalcReverseByte[READ_REGISTER_UCHAR(src + 1)]; + pixel |= (nextpixel << (8 - shift)); + + row = UnpackPixel[pixel] << plane; + + /* Store the data for each pixel in the destination. */ + for (i = 0; i < rightcount; i++) + { + ((PUCHAR)destline)[i] |= (row & 0xFF); + row >>= 8; + } + } + dest += Dest_lDelta; + } + } + +#ifdef VGA_VERIFY + for (j = 0; j < h; j++) + { + for (i = 0; i < w; i+=2) + { + UCHAR c1, c2; + ULONG mask = (i < (w - 1)) ? 0xFF : 0xF0; + + c1 = (vgaGetPixel(x + i, y + j) << 4) | (vgaGetPixel(x + i + 1, y + j)); + c2 = ((PUCHAR)b)[(j * Dest_lDelta) + (i >> 1)]; + if ((c1 & mask) != (c2 & mask)) + { + __asm__("int $3\n\t" : /* no outputs */ : /* no inputs */); + } + } + } +#endif /* VGA_VERIFY */ +} + +#if 0 +void DIB_BltFromVGA(int x, int y, int w, int h, void *b, int Dest_lDelta) +// DIB blt from the VGA. +// For now we just do slow reads -- pixel by pixel, packing each one into the correct 4BPP format. +{ + PBYTE pb = b, opb = b; + BOOLEAN edgePixel = FALSE; + ULONG i, j; + ULONG x2 = x + w; + ULONG y2 = y + h; + BYTE b1, b2; + + // Check if the width is odd + if(mod2(w)>0) + { + edgePixel = TRUE; + x2 -= 1; + } + + for (j=y; j> 4); + offset += 80; + pb += Source_lDelta; + } + } + else + { + for (j = y; j < y2; j++) + { + a = READ_REGISTER_UCHAR(vidmem + offset); + WRITE_REGISTER_UCHAR(vidmem + offset, *pb & 0x0f); + offset += 80; + pb += Source_lDelta; + } + } + + if (StartMod != ((i - x) % 2)) + { + opb++; + } + } +} + + +/* DIB blt to the VGA. */ +void DIB_BltToVGAWithXlate(int x, int y, int w, int h, void *b, int Source_lDelta, XLATEOBJ* Xlate) +{ + PBYTE pb, opb = b; + ULONG i, j; + ULONG x2 = x + w; + ULONG y2 = y + h; + ULONG offset; + UCHAR a; + + for (i = x; i < x2; i++) + { + pb = opb; + offset = xconv[i] + y80[y]; + + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08); // set the mask + WRITE_PORT_UCHAR((PUCHAR)GRA_D, maskbit[i]); + + if (0 == ((i - x) % 2)) + { + for (j = y; j < y2; j++) + { + a = READ_REGISTER_UCHAR(vidmem + offset); + WRITE_REGISTER_UCHAR(vidmem + offset, XLATEOBJ_iXlate(Xlate, (*pb & 0xf0) >> 4)); + offset += 80; + pb += Source_lDelta; + } + } + else + { + for (j = y; j < y2; j++) + { + a = READ_REGISTER_UCHAR(vidmem + offset); + WRITE_REGISTER_UCHAR(vidmem + offset, XLATEOBJ_iXlate(Xlate, *pb & 0x0f)); + offset += 80; + pb += Source_lDelta; + } + } + + if (0 != ((i - x) % 2)) + { + opb++; + } + } +} + +void DIB_TransparentBltToVGA(int x, int y, int w, int h, void *b, int Source_lDelta, ULONG trans) + +// DIB blt to the VGA. +// For now we just do slow writes -- pixel by pixel, packing each one into the correct 4BPP format. +{ + PBYTE pb = b, opb = b; + BOOLEAN edgePixel = FALSE; + ULONG i, j; + ULONG x2 = x + w; + ULONG y2 = y + h; + BYTE b1, b2; + + // Check if the width is odd + if(mod2(w)>0) + { + edgePixel = TRUE; + x2 -= 1; + } + + for (j=y; j> 4; + b2 = *pb & 0x0f; + if(b1 != trans) vgaPutPixel(i, j, b1); + if(b2 != trans) vgaPutPixel(i+1, j, b2); + pb++; + } + + if(edgePixel == TRUE) + { + b1 = *pb; + if(b1 != trans) vgaPutPixel(x2, j, b1); + pb++; + } + + opb += Source_lDelta; + pb = opb; // new test code + + } +} + +// This algorithm goes from left to right, storing each 4BPP pixel +// in an entire byte. +void FASTCALL +vgaReadScan ( int x, int y, int w, void *b ) +{ + unsigned char *vp, *vpP; + unsigned char data, mask, maskP; + unsigned char *bp; + unsigned char plane_mask; + int plane, i; + + ASSIGNVP4(x, y, vpP) + ASSIGNMK4(x, y, maskP) + get_masks(x, w); + WRITE_PORT_USHORT((PUSHORT)GRA_I, 0x0005); // read mode 0 + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x04); // read map select + + memset ( b, 0, w ); + + for ( plane=0, plane_mask=1; plane < 4; plane++, plane_mask<<=1 ) + { + WRITE_PORT_UCHAR((PUCHAR)GRA_D, plane); // read map select + + vp = vpP; + bp = b; + if ( leftMask ) + { + mask = maskP; + data = *vp++; + do + { + if (data & mask) + *bp |= plane_mask; + bp++; + mask >>= 1; + } while (mask & leftMask); + + } + if (byteCounter) + { + for (i=byteCounter; i>0; i--) + { + data = *vp++; + if (data & 0x80) *bp |= plane_mask; + bp++; + if (data & 0x40) *bp |= plane_mask; + bp++; + if (data & 0x20) *bp |= plane_mask; + bp++; + if (data & 0x10) *bp |= plane_mask; + bp++; + if (data & 0x08) *bp |= plane_mask; + bp++; + if (data & 0x04) *bp |= plane_mask; + bp++; + if (data & 0x02) *bp |= plane_mask; + bp++; + if (data & 0x01) *bp |= plane_mask; + bp++; + } + } + if (rightMask) + { + mask = 0x80; + data = *vp; + do + { + if (data & mask) + *bp |= plane_mask; + bp++; + mask >>= 1; + } while (mask & rightMask); + } + } + + // We don't need this if the next call is a DFB blt to VGA (as in the case of moving the mouse pointer) + //WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2 + //WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02); + //WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace + //WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00); +} + +// This algorithm goes from left to right +// It stores each 4BPP pixel in an entire byte. +void FASTCALL +vgaWriteScan ( int x, int y, int w, void *b ) +{ + unsigned char *bp; + unsigned char *vp; + unsigned char init_mask; + volatile unsigned char dummy; + int byte_per_line; + int i, j, off, init_off = x&7; + + bp = b; + ASSIGNVP4(x, y, vp) + ASSIGNMK4(x, y, init_mask) + byte_per_line = SCREEN_X >> 3; + + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2 + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02); + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00); + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08); // bit mask + + //DbgPrint("vgaWriteScan(%i,%i,%i...)\n",x,y,w); + for ( j = 0; j < 8; j++ ) + { + unsigned int mask = 0x80 >> j; + //DbgPrint("j=%i\n",j); + WRITE_PORT_UCHAR ( (PUCHAR)GRA_D, (unsigned char)mask ); + i = j - init_off; + off = 0; + if ( j < init_off ) + i += 8, off++; + while ( i < w ) + { + //DbgPrint("(%i)",i); + dummy = vp[off]; + //DbgPrint("."); + dummy = bp[i]; + //DbgPrint("."); + vp[off] = dummy; + //DbgPrint("."); + i += 8; + off++; + } + //DbgPrint("\n"); + } +} + +void DFB_BltFromVGA(int x, int y, int w, int h, void *b, int bw) + +// This algorithm goes from left to right, and inside that loop, top to bottom. +// It also stores each 4BPP pixel in an entire byte. +{ + unsigned char *vp, *vpY, *vpP; + unsigned char data, mask, maskP; + unsigned char *bp, *bpY; + unsigned char plane_mask; + int byte_per_line = SCREEN_X >> 3; + int plane, i, j; + + ASSIGNVP4(x, y, vpP) + ASSIGNMK4(x, y, maskP) + get_masks(x, w); + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // read mode 0 + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00); + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x04); // read map select + + // clear buffer + bp=b; + for (j=h; j>0; j--) + { + memset(bp, 0, w); + bp += bw; + } + + for ( plane=0, plane_mask=1; plane < 4; plane++, plane_mask<<=1 ) + { + WRITE_PORT_UCHAR((PUCHAR)GRA_D, plane); // read map select + vpY = vpP; + bpY = b; + for ( j=h; j>0; j-- ) + { + vp = vpY; + bp = bpY; + if ( leftMask ) + { + mask = maskP; + data = *vp++; + do + { + if (data & mask) + *bp |= plane_mask; + bp++; + mask >>= 1; + } while (mask & leftMask); + + } + if (byteCounter) + { + for (i=byteCounter; i>0; i--) + { + data = *vp++; + if (data & 0x80) *bp |= plane_mask; + bp++; + if (data & 0x40) *bp |= plane_mask; + bp++; + if (data & 0x20) *bp |= plane_mask; + bp++; + if (data & 0x10) *bp |= plane_mask; + bp++; + if (data & 0x08) *bp |= plane_mask; + bp++; + if (data & 0x04) *bp |= plane_mask; + bp++; + if (data & 0x02) *bp |= plane_mask; + bp++; + if (data & 0x01) *bp |= plane_mask; + bp++; + } + } + if (rightMask) + { + mask = 0x80; + data = *vp; + do + { + if (data & mask) *bp |= plane_mask; + bp++; + mask >>= 1; + } while (mask & rightMask); + } + bpY += bw; + vpY += byte_per_line; + } + } + + // We don't need this if the next call is a DFB blt to VGA (as in the case of moving the mouse pointer) + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2 + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02); + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00); +} + +void DFB_BltToVGA(int x, int y, int w, int h, void *b, int bw) + +// This algorithm goes from left to right, and inside that loop, top to bottom. +// It also stores each 4BPP pixel in an entire byte. +{ + unsigned char *bp, *bpX; + unsigned char *vp, *vpX; + unsigned char mask; + volatile unsigned char dummy; + int byte_per_line; + int i, j; + + bpX = b; + ASSIGNVP4(x, y, vpX) + ASSIGNMK4(x, y, mask) + byte_per_line = SCREEN_X >> 3; + + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2 + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02); + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00); + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08); // bit mask + + for (i=w; i>0; i--) + { + WRITE_PORT_UCHAR((PUCHAR)GRA_D, mask); + bp = bpX; + vp = vpX; + for (j=h; j>0; j--) + { + dummy = *vp; + *vp = *bp; + bp += bw; + vp += byte_per_line; + } + bpX++; + if ((mask >>= 1) == 0) + { + vpX++; + mask = 0x80; + } + } +} + +void DFB_BltToVGA_Transparent(int x, int y, int w, int h, void *b, int bw, char Trans) + +// This algorithm goes from goes from left to right, and inside that loop, top to bottom. +// It also stores each 4BPP pixel in an entire byte. +{ + unsigned char *bp, *bpX; + unsigned char *vp, *vpX; + unsigned char mask; + volatile unsigned char dummy; + int byte_per_line; + int i, j; + + bpX = b; + ASSIGNVP4(x, y, vpX) + ASSIGNMK4(x, y, mask) + byte_per_line = SCREEN_X >> 3; + + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2 + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02); + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00); + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08); // bit mask + + for (i=w; i>0; i--) + { + WRITE_PORT_UCHAR((PUCHAR)GRA_D, mask); + bp = bpX; + vp = vpX; + for (j=h; j>0; j--) + { + if (*bp != Trans) + { + dummy = *vp; + *vp = *bp; + } + bp += bw; + vp += byte_per_line; + } + bpX++; + if ((mask >>= 1) == 0) + { + vpX++; + mask = 0x80; + } + } +} + +void DFB_BltToDIB(int x, int y, int w, int h, void *b, int bw, void *bdib, int dibw) + +// This algorithm converts a DFB into a DIB +// WARNING: This algorithm is buggy +{ + unsigned char *bp, *bpX, *dib, *dibTmp; + int i, j, dib_shift; + + bpX = b; + dib = bdib + y * dibw + (x / 2); + + for (i=w; i>0; i--) { + + // determine the bit shift for the DIB pixel + dib_shift = mod2(w-i); + if(dib_shift > 0) dib_shift = 4; + dibTmp = dib; + + bp = bpX; + for (j=h; j>0; j--) { + *dibTmp = *bp << dib_shift | *(bp + 1); + dibTmp += dibw; + bp += bw; + } + bpX++; + if(dib_shift == 0) dib++; + } +} + + +void DIB_BltToDFB(int x, int y, int w, int h, void *b, int bw, void *bdib, int dibw) + +// This algorithm converts a DIB into a DFB +{ + unsigned char *bp, *bpX, *dib, *dibTmp; + int i, j, dib_shift, dib_and; + + bpX = b; + dib = bdib + y * dibw + (x / 2); + + for (i=w; i>0; i--) { + + // determine the bit shift for the DIB pixel + dib_shift = mod2(w-i); + if(dib_shift > 0) { + dib_shift = 0; + dib_and = 0x0f; + } else { + dib_shift = 4; + dib_and = 0xf0; + } + + dibTmp = dib; + bp = bpX; + + for (j=h; j>0; j--) { + *bp = (*dibTmp & dib_and) >> dib_shift; + dibTmp += dibw; + bp += bw; + } + + bpX++; + if(dib_shift == 0) dib++; + } +} diff --git a/reactos/drivers/video/displays/vga/vgavideo/vgavideo.h b/reactos/drivers/video/displays/vga/vgavideo/vgavideo.h new file mode 100644 index 00000000000..5a49675ad8a --- /dev/null +++ b/reactos/drivers/video/displays/vga/vgavideo/vgavideo.h @@ -0,0 +1,75 @@ +// FIXME: Make these variables so we can also use modes like 800x600 +#define SCREEN_X 640 +#define SCREEN_Y 480 + +#define SCREEN_STRIDE 80 + +#define VGA_NORMAL 0 +#define VGA_AND 8 +#define VGA_OR 16 +#define VGA_XOR 24 + +//This is in mingw standard headers +//typedef struct { int quot, rem; } div_t; + +extern int maskbit[640]; +extern int y80[480]; +extern int xconv[640]; +extern int bit8[640]; +extern int startmasks[8]; +extern int endmasks[8]; + +extern UCHAR PreCalcReverseByte[256]; + +extern char* vidmem; + +#define MISC 0x3c2 +#define SEQ 0x3c4 +#define CRTC 0x3d4 +#define GRAPHICS 0x3ce +#define FEATURE 0x3da +#define ATTRIB 0x3c0 +#define STATUS 0x3da + +typedef struct _VideoMode { + unsigned short VidSeg; + unsigned char Misc; + unsigned char Feature; + unsigned char Seq[5]; + unsigned char Crtc[25]; + unsigned char Gfx[9]; + unsigned char Attrib[21]; +} VideoMode; + +VOID vgaPreCalc(); +VOID vgaPutPixel(INT x, INT y, UCHAR c); +VOID vgaPutByte(INT x, INT y, UCHAR c); +VOID vgaGetByte(ULONG offset, + UCHAR *b, UCHAR *g, + UCHAR *r, UCHAR *i); +INT vgaGetPixel(INT x, INT y); +BOOL vgaHLine(INT x, INT y, INT len, UCHAR c); +BOOL vgaVLine(INT x, INT y, INT len, UCHAR c); +INT abs(INT nm); +BOOL VGADDIIntersectRect(PRECTL prcDst, PRECTL prcSrc1, PRECTL prcSrc2); + +#define SEQ_I 0x3C4 /* Sequencer Index */ +#define SEQ_D 0x3C5 /* Sequencer Data Register */ + +#define GRA_I 0x3CE /* Graphics Controller Index */ +#define GRA_D 0x3CF /* Graphics Controller Data Register */ + +#define LowByte(w) (*((unsigned char *)&(w) + 0)) +#define HighByte(w) (*((unsigned char *)&(w) + 1)) + +#define ASSIGNVP4(x, y, vp) vp = vidmem /* VBUF */ + (((x) + (y)*SCREEN_X) >> 3); +#define ASSIGNMK4(x, y, mask) mask = 0x80 >> ((x) & 7); + +void get_masks(int x, int w); + +#define mod8(n) ((n)&7) +#define mod2(n) ((n)&1) +void DIB_BltFromVGA(int x, int y, int w, int h, void *b, int Dest_lDelta); +void DIB_BltToVGA(int x, int y, int w, int h, void *b, int Source_lDelta, int StartMod); +void DIB_BltToVGAWithXlate(int x, int y, int w, int h, void *b, int Source_lDelta, XLATEOBJ* Xlate); +void DIB_TransparentBltToVGA(int x, int y, int w, int h, void *b, int Source_lDelta, ULONG trans); diff --git a/reactos/drivers/video/makefile b/reactos/drivers/video/makefile new file mode 100644 index 00000000000..cccf9791936 --- /dev/null +++ b/reactos/drivers/video/makefile @@ -0,0 +1,57 @@ +DISPLAY_DRIVERS = vga +MINIPORT_DRIVERS = vga vbe + +all: $(DISPLAY_DRIVERS:%=DD%) $(MINIPORT_DRIVERS:%=MP%) + +implib: $(DISPLAY_DRIVERS:%=DD%_implib) $(MINIPORT_DRIVERS:%=MP%_implib) + +clean: $(DISPLAY_DRIVERS:%=DD%_clean) $(MINIPORT_DRIVERS:%=MP%_clean) + +install: $(DISPLAY_DRIVERS:%=DD%_install) $(MINIPORT_DRIVERS:%=MP%_install) + +bootcd: $(DISPLAY_DRIVERS:%=DD%_bootcd) $(MINIPORT_DRIVERS:%=MP%_bootcd) + +# +# Video display driver rules +# + +$(DISPLAY_DRIVERS:%=DD%): DD%: + $(MAKE) -C displays/$* + +$(DISPLAY_DRIVERS:%=DD%_implib): DD%_implib: + $(MAKE) -C displays/$* implib + +$(DISPLAY_DRIVERS:%=DD%_clean): DD%_clean: + $(MAKE) -C displays/$* clean + +$(DISPLAY_DRIVERS:%=DD%_install): DD%_install: + $(MAKE) -C displays/$* install + +$(DISPLAY_DRIVERS:%=DD%_bootcd): DD%_bootcd: + $(MAKE) -C displays/$* bootcd + +.PHONY: $(DISPLAY_DRIVERS:%=DD%) $(DISPLAY_DRIVERS:%=DD%_implib) $(DISPLAY_DRIVERS:%=DD%_clean)\ + $(DISPLAY_DRIVERS:%=DD%_install) $(DISPLAY_DRIVERS:%=DD%_bootcd) + + +# +# Video miniport driver rules +# + +$(MINIPORT_DRIVERS:%=MP%): MP%: + $(MAKE) -C miniport/$* + +$(MINIPORT_DRIVERS:%=MP%_implib): MP%_implib: + $(MAKE) -C miniport/$* implib + +$(MINIPORT_DRIVERS:%=MP%_clean): MP%_clean: + $(MAKE) -C miniport/$* clean + +$(MINIPORT_DRIVERS:%=MP%_install): MP%_install: + $(MAKE) -C miniport/$* install + +$(MINIPORT_DRIVERS:%=MP%_bootcd): MP%_bootcd: + $(MAKE) -C miniport/$* bootcd + +.PHONY: $(MINIPORT_DRIVERS:%=MP%) $(MINIPORT_DRIVERS:%=MP%_implib) $(MINIPORT_DRIVERS:%=MP%_clean)\ + $(MINIPORT_DRIVERS:%=MP%_install) $(MINIPORT_DRIVERS:%=MP%_bootcd) diff --git a/reactos/drivers/video/miniport/vbe/.cvsignore b/reactos/drivers/video/miniport/vbe/.cvsignore new file mode 100644 index 00000000000..688fcd329e6 --- /dev/null +++ b/reactos/drivers/video/miniport/vbe/.cvsignore @@ -0,0 +1,8 @@ +junk.tmp +base.tmp +temp.exp +vbemp.coff +*.o +*.sym +*.sys +*.map diff --git a/reactos/drivers/video/miniport/vbe/makefile b/reactos/drivers/video/miniport/vbe/makefile new file mode 100644 index 00000000000..1a1da1cb05f --- /dev/null +++ b/reactos/drivers/video/miniport/vbe/makefile @@ -0,0 +1,16 @@ +PATH_TO_TOP = ../../../.. + +TARGET_TYPE = driver + +TARGET_NAME = vbemp + +TARGET_DDKLIBS = videoprt.a ntoskrnl.a + +TARGET_CFLAGS = -Werror -Wall -I$(PATH_TO_TOP)/ntoskrnl/include -D__USE_W32API + +TARGET_OBJECTS = \ + vbemp.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/reactos/drivers/video/miniport/vbe/vbemp.c b/reactos/drivers/video/miniport/vbe/vbemp.c new file mode 100644 index 00000000000..47d5bc52570 --- /dev/null +++ b/reactos/drivers/video/miniport/vbe/vbemp.c @@ -0,0 +1,699 @@ +/* + * ReactOS VBE miniport video driver + * + * Copyright (C) 2004 Filip Navara + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * FIXMEs: + * - Check input parameters everywhere. + * - Add some comments. + * - Implement support power management. + */ + +#include "vbemp.h" + +/******************************************************************************/ + +PVOID FASTCALL +MapPM(ULONG Address, ULONG Size) +{ + LARGE_INTEGER Offset; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING PhysMemName; + HANDLE PhysMemHandle; + NTSTATUS Status; + PVOID BaseAddress; + ULONG ViewSize; + + /* + * Open the physical memory section + */ + RtlInitUnicodeString(&PhysMemName, L"\\Device\\PhysicalMemory"); + InitializeObjectAttributes(&ObjectAttributes, + &PhysMemName, + 0, + NULL, + NULL); + Status = ZwOpenSection(&PhysMemHandle, SECTION_ALL_ACCESS, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + DPRINT(("VBEMP: Couldn't open \\Device\\PhysicalMemory\n")); + return NULL; + } + + /* + * Map the BIOS and device registers into the address space + */ + Offset.QuadPart = Address; + ViewSize = Size; + BaseAddress = (PVOID)Address; + Status = NtMapViewOfSection(PhysMemHandle, + NtCurrentProcess(), + &BaseAddress, + 0, + 8192, + &Offset, + &ViewSize, + ViewUnmap, + 0, + PAGE_EXECUTE_READWRITE); + if (!NT_SUCCESS(Status)) + { + DPRINT(("VBEMP: Couldn't map physical memory (%x)\n", Status)); + NtClose(PhysMemHandle); + return NULL; + } + NtClose(PhysMemHandle); + + if (BaseAddress != (PVOID)Address) + { + DPRINT(("VBEMP: Couldn't map physical memory at the right address " + "(was %x)(%x)\n", BaseAddress, Address)); + return NULL; + } + + return BaseAddress; +} + +ULONG FASTCALL +InitializeVideoAddressSpace(VOID) +{ + NTSTATUS Status; + PVOID BaseAddress; + PVOID NullAddress; + ULONG ViewSize; + CHAR IVT[1024]; + CHAR BDA[256]; + + if (MapPM(0xa0000, 0x30000) == NULL) + { + return FALSE; + } + + /* + * Map some memory to use for the non-BIOS parts of the v86 mode address + * space + */ + BaseAddress = (PVOID)0x1; + ViewSize = 0x20000; + Status = ZwAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &ViewSize, + MEM_COMMIT, + PAGE_EXECUTE_READWRITE); + if (!NT_SUCCESS(Status)) + { + DPRINT(("VBEMP: Failed to allocate virtual memory (Status %x)\n", Status)); + return 0; + } + if (BaseAddress != (PVOID)0x0) + { + DPRINT(("VBEMP: Failed to allocate virtual memory at right address " + "(was %x)\n", BaseAddress)); + return 0; + } + + /* + * Get the real mode IVT from the kernel + */ + Status = NtVdmControl(0, IVT); + if (!NT_SUCCESS(Status)) + { + DPRINT(("VBEMP: NtVdmControl failed (status %x)\n", Status)); + return 0; + } + + /* + * Copy the real mode IVT into the right place + */ + NullAddress = (PVOID)0x0; /* Workaround for GCC 3.4 */ + memcpy(NullAddress, IVT, 1024); + + /* + * Get the BDA from the kernel + */ + Status = NtVdmControl(1, BDA); + if (!NT_SUCCESS(Status)) + { + DPRINT(("VBEMP: NtVdmControl failed (status %x)\n", Status)); + return 0; + } + + /* + * Copy the BDA into the right place + */ + memcpy((PVOID)0x400, BDA, 256); + + return 1; +} + +VP_STATUS STDCALL +DriverEntry(IN PVOID Context1, IN PVOID Context2) +{ + VIDEO_HW_INITIALIZATION_DATA InitData; + + VideoPortZeroMemory(&InitData, sizeof(InitData)); + InitData.HwFindAdapter = VBEFindAdapter; + InitData.HwInitialize = VBEInitialize; + InitData.HwStartIO = VBEStartIO; + InitData.HwDeviceExtensionSize = sizeof(VBE_DEVICE_EXTENSION); + + return VideoPortInitialize(Context1, Context2, &InitData, NULL); +} + +VP_STATUS STDCALL +VBEFindAdapter(IN PVOID HwDeviceExtension, IN PVOID HwContext, + IN PWSTR ArgumentString, IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo, + OUT PUCHAR Again) +{ + KV86M_REGISTERS BiosRegisters; + DWORD ViewSize; + NTSTATUS Status; + PVBE_INFO VbeInfo; + PVBE_DEVICE_EXTENSION VBEDeviceExtension = + (PVBE_DEVICE_EXTENSION)HwDeviceExtension; + + /* + * We support only one adapter. + */ + + *Again = FALSE; + + /* + * Map the BIOS parts of memory into our memory space and intitalize + * the real mode interrupt table. + */ + + InitializeVideoAddressSpace(); + + /* + * Allocate a bit of memory that will be later used for VBE transport + * buffer. This memory must be accessible from V86 mode so it must fit + * in the first megabyte of physical memory. + */ + + VBEDeviceExtension->TrampolineMemory = (PVOID)0x20000; + ViewSize = 0x400; + Status = ZwAllocateVirtualMemory(NtCurrentProcess(), + (PVOID*)&VBEDeviceExtension->TrampolineMemory, 0, &ViewSize, MEM_COMMIT, + PAGE_EXECUTE_READWRITE); + if (!NT_SUCCESS(Status)) + { + DPRINT(("Failed to allocate virtual memory (Status %x)\n", Status)); + return 0; + } + if (VBEDeviceExtension->TrampolineMemory > (PVOID)(0x100000 - 0x400)) + { + DPRINT(("Failed to allocate virtual memory at right address " + "(was %x)\n", VBEDeviceExtension->TrampolineMemory)); + return 0; + } + VBEDeviceExtension->PhysicalAddress.QuadPart = + (UINT_PTR)VBEDeviceExtension->TrampolineMemory; + + /* + * Get the VBE general information. + */ + + VbeInfo = (PVBE_INFO)VBEDeviceExtension->TrampolineMemory; + strncpy(VbeInfo->Signature, "VBE2", 4); + memset(&BiosRegisters, 0, sizeof(BiosRegisters)); + BiosRegisters.Eax = 0x4F00; + BiosRegisters.Edi = VBEDeviceExtension->PhysicalAddress.QuadPart & 0xFF; + BiosRegisters.Es = VBEDeviceExtension->PhysicalAddress.QuadPart >> 4; + Ke386CallBios(0x10, &BiosRegisters); + if (BiosRegisters.Eax == 0x4F) + { + if (VbeInfo->Version >= 0x200) + { + DPRINT(("VBE BIOS Present (%d.%d, %8ld Kb)\n", + VbeInfo->Version / 0x100, VbeInfo->Version & 0xFF, + VbeInfo->TotalMemory * 16)); + + return NO_ERROR; + } + else + { + DPRINT(("VBE BIOS present, but incompatible version.\n")); + + return ERROR_DEV_NOT_EXIST; + } + } + else + { + DPRINT(("No VBE BIOS found.\n")); + + return ERROR_DEV_NOT_EXIST; + } +} + +BOOLEAN STDCALL +VBEInitialize(PVOID HwDeviceExtension) +{ + /* + * Build a mode list here that can be later used by + * IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES and IOCTL_VIDEO_QUERY_AVAIL_MODES + * calls. + */ + + ULONG ModeCount; + ULONG CurrentMode; + KV86M_REGISTERS BiosRegisters; + PVBE_DEVICE_EXTENSION VBEDeviceExtension = + (PVBE_DEVICE_EXTENSION)HwDeviceExtension; + PVBE_INFO VbeInfo; + PVBE_MODEINFO VbeModeInfo; + VBE_MODEINFO TempVbeModeInfo; + WORD TempVbeModeNumber; + WORD *ModeList; + WORD DefaultMode; + + InitializeVideoAddressSpace(); + + /* + * Get the VBE general information. + */ + + VbeInfo = (PVBE_INFO)VBEDeviceExtension->TrampolineMemory; + strncpy(VbeInfo->Signature, "VBE2", 4); + memset(&BiosRegisters, 0, sizeof(BiosRegisters)); + BiosRegisters.Eax = 0x4F00; + BiosRegisters.Edi = VBEDeviceExtension->PhysicalAddress.QuadPart & 0xFF; + BiosRegisters.Es = VBEDeviceExtension->PhysicalAddress.QuadPart >> 4; + Ke386CallBios(0x10, &BiosRegisters); + + VBEDeviceExtension->VBEVersion = VbeInfo->Version; + VBEDeviceExtension->VGACompatible = !(VbeInfo->Capabilities & 2); + /* + * Get the number of supported video modes. + */ + + /* + * No need to be mapped, it's either in BIOS memory or in our trampoline + * memory. Both of them are already mapped. + */ + ModeList = (WORD *)((HIWORD(VbeInfo->VideoModePtr) << 4) + LOWORD(VbeInfo->VideoModePtr)); + for (CurrentMode = 0, ModeCount = 0; + ModeList[CurrentMode] != 0xFFFF && ModeList[CurrentMode] != 0; + CurrentMode++) + { + ModeCount++; + } + + /* + * Allocate space for video modes information. + */ + + VBEDeviceExtension->ModeInfo = + ExAllocatePool(PagedPool, ModeCount * sizeof(VBE_MODEINFO)); + VBEDeviceExtension->ModeNumbers = + ExAllocatePool(PagedPool, ModeCount * sizeof(WORD)); + + /* + * Get the actual mode infos. + */ + + for (CurrentMode = 0, ModeCount = 0, DefaultMode = 0; + ModeList[CurrentMode] != 0xFFFF && CurrentMode < 0x400; + CurrentMode++) + { + BiosRegisters.Eax = 0x4F01; + BiosRegisters.Ecx = ModeList[CurrentMode]; + BiosRegisters.Edi = VBEDeviceExtension->PhysicalAddress.QuadPart & 0xF; + BiosRegisters.Es = VBEDeviceExtension->PhysicalAddress.QuadPart >> 4; + Ke386CallBios(0x10, &BiosRegisters); + VbeModeInfo = (PVBE_MODEINFO)VBEDeviceExtension->TrampolineMemory; + if (BiosRegisters.Eax == 0x4F && + VbeModeInfo->XResolution >= 640 && + VbeModeInfo->YResolution >= 480 && +/* (VbeModeInfo->MemoryModel == 5 || VbeModeInfo->MemoryModel == 6) &&*/ + (VbeModeInfo->ModeAttributes & VBE_MODEATTR_LINEAR)) + { + memcpy(VBEDeviceExtension->ModeInfo + ModeCount, + VBEDeviceExtension->TrampolineMemory, + sizeof(VBE_MODEINFO)); + VBEDeviceExtension->ModeNumbers[ModeCount] = ModeList[CurrentMode] | 0x4000; + if (VbeModeInfo->XResolution == 640 && + VbeModeInfo->YResolution == 480 && + VbeModeInfo->BitsPerPixel == 8) + { + DefaultMode = ModeCount; + } + ModeCount++; + } + } + + /* + * Exchange the default mode so it's at the first place in list. + */ + + memcpy(&TempVbeModeInfo, + VBEDeviceExtension->ModeInfo, + sizeof(VBE_MODEINFO)); + memcpy(VBEDeviceExtension->ModeInfo, + VBEDeviceExtension->ModeInfo + DefaultMode, + sizeof(VBE_MODEINFO)); + memcpy(VBEDeviceExtension->ModeInfo + DefaultMode, + &TempVbeModeInfo, + sizeof(VBE_MODEINFO)); + TempVbeModeNumber = VBEDeviceExtension->ModeNumbers[0]; + VBEDeviceExtension->ModeNumbers[0] = VBEDeviceExtension->ModeNumbers[DefaultMode]; + VBEDeviceExtension->ModeNumbers[DefaultMode] = TempVbeModeNumber; + + if (ModeCount == 0) + { + DPRINT(("VBEMP: No video modes supported\n")); + return FALSE; + } + + VBEDeviceExtension->ModeCount = ModeCount; + +#ifdef DBG + for (CurrentMode = 0; + CurrentMode < ModeCount; + CurrentMode++) + { + DPRINT(("%dx%dx%d\n", + VBEDeviceExtension->ModeInfo[CurrentMode].XResolution, + VBEDeviceExtension->ModeInfo[CurrentMode].YResolution, + VBEDeviceExtension->ModeInfo[CurrentMode].BitsPerPixel)); + } +#endif + + return TRUE; +} + +BOOLEAN STDCALL +VBEStartIO(PVOID HwDeviceExtension, PVIDEO_REQUEST_PACKET RequestPacket) +{ + BOOL Result; + + RequestPacket->StatusBlock->Status = STATUS_UNSUCCESSFUL; + + switch (RequestPacket->IoControlCode) + { + case IOCTL_VIDEO_SET_CURRENT_MODE: + if (RequestPacket->InputBufferLength < sizeof(VIDEO_MODE)) + { + RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER; + return TRUE; + } + Result = VBESetCurrentMode((PVBE_DEVICE_EXTENSION)HwDeviceExtension, + (PVIDEO_MODE)RequestPacket->InputBuffer, RequestPacket->StatusBlock); + break; + + case IOCTL_VIDEO_RESET_DEVICE: + Result = VBEResetDevice((PVBE_DEVICE_EXTENSION)HwDeviceExtension, + RequestPacket->StatusBlock); + break; + + case IOCTL_VIDEO_MAP_VIDEO_MEMORY: + if (RequestPacket->OutputBufferLength < sizeof(VIDEO_MEMORY_INFORMATION) || + RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) + { + RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER; + return TRUE; + } + Result = VBEMapVideoMemory((PVBE_DEVICE_EXTENSION)HwDeviceExtension, + (PVIDEO_MEMORY)RequestPacket->InputBuffer, + (PVIDEO_MEMORY_INFORMATION)RequestPacket->OutputBuffer, + RequestPacket->StatusBlock); + break; + + case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY: + Result = VBEUnmapVideoMemory((PVBE_DEVICE_EXTENSION)HwDeviceExtension, + RequestPacket->StatusBlock); + break; + + case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES: + if (RequestPacket->OutputBufferLength < sizeof(VIDEO_NUM_MODES)) + { + RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER; + return TRUE; + } + Result = VBEQueryNumAvailModes((PVBE_DEVICE_EXTENSION)HwDeviceExtension, + (PVIDEO_NUM_MODES)RequestPacket->OutputBuffer, + RequestPacket->StatusBlock); + break; + + case IOCTL_VIDEO_QUERY_AVAIL_MODES: + if (RequestPacket->OutputBufferLength < + ((PVBE_DEVICE_EXTENSION)HwDeviceExtension)->ModeCount * sizeof(VIDEO_MODE_INFORMATION)) + { + RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER; + return TRUE; + } + Result = VBEQueryAvailModes((PVBE_DEVICE_EXTENSION)HwDeviceExtension, + (PVIDEO_MODE_INFORMATION)RequestPacket->OutputBuffer, + RequestPacket->StatusBlock); + break; + + case IOCTL_VIDEO_QUERY_CURRENT_MODE: + UNIMPLEMENTED; + break; + + case IOCTL_VIDEO_SET_COLOR_REGISTERS: + /* FIXME: Check buffer size! */ + Result = VBESetColorRegisters((PVBE_DEVICE_EXTENSION)HwDeviceExtension, + (PVIDEO_CLUT)RequestPacket->InputBuffer, RequestPacket->StatusBlock); + break; + + default: + RequestPacket->StatusBlock->Status = STATUS_NOT_IMPLEMENTED; + return FALSE; + } + + if (Result) + RequestPacket->StatusBlock->Status = STATUS_SUCCESS; + + return TRUE; +} + +BOOL FASTCALL +VBESetCurrentMode(PVBE_DEVICE_EXTENSION DeviceExtension, + PVIDEO_MODE RequestedMode, PSTATUS_BLOCK StatusBlock) +{ + KV86M_REGISTERS BiosRegisters; + + memset(&BiosRegisters, 0, sizeof(BiosRegisters)); + BiosRegisters.Eax = 0x4F02; + BiosRegisters.Ebx = DeviceExtension->ModeNumbers[RequestedMode->RequestedMode]; + Ke386CallBios(0x10, &BiosRegisters); + if (BiosRegisters.Eax == 0x4F) + { + DeviceExtension->CurrentMode = RequestedMode->RequestedMode; + } + else + { + DPRINT(("VBEMP: VBESetCurrentMode failed (%x)\n", BiosRegisters.Eax)); + DeviceExtension->CurrentMode = -1; + } + return (BiosRegisters.Eax == 0x4F); +} + +BOOL FASTCALL +VBEResetDevice(PVBE_DEVICE_EXTENSION DeviceExtension, + PSTATUS_BLOCK StatusBlock) +{ + VIDEO_X86_BIOS_ARGUMENTS BiosRegisters; + + memset(&BiosRegisters, 0, sizeof(BiosRegisters)); + BiosRegisters.Eax = 0x4F02; + BiosRegisters.Ebx = 0x3; + VideoPortInt10(NULL, &BiosRegisters); + return TRUE; +} + +BOOL FASTCALL +VBEMapVideoMemory(PVBE_DEVICE_EXTENSION DeviceExtension, + PVIDEO_MEMORY RequestedAddress, PVIDEO_MEMORY_INFORMATION MapInformation, + PSTATUS_BLOCK StatusBlock) +{ + KV86M_REGISTERS BiosRegisters; + PVBE_MODEINFO VbeModeInfo; + PHYSICAL_ADDRESS FrameBuffer; + ULONG inIoSpace = 0; + + StatusBlock->Information = sizeof(VIDEO_MEMORY_INFORMATION); + + BiosRegisters.Eax = 0x4F01; + BiosRegisters.Ecx = DeviceExtension->ModeNumbers[DeviceExtension->CurrentMode]; + BiosRegisters.Edi = DeviceExtension->PhysicalAddress.QuadPart & 0xF; + BiosRegisters.Es = DeviceExtension->PhysicalAddress.QuadPart >> 4; + Ke386CallBios(0x10, &BiosRegisters); + VbeModeInfo = (PVBE_MODEINFO)DeviceExtension->TrampolineMemory; + if (BiosRegisters.Eax == 0x4F && + (VbeModeInfo->ModeAttributes & VBE_MODEATTR_LINEAR)) + { + FrameBuffer.QuadPart = VbeModeInfo->PhysBasePtr; + MapInformation->VideoRamBase = RequestedAddress->RequestedVirtualAddress; + MapInformation->VideoRamLength = ( + DeviceExtension->ModeInfo[DeviceExtension->CurrentMode].XResolution * + DeviceExtension->ModeInfo[DeviceExtension->CurrentMode].YResolution * + DeviceExtension->ModeInfo[DeviceExtension->CurrentMode].BitsPerPixel + ) >> 3; + + VideoPortMapMemory(DeviceExtension, FrameBuffer, + &MapInformation->VideoRamLength, &inIoSpace, + &MapInformation->VideoRamBase); + + MapInformation->FrameBufferBase = MapInformation->VideoRamBase; + MapInformation->FrameBufferLength = MapInformation->VideoRamLength; + + DeviceExtension->FrameBufferMemory = MapInformation->VideoRamBase; + + return TRUE; + } + else + { + DPRINT(("VBEMP: VBEMapVideoMemory Failed (%lx)\n", BiosRegisters.Eax)); + + return FALSE; + } +} + +BOOL FASTCALL +VBEUnmapVideoMemory(PVBE_DEVICE_EXTENSION DeviceExtension, + PSTATUS_BLOCK StatusBlock) +{ + VideoPortUnmapMemory(DeviceExtension, DeviceExtension->FrameBufferMemory, + NULL); + return TRUE; +} + +BOOL FASTCALL +VBEQueryNumAvailModes(PVBE_DEVICE_EXTENSION DeviceExtension, + PVIDEO_NUM_MODES Modes, PSTATUS_BLOCK StatusBlock) +{ + Modes->NumModes = DeviceExtension->ModeCount; + Modes->ModeInformationLength = sizeof(VIDEO_MODE_INFORMATION); + StatusBlock->Information = sizeof(VIDEO_NUM_MODES); + return TRUE; +} + +BOOL FASTCALL +VBEQueryAvailModes(PVBE_DEVICE_EXTENSION DeviceExtension, + PVIDEO_MODE_INFORMATION ReturnedModes, PSTATUS_BLOCK StatusBlock) +{ + ULONG CurrentModeId; + PVIDEO_MODE_INFORMATION CurrentMode; + PVBE_MODEINFO CurrentVBEMode; + + for (CurrentModeId = 0, CurrentMode = ReturnedModes, + CurrentVBEMode = DeviceExtension->ModeInfo; + CurrentModeId < DeviceExtension->ModeCount; + CurrentModeId++, CurrentMode++, CurrentVBEMode++) + { + CurrentMode->Length = sizeof(VIDEO_MODE_INFORMATION); + CurrentMode->ModeIndex = CurrentModeId; + CurrentMode->VisScreenWidth = CurrentVBEMode->XResolution; + CurrentMode->VisScreenHeight = CurrentVBEMode->YResolution; + CurrentMode->ScreenStride = CurrentVBEMode->BytesPerScanLine; + CurrentMode->NumberOfPlanes = CurrentVBEMode->NumberOfPlanes; + CurrentMode->BitsPerPlane = CurrentVBEMode->BitsPerPixel / + CurrentVBEMode->NumberOfPlanes; + CurrentMode->Frequency = 0; /* FIXME */ + CurrentMode->XMillimeter = 0; /* FIXME */ + CurrentMode->YMillimeter = 0; /* FIXME */ + if (CurrentVBEMode->BitsPerPixel > 8) + { + if (DeviceExtension->VBEVersion < 0x300) + { + CurrentMode->NumberRedBits = CurrentVBEMode->RedMaskSize; + CurrentMode->NumberGreenBits = CurrentVBEMode->GreenMaskSize; + CurrentMode->NumberBlueBits = CurrentVBEMode->BlueMaskSize; + CurrentMode->RedMask = ((1 << CurrentVBEMode->RedMaskSize) - 1) << CurrentVBEMode->RedFieldPosition; + CurrentMode->GreenMask = ((1 << CurrentVBEMode->GreenMaskSize) - 1) << CurrentVBEMode->GreenFieldPosition; + CurrentMode->BlueMask = ((1 << CurrentVBEMode->BlueMaskSize) - 1) << CurrentVBEMode->BlueFieldPosition; + } + else + { + CurrentMode->NumberRedBits = CurrentVBEMode->LinRedMaskSize; + CurrentMode->NumberGreenBits = CurrentVBEMode->LinGreenMaskSize; + CurrentMode->NumberBlueBits = CurrentVBEMode->LinBlueMaskSize; + CurrentMode->RedMask = ((1 << CurrentVBEMode->LinRedMaskSize) - 1) << CurrentVBEMode->LinRedFieldPosition; + CurrentMode->GreenMask = ((1 << CurrentVBEMode->LinGreenMaskSize) - 1) << CurrentVBEMode->LinGreenFieldPosition; + CurrentMode->BlueMask = ((1 << CurrentVBEMode->LinBlueMaskSize) - 1) << CurrentVBEMode->LinBlueFieldPosition; + } + } + else + { + CurrentMode->NumberRedBits = + CurrentMode->NumberGreenBits = + CurrentMode->NumberBlueBits = 6; + CurrentMode->RedMask = + CurrentMode->GreenMask = + CurrentMode->BlueMask = 0; + } + CurrentMode->VideoMemoryBitmapWidth = CurrentVBEMode->XResolution; + CurrentMode->VideoMemoryBitmapHeight = CurrentVBEMode->YResolution; + CurrentMode->AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | + VIDEO_MODE_NO_OFF_SCREEN; + if (CurrentMode->BitsPerPlane <= 8) + CurrentMode->AttributeFlags |= VIDEO_MODE_PALETTE_DRIVEN; + CurrentMode->DriverSpecificAttributeFlags = 0; + } + + StatusBlock->Information = + sizeof(VIDEO_MODE_INFORMATION) * DeviceExtension->ModeCount; + + return TRUE; +} + +BOOL FASTCALL +VBESetColorRegisters(PVBE_DEVICE_EXTENSION DeviceExtension, + PVIDEO_CLUT ColorLookUpTable, PSTATUS_BLOCK StatusBlock) +{ + KV86M_REGISTERS BiosRegisters; + + if (DeviceExtension->VGACompatible) + { + ULONG Entry; + + for (Entry = ColorLookUpTable->FirstEntry; + Entry < ColorLookUpTable->NumEntries + ColorLookUpTable->FirstEntry; + Entry++) + { + VideoPortWritePortUchar((PUCHAR)0x03c8, Entry); + VideoPortWritePortUchar((PUCHAR)0x03c9, ColorLookUpTable->LookupTable[Entry].RgbArray.Red); + VideoPortWritePortUchar((PUCHAR)0x03c9, ColorLookUpTable->LookupTable[Entry].RgbArray.Green); + VideoPortWritePortUchar((PUCHAR)0x03c9, ColorLookUpTable->LookupTable[Entry].RgbArray.Blue); + } + return TRUE; + } + else + { + /* + * FIXME: + * This is untested code path, it's possible that it will + * not work at all or that Red and Blue colors will be swapped. + */ + + memcpy(DeviceExtension->TrampolineMemory, + &ColorLookUpTable->LookupTable[0].RgbArray, + sizeof(DWORD) * ColorLookUpTable->NumEntries); + BiosRegisters.Eax = 0x4F09; + BiosRegisters.Ebx = 0; + BiosRegisters.Ecx = ColorLookUpTable->NumEntries; + BiosRegisters.Edx = ColorLookUpTable->FirstEntry; + BiosRegisters.Edi = DeviceExtension->PhysicalAddress.QuadPart & 0xF; + BiosRegisters.Es = DeviceExtension->PhysicalAddress.QuadPart >> 4; + Ke386CallBios(0x10, &BiosRegisters); + return (BiosRegisters.Eax == 0x4F); + } +} diff --git a/reactos/drivers/video/miniport/vbe/vbemp.h b/reactos/drivers/video/miniport/vbe/vbemp.h new file mode 100644 index 00000000000..ac233d5da21 --- /dev/null +++ b/reactos/drivers/video/miniport/vbe/vbemp.h @@ -0,0 +1,208 @@ +/* + * ReactOS VBE miniport video driver + * + * Copyright (C) 2004 Filip Navara + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef VBEMP_H +#define VBEMP_H + +/* INCLUDES *******************************************************************/ + +#include "stddef.h" +#include "windef.h" +#include "wingdi.h" +#include +#include +#include +#include + +/* For Ke386CallBios */ +#include "internal/v86m.h" + +/* FIXME: Missing define in w32api! */ +#ifndef NtCurrentProcess +#define NtCurrentProcess() ((HANDLE)(LONG_PTR)-1) +#endif + +/* + * Print a message and hang for unimplemented functions. + */ +#define UNIMPLEMENTED DbgPrint("%s:%d UNIMPLEMENTED", __FILE__, __LINE__); for (;;) + +#ifdef DBG +#define DPRINT(arg) DbgPrint arg; +#else +#define DPRINT(arg) +#endif + +#include + +/* + * VBE specification defined structure for general adapter info + * returned by function 0x4F00. + */ +typedef struct +{ + CHAR Signature[4]; + WORD Version; + DWORD OemStringPtr; + LONG Capabilities; + DWORD VideoModePtr; + WORD TotalMemory; + WORD OemSoftwareRevision; + DWORD OemVendorNamePtr; + DWORD OemProductNamePtr; + DWORD OemProductRevPtr; + CHAR Reserved[222]; + CHAR OemData[256]; +} VBE_INFO, *PVBE_INFO; + +/* + * VBE specification defined structure for specific video mode + * info returned by function 0x4F01. + */ +typedef struct { + /* Mandatory information for all VBE revisions */ + WORD ModeAttributes; + BYTE WinAAttributes; + BYTE WinBAttributes; + WORD WinGranularity; + WORD WinSize; + WORD WinASegment; + WORD WinBSegment; + DWORD WinFuncPtr; + WORD BytesPerScanLine; + + /* Mandatory information for VBE 1.2 and above */ + WORD XResolution; + WORD YResolution; + BYTE XCharSize; + BYTE YCharSize; + BYTE NumberOfPlanes; + BYTE BitsPerPixel; + BYTE NumberOfBanks; + BYTE MemoryModel; + BYTE BankSize; + BYTE NumberOfImagePages; + BYTE Reserved1; + + /* Direct Color fields (required for Direct/6 and YUV/7 memory models) */ + BYTE RedMaskSize; + BYTE RedFieldPosition; + BYTE GreenMaskSize; + BYTE GreenFieldPosition; + BYTE BlueMaskSize; + BYTE BlueFieldPosition; + BYTE ReservedMaskSize; + BYTE ReservedFieldPosition; + BYTE DirectColorModeInfo; + + /* Mandatory information for VBE 2.0 and above */ + DWORD PhysBasePtr; + DWORD Reserved2; + WORD Reserved3; + + /* Mandatory information for VBE 3.0 and above */ + WORD LinBytesPerScanLine; + BYTE BnkNumberOfImagePages; + BYTE LinNumberOfImagePages; + BYTE LinRedMaskSize; + BYTE LinRedFieldPosition; + BYTE LinGreenMaskSize; + BYTE LinGreenFieldPosition; + BYTE LinBlueMaskSize; + BYTE LinBlueFieldPosition; + BYTE LinReservedMaskSize; + BYTE LinReservedFieldPosition; + DWORD MaxPixelClock; + + CHAR Reserved4[189]; +} VBE_MODEINFO, *PVBE_MODEINFO; + +#define VBE_MODEATTR_LINEAR 0x80 + +#include + +typedef struct { + /* Trampoline memory for communication with VBE real-mode interface. */ + PHYSICAL_ADDRESS PhysicalAddress; + PVOID TrampolineMemory; + + /* Pointer to mapped frame buffer memory */ + PVOID FrameBufferMemory; + + /* General controller/BIOS information */ + BOOL VGACompatible; + WORD VBEVersion; + + /* Saved information about video modes */ + ULONG ModeCount; + WORD *ModeNumbers; + PVBE_MODEINFO ModeInfo; + WORD CurrentMode; +} VBE_DEVICE_EXTENSION, *PVBE_DEVICE_EXTENSION; + +VP_STATUS STDCALL +VBEFindAdapter(IN PVOID HwDeviceExtension, IN PVOID HwContext, + IN PWSTR ArgumentString, IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo, + OUT PUCHAR Again); + +BOOLEAN STDCALL +VBEInitialize(PVOID HwDeviceExtension); + +BOOLEAN STDCALL +VBEStartIO(PVOID HwDeviceExtension, PVIDEO_REQUEST_PACKET RequestPacket); + +VP_STATUS STDCALL +VBESetPowerState(PVOID HwDeviceExtension, ULONG HwId, + PVIDEO_POWER_MANAGEMENT VideoPowerControl); + +VP_STATUS STDCALL +VBEGetPowerState(PVOID HwDeviceExtension, ULONG HwId, + PVIDEO_POWER_MANAGEMENT VideoPowerControl); + +BOOL FASTCALL +VBESetCurrentMode(PVBE_DEVICE_EXTENSION DeviceExtension, + PVIDEO_MODE RequestedMode, PSTATUS_BLOCK StatusBlock); + +BOOL FASTCALL +VBEResetDevice(PVBE_DEVICE_EXTENSION DeviceExtension, + PSTATUS_BLOCK StatusBlock); + +BOOL FASTCALL +VBEMapVideoMemory(PVBE_DEVICE_EXTENSION DeviceExtension, + PVIDEO_MEMORY RequestedAddress, PVIDEO_MEMORY_INFORMATION MapInformation, + PSTATUS_BLOCK StatusBlock); + +BOOL FASTCALL +VBEUnmapVideoMemory(PVBE_DEVICE_EXTENSION DeviceExtension, + PSTATUS_BLOCK StatusBlock); + +BOOL FASTCALL +VBEQueryNumAvailModes(PVBE_DEVICE_EXTENSION DeviceExtension, + PVIDEO_NUM_MODES Modes, PSTATUS_BLOCK StatusBlock); + +BOOL FASTCALL +VBEQueryAvailModes(PVBE_DEVICE_EXTENSION DeviceExtension, + PVIDEO_MODE_INFORMATION ReturnedModes, PSTATUS_BLOCK StatusBlock); + +BOOL FASTCALL +VBESetColorRegisters(PVBE_DEVICE_EXTENSION DeviceExtension, + PVIDEO_CLUT ColorLookUpTable, PSTATUS_BLOCK StatusBlock); + +#endif /* VBEMP_H */ diff --git a/reactos/drivers/video/miniport/vbe/vbemp.rc b/reactos/drivers/video/miniport/vbe/vbemp.rc new file mode 100644 index 00000000000..1497680922c --- /dev/null +++ b/reactos/drivers/video/miniport/vbe/vbemp.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "VGA Miniport Device Driver\0" + VALUE "FileVersion", "0.0.0\0" + VALUE "InternalName", "vgamp\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "vgamp.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/reactos/drivers/video/miniport/vga/.cvsignore b/reactos/drivers/video/miniport/vga/.cvsignore new file mode 100644 index 00000000000..50811c0c7e9 --- /dev/null +++ b/reactos/drivers/video/miniport/vga/.cvsignore @@ -0,0 +1,8 @@ +junk.tmp +base.tmp +temp.exp +vgamp.coff +*.o +*.sym +*.sys +*.map diff --git a/reactos/drivers/video/miniport/vga/initvga.c b/reactos/drivers/video/miniport/vga/initvga.c new file mode 100644 index 00000000000..7de39809f5b --- /dev/null +++ b/reactos/drivers/video/miniport/vga/initvga.c @@ -0,0 +1,129 @@ +#include +#include +#include "vgavideo.h" + +#define NDEBUG +#include + +void outxay(PUSHORT ad, UCHAR x, UCHAR y) +{ + USHORT xy = (x << 8) + y; + + VideoPortWritePortUshort(ad, xy); +} + +void setMode(VideoMode mode) +{ + unsigned char x; + + VideoPortWritePortUchar((PUCHAR)MISC, mode.Misc); + VideoPortWritePortUchar((PUCHAR)STATUS, 0); + VideoPortWritePortUchar((PUCHAR)FEATURE, mode.Feature); + + for(x=0; x<5; x++) + { + outxay((PUSHORT)SEQ, mode.Seq[x], x); + } + + VideoPortWritePortUshort((PUSHORT)CRTC, 0x11); + VideoPortWritePortUshort((PUSHORT)CRTC, (mode.Crtc[0x11] & 0x7f)); + + for(x=0; x<25; x++) + { + outxay((PUSHORT)CRTC, mode.Crtc[x], x); + } + + for(x=0; x<9; x++) + { + outxay((PUSHORT)GRAPHICS, mode.Gfx[x], x); + } + + x=VideoPortReadPortUchar((PUCHAR)FEATURE); + + for(x=0; x<21; x++) + { + VideoPortWritePortUchar((PUCHAR)ATTRIB, x); + VideoPortWritePortUchar((PUCHAR)ATTRIB, mode.Attrib[x]); + } + + x=VideoPortReadPortUchar((PUCHAR)STATUS); + + VideoPortWritePortUchar((PUCHAR)ATTRIB, 0x20); +} + +VideoMode Mode12 = { + 0xa000, 0xe3, 0x00, + + {0x03, 0x01, 0x0f, 0x00, 0x06 }, + + {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x59, 0xea, 0x8c, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3, + 0xff}, + + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff}, + + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x81, 0x00, 0x0f, 0x00, 0x00} +}; + +void InitVGAMode() +{ + int i; + VIDEO_X86_BIOS_ARGUMENTS vxba; + VP_STATUS vps; + + // FIXME: Use Vidport to map the memory properly + vidmem = (char *)(0xd0000000 + 0xa0000); + memset(&vxba, 0, sizeof(vxba)); + vxba.Eax = 0x0012; + vps = VideoPortInt10(NULL, &vxba); + + // Get VGA registers into the correct state (mainly for setting up the palette registers correctly) + setMode(Mode12); + + // Get the VGA into the mode we want to work with + WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08); // Set + WRITE_PORT_UCHAR((PUCHAR)GRA_D,0); // the MASK + WRITE_PORT_USHORT((PUSHORT)GRA_I,0x0205); // write mode = 2 (bits 0,1) read mode = 0 (bit 3) + i = READ_REGISTER_UCHAR(vidmem); // Update bit buffer + WRITE_REGISTER_UCHAR(vidmem, 0); // Write the pixel + WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08); + WRITE_PORT_UCHAR((PUCHAR)GRA_D,0xff); + + // Zero out video memory (clear a possibly trashed screen) + RtlZeroMemory(vidmem, 64000); + + vgaPreCalc(); +} + +VOID VGAResetDevice(OUT PSTATUS_BLOCK StatusBlock) +{ + HANDLE Event; + OBJECT_ATTRIBUTES Attr; + UNICODE_STRING Name = ROS_STRING_INITIALIZER(L"\\TextConsoleRefreshEvent"); + NTSTATUS Status; + VIDEO_X86_BIOS_ARGUMENTS vxba; + VP_STATUS vps; + ULONG ThreadRelease = 1; + + CHECKPOINT; + Event = 0; + + memset(&vxba, 0, sizeof(vxba)); + vxba.Eax = 0x0003; + vps = VideoPortInt10(NULL, &vxba); + memset(&vxba, 0, sizeof(vxba)); + vxba.Eax = 0x1112; + vps = VideoPortInt10(NULL, &vxba); + InitializeObjectAttributes( &Attr, &Name, 0, 0, 0 ); + Status = ZwOpenEvent( &Event, STANDARD_RIGHTS_ALL, &Attr ); + if( !NT_SUCCESS( Status ) ) + DbgPrint( "VGA: Failed to open refresh event\n" ); + else { + ZwSetEvent( Event, &ThreadRelease ); + ZwClose( Event ); + } +} + + + diff --git a/reactos/drivers/video/miniport/vga/makefile b/reactos/drivers/video/miniport/vga/makefile new file mode 100644 index 00000000000..6d643647e95 --- /dev/null +++ b/reactos/drivers/video/miniport/vga/makefile @@ -0,0 +1,20 @@ +# $Id: makefile,v 1.1 2004/01/10 14:39:21 navaraf Exp $ + +PATH_TO_TOP = ../../../.. + +TARGET_TYPE = driver + +TARGET_NAME = vgamp + +TARGET_DDKLIBS = videoprt.a + +TARGET_CFLAGS = -Werror -Wall + +TARGET_OBJECTS = \ + initvga.o \ + vgamp.o \ + vgavideo.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/reactos/drivers/video/miniport/vga/vgamp.c b/reactos/drivers/video/miniport/vga/vgamp.c new file mode 100644 index 00000000000..8dd9cd116c0 --- /dev/null +++ b/reactos/drivers/video/miniport/vga/vgamp.c @@ -0,0 +1,486 @@ +/* + * VGA.C - a generic VGA miniport driver + * + */ + +#include +#include + +#define UNIMPLEMENTED do {DbgPrint("%s:%d: Function not implemented", __FILE__, __LINE__); for(;;);} while (0) + +#define VERSION "0.0.0" +void InitVGAMode(); +// ---------------------------------------------------- Forward Declarations +static VP_STATUS STDCALL +VGAFindAdapter(PVOID DeviceExtension, + PVOID Context, + PWSTR ArgumentString, + PVIDEO_PORT_CONFIG_INFO ConfigInfo, + PUCHAR Again); +static BOOLEAN STDCALL +VGAInitialize(PVOID DeviceExtension); +static BOOLEAN STDCALL +VGAStartIO(PVOID DeviceExtension, + PVIDEO_REQUEST_PACKET RequestPacket); +/* +static BOOLEAN STDCALL +VGAInterrupt(PVOID DeviceExtension);*/ +static BOOLEAN STDCALL +VGAResetHw(PVOID DeviceExtension, + ULONG Columns, + ULONG Rows); +/*static VOID STDCALL +VGATimer(PVOID DeviceExtension); +*/ + +/* Mandatory IoControl routines */ +VOID VGAMapVideoMemory(IN PVIDEO_MEMORY RequestedAddress, + OUT PVIDEO_MEMORY_INFORMATION MapInformation, + OUT PSTATUS_BLOCK StatusBlock); +VOID VGAQueryAvailModes(OUT PVIDEO_MODE_INFORMATION ReturnedModes, + OUT PSTATUS_BLOCK StatusBlock); +VOID VGAQueryCurrentMode(OUT PVIDEO_MODE_INFORMATION CurrentMode, + OUT PSTATUS_BLOCK StatusBlock); +VOID VGAQueryNumAvailModes(OUT PVIDEO_NUM_MODES NumberOfModes, + OUT PSTATUS_BLOCK StatusBlock); +VOID VGAResetDevice(OUT PSTATUS_BLOCK StatusBlock); +VOID VGASetColorRegisters(IN PVIDEO_CLUT ColorLookUpTable, + OUT PSTATUS_BLOCK StatusBlock); +VOID VGASetPaletteRegisters(IN PWORD PaletteRegisters, + OUT PSTATUS_BLOCK StatusBlock); +VOID VGASetCurrentMode(IN PVIDEO_MODE RequestedMode, + OUT PSTATUS_BLOCK StatusBlock); +VOID VGAShareVideoMemory(IN PVIDEO_SHARE_MEMORY RequestedMemory, + OUT PVIDEO_MEMORY_INFORMATION ReturnedMemory, + OUT PSTATUS_BLOCK StatusBlock); +VOID VGAUnmapVideoMemory(IN PVIDEO_MEMORY MemoryToUnmap, + OUT PSTATUS_BLOCK StatusBlock); +VOID VGAUnshareVideoMemory(IN PVIDEO_MEMORY MemoryToUnshare, + OUT PSTATUS_BLOCK StatusBlock); + +// ------------------------------------------------------- Public Interface + +// DriverEntry +// +// DESCRIPTION: +// This function initializes the driver. +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// IN PVOID Context1 Context parameter to pass to VidPortInitialize +// IN PVOID Context2 Context parameter to pass to VidPortInitialize +// RETURNS: +// VP_STATUS + +VP_STATUS STDCALL +DriverEntry(IN PVOID Context1, + IN PVOID Context2) +{ + VIDEO_HW_INITIALIZATION_DATA InitData; + + VideoPortZeroMemory(&InitData, sizeof InitData); + + /* FIXME: Fill in InitData members */ + InitData.StartingDeviceNumber = 0; + + /* Export driver entry points... */ + InitData.HwFindAdapter = VGAFindAdapter; + InitData.HwInitialize = VGAInitialize; + InitData.HwStartIO = VGAStartIO; + /* InitData.HwInterrupt = VGAInterrupt; */ + InitData.HwResetHw = VGAResetHw; + /* InitData.HwTimer = VGATimer; */ + + return VideoPortInitialize(Context1, Context2, &InitData, NULL); +} + +// VGAFindAdapter +// +// DESCRIPTION: +// This routine is called by the videoport driver to find and allocate +// the adapter for a given bus. The miniport driver needs to do the +// following in this routine: +// - Determine if the adapter is present +// - Claim any necessary memory/IO resources for the adapter +// - Map resources into system memory for the adapter +// - fill in relevant information in the VIDEO_PORT_CONFIG_INFO buffer +// - update registry settings for adapter specifics. +// - Set 'Again' based on whether the function should be called again +// another adapter on the same bus. +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// PVOID DeviceExtension +// PVOID Context +// PWSTR ArgumentString +// PVIDEO_PORT_CONFIG_INFO ConfigInfo +// PUCHAR Again +// RETURNS: +// VP_STATUS + +static VP_STATUS STDCALL +VGAFindAdapter(PVOID DeviceExtension, + PVOID Context, + PWSTR ArgumentString, + PVIDEO_PORT_CONFIG_INFO ConfigInfo, + PUCHAR Again) +{ + /* FIXME: Determine if the adapter is present */ + *Again = FALSE; + + return STATUS_SUCCESS; + + /* FIXME: Claim any necessary memory/IO resources for the adapter */ + /* FIXME: Map resources into system memory for the adapter */ + /* FIXME: Fill in relevant information in the VIDEO_PORT_CONFIG_INFO buffer */ + /* FIXME: Update registry settings for adapter specifics. */ +// return NO_ERROR; +} + +// VGAInitialize +// +// DESCRIPTION: +// Perform initialization tasks, but leave the adapter in the same +// user visible state +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// PVOID DeviceExtension +// RETURNS: +// BOOLEAN Success or failure +static BOOLEAN STDCALL +VGAInitialize(PVOID DeviceExtension) +{ + return TRUE; +} + +// VGAStartIO +// +// DESCRIPTION: +// This function gets called in responce to GDI EngDeviceIoControl +// calls. Device requests are passed in VRPs. +// Required VRPs: +// IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES +// IOCTL_VIDEO_QUERY_AVAIL_MODES +// IOCTL_VIDEO_QUERY_CURRENT_MODE +// IOCTL_VIDEO_SET_CURRENT_MODE +// IOCTL_VIDEO_RESET_DEVICE +// IOCTL_VIDEO_MAP_VIDEO_MEMORY +// IOCTL_VIDEO_UNMAP_VIDEO_MEMORY +// IOCTL_VIDEO_SHARE_VIDEO_MEMORY +// IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY +// Optional VRPs: +// IOCTL_VIDEO_GET_PUBLIC_ACCESS_RANGES +// IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES +// IOCTL_VIDEO_GET_POWER_MANAGEMENT +// IOCTL_VIDEO_SET_POWER_MANAGEMENT +// IOCTL_QUERY_COLOR_CAPABILITIES +// IOCTL_VIDEO_SET_COLOR_REGISTERS (required if the device has a palette) +// IOCTL_VIDEO_DISABLE_POINTER +// IOCTL_VIDEO_ENABLE_POINTER +// IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES +// IOCTL_VIDEO_QUERY_POINTER_ATTR +// IOCTL_VIDEO_SET_POINTER_ATTR +// IOCTL_VIDEO_QUERY_POINTER_POSITION +// IOCTL_VIDEO_SET_POINTER_POSITION +// IOCTL_VIDEO_SAVE_HARDWARE_STATE +// IOCTL_VIDEO_RESTORE_HARDWARE_STATE +// IOCTL_VIDEO_DISABLE_CURSOR +// IOCTL_VIDEO_ENABLE_CURSOR +// IOCTL_VIDEO_QUERY_CURSOR_ATTR +// IOCTL_VIDEO_SET_CURSOR_ATTR +// IOCTL_VIDEO_QUERY_CURSOR_POSITION +// IOCTL_VIDEO_SET_CURSOR_POSITION +// IOCTL_VIDEO_GET_BANK_SELECT_CODE +// IOCTL_VIDEO_SET_PALETTE_REGISTERS +// IOCTL_VIDEO_LOAD_AND_SET_FONT +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// PVOID DeviceExtension +// PVIDEO_REQUEST_PACKET RequestPacket +// RETURNS: +// BOOLEAN This function must return TRUE, and complete the work or +// set an error status in the VRP. + +static BOOLEAN STDCALL +VGAStartIO(PVOID DeviceExtension, + PVIDEO_REQUEST_PACKET RequestPacket) +{ + switch (RequestPacket->IoControlCode) + { + case IOCTL_VIDEO_MAP_VIDEO_MEMORY: + VGAMapVideoMemory((PVIDEO_MEMORY) RequestPacket->InputBuffer, + (PVIDEO_MEMORY_INFORMATION) + RequestPacket->OutputBuffer, + RequestPacket->StatusBlock); + break; + + case IOCTL_VIDEO_QUERY_AVAIL_MODES: + VGAQueryAvailModes((PVIDEO_MODE_INFORMATION) RequestPacket->OutputBuffer, + RequestPacket->StatusBlock); + break; + + case IOCTL_VIDEO_QUERY_CURRENT_MODE: + VGAQueryCurrentMode((PVIDEO_MODE_INFORMATION) RequestPacket->OutputBuffer, + RequestPacket->StatusBlock); + break; + + case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES: + VGAQueryNumAvailModes((PVIDEO_NUM_MODES) RequestPacket->OutputBuffer, + RequestPacket->StatusBlock); + break; + + case IOCTL_VIDEO_RESET_DEVICE: + VGAResetDevice(RequestPacket->StatusBlock); + break; + + case IOCTL_VIDEO_SET_COLOR_REGISTERS: + VGASetColorRegisters((PVIDEO_CLUT) RequestPacket->InputBuffer, + RequestPacket->StatusBlock); + break; + + case IOCTL_VIDEO_SET_CURRENT_MODE: + VGASetCurrentMode((PVIDEO_MODE) RequestPacket->InputBuffer, + RequestPacket->StatusBlock); + break; + + case IOCTL_VIDEO_SHARE_VIDEO_MEMORY: + VGAShareVideoMemory((PVIDEO_SHARE_MEMORY) RequestPacket->InputBuffer, + (PVIDEO_MEMORY_INFORMATION) RequestPacket->OutputBuffer, + RequestPacket->StatusBlock); + break; + + case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY: + VGAUnmapVideoMemory((PVIDEO_MEMORY) RequestPacket->InputBuffer, + RequestPacket->StatusBlock); + break; + + case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY: + VGAUnshareVideoMemory((PVIDEO_MEMORY) RequestPacket->InputBuffer, + RequestPacket->StatusBlock); + break; + case IOCTL_VIDEO_SET_PALETTE_REGISTERS: + VGASetPaletteRegisters((PWORD) RequestPacket->InputBuffer, + RequestPacket->StatusBlock); + break; + +#if 0 + case IOCTL_VIDEO_DISABLE_CURSOR: + case IOCTL_VIDEO_DISABLE_POINTER: + case IOCTL_VIDEO_ENABLE_CURSOR: + case IOCTL_VIDEO_ENABLE_POINTER: + + case IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES: + VGAFreePublicAccessRanges((PVIDEO_PUBLIC_ACCESS_RANGES) + RequestPacket->InputBuffer, + RequestPacket->StatusBlock); + break; + + case IOCTL_VIDEO_GET_BANK_SELECT_CODE: + case IOCTL_VIDEO_GET_POWER_MANAGEMENT: + case IOCTL_VIDEO_LOAD_AND_SET_FONT: + case IOCTL_VIDEO_QUERY_CURSOR_POSITION: + case IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES: + case IOCTL_VIDEO_QUERY_CURSOR_ATTR: + case IOCTL_VIDEO_QUERY_POINTER_ATTR: + case IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES: + case IOCTL_VIDEO_QUERY_POINTER_POSITION: + + case IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES: + VGAQueryPublicAccessRanges((PVIDEO_PUBLIC_ACCESS_RANGES) + RequestPacket->OutputBuffer, + RequestPacket->StatusBlock); + break; + + case IOCTL_VIDEO_RESTORE_HARDWARE_STATE: + case IOCTL_VIDEO_SAVE_HARDWARE_STATE: + case IOCTL_VIDEO_SET_CURSOR_ATTR: + case IOCTL_VIDEO_SET_CURSOR_POSITION: + case IOCTL_VIDEO_SET_POINTER_ATTR: + case IOCTL_VIDEO_SET_POINTER_POSITION: + case IOCTL_VIDEO_SET_POWER_MANAGEMENT: + +#endif + + default: + RequestPacket->StatusBlock->Status = STATUS_NOT_IMPLEMENTED; + break; + } + + return TRUE; +} + +#if 0 +// VGAInterrupt +// +// DESCRIPTION: +// This function will be called upon receipt of a adapter generated +// interrupt when enabled. +// +// RUN LEVEL: +// IRQL +// +// ARGUMENTS: +// PVOID DeviceExtension +// RETURNS: +// BOOLEAN TRUE if the interrupt was handled by the routine + +static BOOLEAN STDCALL +VGAInterrupt(PVOID DeviceExtension) +{ + return(TRUE); +} +#endif + +// VGAResetHw +// +// DESCRIPTION: +// This function is called to reset the hardware to a known state +// if calling a BIOS int 10 reset will not achieve this result. +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// PVOID DeviceExtension +// ULONG Columns Columns and Rows specify the mode parameters +// ULONG Rows to reset to. +// RETURNS: +// BOOLEAN TRUE if no further action is necessary, FALSE if the system +// needs to still do a BOIS int 10 reset. + +static BOOLEAN STDCALL +VGAResetHw(PVOID DeviceExtension, + ULONG Columns, + ULONG Rows) +{ + /* We don't anything to the vga that int10 can't cope with. */ + return(FALSE); +} + +#if 0 +// VGATimer +// +// DESCRIPTION: +// This function will be called once a second when enabled +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// PVOID DeviceExtension +// RETURNS: +// VOID + +static VOID STDCALL +VGATimer(PVOID DeviceExtension) +{ +} + +#endif + +VOID VGAMapVideoMemory(IN PVIDEO_MEMORY RequestedAddress, + OUT PVIDEO_MEMORY_INFORMATION MapInformation, + OUT PSTATUS_BLOCK StatusBlock) +{ + UNIMPLEMENTED; +} + +VOID VGAQueryAvailModes(OUT PVIDEO_MODE_INFORMATION ReturnedModes, + OUT PSTATUS_BLOCK StatusBlock) +{ + UNIMPLEMENTED; +} + +VOID VGAQueryCurrentMode(OUT PVIDEO_MODE_INFORMATION CurrentMode, + OUT PSTATUS_BLOCK StatusBlock) +{ + UNIMPLEMENTED; +} + +VOID VGAQueryNumAvailModes(OUT PVIDEO_NUM_MODES NumberOfModes, + OUT PSTATUS_BLOCK StatusBlock) +{ + UNIMPLEMENTED; +} + +VOID VGASetPaletteRegisters(IN PWORD PaletteRegisters, + OUT PSTATUS_BLOCK StatusBlock) +{ + ; + +/* + We don't need the following code because the palette registers are set correctly on VGA initialization. + Still, we may include\test this is in the future. + + int i, j = 2; + char tmp, v; + + tmp = VideoPortReadPortUchar(0x03da); + v = VideoPortReadPortUchar(0x03c0); + + // Set the first 16 palette registers to map to the first 16 palette colors + for (i=PaletteRegisters[1]; iFirstEntry; iNumEntries; i++) + { + VideoPortWritePortUchar((PUCHAR)0x03c8, i); + VideoPortWritePortUchar((PUCHAR)0x03c9, ColorLookUpTable->LookupTable[i].RgbArray.Red); + VideoPortWritePortUchar((PUCHAR)0x03c9, ColorLookUpTable->LookupTable[i].RgbArray.Green); + VideoPortWritePortUchar((PUCHAR)0x03c9, ColorLookUpTable->LookupTable[i].RgbArray.Blue); + } +} + +VOID VGASetCurrentMode(IN PVIDEO_MODE RequestedMode, + OUT PSTATUS_BLOCK StatusBlock) +{ + if(RequestedMode->RequestedMode == 12) + { + InitVGAMode(); + } else { + DbgPrint("Unrecognised mode for VGASetCurrentMode\n"); + } +} + +VOID VGAShareVideoMemory(IN PVIDEO_SHARE_MEMORY RequestedMemory, + OUT PVIDEO_MEMORY_INFORMATION ReturnedMemory, + OUT PSTATUS_BLOCK StatusBlock) +{ + UNIMPLEMENTED; +} + +VOID VGAUnmapVideoMemory(IN PVIDEO_MEMORY MemoryToUnmap, + OUT PSTATUS_BLOCK StatusBlock) +{ + UNIMPLEMENTED; +} + +VOID VGAUnshareVideoMemory(IN PVIDEO_MEMORY MemoryToUnshare, + OUT PSTATUS_BLOCK StatusBlock) +{ + UNIMPLEMENTED; +} diff --git a/reactos/drivers/video/miniport/vga/vgamp.rc b/reactos/drivers/video/miniport/vga/vgamp.rc new file mode 100644 index 00000000000..1497680922c --- /dev/null +++ b/reactos/drivers/video/miniport/vga/vgamp.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "VGA Miniport Device Driver\0" + VALUE "FileVersion", "0.0.0\0" + VALUE "InternalName", "vgamp\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "vgamp.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/reactos/drivers/video/miniport/vga/vgavideo.c b/reactos/drivers/video/miniport/vga/vgavideo.c new file mode 100644 index 00000000000..7020e660426 --- /dev/null +++ b/reactos/drivers/video/miniport/vga/vgavideo.c @@ -0,0 +1,94 @@ +#include "vgavideo.h" + +div_t div(int num, int denom) +{ + div_t r; + if (num > 0 && denom < 0) { + num = -num; + denom = -denom; + } + r.quot = num / denom; + r.rem = num % denom; + if (num < 0 && denom > 0) + { + if (r.rem > 0) + { + r.quot++; + r.rem -= denom; + } + } + return r; +} + +int mod(int num, int denom) +{ + div_t dvt = div(num, denom); + return dvt.rem; +} + +VOID vgaPreCalc() +{ + ULONG j; + + startmasks[1] = 127; + startmasks[2] = 63; + startmasks[3] = 31; + startmasks[4] = 15; + startmasks[5] = 7; + startmasks[6] = 3; + startmasks[7] = 1; + startmasks[8] = 255; + + endmasks[0] = 128; + endmasks[1] = 192; + endmasks[2] = 224; + endmasks[3] = 240; + endmasks[4] = 248; + endmasks[5] = 252; + endmasks[6] = 254; + endmasks[7] = 255; + endmasks[8] = 255; + + for(j=0; j<80; j++) + { + maskbit[j*8] = 128; + maskbit[j*8+1] = 64; + maskbit[j*8+2] = 32; + maskbit[j*8+3] = 16; + maskbit[j*8+4] = 8; + maskbit[j*8+5] = 4; + maskbit[j*8+6] = 2; + maskbit[j*8+7] = 1; + + bit8[j*8] = 7; + bit8[j*8+1] = 6; + bit8[j*8+2] = 5; + bit8[j*8+3] = 4; + bit8[j*8+4] = 3; + bit8[j*8+5] = 2; + bit8[j*8+6] = 1; + bit8[j*8+7] = 0; + } + for(j=0; j<480; j++) + { + y80[j] = j*80; + } + for(j=0; j<640; j++) + { + xconv[j] = j >> 3; + } +} + +void vgaSetWriteMode(char mode) +{ + VideoPortWritePortUchar((PUCHAR)GRA_I, 0x03); + VideoPortWritePortUchar((PUCHAR)GRA_D, mode); +} + +void vgaSetColor(int cindex, int red, int green, int blue) +{ + VideoPortWritePortUchar((PUCHAR)0x03c8, cindex); + VideoPortWritePortUchar((PUCHAR)0x03c9, red); + VideoPortWritePortUchar((PUCHAR)0x03c9, green); + VideoPortWritePortUchar((PUCHAR)0x03c9, blue); +} diff --git a/reactos/drivers/video/miniport/vga/vgavideo.h b/reactos/drivers/video/miniport/vga/vgavideo.h new file mode 100644 index 00000000000..4fd64e3ed34 --- /dev/null +++ b/reactos/drivers/video/miniport/vga/vgavideo.h @@ -0,0 +1,41 @@ +#include +#include + +#define VGA_NORMAL 0 +#define VGA_AND 8 +#define VGA_OR 16 +#define VGA_XOR 24 + +//This is in mingw standard headers +//typedef struct { int quot, rem; } div_t; + +int maskbit[640], y80[480], xconv[640], bit8[640], startmasks[8], endmasks[8]; + +char* vidmem; + +#define MISC 0x3c2 +#define SEQ 0x3c4 +#define CRTC 0x3d4 +#define GRAPHICS 0x3ce +#define FEATURE 0x3da +#define ATTRIB 0x3c0 +#define STATUS 0x3da + +#define SEQ_I 0x3C4 /* Sequencer Index */ +#define SEQ_D 0x3C5 /* Sequencer Data Register */ + +#define GRA_I 0x3CE /* Graphics Controller Index */ +#define GRA_D 0x3CF /* Graphics Controller Data Register */ + + +typedef struct _VideoMode { + unsigned short VidSeg; + unsigned char Misc; + unsigned char Feature; + unsigned short Seq[6]; + unsigned short Crtc[25]; + unsigned short Gfx[9]; + unsigned char Attrib[21]; +} VideoMode; + +VOID vgaPreCalc();