Merge from trunk. Inform HAL about the switch to graphics modeas late as possible. Fixes bug 880. Modified: branches/ros-branch-0_2_8/reactos/drivers/video/videoprt/dispatch.c Modified: branches/ros-branch-0_2_8/reactos/drivers/video/videoprt/videoprt.c Modified: branches/ros-branch-0_2_8/reactos/drivers/video/videoprt/videoprt.h Modified: branches/ros-branch-0_2_8/reactos/subsys/win32k/objects/dc.c _____
Modified: branches/ros-branch-0_2_8/reactos/drivers/video/videoprt/dispatch.c --- branches/ros-branch-0_2_8/reactos/drivers/video/videoprt/dispatch.c 2005-10-17 21:47:17 UTC (rev 18532) +++ branches/ros-branch-0_2_8/reactos/drivers/video/videoprt/dispatch.c 2005-10-17 21:48:12 UTC (rev 18533) @@ -18,7 +18,6 @@
* If not, write to the Free Software Foundation, * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - * $Id$ */
#include "videoprt.h" @@ -133,18 +132,6 @@ Irp->IoStatus.Status = STATUS_SUCCESS;
InterlockedIncrement((PLONG)&DeviceExtension->DeviceOpened); - - /* - * Storing the device extension pointer in a static variable is an - * ugly hack. Unfortunately, we need it in VideoPortResetDisplayParameters - * and HalAcquireDisplayOwnership doesn't allow us to pass a userdata - * parameter. On the bright side, the DISPLAY device is opened - * exclusively, so there can be only one device extension active at - * any point in time. - */ - - ResetDisplayParametersDeviceExtension = DeviceExtension; - HalAcquireDisplayOwnership(IntVideoPortResetDisplayParameters); } else { @@ -264,7 +251,57 @@ return Status; }
+/* + * IntVideoPortWrite + * + * This is a bit of a hack. We want to take ownership of the display as late + * as possible, just before the switch to graphics mode. Win32k knows when + * this happens, we don't. So we need Win32k to inform us. This could be done + * using an IOCTL, but there's no way of knowing which IOCTL codes are unused + * in the communication between GDI driver and miniport driver. So we use + * IRP_MJ_WRITE as the signal that win32k is ready to switch to graphics mode, + * since we know for certain that there is no read/write activity going on + * between GDI and miniport drivers. + * We don't actually need the data that is passed, we just trigger on the fact + * that an IRP_MJ_WRITE was sent. + * + * Run Level + * PASSIVE_LEVEL + */ + NTSTATUS NTAPI +IntVideoPortDispatchWrite( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION piosStack = IoGetCurrentIrpStackLocation(Irp); + PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; + NTSTATUS nErrCode; + + DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + /* + * Storing the device extension pointer in a static variable is an + * ugly hack. Unfortunately, we need it in VideoPortResetDisplayParameters + * and HalAcquireDisplayOwnership doesn't allow us to pass a userdata + * parameter. On the bright side, the DISPLAY device is opened + * exclusively, so there can be only one device extension active at + * any point in time. + */ + + ResetDisplayParametersDeviceExtension = DeviceExtension; + HalAcquireDisplayOwnership(IntVideoPortResetDisplayParameters); + + nErrCode = STATUS_SUCCESS; + Irp->IoStatus.Information = piosStack->Parameters.Write.Length; + Irp->IoStatus.Status = nErrCode; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return nErrCode; +} + + +NTSTATUS NTAPI IntVideoPortPnPStartDevice( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) _____
Modified: branches/ros-branch-0_2_8/reactos/drivers/video/videoprt/videoprt.c --- branches/ros-branch-0_2_8/reactos/drivers/video/videoprt/videoprt.c 2005-10-17 21:47:17 UTC (rev 18532) +++ branches/ros-branch-0_2_8/reactos/drivers/video/videoprt/videoprt.c 2005-10-17 21:48:12 UTC (rev 18533) @@ -646,6 +646,7 @@
DriverObject->MajorFunction[IRP_MJ_CREATE] = IntVideoPortDispatchOpen; DriverObject->MajorFunction[IRP_MJ_CLOSE] = IntVideoPortDispatchClose; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IntVideoPortDispatchDeviceControl; + DriverObject->MajorFunction[IRP_MJ_WRITE] = IntVideoPortDispatchWrite; DriverObject->DriverUnload = IntVideoPortUnload;
/* _____
Modified: branches/ros-branch-0_2_8/reactos/drivers/video/videoprt/videoprt.h --- branches/ros-branch-0_2_8/reactos/drivers/video/videoprt/videoprt.h 2005-10-17 21:47:17 UTC (rev 18532) +++ branches/ros-branch-0_2_8/reactos/drivers/video/videoprt/videoprt.h 2005-10-17 21:48:12 UTC (rev 18533) @@ -148,6 +148,11 @@
IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS NTAPI +IntVideoPortDispatchWrite( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + VOID NTAPI IntVideoPortUnload(PDRIVER_OBJECT DriverObject);
_____
Modified: branches/ros-branch-0_2_8/reactos/subsys/win32k/objects/dc.c --- branches/ros-branch-0_2_8/reactos/subsys/win32k/objects/dc.c 2005-10-17 21:47:17 UTC (rev 18532) +++ branches/ros-branch-0_2_8/reactos/subsys/win32k/objects/dc.c 2005-10-17 21:48:12 UTC (rev 18533) @@ -661,6 +661,61 @@
return (PrimarySurface.PreparedDriver ? TRUE : IntPrepareDriver()); }
+static BOOL FASTCALL +PrepareVideoPrt() +{ + PIRP Irp; + NTSTATUS Status; + IO_STATUS_BLOCK Iosb; + BOOL Prepare = TRUE; + ULONG Length = sizeof(BOOL); + PIO_STACK_LOCATION StackPtr; + LARGE_INTEGER StartOffset; + PFILE_OBJECT FileObject = PrimarySurface.VideoFileObject; + PDEVICE_OBJECT DeviceObject = FileObject->DeviceObject; + + DPRINT("PrepareVideoPrt() called\n"); + + KeClearEvent(&PrimarySurface.VideoFileObject->Event); + + ObReferenceObjectByPointer(FileObject, 0, IoFileObjectType, KernelMode); + + StartOffset.QuadPart = 0; + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE, + DeviceObject, + (PVOID) &Prepare, + Length, + &StartOffset, + NULL, + &Iosb); + if (NULL == Irp) + { + return FALSE; + } + + /* Set up IRP Data */ + Irp->Tail.Overlay.OriginalFileObject = FileObject; + Irp->RequestorMode = KernelMode; + Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; + Irp->Overlay.AsynchronousParameters.UserApcContext = NULL; + Irp->Flags |= IRP_WRITE_OPERATION; + + /* Setup Stack Data */ + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->FileObject = PrimarySurface.VideoFileObject; + StackPtr->Parameters.Write.Key = 0; + + Status = IoCallDriver(DeviceObject, Irp); + + if (STATUS_PENDING == Status) + { + KeWaitForSingleObject(&FileObject->Event, Executive, KernelMode, TRUE, 0); + Status = Iosb.Status; + } + + return NT_SUCCESS(Status); +} + BOOL FASTCALL IntCreatePrimarySurface() { @@ -674,6 +729,11 @@ return FALSE; }
+ if (! PrepareVideoPrt()) + { + return FALSE; + } + DPRINT("calling EnableSurface\n"); /* Enable the drawing surface */ PrimarySurface.Handle =