diff --git a/reactos/drivers/dd/vga/miniport/makefile b/reactos/drivers/dd/vga/miniport/makefile index 9b439354862..e87b801f0a1 100644 --- a/reactos/drivers/dd/vga/miniport/makefile +++ b/reactos/drivers/dd/vga/miniport/makefile @@ -1,4 +1,4 @@ -# $Id: makefile,v 1.9 2001/08/21 20:13:12 chorns Exp $ +# $Id: makefile,v 1.10 2003/02/15 19:16:33 gvg Exp $ PATH_TO_TOP = ../../../.. @@ -6,7 +6,7 @@ TARGET_TYPE = driver TARGET_NAME = vgamp -TARGET_DDKLIBS = vidport.a +TARGET_DDKLIBS = videoprt.a TARGET_OBJECTS = \ initvga.o \ diff --git a/reactos/drivers/dd/videoprt/.cvsignore b/reactos/drivers/dd/videoprt/.cvsignore new file mode 100644 index 00000000000..ed28e11f8c8 --- /dev/null +++ b/reactos/drivers/dd/videoprt/.cvsignore @@ -0,0 +1,4 @@ +vidport.coff +*.o +*.sym +*.sys diff --git a/reactos/drivers/dd/videoprt/videoprt.c b/reactos/drivers/dd/videoprt/videoprt.c new file mode 100644 index 00000000000..05a5cabb067 --- /dev/null +++ b/reactos/drivers/dd/videoprt/videoprt.c @@ -0,0 +1,965 @@ +/* $Id: videoprt.c,v 1.1 2003/02/15 19:16:32 gvg Exp $ + * + * VideoPort driver + * Written by Rex Jolliff + * + * FIXME: + * There are two ugly and temporary hacks in this file, to get the VMware driver to + * work. + * First, the miniport driver is allowed to call VideoPortInitialize() multiple times. + * VideoPortInitialize() will create a device and then call the miniport's + * HwFindAdapter(). If that call returns with an error code, the device will be + * deleted. The next time VideoPortInitialize() is called, it will be create a + * new device with the same name as the first time. The first device was deleted so + * this shouldn't be a problem, the device is created successfully. Initialization + * then continues. + * The problems start when it's time to start the device. When the driver is opened, + * the caller will receive a pointer to the FIRST device, the one which was later + * deleted. This is propably due to a problem in the Io subsystem which needs to + * be investigated. To get around this, a pointer is kept to the last successfully + * opened device (pdoLastOpened) and this device is used instead of the pointer + * passed in. + * The second problem has to do with resources. The miniport driver will call + * VideoPortGetDeviceBase() to map a physical address to a virtual address. Later, + * it will call VideoPortMapMemory() with the same physical address. It should + * map to the same virtual address, but I couldn't get this to work at the moment. + * So, as a workaround, a maximum of 2 physical addresses with their corresponding + * virtual addresses are kept in the device extension block. They are filled by + * VideoPortGetDeviceBase() and looked-up by VideoPortMapMemory(). + */ + +#include +#include +#include + +#include "../../../ntoskrnl/include/internal/v86m.h" + +#include "videoprt.h" + +#define NDEBUG +#include + +#define VERSION "0.0.0" + +static VOID STDCALL VidStartIo(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); +static NTSTATUS STDCALL VidDispatchOpenClose(IN PDEVICE_OBJECT pDO, IN PIRP Irp); +static NTSTATUS STDCALL VidDispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); + +static BOOLEAN CsrssInitialized = FALSE; +static HANDLE CsrssHandle = 0; +static struct _EPROCESS* Csrss = NULL; + +/* FIXME: see file header */ +static PDEVICE_OBJECT pdoLastOpened; +static PVOID Virt7efc0000; +static PVOID Virt7ffc0000; + +PBYTE ReturnCsrssAddress(void) +{ + DPRINT("ReturnCsrssAddress()\n"); + return (PBYTE)Csrss; +} + +// ------------------------------------------------------- Public Interface + +// DriverEntry +// +// DESCRIPTION: +// This function initializes the driver. +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// IN PDRIVER_OBJECT DriverObject System allocated Driver Object +// for this driver +// IN PUNICODE_STRING RegistryPath Name of registry driver service +// key +// +// RETURNS: +// NTSTATUS + +STDCALL NTSTATUS +DriverEntry(IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) +{ + DPRINT("DriverEntry()\n"); + return(STATUS_SUCCESS); +} + +VOID +VideoPortDebugPrint(IN ULONG DebugPrintLevel, + IN PCHAR DebugMessage, ...) +{ + char Buffer[256]; + va_list ap; + +/* + if (DebugPrintLevel > InternalDebugLevel) + return; +*/ + va_start (ap, DebugMessage); + vsprintf (Buffer, DebugMessage, ap); + va_end (ap); + + DbgPrint (Buffer); +} + +VP_STATUS +STDCALL +VideoPortDisableInterrupt(IN PVOID HwDeviceExtension) +{ + DPRINT("VideoPortDisableInterrupt\n"); + UNIMPLEMENTED; +} + +VP_STATUS +STDCALL +VideoPortEnableInterrupt(IN PVOID HwDeviceExtension) +{ + DPRINT("VideoPortEnableInterrupt\n"); + UNIMPLEMENTED; +} + +VOID +STDCALL +VideoPortFreeDeviceBase(IN PVOID HwDeviceExtension, + IN PVOID MappedAddress) +{ + DPRINT1("VideoPortFreeDeviceBase not implemented\n"); +} + +ULONG +STDCALL +VideoPortGetBusData(IN PVOID HwDeviceExtension, + IN BUS_DATA_TYPE BusDataType, + IN ULONG SlotNumber, + OUT PVOID Buffer, + IN ULONG Offset, + IN ULONG Length) +{ + DPRINT("VideoPortGetBusData\n"); + return HalGetBusDataByOffset(BusDataType, + 0, + SlotNumber, + Buffer, + Offset, + Length); +} + +UCHAR +STDCALL +VideoPortGetCurrentIrql(VOID) +{ + DPRINT("VideoPortGetCurrentIrql\n"); + return KeGetCurrentIrql(); +} + +PVOID +STDCALL +VideoPortGetDeviceBase(IN PVOID HwDeviceExtension, + IN PHYSICAL_ADDRESS IoAddress, + IN ULONG NumberOfUchars, + IN UCHAR InIoSpace) +{ + PHYSICAL_ADDRESS TranslatedAddress; + PVOID Virtual; + ULONG AddressSpace; + PVIDEOPORT_EXTENSION_DATA ExtensionData = + MPExtensionToVPExtension(HwDeviceExtension); + + DPRINT("VideoPortGetDeviceBase\n"); + AddressSpace = (InIoSpace ? 1 : 0); + + if (HalTranslateBusAddress(PCIBus, 0, IoAddress, &AddressSpace, &TranslatedAddress)) + { + if (AddressSpace) + { + return (PVOID)(DWORD)(TranslatedAddress.QuadPart); + } + else + { + Virtual = MmMapIoSpace(TranslatedAddress, NumberOfUchars, MmNonCached); + /* FIXME: see file header */ + DPRINT("Mapped 0x%08x to 0x%08x\n", IoAddress.u.LowPart, Virtual); + if (0x7efc0000 == IoAddress.u.LowPart) + { + Virt7efc0000 = Virtual; + } + if (0x7ffc0000 == IoAddress.u.LowPart) + { + Virt7ffc0000 = Virtual; + } + } + } + else + { + return NULL; + } +} + +VP_STATUS +STDCALL +VideoPortGetDeviceData(IN PVOID HwDeviceExtension, + IN VIDEO_DEVICE_DATA_TYPE DeviceDataType, + IN PMINIPORT_QUERY_DEVICE_ROUTINE CallbackRoutine, + IN PVOID Context) +{ + DPRINT("VideoPortGetDeviceData\n"); + UNIMPLEMENTED; +} + +VP_STATUS +STDCALL +VideoPortGetAccessRanges(IN PVOID HwDeviceExtension, + IN ULONG NumRequestedResources, + IN PIO_RESOURCE_DESCRIPTOR RequestedResources OPTIONAL, + IN ULONG NumAccessRanges, + IN PVIDEO_ACCESS_RANGE AccessRanges, + IN PVOID VendorId, + IN PVOID DeviceId, + IN PULONG Slot) +{ + DPRINT("VideoPortGetAccessRanges\n"); + UNIMPLEMENTED; +} + +VP_STATUS +STDCALL +VideoPortGetRegistryParameters(IN PVOID HwDeviceExtension, + IN PWSTR ParameterName, + IN UCHAR IsParameterFileName, + IN PMINIPORT_GET_REGISTRY_ROUTINE GetRegistryRoutine, + IN PVOID Context) +{ + DPRINT("VideoPortGetRegistryParameters\n"); + UNIMPLEMENTED; +} + +ULONG STDCALL +VideoPortInitialize(IN PVOID Context1, + IN PVOID Context2, + IN PVIDEO_HW_INITIALIZATION_DATA HwInitializationData, + IN PVOID HwContext) +{ + UCHAR Again; + WCHAR DeviceBuffer[20]; + WCHAR SymlinkBuffer[20]; + NTSTATUS Status; + PDRIVER_OBJECT MPDriverObject = (PDRIVER_OBJECT) Context1; + PDEVICE_OBJECT MPDeviceObject; + VIDEO_PORT_CONFIG_INFO ConfigInfo; + PVIDEOPORT_EXTENSION_DATA ExtensionData; + ULONG DeviceNumber = 0; + UNICODE_STRING DeviceName; + UNICODE_STRING SymlinkName; + CLIENT_ID Cid; + + DPRINT("VideoPortInitialize\n"); + + /* Build Dispatch table from passed data */ + MPDriverObject->DriverStartIo = (PDRIVER_STARTIO) HwInitializationData->HwStartIO; + + /* Create a unicode device name */ + Again = FALSE; + do + { + swprintf(DeviceBuffer, L"\\Device\\Video%lu", DeviceNumber); + RtlInitUnicodeString(&DeviceName, DeviceBuffer); + + /* Create the device */ + Status = IoCreateDevice(MPDriverObject, + HwInitializationData->HwDeviceExtensionSize + + sizeof(VIDEOPORT_EXTENSION_DATA), + &DeviceName, + FILE_DEVICE_VIDEO, + 0, + TRUE, + &MPDeviceObject); + if (!NT_SUCCESS(Status)) + { + DPRINT("IoCreateDevice call failed with status 0x%08x\n", Status); + return Status; + } + + MPDriverObject->DeviceObject = MPDeviceObject; + + /* initialize the miniport drivers dispatch table */ + MPDriverObject->MajorFunction[IRP_MJ_CREATE] = VidDispatchOpenClose; + MPDriverObject->MajorFunction[IRP_MJ_CLOSE] = VidDispatchOpenClose; + MPDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VidDispatchDeviceControl; + + /* create symbolic link "\??\DISPLAYx" */ + swprintf(SymlinkBuffer, L"\\??\\DISPLAY%lu", DeviceNumber+1); + RtlInitUnicodeString (&SymlinkName, + SymlinkBuffer); + IoCreateSymbolicLink (&SymlinkName, + &DeviceName); + + ExtensionData = + (PVIDEOPORT_EXTENSION_DATA) MPDeviceObject->DeviceExtension; + ExtensionData->DeviceObject = MPDeviceObject; + ExtensionData->HwInitialize = HwInitializationData->HwInitialize; + + /* Set the buffering strategy here... */ + /* If you change this, remember to change VidDispatchDeviceControl too */ + MPDeviceObject->Flags |= DO_BUFFERED_IO; + + RtlZeroMemory(&ConfigInfo, sizeof(VIDEO_PORT_CONFIG_INFO)); + ConfigInfo.Length = sizeof(VIDEO_PORT_CONFIG_INFO); + ConfigInfo.AdapterInterfaceType = HwInitializationData->AdapterInterfaceType; + /* Call HwFindAdapter entry point */ + /* FIXME: Need to figure out what string to pass as param 3 */ + Status = HwInitializationData->HwFindAdapter(VPExtensionToMPExtension(ExtensionData), + Context2, + NULL, + &ConfigInfo, + &Again); + if (NO_ERROR != Status) + { + DPRINT("HwFindAdapter call failed with error %d\n", Status); + IoDeleteDevice(MPDeviceObject); + IoDeleteSymbolicLink(&SymlinkName); + + return Status; + } + /* FIXME: see file header */ + pdoLastOpened = MPDeviceObject; + DPRINT("Setting last opened device to 0x%08x\n", pdoLastOpened); + + /* FIXME: Allocate hardware resources for device */ + + /* Allocate interrupt for device */ + if (HwInitializationData->HwInterrupt != NULL && + !(ConfigInfo.BusInterruptLevel == 0 && + ConfigInfo.BusInterruptVector == 0)) + { +#if 0 + ExtensionData->IRQL = ConfigInfo.BusInterruptLevel; + ExtensionData->InterruptLevel = + HalGetInterruptVector(ConfigInfo.AdapterInterfaceType, + ConfigInfo.SystemIoBusNumber, + ConfigInfo.BusInterruptLevel, + ConfigInfo.BusInterruptVector, + &ExtensionData->IRQL, + &ExtensionData->Affinity); + KeInitializeSpinLock(&ExtensionData->InterruptSpinLock); + Status = IoConnectInterrupt(&ExtensionData->InterruptObject, + (PKSERVICE_ROUTINE) + HwInitializationData->HwInterrupt, + VPExtensionToMPExtension(ExtensionData), + &ExtensionData->InterruptSpinLock, + ExtensionData->InterruptLevel, + ExtensionData->IRQL, + ExtensionData->IRQL, + ConfigInfo.InterruptMode, + FALSE, + ExtensionData->Affinity, + FALSE); + if (!NT_SUCCESS(Status)) + { + DPRINT("IoConnectInterrupt failed with status 0x%08x\n", Status); + IoDeleteDevice(MPDeviceObject); + + return Status; + } +#endif + } + DeviceNumber++; + } + while (Again); + + /* FIXME: initialize timer routine for MP Driver */ + if (HwInitializationData->HwTimer != NULL) + { + Status = IoInitializeTimer(MPDeviceObject, + (PIO_TIMER_ROUTINE) + HwInitializationData->HwTimer, + VPExtensionToMPExtension(ExtensionData)); + if (!NT_SUCCESS(Status)) + { + DPRINT("IoInitializeTimer failed with status 0x%08x\n", Status); + + if (HwInitializationData->HwInterrupt != NULL) + { + IoDisconnectInterrupt(ExtensionData->InterruptObject); + } + IoDeleteDevice(MPDeviceObject); + + return Status; + } + } + + return STATUS_SUCCESS; +} + +VP_STATUS STDCALL +VideoPortInt10(IN PVOID HwDeviceExtension, + IN PVIDEO_X86_BIOS_ARGUMENTS BiosArguments) +{ + KV86M_REGISTERS Regs; + NTSTATUS Status; + + DPRINT("VideoPortInt10\n"); + KeAttachProcess(Csrss); + + memset(&Regs, 0, sizeof(Regs)); + Regs.Eax = BiosArguments->Eax; + Regs.Ebx = BiosArguments->Ebx; + Regs.Ecx = BiosArguments->Ecx; + Regs.Edx = BiosArguments->Edx; + Regs.Esi = BiosArguments->Esi; + Regs.Edi = BiosArguments->Edi; + Regs.Ebp = BiosArguments->Ebp; + Status = Ke386CallBios(0x10, &Regs); + + KeDetachProcess(); + + return(Status); +} + +VOID +STDCALL +VideoPortLogError(IN PVOID HwDeviceExtension, + IN PVIDEO_REQUEST_PACKET Vrp OPTIONAL, + IN VP_STATUS ErrorCode, + IN ULONG UniqueId) +{ + DPRINT("VideoPortLogError\n"); + UNIMPLEMENTED; +} + +VP_STATUS +STDCALL +VideoPortMapBankedMemory(IN PVOID HwDeviceExtension, + IN PHYSICAL_ADDRESS PhysicalAddress, + IN PULONG Length, + IN PULONG InIoSpace, + OUT PVOID *VirtualAddress, + IN ULONG BankLength, + IN UCHAR ReadWriteBank, + IN PBANKED_SECTION_ROUTINE BankRoutine, + IN PVOID Context) +{ + DPRINT("VideoPortMapBankedMemory\n"); + UNIMPLEMENTED; +} + +VP_STATUS +STDCALL +VideoPortMapMemory(IN PVOID HwDeviceExtension, + IN PHYSICAL_ADDRESS PhysicalAddress, + IN PULONG Length, + IN PULONG InIoSpace, + OUT PVOID *VirtualAddress) +{ + PHYSICAL_ADDRESS TranslatedAddress; + ULONG AddressSpace; + PVIDEOPORT_EXTENSION_DATA ExtensionData = + MPExtensionToVPExtension(HwDeviceExtension); + + DPRINT("VideoPortMapMemory\n"); + + /* FIXME: see file header */ + if (0x7efc0000 == PhysicalAddress.u.LowPart) + { + DPRINT("Using saved mapping for 0x7efc0000\n"); + *VirtualAddress = Virt7efc0000; + return STATUS_SUCCESS; + } + if (0x7ffc0000 == PhysicalAddress.u.LowPart) + { + DPRINT("Using saved mapping for 0x7ffc0000\n"); + *VirtualAddress = Virt7ffc0000; + return STATUS_SUCCESS; + } + + AddressSpace = (*InIoSpace ? 1 : 0); + + if (HalTranslateBusAddress(PCIBus, 0, PhysicalAddress, &AddressSpace, &TranslatedAddress)) + { + if (AddressSpace) + { + *VirtualAddress = (PVOID)(DWORD)(TranslatedAddress.QuadPart); + return STATUS_SUCCESS; + } + else + { + *VirtualAddress = MmMapIoSpace(TranslatedAddress, *Length, MmNonCached); + return NULL != *VirtualAddress ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES; + } + } + else + { + return STATUS_UNSUCCESSFUL; + } +} + +UCHAR +STDCALL +VideoPortReadPortUchar(IN PUCHAR Port) +{ + DPRINT("VideoPortReadPortUchar\n"); + return READ_PORT_UCHAR(Port); +} + +USHORT +STDCALL +VideoPortReadPortUshort(IN PUSHORT Port) +{ + DPRINT("VideoPortReadPortUshort\n"); + return READ_PORT_USHORT(Port); +} + +ULONG +STDCALL +VideoPortReadPortUlong(IN PULONG Port) +{ + DPRINT("VideoPortReadPortUlong\n"); + return READ_PORT_ULONG(Port); +} + +VOID +STDCALL +VideoPortReadPortBufferUchar(IN PUCHAR Port, + OUT PUCHAR Buffer, + IN ULONG Count) +{ + DPRINT("VideoPortReadPortBufferUchar\n"); + READ_PORT_BUFFER_UCHAR(Port, Buffer, Count); +} + +VOID +STDCALL +VideoPortReadPortBufferUshort(IN PUSHORT Port, + OUT PUSHORT Buffer, + IN ULONG Count) +{ + DPRINT("VideoPortReadPortBufferUshort\n"); + READ_PORT_BUFFER_USHORT(Port, Buffer, Count); +} + +VOID +STDCALL +VideoPortReadPortBufferUlong(IN PULONG Port, + OUT PULONG Buffer, + IN ULONG Count) +{ + DPRINT("VideoPortReadPortBufferUlong\n"); + READ_PORT_BUFFER_ULONG(Port, Buffer, Count); +} + +UCHAR +STDCALL +VideoPortReadRegisterUchar(IN PUCHAR Register) +{ + DPRINT("VideoPortReadPortRegisterUchar\n"); + return READ_REGISTER_UCHAR(Register); +} + +USHORT +STDCALL +VideoPortReadRegisterUshort(IN PUSHORT Register) +{ + DPRINT("VideoPortReadPortRegisterUshort\n"); + return READ_REGISTER_USHORT(Register); +} + +ULONG +STDCALL +VideoPortReadRegisterUlong(IN PULONG Register) +{ + DPRINT("VideoPortReadPortRegisterUlong\n"); + return READ_REGISTER_ULONG(Register); +} + +VOID +STDCALL +VideoPortReadRegisterBufferUchar(IN PUCHAR Register, + OUT PUCHAR Buffer, + IN ULONG Count) +{ + DPRINT("VideoPortReadPortRegisterBufferUchar\n"); + READ_REGISTER_BUFFER_UCHAR(Register, Buffer, Count); +} + +VOID +STDCALL +VideoPortReadRegisterBufferUshort(IN PUSHORT Register, + OUT PUSHORT Buffer, + IN ULONG Count) +{ + DPRINT("VideoPortReadPortRegisterBufferUshort\n"); + READ_REGISTER_BUFFER_USHORT(Register, Buffer, Count); +} + +VOID +STDCALL +VideoPortReadRegisterBufferUlong(IN PULONG Register, + OUT PULONG Buffer, + IN ULONG Count) +{ + DPRINT("VideoPortReadPortRegisterBufferUlong\n"); + READ_REGISTER_BUFFER_ULONG(Register, Buffer, Count); +} + +BOOLEAN +STDCALL +VideoPortScanRom(IN PVOID HwDeviceExtension, + IN PUCHAR RomBase, + IN ULONG RomLength, + IN PUCHAR String) +{ + DPRINT("VideoPortScanRom\n"); + UNIMPLEMENTED; +} + +ULONG +STDCALL +VideoPortSetBusData(IN PVOID HwDeviceExtension, + IN BUS_DATA_TYPE BusDataType, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length) +{ + DPRINT("VideoPortSetBusData\n"); + return HalSetBusDataByOffset(BusDataType, + 0, + SlotNumber, + Buffer, + Offset, + Length); +} + +VP_STATUS +STDCALL +VideoPortSetRegistryParameters(IN PVOID HwDeviceExtension, + IN PWSTR ValueName, + IN PVOID ValueData, + IN ULONG ValueLength) +{ + DPRINT1("VideoPortSetRegistryParameters not implemented\n"); + return NO_ERROR; +} + +VP_STATUS +STDCALL +VideoPortSetTrappedEmulatorPorts(IN PVOID HwDeviceExtension, + IN ULONG NumAccessRanges, + IN PVIDEO_ACCESS_RANGE AccessRange) +{ + DPRINT("VideoPortSetTrappedEmulatorPorts\n"); + UNIMPLEMENTED; +} + +VOID +STDCALL +VideoPortStartTimer(IN PVOID HwDeviceExtension) +{ + PVIDEOPORT_EXTENSION_DATA ExtensionData = + MPExtensionToVPExtension(HwDeviceExtension); + + DPRINT("VideoPortStartTimer\n"); + IoStartTimer(ExtensionData->DeviceObject); +} + +VOID +STDCALL +VideoPortStopTimer(IN PVOID HwDeviceExtension) +{ + PVIDEOPORT_EXTENSION_DATA ExtensionData = + MPExtensionToVPExtension(HwDeviceExtension); + + DPRINT("VideoPortStopTimer\n"); + IoStopTimer(ExtensionData->DeviceObject); +} + +BOOLEAN +STDCALL +VideoPortSynchronizeExecution(IN PVOID HwDeviceExtension, + IN VIDEO_SYNCHRONIZE_PRIORITY Priority, + IN PMINIPORT_SYNCHRONIZE_ROUTINE SynchronizeRoutine, + OUT PVOID Context) +{ + DPRINT("VideoPortSynchronizeExecution\n"); + UNIMPLEMENTED; +} + +VP_STATUS +STDCALL +VideoPortUnmapMemory(IN PVOID HwDeviceExtension, + IN PVOID VirtualAddress, + IN HANDLE ProcessHandle) +{ + DPRINT1("VideoPortUnmapMemory not implemented\n"); + return NO_ERROR; +} + +VP_STATUS +STDCALL +VideoPortVerifyAccessRanges(IN PVOID HwDeviceExtension, + IN ULONG NumAccessRanges, + IN PVIDEO_ACCESS_RANGE AccessRanges) +{ + DPRINT1("VideoPortVerifyAccessRanges not implemented\n"); + return NO_ERROR; +} + +VOID +STDCALL +VideoPortWritePortUchar(IN PUCHAR Port, + IN UCHAR Value) +{ + DPRINT("VideoPortWritePortUchar\n"); + WRITE_PORT_UCHAR(Port, Value); +} + +VOID +STDCALL +VideoPortWritePortUshort(IN PUSHORT Port, + IN USHORT Value) +{ + DPRINT("VideoPortWritePortUshort\n"); + WRITE_PORT_USHORT(Port, Value); +} + +VOID +STDCALL +VideoPortWritePortUlong(IN PULONG Port, + IN ULONG Value) +{ + DPRINT("VideoPortWritePortUlong\n"); + WRITE_PORT_ULONG(Port, Value); +} + +VOID +STDCALL +VideoPortWritePortBufferUchar(IN PUCHAR Port, + IN PUCHAR Buffer, + IN ULONG Count) +{ + DPRINT("VideoPortWritePortBufferUchar\n"); + WRITE_PORT_BUFFER_UCHAR(Port, Buffer, Count); +} + +VOID +STDCALL +VideoPortWritePortBufferUshort(IN PUSHORT Port, + IN PUSHORT Buffer, + IN ULONG Count) +{ + DPRINT("VideoPortWritePortBufferUshort\n"); + WRITE_PORT_BUFFER_USHORT(Port, Buffer, Count); +} + +VOID +STDCALL +VideoPortWritePortBufferUlong(IN PULONG Port, + IN PULONG Buffer, + IN ULONG Count) +{ + DPRINT("VideoPortWritePortBufferUlong\n"); + WRITE_PORT_BUFFER_ULONG(Port, Buffer, Count); +} + +VOID +STDCALL +VideoPortWriteRegisterUchar(IN PUCHAR Register, + IN UCHAR Value) +{ + DPRINT("VideoPortWriteRegisterUchar\n"); + WRITE_REGISTER_UCHAR(Register, Value); +} + +VOID +STDCALL +VideoPortWriteRegisterUshort(IN PUSHORT Register, + IN USHORT Value) +{ + DPRINT("VideoPortWriteRegisterUshort\n"); + WRITE_REGISTER_USHORT(Register, Value); +} + +VOID +STDCALL +VideoPortWriteRegisterUlong(IN PULONG Register, + IN ULONG Value) +{ + DPRINT("VideoPortWriteRegisterUlong\n"); + WRITE_REGISTER_ULONG(Register, Value); +} + +VOID +STDCALL +VideoPortWriteRegisterBufferUchar(IN PUCHAR Register, + IN PUCHAR Buffer, + IN ULONG Count) +{ + DPRINT("VideoPortWriteRegisterBufferUchar\n"); + WRITE_REGISTER_BUFFER_UCHAR(Register, Buffer, Count); +} + +VOID STDCALL +VideoPortWriteRegisterBufferUshort(IN PUSHORT Register, + IN PUSHORT Buffer, + IN ULONG Count) +{ + DPRINT("VideoPortWriteRegisterBufferUshort\n"); + WRITE_REGISTER_BUFFER_USHORT(Register, Buffer, Count); +} + +VOID STDCALL +VideoPortWriteRegisterBufferUlong(IN PULONG Register, + IN PULONG Buffer, + IN ULONG Count) +{ + DPRINT("VideoPortWriteRegisterBufferUlong\n"); + WRITE_REGISTER_BUFFER_ULONG(Register, Buffer, Count); +} + +VOID STDCALL +VideoPortZeroDeviceMemory(OUT PVOID Destination, + IN ULONG Length) +{ + DPRINT("VideoPortZeroDeviceMemory\n"); + UNIMPLEMENTED; +} + + +// ------------------------------------------- Nondiscardable statics + +// VidDispatchOpenClose +// +// DESCRIPTION: +// Answer requests for Open/Close calls: a null operation +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// Standard dispatch arguments +// +// RETURNS: +// NTSTATUS +// + +static NTSTATUS STDCALL +VidDispatchOpenClose(IN PDEVICE_OBJECT pDO, + IN PIRP Irp) +{ + PIO_STACK_LOCATION IrpStack; + PVIDEOPORT_EXTENSION_DATA ExtensionData; + + DPRINT("VidDispatchOpenClose() called\n"); + + /* FIXME: see file header */ + DPRINT("Using device 0x%08x instead of 0x%08x\n", pdoLastOpened, pDO); + pDO = pdoLastOpened; + IrpStack = IoGetCurrentIrpStackLocation(Irp); + + if (IrpStack->MajorFunction == IRP_MJ_CREATE && + CsrssInitialized == FALSE) + { + DPRINT("Referencing CSRSS\n"); + Csrss = PsGetCurrentProcess(); + CsrssInitialized = TRUE; + DPRINT("Csrss %p\n", Csrss); + ExtensionData = (PVIDEOPORT_EXTENSION_DATA) pDO->DeviceExtension; + if (ExtensionData->HwInitialize(VPExtensionToMPExtension(ExtensionData))) + { + Irp->IoStatus.Status = STATUS_SUCCESS; + } + else + { + Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; + } + } + else + { + Irp->IoStatus.Status = STATUS_SUCCESS; + } + + Irp->IoStatus.Information = FILE_OPENED; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return STATUS_SUCCESS; +} + +// VidStartIo +// +// DESCRIPTION: +// Get the next requested I/O packet started +// +// RUN LEVEL: +// DISPATCH_LEVEL +// +// ARGUMENTS: +// Dispatch routine standard arguments +// +// RETURNS: +// NTSTATUS +// + +static VOID STDCALL +VidStartIo(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + DPRINT("VidStartIo\n"); + UNIMPLEMENTED; +} + +// VidDispatchDeviceControl +// +// DESCRIPTION: +// Answer requests for device control calls +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// Standard dispatch arguments +// +// RETURNS: +// NTSTATUS +// + +static NTSTATUS STDCALL +VidDispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION IrpStack; + PVIDEO_REQUEST_PACKET vrp; + + DPRINT("VidDispatchDeviceControl\n"); + /* FIXME: See file header */ + DPRINT("Using device 0x%08x instead of 0x%08x\n", pdoLastOpened, DeviceObject); + DeviceObject = pdoLastOpened; + IrpStack = IoGetCurrentIrpStackLocation(Irp); + + // Translate the IRP to a VRP + vrp = ExAllocatePool(PagedPool, sizeof(VIDEO_REQUEST_PACKET)); + vrp->StatusBlock = ExAllocatePool(PagedPool, sizeof(STATUS_BLOCK)); + vrp->IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode; + + // We're assuming METHOD_BUFFERED + vrp->InputBuffer = Irp->AssociatedIrp.SystemBuffer; + vrp->InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; + vrp->OutputBuffer = Irp->UserBuffer; + vrp->OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; + + // Call the Miniport Driver with the VRP + DeviceObject->DriverObject->DriverStartIo(VPExtensionToMPExtension(DeviceObject->DeviceExtension), (PIRP)vrp); + + // Translate the VRP back into the IRP for OutputBuffer + Irp->UserBuffer = vrp->OutputBuffer; + IrpStack->Parameters.DeviceIoControl.OutputBufferLength = vrp->OutputBufferLength; + Irp->IoStatus.Status = vrp->StatusBlock->Status; + Irp->IoStatus.Information = vrp->StatusBlock->Information; + + // Free the VRP + ExFreePool(vrp->StatusBlock); + ExFreePool(vrp); + + return STATUS_SUCCESS; +} diff --git a/reactos/drivers/dd/videoprt/videoprt.def b/reactos/drivers/dd/videoprt/videoprt.def new file mode 100644 index 00000000000..39755ed38d3 --- /dev/null +++ b/reactos/drivers/dd/videoprt/videoprt.def @@ -0,0 +1,60 @@ +; $Id: videoprt.def,v 1.1 2003/02/15 19:16:32 gvg Exp $ +; +; vidport.def - export definition file for ReactOS +; +EXPORTS +ReturnCsrssAddress +VideoPortCompareMemory@12 +VideoPortDebugPrint +VideoPortDisableInterrupt@4 +VideoPortEnableInterrupt@4 +VideoPortFreeDeviceBase@8 +VideoPortGetBusData@24 +VideoPortGetCurrentIrql@0 +VideoPortGetDeviceBase@20 +VideoPortGetDeviceData@16 +VideoPortGetAccessRanges@32 +VideoPortGetRegistryParameters@20 +VideoPortInitialize@16 +VideoPortInt10@8 +VideoPortLogError@16 +VideoPortMapBankedMemory@40 +VideoPortMapMemory@24 +VideoPortMoveMemory@12 +VideoPortReadPortUchar@4 +VideoPortReadPortUshort@4 +VideoPortReadPortUlong@4 +VideoPortReadPortBufferUchar@12 +VideoPortReadPortBufferUshort@12 +VideoPortReadPortBufferUlong@12 +VideoPortReadRegisterUchar@4 +VideoPortReadRegisterUshort@4 +VideoPortReadRegisterUlong@4 +VideoPortReadRegisterBufferUchar@12 +VideoPortReadRegisterBufferUshort@12 +VideoPortReadRegisterBufferUlong@12 +VideoPortScanRom@16 +VideoPortSetBusData@24 +VideoPortSetRegistryParameters@16 +VideoPortSetTrappedEmulatorPorts@12 +VideoPortStallExecution@4 +VideoPortStartTimer@4 +VideoPortStopTimer@4 +VideoPortSynchronizeExecution@16 +VideoPortUnmapMemory@12 +VideoPortVerifyAccessRanges@12 +VideoPortWritePortUchar@8 +VideoPortWritePortUshort@8 +VideoPortWritePortUlong@8 +VideoPortWritePortBufferUchar@12 +VideoPortWritePortBufferUshort@12 +VideoPortWritePortBufferUlong@12 +VideoPortWriteRegisterUchar@8 +VideoPortWriteRegisterUshort@8 +VideoPortWriteRegisterUlong@8 +VideoPortWriteRegisterBufferUchar@12 +VideoPortWriteRegisterBufferUshort@12 +VideoPortWriteRegisterBufferUlong@12 +VideoPortZeroMemory@8 +VideoPortZeroDeviceMemory@8 + diff --git a/reactos/drivers/dd/videoprt/videoprt.edf b/reactos/drivers/dd/videoprt/videoprt.edf new file mode 100644 index 00000000000..4f09940ad19 --- /dev/null +++ b/reactos/drivers/dd/videoprt/videoprt.edf @@ -0,0 +1,61 @@ +; $Id: videoprt.edf,v 1.1 2003/02/15 19:16:32 gvg Exp $ +; +; vidport.def - export definition file for ReactOS +; +EXPORTS +ReturnCsrssAddress +VideoPortCompareMemory=NTOSKRNL.RtlCompareMemory +VideoPortDebugPrint +VideoPortDisableInterrupt=VideoPortDisableInterrupt@4 +VideoPortEnableInterrupt=VideoPortEnableInterrupt@4 +VideoPortFreeDeviceBase=VideoPortFreeDeviceBase@8 +VideoPortGetBusData=VideoPortGetBusData@24 +VideoPortGetCurrentIrql=VideoPortGetCurrentIrql@0 +VideoPortGetDeviceBase=VideoPortGetDeviceBase@20 +VideoPortGetDeviceData=VideoPortGetDeviceData@16 +VideoPortGetAccessRanges=VideoPortGetAccessRanges@32 +VideoPortGetRegistryParameters=VideoPortGetRegistryParameters@20 +VideoPortInitialize=VideoPortInitialize@16 +VideoPortInt10=VideoPortInt10@8 +VideoPortLogError=VideoPortLogError@16 +VideoPortMapBankedMemory=VideoPortMapBankedMemory@40 +VideoPortMapMemory=VideoPortMapMemory@24 +VideoPortMoveMemory=NTOSKRNL.RtlMoveMemory +VideoPortReadPortUchar=VideoPortReadPortUchar@4 +VideoPortReadPortUshort=VideoPortReadPortUshort@4 +VideoPortReadPortUlong=VideoPortReadPortUlong@4 +VideoPortReadPortBufferUchar=VideoPortReadPortBufferUchar@12 +VideoPortReadPortBufferUshort=VideoPortReadPortBufferUshort@12 +VideoPortReadPortBufferUlong=VideoPortReadPortBufferUlong@12 +VideoPortReadRegisterUchar=VideoPortReadRegisterUchar@4 +VideoPortReadRegisterUshort=VideoPortReadRegisterUshort@4 +VideoPortReadRegisterUlong=VideoPortReadRegisterUlong@4 +VideoPortReadRegisterBufferUchar=VideoPortReadRegisterBufferUchar@12 +VideoPortReadRegisterBufferUshort=VideoPortReadRegisterBufferUshort@12 +VideoPortReadRegisterBufferUlong=VideoPortReadRegisterBufferUlong@12 +VideoPortScanRom=VideoPortScanRom@16 +VideoPortSetBusData=VideoPortSetBusData@24 +VideoPortSetRegistryParameters=VideoPortSetRegistryParameters@16 +VideoPortSetTrappedEmulatorPorts=VideoPortSetTrappedEmulatorPorts@12 +;VideoPortStallExecution=HAL.KeStallExecutionProcessor +VideoPortStallExecution=NTOSKRNL.KeStallExecutionProcessor +VideoPortStartTimer=VideoPortStartTimer@4 +VideoPortStopTimer=VideoPortStopTimer@4 +VideoPortSynchronizeExecution=VideoPortSynchronizeExecution@16 +VideoPortUnmapMemory=VideoPortUnmapMemory@12 +VideoPortVerifyAccessRanges=VideoPortVerifyAccessRanges@12 +VideoPortWritePortUchar=VideoPortWritePortUchar@8 +VideoPortWritePortUshort=VideoPortWritePortUshort@8 +VideoPortWritePortUlong=VideoPortWritePortUlong@8 +VideoPortWritePortBufferUchar=VideoPortWritePortBufferUchar@12 +VideoPortWritePortBufferUshort=VideoPortWritePortBufferUshort@12 +VideoPortWritePortBufferUlong=VideoPortWritePortBufferUlong@12 +VideoPortWriteRegisterUchar=VideoPortWriteRegisterUchar@8 +VideoPortWriteRegisterUshort=VideoPortWriteRegisterUshort@8 +VideoPortWriteRegisterUlong=VideoPortWriteRegisterUlong@8 +VideoPortWriteRegisterBufferUchar=VideoPortWriteRegisterBufferUchar@12 +VideoPortWriteRegisterBufferUshort=VideoPortWriteRegisterBufferUshort@12 +VideoPortWriteRegisterBufferUlong=VideoPortWriteRegisterBufferUlong@12 +VideoPortZeroMemory=NTOSKRNL.RtlZeroMemory +VideoPortZeroDeviceMemory=VideoPortZeroDeviceMemory@8 + diff --git a/reactos/drivers/dd/videoprt/videoprt.h b/reactos/drivers/dd/videoprt/videoprt.h new file mode 100644 index 00000000000..01be32e933c --- /dev/null +++ b/reactos/drivers/dd/videoprt/videoprt.h @@ -0,0 +1,17 @@ + +typedef struct _VIDEOPORT_EXTENSTION_DATA +{ + PDEVICE_OBJECT DeviceObject; + PKINTERRUPT InterruptObject; + KSPIN_LOCK InterruptSpinLock; + ULONG InterruptLevel; + KIRQL IRQL; + KAFFINITY Affinity; + PVIDEO_HW_INITIALIZE HwInitialize; +} VIDEOPORT_EXTENSION_DATA, *PVIDEOPORT_EXTENSION_DATA; + +#define MPExtensionToVPExtension(MPX) \ + ((PVIDEOPORT_EXTENSION_DATA) ((DWORD) (MPX) - sizeof(VIDEOPORT_EXTENSION_DATA))) +#define VPExtensionToMPExtension(VPX) \ + ((PVOID) ((DWORD) (VPX) + sizeof(VIDEOPORT_EXTENSION_DATA))) + diff --git a/reactos/drivers/input/mouclass/mouclass.c b/reactos/drivers/input/mouclass/mouclass.c index 8f5d431717f..3e32d2afb37 100644 --- a/reactos/drivers/input/mouclass/mouclass.c +++ b/reactos/drivers/input/mouclass/mouclass.c @@ -20,6 +20,40 @@ BOOLEAN AlreadyOpened = FALSE; +VOID MouseClassPassiveCallback(PDEVICE_OBJECT ClassDeviceObject, PVOID Context) +{ + PDEVICE_EXTENSION ClassDeviceExtension = ClassDeviceObject->DeviceExtension; + MOUSE_INPUT_DATA PortData[MOUSE_BUFFER_SIZE]; + ULONG InputCount; + KIRQL OldIrql; + + assert(NULL != ClassDeviceExtension->GDIInformation.CallBack); + KeAcquireSpinLock(&(ClassDeviceExtension->SpinLock), &OldIrql); + DPRINT("Entering MouseClassPassiveCallback\n"); + while (0 != ClassDeviceExtension->InputCount) { + ClassDeviceExtension->PortData -= ClassDeviceExtension->InputCount; + RtlMoveMemory(PortData, ClassDeviceExtension->PortData, + ClassDeviceExtension->InputCount * sizeof(MOUSE_INPUT_DATA)); + InputCount = ClassDeviceExtension->InputCount; + ClassDeviceExtension->InputCount = 0; + KeReleaseSpinLock(&(ClassDeviceExtension->SpinLock), OldIrql); + + DPRINT("MouseClassPassiveCallBack() Calling GDI callback at %p\n", + ClassDeviceExtension->GDIInformation.CallBack); + /* We're jumping through hoops to get to run at PASSIVE_LEVEL, let's make + sure we succeeded */ + ASSERT_IRQL(PASSIVE_LEVEL); + (*(PGDI_SERVICE_CALLBACK_ROUTINE)ClassDeviceExtension->GDIInformation.CallBack) + (PortData, InputCount); + + KeAcquireSpinLock(&(ClassDeviceExtension->SpinLock), &OldIrql); + } + + ClassDeviceExtension->PassiveCallbackQueued = FALSE; + DPRINT("Leaving MouseClassPassiveCallback\n"); + KeReleaseSpinLock(&(ClassDeviceExtension->SpinLock), OldIrql); +} + BOOLEAN MouseClassCallBack(PDEVICE_OBJECT ClassDeviceObject, PMOUSE_INPUT_DATA MouseDataStart, PMOUSE_INPUT_DATA MouseDataEnd, PULONG InputCount) { @@ -27,11 +61,13 @@ BOOLEAN MouseClassCallBack(PDEVICE_OBJECT ClassDeviceObject, PMOUSE_INPUT_DATA M PIRP Irp; ULONG ReadSize; PIO_STACK_LOCATION Stack; + KIRQL OldIrql; // In classical NT, you would take the input data and pipe it through the IO system, for the GDI to read. // In ReactOS, however, we use a GDI callback for increased mouse responsiveness. The reason we don't // simply call from the port driver is so that our mouse class driver can support NT mouse port drivers. + DPRINT("Entering MouseClassCallBack\n"); /* if(ClassDeviceExtension->ReadIsPending == TRUE) { Irp = ClassDeviceObject->CurrentIrp; @@ -56,6 +92,8 @@ BOOLEAN MouseClassCallBack(PDEVICE_OBJECT ClassDeviceObject, PMOUSE_INPUT_DATA M // If we have data from the port driver and a higher service to send the data to if((*InputCount>0) && (*(PGDI_SERVICE_CALLBACK_ROUTINE)ClassDeviceExtension->GDIInformation.CallBack != NULL)) { + KeAcquireSpinLock(&(ClassDeviceExtension->SpinLock), &OldIrql); + if(ClassDeviceExtension->InputCount + *InputCount > MOUSE_BUFFER_SIZE) { ReadSize = MOUSE_BUFFER_SIZE - ClassDeviceExtension->InputCount; @@ -74,22 +112,26 @@ BOOLEAN MouseClassCallBack(PDEVICE_OBJECT ClassDeviceObject, PMOUSE_INPUT_DATA M ClassDeviceExtension->PortData += ReadSize; ClassDeviceExtension->InputCount += ReadSize; - // Throw data up to GDI callback if(*(PGDI_SERVICE_CALLBACK_ROUTINE)ClassDeviceExtension->GDIInformation.CallBack != NULL) { - DPRINT("MouseClassCallBack() Calling GDI callback at %p\n", ClassDeviceExtension->GDIInformation.CallBack); - (*(PGDI_SERVICE_CALLBACK_ROUTINE)ClassDeviceExtension->GDIInformation.CallBack) - (ClassDeviceExtension->PortData - ReadSize, ReadSize); - } else { - DPRINT("MouseClassCallBack() NO GDI callback installed\n"); + if (! ClassDeviceExtension->PassiveCallbackQueued) { + if (NULL == ClassDeviceExtension->WorkItem) { + ClassDeviceExtension->WorkItem = IoAllocateWorkItem(ClassDeviceObject); } - - ClassDeviceExtension->PortData -= ReadSize; - ClassDeviceExtension->InputCount -= ReadSize; - ClassDeviceExtension->ReadIsPending = FALSE; + if (NULL != ClassDeviceExtension->WorkItem) { + DPRINT("Queueing workitem\n"); + IoQueueWorkItem(ClassDeviceExtension->WorkItem, MouseClassPassiveCallback, DelayedWorkQueue, NULL); + ClassDeviceExtension->PassiveCallbackQueued = TRUE; + } + } + } else { + DPRINT("MouseClassCallBack() NO GDI callback installed\n"); + } + KeReleaseSpinLock(&(ClassDeviceExtension->SpinLock), OldIrql); } else { DPRINT("MouseClassCallBack() entered, InputCount = %d - DOING NOTHING\n", *InputCount); } + DPRINT("Leaving MouseClassCallBack\n"); return TRUE; } @@ -122,6 +164,9 @@ NTSTATUS ConnectMousePortDriver(PDEVICE_OBJECT ClassDeviceObject) DeviceExtension->PortData = ExAllocatePool(NonPagedPool, MOUSE_BUFFER_SIZE * sizeof(MOUSE_INPUT_DATA)); DeviceExtension->InputCount = 0; DeviceExtension->ReadIsPending = FALSE; + DeviceExtension->WorkItem = NULL; + KeInitializeSpinLock(&(DeviceExtension->SpinLock)); + DeviceExtension->PassiveCallbackQueued = FALSE; // Connect our callback to the port driver diff --git a/reactos/drivers/input/mouclass/mouclass.h b/reactos/drivers/input/mouclass/mouclass.h index cf77cb70555..eebba4a343a 100644 --- a/reactos/drivers/input/mouclass/mouclass.h +++ b/reactos/drivers/input/mouclass/mouclass.h @@ -1,4 +1,7 @@ typedef struct _DEVICE_EXTENSION { + PIO_WORKITEM WorkItem; + KSPIN_LOCK SpinLock; + BOOLEAN PassiveCallbackQueued; BOOLEAN ReadIsPending; ULONG InputCount; PMOUSE_INPUT_DATA PortData; diff --git a/reactos/subsys/win32k/dib/dib.h b/reactos/subsys/win32k/dib/dib.h index 4d00fed2899..aae48473862 100644 --- a/reactos/subsys/win32k/dib/dib.h +++ b/reactos/subsys/win32k/dib/dib.h @@ -25,6 +25,15 @@ BOOLEAN DIB_To_4BPP_Bitblt( SURFOBJ *DestSurf, SURFOBJ *SourceSurf, PRECTL DestRect, POINTL *SourcePoint, LONG Delta, XLATEOBJ *ColorTranslation); +VOID DIB_16BPP_PutPixel(PSURFOBJ SurfObj, LONG x, LONG y, ULONG c); +ULONG DIB_16BPP_GetPixel(PSURFOBJ SurfObj, LONG x, LONG y); +VOID DIB_16BPP_HLine(PSURFOBJ SurfObj, LONG x1, LONG x2, LONG y, ULONG c); +VOID DIB_16BPP_VLine(PSURFOBJ SurfObj, LONG x, LONG y1, LONG y2, ULONG c); +BOOL DIB_To_16BPP_Bitblt( SURFOBJ *DestSurf, SURFOBJ *SourceSurf, + SURFGDI *DestGDI, SURFGDI *SourceGDI, + PRECTL DestRect, POINTL *SourcePoint, + LONG Delta, XLATEOBJ *ColorTranslation); + PFN_DIB_PutPixel DIB_24BPP_PutPixel(PSURFOBJ SurfObj, LONG x, LONG y, ULONG c); PFN_DIB_GetPixel DIB_24BPP_GetPixel(PSURFOBJ SurfObj, LONG x, LONG y); PFN_DIB_HLine DIB_24BPP_HLine(PSURFOBJ SurfObj, LONG x1, LONG x2, LONG y, ULONG c); diff --git a/reactos/subsys/win32k/dib/dib16bpp.c b/reactos/subsys/win32k/dib/dib16bpp.c new file mode 100644 index 00000000000..227d78a8a26 --- /dev/null +++ b/reactos/subsys/win32k/dib/dib16bpp.c @@ -0,0 +1,159 @@ +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include +#include "../eng/objects.h" +#include "dib.h" + +VOID DIB_16BPP_PutPixel(PSURFOBJ SurfObj, LONG x, LONG y, ULONG c) +{ + PBYTE byteaddr = SurfObj->pvBits + y * SurfObj->lDelta; + PWORD addr = (PWORD)byteaddr + x; + + *addr = (WORD)c; +} + +ULONG DIB_16BPP_GetPixel(PSURFOBJ SurfObj, LONG x, LONG y) +{ + PBYTE byteaddr = SurfObj->pvBits + y * SurfObj->lDelta; + PWORD addr = (PWORD)byteaddr + x; + + return (ULONG)(*addr); +} + +VOID DIB_16BPP_HLine(PSURFOBJ SurfObj, LONG x1, LONG x2, LONG y, ULONG c) +{ + PBYTE byteaddr = SurfObj->pvBits + y * SurfObj->lDelta; + PWORD addr = (PWORD)byteaddr + x1; + LONG cx = x1; + + while(cx <= x2) { + *addr = (WORD)c; + ++addr; + ++cx; + } +} + +VOID DIB_16BPP_VLine(PSURFOBJ SurfObj, LONG x, LONG y1, LONG y2, ULONG c) +{ + PBYTE byteaddr = SurfObj->pvBits + y1 * SurfObj->lDelta; + PWORD addr = (PWORD)byteaddr + x; + LONG lDelta = SurfObj->lDelta; + + byteaddr = (PBYTE)addr; + while(y1++ <= y2) { + *addr = (WORD)c; + + byteaddr += lDelta; + addr = (PWORD)byteaddr; + } +} + +BOOL DIB_To_16BPP_Bitblt( SURFOBJ *DestSurf, SURFOBJ *SourceSurf, + SURFGDI *DestGDI, SURFGDI *SourceGDI, + PRECTL DestRect, POINTL *SourcePoint, + LONG Delta, XLATEOBJ *ColorTranslation) +{ + LONG i, j, sx, sy, xColor, f1; + PBYTE SourceBits, DestBits, SourceLine, DestLine; + PBYTE SourceBits_4BPP, SourceLine_4BPP; + DestBits = DestSurf->pvBits + (DestRect->top * DestSurf->lDelta) + 2 * DestRect->left; + + switch(SourceGDI->BitsPerPixel) + { + case 1: + sx = SourcePoint->x; + sy = SourcePoint->y; + + for (j=DestRect->top; jbottom; j++) + { + sx = SourcePoint->x; + for (i=DestRect->left; iright; i++) + { + if(DIB_1BPP_GetPixel(SourceSurf, sx, sy) == 0) + { + DIB_16BPP_PutPixel(DestSurf, i, j, XLATEOBJ_iXlate(ColorTranslation, 0)); + } else { + DIB_16BPP_PutPixel(DestSurf, i, j, XLATEOBJ_iXlate(ColorTranslation, 1)); + } + sx++; + } + sy++; + } + break; + + case 4: + SourceBits_4BPP = SourceSurf->pvBits + (SourcePoint->y * SourceSurf->lDelta) + SourcePoint->x; + + for (j=DestRect->top; jbottom; j++) + { + SourceLine_4BPP = SourceBits_4BPP; + sx = SourcePoint->x; + f1 = sx & 1; + + for (i=DestRect->left; iright; i++) + { + xColor = XLATEOBJ_iXlate(ColorTranslation, + (*SourceLine_4BPP & altnotmask[sx&1]) >> (4 * (1-(sx & 1)))); + DIB_16BPP_PutPixel(DestSurf, i, j, xColor); + if(f1 == 1) { SourceLine_4BPP++; f1 = 0; } else { f1 = 1; } + sx++; + } + + SourceBits_4BPP += SourceSurf->lDelta; + } + break; + + case 16: + if (NULL == ColorTranslation || 0 != (ColorTranslation->flXlate & XO_TRIVIAL)) + { + SourceBits = SourceSurf->pvBits + (SourcePoint->y * SourceSurf->lDelta) + 2 * SourcePoint->x; + for (j = DestRect->top; j < DestRect->bottom; j++) + { + RtlCopyMemory(DestBits, SourceBits, 2 * (DestRect->right - DestRect->left)); + SourceBits += SourceSurf->lDelta; + DestBits += DestSurf->lDelta; + } + } + else + { + /* FIXME */ + DPRINT1("DIB_16BPP_Bitblt: Unhandled ColorTranslation for 16 -> 16 copy"); + return FALSE; + } + break; + + case 24: + SourceLine = SourceSurf->pvBits + (SourcePoint->y * SourceSurf->lDelta) + 3 * SourcePoint->x; + DestLine = DestBits; + + for (j = DestRect->top; j < DestRect->bottom; j++) + { + SourceBits = SourceLine; + DestBits = DestLine; + + for (i = DestRect->left; i < DestRect->right; i++) + { + xColor = (*(SourceBits + 2) << 0x10) + + (*(SourceBits + 1) << 0x08) + + (*(SourceBits)); + *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(ColorTranslation, xColor); + SourceBits += 3; + DestBits += 2; + } + + SourceLine += SourceSurf->lDelta; + DestLine += DestSurf->lDelta; + } + break; + + default: + DbgPrint("DIB_16BPP_Bitblt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel); + return FALSE; + } + + return TRUE; +} diff --git a/reactos/subsys/win32k/dib/dib24bpp.c b/reactos/subsys/win32k/dib/dib24bpp.c index 1e27752d6b6..280895eeebc 100644 --- a/reactos/subsys/win32k/dib/dib24bpp.c +++ b/reactos/subsys/win32k/dib/dib24bpp.c @@ -146,6 +146,28 @@ BOOLEAN DIB_To_24BPP_Bitblt( SURFOBJ *DestSurf, SURFOBJ *SourceSurf, } break; + case 16: + SourceBits_16BPP = SourceSurf->pvBits + (SourcePoint->y * SourceSurf->lDelta) + 2 * SourcePoint->x; + + for (j=DestRect->top; jbottom; j++) + { + SourceLine_16BPP = SourceBits_16BPP; + DestLine = DestBits; + + for (i=DestRect->left; iright; i++) + { + xColor = XLATEOBJ_iXlate(ColorTranslation, *SourceLine_16BPP); + *DestLine++ = xColor & 0xff; + *(PWORD)DestLine = xColor >> 8; + DestLine += 2; + SourceLine_16BPP++; + } + + SourceBits_16BPP = (PWORD)((PBYTE)SourceBits_16BPP + SourceSurf->lDelta); + DestBits += DestSurf->lDelta; + } + break; + default: DbgPrint("DIB_24BPP_Bitblt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel); return FALSE; diff --git a/reactos/subsys/win32k/eng/bitblt.c b/reactos/subsys/win32k/eng/bitblt.c index c582ebf678d..b582cb0cbae 100644 --- a/reactos/subsys/win32k/eng/bitblt.c +++ b/reactos/subsys/win32k/eng/bitblt.c @@ -14,12 +14,16 @@ #include "brush.h" #include "clip.h" #include "objects.h" +#include "../dib/dib.h" #include #include #include #include #include +#define NDEBUG +#include + BOOL EngIntersectRect(PRECTL prcDst, PRECTL prcSrc1, PRECTL prcSrc2) { static const RECTL rclEmpty = { 0, 0, 0, 0 }; @@ -40,6 +44,120 @@ BOOL EngIntersectRect(PRECTL prcDst, PRECTL prcSrc1, PRECTL prcSrc2) return(FALSE); } +static BOOL STDCALL +BltMask(SURFOBJ *Dest, PSURFGDI DestGDI, SURFOBJ *Mask, + RECTL *DestRect, POINTL *MaskPoint, BRUSHOBJ* Brush, + POINTL* BrushPoint) +{ + LONG i, j, dx, dy, c8; + BYTE *tMask, *lMask; + PFN_DIB_PutPixel DIB_PutPixel; + static BYTE maskbit[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; + + // Assign DIB functions according to bytes per pixel + switch(BitsPerFormat(Dest->iBitmapFormat)) + { + case 1: + DIB_PutPixel = (PFN_DIB_PutPixel)DIB_1BPP_PutPixel; + break; + + case 4: + DIB_PutPixel = (PFN_DIB_PutPixel)DIB_4BPP_PutPixel; + break; + + case 16: + DIB_PutPixel = (PFN_DIB_PutPixel)DIB_16BPP_PutPixel; + break; + + case 24: + DIB_PutPixel = (PFN_DIB_PutPixel)DIB_24BPP_PutPixel; + break; + + default: + DbgPrint("BltMask: unsupported DIB format %u (bitsPerPixel:%u)\n", Dest->iBitmapFormat, + BitsPerFormat(Dest->iBitmapFormat)); + return FALSE; + } + + dx = DestRect->right - DestRect->left; + dy = DestRect->bottom - DestRect->top; + + if (Mask != NULL) + { + tMask = Mask->pvBits; + for (j = 0; j < dy; j++) + { + lMask = tMask; + c8 = 0; + for (i = 0; i < dx; i++) + { + if (0 != (*lMask & maskbit[c8])) + { + DIB_PutPixel(Dest, DestRect->left + i, DestRect->top + j, Brush->iSolidColor); + } + c8++; + if (8 == c8) + { + lMask++; + c8=0; + } + } + tMask += Mask->lDelta; + } + return TRUE; + } + else + { + return FALSE; + } +} + +static BOOL STDCALL +BltPatCopy(SURFOBJ *Dest, PSURFGDI DestGDI, SURFOBJ *Mask, + RECTL *DestRect, POINTL *MaskPoint, BRUSHOBJ* Brush, + POINTL* BrushPoint) +{ + // These functions are assigned if we're working with a DIB + // The assigned functions depend on the bitsPerPixel of the DIB + PFN_DIB_HLine DIB_HLine; + LONG y; + ULONG LineWidth; + + MouseSafetyOnDrawStart(Dest, DestGDI, DestRect->left, DestRect->top, DestRect->right, DestRect->bottom); + // Assign DIB functions according to bytes per pixel + DPRINT("BPF: %d\n", BitsPerFormat(Dest->iBitmapFormat)); + switch(BitsPerFormat(Dest->iBitmapFormat)) + { + case 4: + DIB_HLine = (PFN_DIB_HLine)DIB_4BPP_HLine; + break; + + case 16: + DIB_HLine = (PFN_DIB_HLine)DIB_16BPP_HLine; + break; + + case 24: + DIB_HLine = (PFN_DIB_HLine)DIB_24BPP_HLine; + break; + + default: + DbgPrint("BltPatCopy: unsupported DIB format %u (bitsPerPixel:%u)\n", Dest->iBitmapFormat, + BitsPerFormat(Dest->iBitmapFormat)); + + MouseSafetyOnDrawEnd(Dest, DestGDI); + return FALSE; + } + + LineWidth = DestRect->right - DestRect->left; + for (y = DestRect->top; y < DestRect->bottom; y++) + { + DIB_HLine(Dest, DestRect->left, DestRect->right, y, Brush->iSolidColor); + } + MouseSafetyOnDrawEnd(Dest, DestGDI); + + return TRUE; +} + INT abs(INT nm); BOOL STDCALL @@ -50,7 +168,7 @@ EngBitBlt(SURFOBJ *Dest, XLATEOBJ *ColorTranslation, RECTL *DestRect, POINTL *SourcePoint, - POINTL *MaskRect, + POINTL *MaskOrigin, BRUSHOBJ *Brush, POINTL *BrushOrigin, ROP4 rop4) @@ -82,7 +200,7 @@ EngBitBlt(SURFOBJ *Dest, // If we don't have to do anything special, we can punt to DrvCopyBits // if it exists - if( (Mask == NULL) && (MaskRect == NULL) && (Brush == NULL) && + if( (Mask == NULL) && (MaskOrigin == NULL) && (Brush == NULL) && (BrushOrigin == NULL) && (rop4 == 0) ) { canCopyBits = TRUE; @@ -119,7 +237,7 @@ EngBitBlt(SURFOBJ *Dest, ret = DestGDI->BitBlt(Dest, TempSurf, Mask, ClipRegion, NULL, DestRect, &TempPoint, - MaskRect, Brush, BrushOrigin, rop4); + MaskOrigin, Brush, BrushOrigin, rop4); MouseSafetyOnDrawEnd(Source, SourceGDI); MouseSafetyOnDrawEnd(Dest, DestGDI); @@ -130,21 +248,21 @@ EngBitBlt(SURFOBJ *Dest, /* The code currently assumes there will be a source bitmap. This is not true when, for example, using this function to * paint a brush pattern on the destination. */ - if(!Source) + if(!Source && 0xaacc != rop4 && PATCOPY != rop4) { DbgPrint("EngBitBlt: A source is currently required, even though not all operations require one (FIXME)\n"); return FALSE; } // * The source bitmap is not managed by the GDI and we didn't already obtain it using EngCopyBits from the device - if(Source->iType != STYPE_BITMAP && SourceGDI->CopyBits == NULL) + if(NULL != Source && STYPE_BITMAP != Source->iType && NULL == SourceGDI->CopyBits) { if (SourceGDI->BitBlt!=NULL) { // Request the device driver to return the bitmap in a format compatible with the device ret = SourceGDI->BitBlt(Dest, Source, Mask, ClipRegion, NULL, DestRect, SourcePoint, - MaskRect, Brush, BrushOrigin, rop4); + MaskOrigin, Brush, BrushOrigin, rop4); MouseSafetyOnDrawEnd(Source, SourceGDI); MouseSafetyOnDrawEnd(Dest, DestGDI); @@ -163,6 +281,14 @@ EngBitBlt(SURFOBJ *Dest, clippingType = ClipRegion->iDComplexity; } + if (0xaacc == rop4) + { + return BltMask(Dest, DestGDI, Mask, DestRect, MaskOrigin, Brush, BrushOrigin); + } else if (PATCOPY == rop4) { + return BltPatCopy(Dest, DestGDI, Mask, DestRect, MaskOrigin, Brush, BrushOrigin); + } + + // We don't handle color translation just yet [we dont have to.. REMOVE REMOVE REMOVE] switch(clippingType) { diff --git a/reactos/subsys/win32k/eng/clip.c b/reactos/subsys/win32k/eng/clip.c index 244b3bdbada..18a2953fe6b 100644 --- a/reactos/subsys/win32k/eng/clip.c +++ b/reactos/subsys/win32k/eng/clip.c @@ -14,6 +14,7 @@ #include "clip.h" #include +#define NDEBUG #include VOID IntEngDeleteClipRegion(CLIPOBJ *ClipObj) @@ -120,16 +121,15 @@ CLIPOBJ_bEnum(IN PCLIPOBJ ClipObj, PENUMRECTS pERects = (PENUMRECTS)EnumRects; //calculate how many rectangles we should copy - nCopy = MIN( ClipGDI->EnumMax-ClipGDI->EnumPos, - MIN( ClipGDI->EnumRects.c, (ObjSize-sizeof(ULONG))/sizeof(RECTL))); + nCopy = MIN( ClipGDI->EnumMax - ClipGDI->EnumPos, + MIN( ClipGDI->EnumRects.c - ClipGDI->EnumPos, + (ObjSize - sizeof(ULONG)) / sizeof(RECTL))); - RtlCopyMemory( &(pERects->arcl), &(ClipGDI->EnumRects.arcl), nCopy*sizeof(RECTL) ); + RtlCopyMemory( pERects->arcl, ClipGDI->EnumRects.arcl + ClipGDI->EnumPos, + nCopy * sizeof(RECTL) ); pERects->c = nCopy; ClipGDI->EnumPos+=nCopy; - if(ClipGDI->EnumPos > ClipGDI->EnumRects.c) - return FALSE; - else - return TRUE; + return ClipGDI->EnumPos < ClipGDI->EnumRects.c; } diff --git a/reactos/subsys/win32k/eng/copybits.c b/reactos/subsys/win32k/eng/copybits.c index d3f4528223e..7909a53bbbb 100644 --- a/reactos/subsys/win32k/eng/copybits.c +++ b/reactos/subsys/win32k/eng/copybits.c @@ -44,6 +44,11 @@ BOOLEAN CopyBitsCopy(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, DestRect, SourcePoint, Delta, ColorTranslation); break; + case 16: + return DIB_To_16BPP_Bitblt(DestSurf, SourceSurf, DestGDI, SourceGDI, + DestRect, SourcePoint, Delta, ColorTranslation); + break; + case 24: return DIB_To_24BPP_Bitblt(DestSurf, SourceSurf, DestGDI, SourceGDI, DestRect, SourcePoint, Delta, ColorTranslation); diff --git a/reactos/subsys/win32k/eng/lineto.c b/reactos/subsys/win32k/eng/lineto.c index ce09b708546..ad94024ae24 100644 --- a/reactos/subsys/win32k/eng/lineto.c +++ b/reactos/subsys/win32k/eng/lineto.c @@ -1,4 +1,5 @@ #include +#include #include "objects.h" #include "../dib/dib.h" @@ -17,9 +18,8 @@ EngLineTo(SURFOBJ *Surface, RECTL *RectBounds, MIX mix) { - BOOLEAN ret; - SURFGDI *SurfGDI; - LONG x, y, d, deltax, deltay, i, length, xchange, ychange, error, hx, vy; + LONG x, y, deltax, deltay, i, length, xchange, ychange, error, hx, vy; + ULONG Pixel = Brush->iSolidColor; // These functions are assigned if we're working with a DIB // The assigned functions depend on the bitsPerPixel of the DIB @@ -27,18 +27,6 @@ EngLineTo(SURFOBJ *Surface, PFN_DIB_HLine DIB_HLine; PFN_DIB_VLine DIB_VLine; - SurfGDI = (SURFGDI*)AccessInternalObjectFromUserObject(Surface); - - MouseSafetyOnDrawStart(Surface, SurfGDI, x1, y1, x2, y2); - - if(Surface->iType!=STYPE_BITMAP) - { - // Call the driver's DrvLineTo - ret = SurfGDI->LineTo(Surface, Clip, Brush, x1, y1, x2, y2, RectBounds, mix); - MouseSafetyOnDrawEnd(Surface, SurfGDI); - return ret; - } - // Assign DIB functions according to bytes per pixel switch(BitsPerFormat(Surface->iBitmapFormat)) { @@ -54,6 +42,12 @@ EngLineTo(SURFOBJ *Surface, DIB_VLine = (PFN_DIB_VLine)DIB_4BPP_VLine; break; + case 16: + DIB_PutPixel = (PFN_DIB_PutPixel)DIB_16BPP_PutPixel; + DIB_HLine = (PFN_DIB_HLine)DIB_16BPP_HLine; + DIB_VLine = (PFN_DIB_VLine)DIB_16BPP_VLine; + break; + case 24: DIB_PutPixel = (PFN_DIB_PutPixel)DIB_24BPP_PutPixel; DIB_HLine = (PFN_DIB_HLine)DIB_24BPP_HLine; @@ -63,8 +57,6 @@ EngLineTo(SURFOBJ *Surface, default: DbgPrint("EngLineTo: unsupported DIB format %u (bitsPerPixel:%u)\n", Surface->iBitmapFormat, BitsPerFormat(Surface->iBitmapFormat)); - - MouseSafetyOnDrawEnd(Surface, SurfGDI); return FALSE; } @@ -96,8 +88,8 @@ EngLineTo(SURFOBJ *Surface, vy = y1; } - if(y1==y2) { DIB_HLine(Surface, hx, hx + deltax, y1, Brush->iSolidColor); MouseSafetyOnDrawEnd(Surface, SurfGDI); return TRUE; } - if(x1==x2) { DIB_VLine(Surface, x1, vy, vy + deltay, Brush->iSolidColor); MouseSafetyOnDrawEnd(Surface, SurfGDI); return TRUE; } + if(y1==y2) { DIB_HLine(Surface, hx, hx + deltax, y1, Pixel); return TRUE; } + if(x1==x2) { DIB_VLine(Surface, x1, vy, vy + deltay, Pixel); return TRUE; } error=0; i=0; @@ -107,7 +99,7 @@ EngLineTo(SURFOBJ *Surface, length=deltay+1; while(iiSolidColor); + DIB_PutPixel(Surface, x, y, Pixel); y=y+ychange; error=error+deltax; @@ -123,7 +115,7 @@ EngLineTo(SURFOBJ *Surface, length=deltax+1; while(iiSolidColor); + DIB_PutPixel(Surface, x, y, Pixel); x=x+xchange; error=error+deltay; if(error>deltax) @@ -135,7 +127,45 @@ EngLineTo(SURFOBJ *Surface, } } - MouseSafetyOnDrawEnd(Surface, SurfGDI); - return TRUE; } + +BOOL STDCALL +IntEngLineTo(SURFOBJ *Surface, + CLIPOBJ *Clip, + BRUSHOBJ *Brush, + LONG x1, + LONG y1, + LONG x2, + LONG y2, + RECTL *RectBounds, + MIX mix) +{ + BOOLEAN ret; + SURFGDI *SurfGDI; + + /* No success yet */ + ret = FALSE; + SurfGDI = (SURFGDI*)AccessInternalObjectFromUserObject(Surface); + + MouseSafetyOnDrawStart(Surface, SurfGDI, x1, y1, x2, y2); + + if (NULL != SurfGDI->LineTo) { + /* Call the driver's DrvLineTo */ + ret = SurfGDI->LineTo(Surface, Clip, Brush, x1, y1, x2, y2, RectBounds, mix); + } + +#if 0 + if (! ret && NULL != SurfGDI->StrokePath) { + /* FIXME: Emulate LineTo using drivers DrvStrokePath and set ret on success */ + } +#endif + + if (! ret) { + ret = EngLineTo(Surface, Clip, Brush, x1, y1, x2, y2, RectBounds, mix); + } + + MouseSafetyOnDrawEnd(Surface, SurfGDI); + + return ret; +} diff --git a/reactos/subsys/win32k/eng/mouse.c b/reactos/subsys/win32k/eng/mouse.c index e3499c75142..cf4db2ffef9 100644 --- a/reactos/subsys/win32k/eng/mouse.c +++ b/reactos/subsys/win32k/eng/mouse.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: mouse.c,v 1.16 2003/01/24 23:25:34 ei Exp $ +/* $Id: mouse.c,v 1.17 2003/02/15 19:16:33 gvg Exp $ * * PROJECT: ReactOS kernel * PURPOSE: Mouse @@ -34,6 +34,9 @@ #include "objects.h" #include "include/msgqueue.h" +#define NDEBUG +#include + /* GLOBALS *******************************************************************/ static BOOLEAN SafetySwitch = FALSE; @@ -122,6 +125,9 @@ MouseSafetyOnDrawStart(PSURFOBJ SurfObj, PSURFGDI SurfGDI, LONG HazardX1, RECTL MouseRect; LONG tmp; + /* Mouse is not allowed to move if GDI is busy drawing */ + SafetySwitch2 = TRUE; + if (SurfObj == NULL) { return(FALSE); @@ -144,13 +150,10 @@ MouseSafetyOnDrawStart(PSURFOBJ SurfObj, PSURFGDI SurfGDI, LONG HazardX1, if (((mouse_x + mouse_width) >= HazardX1) && (mouse_x <= HazardX2) && ((mouse_y + mouse_height) >= HazardY1) && (mouse_y <= HazardY2)) { - SurfGDI->MovePointer(SurfObj, -1, -1, &MouseRect); SafetySwitch = TRUE; + SurfGDI->MovePointer(SurfObj, -1, -1, &MouseRect); } - /* Mouse is not allowed to move if GDI is busy drawing */ - SafetySwitch2 = TRUE; - return(TRUE); } diff --git a/reactos/subsys/win32k/eng/objects.h b/reactos/subsys/win32k/eng/objects.h index 23bb15c1ccc..aa5b696c679 100644 --- a/reactos/subsys/win32k/eng/objects.h +++ b/reactos/subsys/win32k/eng/objects.h @@ -131,7 +131,7 @@ typedef VOID STDCALL (*PFN_Synchronize)(DHPDEV, PRECTL); typedef VOID STDCALL (*PFN_MovePointer)(PSURFOBJ, LONG, LONG, PRECTL); -typedef VOID STDCALL (*PFN_SetPointerShape)(PSURFOBJ, PSURFOBJ, PSURFOBJ, PXLATEOBJ, +typedef ULONG STDCALL (*PFN_SetPointerShape)(PSURFOBJ, PSURFOBJ, PSURFOBJ, PXLATEOBJ, LONG, LONG, LONG, LONG, PRECTL, ULONG); typedef HBITMAP STDCALL (*PFN_CreateDeviceBitmap)(DHPDEV, SIZEL, ULONG); @@ -174,6 +174,14 @@ typedef struct _XLATEGDI { HPALETTE SourcePal; ULONG *translationTable; + + ULONG RedMask; + ULONG GreenMask; + ULONG BlueMask; + INT RedShift; + INT GreenShift; + INT BlueShift; + BOOL UseShiftAndMask; } XLATEGDI; // List of GDI objects diff --git a/reactos/subsys/win32k/eng/paint.c b/reactos/subsys/win32k/eng/paint.c index a5009693384..0a78731aa38 100644 --- a/reactos/subsys/win32k/eng/paint.c +++ b/reactos/subsys/win32k/eng/paint.c @@ -20,7 +20,7 @@ #include "brush.h" #include "clip.h" -//#define NDEBUG +#define NDEBUG #include BOOL FillSolid(SURFOBJ *Surface, PRECTL pRect, ULONG iColor) @@ -55,6 +55,12 @@ BOOL FillSolid(SURFOBJ *Surface, PRECTL pRect, ULONG iColor) DIB_VLine = (PFN_DIB_VLine)DIB_4BPP_VLine; break; + case 16: + DIB_PutPixel = (PFN_DIB_PutPixel)DIB_16BPP_PutPixel; + DIB_HLine = (PFN_DIB_HLine)DIB_16BPP_HLine; + DIB_VLine = (PFN_DIB_VLine)DIB_16BPP_VLine; + break; + case 24: DIB_PutPixel = (PFN_DIB_PutPixel)DIB_24BPP_PutPixel; DIB_HLine = (PFN_DIB_HLine)DIB_24BPP_HLine; @@ -62,7 +68,7 @@ BOOL FillSolid(SURFOBJ *Surface, PRECTL pRect, ULONG iColor) break; default: - DbgPrint("EngLineTo: unsupported DIB format %u (bitsPerPixel:%u)\n", Surface->iBitmapFormat, + DbgPrint("FillSolid: unsupported DIB format %u (bitsPerPixel:%u)\n", Surface->iBitmapFormat, BitsPerFormat(Surface->iBitmapFormat)); MouseSafetyOnDrawEnd(Surface, SurfaceGDI); @@ -86,6 +92,7 @@ BOOL EngPaintRgn(SURFOBJ *Surface, CLIPOBJ *ClipRegion, ULONG iColor, MIX Mix, { RECT_ENUM RectEnum; BOOL EnumMore; + ULONG i; DPRINT("ClipRegion->iMode:%d, ClipRegion->iDComplexity: %d\n Color: %d", ClipRegion->iMode, ClipRegion->iDComplexity, iColor); switch(ClipRegion->iMode) { @@ -106,7 +113,9 @@ BOOL EngPaintRgn(SURFOBJ *Surface, CLIPOBJ *ClipRegion, ULONG iColor, MIX Mix, do { EnumMore = CLIPOBJ_bEnum(ClipRegion, sizeof(RectEnum), (PVOID) &RectEnum); - FillSolid(Surface, &RectEnum.arcl[0], iColor); + for (i = 0; i < RectEnum.c; i++) { + FillSolid(Surface, RectEnum.arcl + i, iColor); + } } while (EnumMore); } diff --git a/reactos/subsys/win32k/eng/surface.c b/reactos/subsys/win32k/eng/surface.c index 3ec09671d6f..cba32dbfc55 100644 --- a/reactos/subsys/win32k/eng/surface.c +++ b/reactos/subsys/win32k/eng/surface.c @@ -19,7 +19,7 @@ #include #include "handle.h" -//#define NDEBUG +#define NDEBUG #include INT BitsPerFormat(ULONG Format) @@ -243,3 +243,9 @@ EngLockSurface(IN HSURF Surface) // FIXME: Call GDI_LockObject (see subsys/win32k/objects/gdi.c) return (SURFOBJ*)AccessUserObject((ULONG)Surface); } + +VOID STDCALL +EngUnlockSurface(IN SURFOBJ *Surface) +{ + // FIXME: Call GDI_UnlockObject +} diff --git a/reactos/subsys/win32k/eng/xlate.c b/reactos/subsys/win32k/eng/xlate.c index da8377693a2..aad5b8a1dac 100644 --- a/reactos/subsys/win32k/eng/xlate.c +++ b/reactos/subsys/win32k/eng/xlate.c @@ -17,7 +17,7 @@ #include #include "handle.h" -//#define NDEBUG +#define NDEBUG #include ULONG CCMLastSourceColor = 0, CCMLastColorMatch = 0; @@ -91,6 +91,71 @@ VOID IndexedToIndexedTranslationTable(ULONG *TranslationTable, } } +static VOID BitMasksFromPal(USHORT PalType, PPALGDI Palette, + PULONG RedMask, PULONG BlueMask, PULONG GreenMask) +{ + switch(PalType) + { + case PAL_RGB: + *RedMask = RGB(255, 0, 0); + *GreenMask = RGB(0, 255, 0); + *BlueMask = RGB(0, 0, 255); + break; + case PAL_BGR: + *RedMask = RGB(0, 0, 255); + *GreenMask = RGB(0, 255, 0); + *BlueMask = RGB(255, 0, 0); + break; + case PAL_BITFIELDS: + *RedMask = Palette->RedMask; + *BlueMask = Palette->BlueMask; + *GreenMask = Palette->GreenMask; + break; + } +} + +/* + * Calculate the number of bits Mask must be shift to the left to get a + * 1 in the most significant bit position + */ +static INT CalculateShift(ULONG Mask) +{ + INT Shift = 0; + ULONG LeftmostBit = 1 << (8 * sizeof(ULONG) - 1); + + while (0 == (Mask & LeftmostBit) && Shift < 8 * sizeof(ULONG)) + { + Mask = Mask << 1; + Shift++; + } + + return Shift; +} + +static ULONG ShiftAndMask(XLATEGDI *XlateGDI, ULONG Color) +{ + ULONG TranslatedColor; + + TranslatedColor = 0; + if (XlateGDI->RedShift < 0) + { + TranslatedColor = (Color >> -(XlateGDI->RedShift)) & XlateGDI->RedMask; + } else + TranslatedColor = (Color << XlateGDI->RedShift) & XlateGDI->RedMask; + if (XlateGDI->GreenShift < 0) + { + TranslatedColor |= (Color >> -(XlateGDI->GreenShift)) & XlateGDI->GreenMask; + } else + TranslatedColor |= (Color << XlateGDI->GreenShift) & XlateGDI->GreenMask; + if (XlateGDI->BlueShift < 0) + { + TranslatedColor |= (Color >> -(XlateGDI->BlueShift)) & XlateGDI->BlueMask; + } else + TranslatedColor |= (Color << XlateGDI->BlueShift) & XlateGDI->BlueMask; + + return TranslatedColor; +} + XLATEOBJ *EngCreateXlate(USHORT DestPalType, USHORT SourcePalType, HPALETTE PaletteDest, HPALETTE PaletteSource) { @@ -101,20 +166,21 @@ XLATEOBJ *EngCreateXlate(USHORT DestPalType, USHORT SourcePalType, XLATEGDI *XlateGDI; PALGDI *SourcePalGDI, *DestPalGDI; ULONG IndexedColors; + ULONG SourceRedMask, SourceGreenMask, SourceBlueMask; + ULONG DestRedMask, DestGreenMask, DestBlueMask; + UINT i; NewXlate = (HPALETTE)CreateGDIHandle(sizeof( XLATEGDI ), sizeof( XLATEOBJ )); if( !ValidEngHandle( NewXlate ) ) return NULL; - XlateObj = (XLATEOBJ*) AccessUserObject( NewXlate ); - XlateGDI = (XLATEGDI*) AccessInternalObject( NewXlate ); + XlateObj = (XLATEOBJ*) AccessUserObject( (ULONG) NewXlate ); + XlateGDI = (XLATEGDI*) AccessInternalObject( (ULONG) NewXlate ); ASSERT( XlateObj ); ASSERT( XlateGDI ); - if(SourcePalType == PAL_INDEXED) - SourcePalGDI = (PALGDI*)AccessInternalObject((ULONG)PaletteSource); - if(DestPalType == PAL_INDEXED) - DestPalGDI = (PALGDI*)AccessInternalObject((ULONG)PaletteDest); + SourcePalGDI = (PALGDI*)AccessInternalObject((ULONG)PaletteSource); + DestPalGDI = (PALGDI*)AccessInternalObject((ULONG)PaletteDest); XlateObj->iSrcType = SourcePalType; XlateObj->iDstType = DestPalType; @@ -125,6 +191,23 @@ XLATEOBJ *EngCreateXlate(USHORT DestPalType, USHORT SourcePalType, XlateObj->flXlate = 0; + XlateGDI->UseShiftAndMask = FALSE; + + /* Compute bit fiddeling constants unless both palettes are indexed, then we don't need them */ + if (PAL_INDEXED != SourcePalType || PAL_INDEXED != DestPalType) + { + BitMasksFromPal(PAL_INDEXED == SourcePalType ? PAL_RGB : SourcePalType, + SourcePalGDI, &SourceRedMask, &SourceBlueMask, &SourceGreenMask); + BitMasksFromPal(PAL_INDEXED == DestPalType ? PAL_RGB : DestPalType, + DestPalGDI, &DestRedMask, &DestBlueMask, &DestGreenMask); + XlateGDI->RedShift = CalculateShift(SourceRedMask) - CalculateShift(DestRedMask); + XlateGDI->RedMask = DestRedMask; + XlateGDI->GreenShift = CalculateShift(SourceGreenMask) - CalculateShift(DestGreenMask); + XlateGDI->GreenMask = DestGreenMask; + XlateGDI->BlueShift = CalculateShift(SourceBlueMask) - CalculateShift(DestBlueMask); + XlateGDI->BlueMask = DestBlueMask; + } + // If source and destination palettes are the same or if they're RGB/BGR if( (PaletteDest == PaletteSource) || ((DestPalType == PAL_RGB) && (SourcePalType == PAL_RGB)) || @@ -134,6 +217,20 @@ XLATEOBJ *EngCreateXlate(USHORT DestPalType, USHORT SourcePalType, return XlateObj; } + /* If source and destination are bitfield based (RGB and BGR are just special bitfields) */ + if ((PAL_RGB == DestPalType || PAL_BGR == DestPalType || PAL_BITFIELDS == DestPalType) && + (PAL_RGB == SourcePalType || PAL_BGR == SourcePalType || PAL_BITFIELDS == SourcePalType)) + { + if (SourceRedMask == DestRedMask && + SourceBlueMask == DestBlueMask && + SourceGreenMask == DestGreenMask) + { + XlateObj->flXlate |= XO_TRIVIAL; + } + XlateGDI->UseShiftAndMask = TRUE; + return XlateObj; + } + // Prepare the translation table if( (SourcePalType == PAL_INDEXED) || (SourcePalType == PAL_RGB) ) { @@ -160,7 +257,7 @@ XLATEOBJ *EngCreateXlate(USHORT DestPalType, USHORT SourcePalType, // Converting from indexed to indexed IndexedToIndexedTranslationTable(XlateGDI->translationTable, DestPalGDI, SourcePalGDI); } else - if(XlateObj->iDstType == PAL_RGB) + if (PAL_RGB == XlateObj->iDstType || PAL_BITFIELDS == XlateObj->iDstType ) { // FIXME: Is this necessary? I think the driver has to call this // function anyways if pulXlate is NULL and Source is PAL_INDEXED @@ -170,6 +267,13 @@ XLATEOBJ *EngCreateXlate(USHORT DestPalType, USHORT SourcePalType, XLATEOBJ_cGetPalette(XlateObj, XO_SRCPALETTE, SourcePalGDI->NumColors, XlateGDI->translationTable); + if (PAL_BITFIELDS == XlateObj->iDstType) + { + for (i = 0; i < SourcePalGDI->NumColors; i++) + { + XlateGDI->translationTable[i] = ShiftAndMask(XlateGDI, XlateGDI->translationTable[i]); + } + } } XlateObj->pulXlate = XlateGDI->translationTable; @@ -232,6 +336,10 @@ XLATEOBJ_iXlate(XLATEOBJ *XlateObj, { return Color; } else + if(XlateGDI->UseShiftAndMask) + { + return ShiftAndMask(XlateGDI, Color); + } else if(XlateObj->iSrcType == PAL_RGB) { // FIXME: should we cache colors used often? diff --git a/reactos/subsys/win32k/include/inteng.h b/reactos/subsys/win32k/include/inteng.h new file mode 100644 index 00000000000..9580fdf8368 --- /dev/null +++ b/reactos/subsys/win32k/include/inteng.h @@ -0,0 +1,16 @@ +#ifndef __WIN32K_INTENG_H +#define __WIN32K_INTENG_H + +/* Definitions of IntEngXxx functions */ + +extern BOOL STDCALL IntEngLineTo(SURFOBJ *Surface, + CLIPOBJ *Clip, + BRUSHOBJ *Brush, + LONG x1, + LONG y1, + LONG x2, + LONG y2, + RECTL *RectBounds, + MIX mix); + +#endif diff --git a/reactos/subsys/win32k/makefile b/reactos/subsys/win32k/makefile index 8719567a684..2570c8a8633 100644 --- a/reactos/subsys/win32k/makefile +++ b/reactos/subsys/win32k/makefile @@ -1,4 +1,4 @@ -# $Id: makefile,v 1.54 2002/11/24 20:18:35 jfilby Exp $ +# $Id: makefile,v 1.55 2003/02/15 19:16:33 gvg Exp $ PATH_TO_TOP = ../.. @@ -40,7 +40,7 @@ OBJECTS_OBJECTS = objects/bitmaps.o objects/brush.o objects/cliprgn.o \ objects/region.o objects/text.o objects/wingl.o \ objects/bezier.o objects/objconv.o objects/dib.o \ objects/palette.o objects/rect.o -DIB_OBJECTS = dib/dib1bpp.o dib/dib4bpp.o dib/dib24bpp.o +DIB_OBJECTS = dib/dib1bpp.o dib/dib4bpp.o dib/dib16bpp.o dib/dib24bpp.o FREETYPE_OBJECTS = freetype/ctype.o freetype/grfont.o \ freetype/src/base/ftsystem.o freetype/src/base/ftdebug.o \ freetype/src/base/ftinit.o freetype/src/base/ftbase.o \ diff --git a/reactos/subsys/win32k/objects/dc.c b/reactos/subsys/win32k/objects/dc.c index 7a67a9463e1..22b5317a5a8 100644 --- a/reactos/subsys/win32k/objects/dc.c +++ b/reactos/subsys/win32k/objects/dc.c @@ -1,4 +1,4 @@ -/* $Id: dc.c,v 1.45 2003/01/25 23:09:40 ei Exp $ +/* $Id: dc.c,v 1.46 2003/02/15 19:16:34 gvg Exp $ * * DC.C - Device context functions * @@ -20,7 +20,7 @@ #include #include "../eng/handle.h" -//#define NDEBUG +#define NDEBUG #include static GDIDEVICE PrimarySurface; @@ -276,9 +276,11 @@ HDC STDCALL W32kCreateDC(LPCWSTR Driver, LPCWSTR Output, CONST PDEVMODEW InitData) { - HDC hNewDC; - PDC NewDC; - HDC hDC = NULL; + HDC hNewDC; + PDC NewDC; + HDC hDC = NULL; + PSURFOBJ SurfObj; + PSURFGDI SurfGDI; /* Check for existing DC object */ if ((hNewDC = DC_FindOpenDC(Driver)) != NULL) @@ -323,13 +325,14 @@ HDC STDCALL W32kCreateDC(LPCWSTR Driver, /* FIXME: get mode selection information from somewhere */ NewDC->DMW.dmLogPixels = 96; - NewDC->DMW.dmBitsPerPel = 4; - NewDC->DMW.dmPelsWidth = 640; - NewDC->DMW.dmPelsHeight = 480; + SurfGDI = (PSURFGDI)AccessInternalObject(PrimarySurface.Handle); + NewDC->DMW.dmBitsPerPel = SurfGDI->BitsPerPixel; + NewDC->DMW.dmPelsWidth = SurfGDI->SurfObj.sizlBitmap.cx; + NewDC->DMW.dmPelsHeight = SurfGDI->SurfObj.sizlBitmap.cy; NewDC->DMW.dmDisplayFlags = 0; NewDC->DMW.dmDisplayFrequency = 0; - NewDC->w.bitsPerPixel = 4; // FIXME: set this here?? + NewDC->w.bitsPerPixel = SurfGDI->BitsPerPixel; // FIXME: set this here?? NewDC->w.hPalette = NewDC->DevInfo.hpalDefault; diff --git a/reactos/subsys/win32k/objects/fillshap.c b/reactos/subsys/win32k/objects/fillshap.c index a5e424eadec..fe270964728 100644 --- a/reactos/subsys/win32k/objects/fillshap.c +++ b/reactos/subsys/win32k/objects/fillshap.c @@ -6,8 +6,9 @@ #include #include #include +#include -// #define NDEBUG +#define NDEBUG #include BOOL @@ -106,33 +107,33 @@ W32kRectangle(HDC hDC, TopRect += dc->w.DCOrgY; BottomRect += dc->w.DCOrgY; - ret = EngLineTo(SurfObj, - NULL, // ClipObj, - BrushObj, - LeftRect, TopRect, RightRect, TopRect, - RectBounds, // Bounding rectangle - dc->w.ROPmode); // MIX + ret = IntEngLineTo(SurfObj, + NULL, // ClipObj, + BrushObj, + LeftRect, TopRect, RightRect, TopRect, + RectBounds, // Bounding rectangle + dc->w.ROPmode); // MIX - ret = EngLineTo(SurfObj, - NULL, // ClipObj, - BrushObj, - RightRect, TopRect, RightRect, BottomRect, - RectBounds, // Bounding rectangle - dc->w.ROPmode); // MIX + ret = IntEngLineTo(SurfObj, + NULL, // ClipObj, + BrushObj, + RightRect, TopRect, RightRect, BottomRect, + RectBounds, // Bounding rectangle + dc->w.ROPmode); // MIX - ret = EngLineTo(SurfObj, - NULL, // ClipObj, - BrushObj, - LeftRect, BottomRect, RightRect, BottomRect, - RectBounds, // Bounding rectangle - dc->w.ROPmode); // MIX + ret = IntEngLineTo(SurfObj, + NULL, // ClipObj, + BrushObj, + LeftRect, BottomRect, RightRect, BottomRect, + RectBounds, // Bounding rectangle + dc->w.ROPmode); // MIX - ret = EngLineTo(SurfObj, - NULL, // ClipObj, - BrushObj, - LeftRect, TopRect, LeftRect, BottomRect, - RectBounds, // Bounding rectangle - dc->w.ROPmode); // MIX */ + ret = IntEngLineTo(SurfObj, + NULL, // ClipObj, + BrushObj, + LeftRect, TopRect, LeftRect, BottomRect, + RectBounds, // Bounding rectangle + dc->w.ROPmode); // MIX */ // FIXME: BrushObj is obtained above; decide which one is correct BrushObj = (BRUSHOBJ*) GDIOBJ_LockObj(dc->w.hBrush, GO_BRUSH_MAGIC); diff --git a/reactos/subsys/win32k/objects/line.c b/reactos/subsys/win32k/objects/line.c index c4b1ac1cd68..43468473f80 100644 --- a/reactos/subsys/win32k/objects/line.c +++ b/reactos/subsys/win32k/objects/line.c @@ -8,10 +8,12 @@ #include #include #include +#include -// #define NDEBUG +#define NDEBUG #include + BOOL STDCALL W32kAngleArc(HDC hDC, @@ -109,6 +111,9 @@ W32kLineTo(HDC hDC, BOOL ret; PPENOBJ pen; PROSRGNDATA reg; +#ifndef TODO + RECT defaultrect; +#endif if(!dc) return FALSE; @@ -120,18 +125,28 @@ W32kLineTo(HDC hDC, ASSERT( pen ); // not yet implemented ASSERT( reg ); +#ifndef TODO + if (NULL == reg) { + defaultrect.left = 0; + defaultrect.top = 0; + defaultrect.right = 640; + defaultrect.bottom = 480; + + reg = &defaultrect; + } +#endif /* Draw the line according to the DC origin */ - ret = EngLineTo(SurfObj, - NULL, // ClipObj - PenToBrushObj(dc, pen), - dc->w.DCOrgX + dc->w.CursPosX, dc->w.DCOrgY + dc->w.CursPosY, - dc->w.DCOrgX + XEnd, dc->w.DCOrgY + YEnd, - reg, // Bounding rectangle - dc->w.ROPmode); // MIX + ret = IntEngLineTo(SurfObj, + NULL, // ClipObj + PenToBrushObj(dc, pen), + dc->w.DCOrgX + dc->w.CursPosX, dc->w.DCOrgY + dc->w.CursPosY, + dc->w.DCOrgX + XEnd, dc->w.DCOrgY + YEnd, + reg, // Bounding rectangle + dc->w.ROPmode); // MIX - GDIOBJ_UnlockObj( dc->w.hGCClipRgn, GO_REGION_MAGIC ); - GDIOBJ_UnlockObj( dc->w.hPen, GO_PEN_MAGIC); + GDIOBJ_UnlockObj( dc->w.hGCClipRgn, GO_REGION_MAGIC ); + GDIOBJ_UnlockObj( dc->w.hPen, GO_PEN_MAGIC); } if(ret) { dc->w.CursPosX = XEnd; diff --git a/reactos/subsys/win32k/stubs/stubs.c b/reactos/subsys/win32k/stubs/stubs.c index 0f1898f9c90..8e381d71b03 100644 --- a/reactos/subsys/win32k/stubs/stubs.c +++ b/reactos/subsys/win32k/stubs/stubs.c @@ -71,7 +71,6 @@ STUB(EngTextOut) STUB(EngUnicodeToMultiByteN) STUB(EngUnloadImage) STUB(EngUnlockDriverObj) -STUB(EngUnlockSurface) STUB(EngUnmapEvent) STUB(EngUnmapFontFile) STUB(EngUnsecureMem) diff --git a/reactos/subsys/win32k/win32k.def b/reactos/subsys/win32k/win32k.def index 29eadfe1529..f6b18711494 100644 --- a/reactos/subsys/win32k/win32k.def +++ b/reactos/subsys/win32k/win32k.def @@ -1,4 +1,4 @@ -; $Id: win32k.def,v 1.14 2002/10/28 15:03:18 robd Exp $ +; $Id: win32k.def,v 1.15 2003/02/15 19:16:33 gvg Exp $ ; ; win32k.def ; @@ -72,7 +72,7 @@ EngMapFontFile EngMapModule EngMarkBandingSurface EngMovePointer -EngMulDiv +EngMulDiv@12 EngMultiByteToUnicodeN EngMultiByteToWideChar EngPaint@20 @@ -101,7 +101,7 @@ EngTransparentBlt@32 EngUnicodeToMultiByteN EngUnloadImage EngUnlockDriverObj -EngUnlockSurface +EngUnlockSurface@4 EngUnmapEvent EngUnmapFontFile ; EngUnsecureMem = NTOSKRNL.MmUnsecureVirtualMemory diff --git a/reactos/subsys/win32k/win32k.edf b/reactos/subsys/win32k/win32k.edf index 0ce03715058..7f7cfecffe3 100644 --- a/reactos/subsys/win32k/win32k.edf +++ b/reactos/subsys/win32k/win32k.edf @@ -1,4 +1,4 @@ -; $Id: win32k.edf,v 1.7 2002/10/28 15:03:18 robd Exp $ +; $Id: win32k.edf,v 1.8 2003/02/15 19:16:33 gvg Exp $ ; ; win32k.def ; @@ -72,7 +72,7 @@ EngMapFontFile EngMapModule EngMarkBandingSurface EngMovePointer -EngMulDiv +EngMulDiv=EngMulDiv@12 EngMultiByteToUnicodeN EngMultiByteToWideChar EngPaint=EngPaint@20 @@ -101,7 +101,7 @@ EngTransparentBlt=EngTransparentBlt@32 EngUnicodeToMultiByteN EngUnloadImage EngUnlockDriverObj -EngUnlockSurface +EngUnlockSurface=EngUnlockSurface@4 EngUnmapEvent EngUnmapFontFile ; EngUnsecureMem = NTOSKRNL.MmUnsecureVirtualMemory