2016-11-04 11:57:01 +01:00
/*
* Copyright 2013 - 2016 Red Hat , Inc .
2016-11-07 10:45:05 +01:00
*
2016-11-04 11:57:01 +01:00
* Licensed under the Apache License , Version 2.0 ( the " License " ) ;
* you may not use this file except in compliance with the License .
*
* You may obtain a copy of the License at
* http : //www.apache.org/licenses/LICENSE-2.0
*/
2014-09-02 09:36:27 +02:00
# include "driver.h"
# include "qxldod.h"
2015-02-08 11:04:39 +01:00
# include "qxl_windows.h"
2016-09-28 13:31:04 +02:00
# include "compat.h"
2017-07-09 09:54:24 +02:00
# if !DBG
# include "qxldod.tmh"
# endif
2014-09-02 09:36:27 +02:00
2016-09-13 00:02:01 +02:00
# pragma code_seg("PAGE")
2016-09-04 16:12:33 +02:00
# define WIN_QXL_INT_MASK ((QXL_INTERRUPT_DISPLAY) | \
( QXL_INTERRUPT_CURSOR ) | \
( QXL_INTERRUPT_IO_CMD ) )
2017-04-01 18:40:34 +02:00
# define VSYNC_PERIOD 200 // ms, use 0 for auto
2017-02-16 15:30:58 +01:00
# define VSYNC_RATE 75
BOOLEAN g_bSupportVSync ;
2014-09-02 09:36:27 +02:00
// BEGIN: Non-Paged Code
// Bit is 1 from Idx to end of byte, with bit count starting at high order
BYTE lMaskTable [ BITS_PER_BYTE ] = { 0xff , 0x7f , 0x3f , 0x1f , 0x0f , 0x07 , 0x03 , 0x01 } ;
// Bit is 1 from Idx to start of byte, with bit count starting at high order
BYTE rMaskTable [ BITS_PER_BYTE ] = { 0x80 , 0xc0 , 0xe0 , 0xf0 , 0xf8 , 0xfc , 0xfe , 0xff } ;
// Bit of Idx is 1, with bit count starting at high order
BYTE PixelMask [ BITS_PER_BYTE ] = { 0x80 , 0x40 , 0x20 , 0x10 , 0x08 , 0x04 , 0x02 , 0x01 } ;
// For the following macros, pPixel must be a BYTE* pointing to the start of a 32 bit pixel
# define CONVERT_32BPP_TO_16BPP(pPixel) ((UPPER_5_BITS(pPixel[2]) << SHIFT_FOR_UPPER_5_IN_565) | \
( UPPER_6_BITS ( pPixel [ 1 ] ) < < SHIFT_FOR_MIDDLE_6_IN_565 ) | \
( UPPER_5_BITS ( pPixel [ 0 ] ) ) )
// 8bpp is done with 6 levels per color channel since this gives true grays, even if it leaves 40 empty palette entries
// The 6 levels per color is the reason for dividing below by 43 (43 * 6 == 258, closest multiple of 6 to 256)
// It is also the reason for multiplying the red channel by 36 (== 6*6) and the green channel by 6, as this is the
// equivalent to bit shifting in a 3:3:2 model. Changes to this must be reflected in vesasup.cxx with the Blues/Greens/Reds arrays
# define CONVERT_32BPP_TO_8BPP(pPixel) (((pPixel[2] / 43) * 36) + \
( ( pPixel [ 1 ] / 43 ) * 6 ) + \
( ( pPixel [ 0 ] / 43 ) ) )
// 4bpp is done with strict grayscale since this has been found to be usable
// 30% of the red value, 59% of the green value, and 11% of the blue value is the standard way to convert true color to grayscale
# define CONVERT_32BPP_TO_4BPP(pPixel) ((BYTE)(((pPixel[2] * 30) + \
( pPixel [ 1 ] * 59 ) + \
( pPixel [ 0 ] * 11 ) ) / ( 100 * 16 ) ) )
// For the following macro, Pixel must be a WORD representing a 16 bit pixel
# define CONVERT_16BPP_TO_32BPP(Pixel) (((ULONG)LOWER_5_BITS((Pixel) >> SHIFT_FOR_UPPER_5_IN_565) << SHIFT_UPPER_5_IN_565_BACK) | \
( ( ULONG ) LOWER_6_BITS ( ( Pixel ) > > SHIFT_FOR_MIDDLE_6_IN_565 ) < < SHIFT_MIDDLE_6_IN_565_BACK ) | \
( ( ULONG ) LOWER_5_BITS ( ( Pixel ) ) < < SHIFT_LOWER_5_IN_565_BACK ) )
2016-09-11 15:05:21 +02:00
struct QXLEscape {
uint32_t ioctl ;
union {
QXLEscapeSetCustomDisplay custom_display ;
QXLHead monitor_config ;
} ;
} ;
2014-09-02 09:36:27 +02:00
QxlDod : : QxlDod ( _In_ DEVICE_OBJECT * pPhysicalDeviceObject ) : m_pPhysicalDevice ( pPhysicalDeviceObject ) ,
m_MonitorPowerState ( PowerDeviceD0 ) ,
m_AdapterPowerState ( PowerDeviceD0 )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " ---> %s \n " , __FUNCTION__ ) ) ;
* ( ( UINT * ) & m_Flags ) = 0 ;
2016-09-26 15:00:11 +02:00
m_Flags . DriverStarted = FALSE ;
2014-09-02 09:36:27 +02:00
RtlZeroMemory ( & m_DxgkInterface , sizeof ( m_DxgkInterface ) ) ;
RtlZeroMemory ( & m_DeviceInfo , sizeof ( m_DeviceInfo ) ) ;
RtlZeroMemory ( m_CurrentModes , sizeof ( m_CurrentModes ) ) ;
RtlZeroMemory ( & m_PointerShape , sizeof ( m_PointerShape ) ) ;
m_pHWDevice = NULL ;
2017-02-16 15:31:01 +01:00
KeInitializeDpc ( & m_VsyncTimerDpc , VsyncTimerProcGate , this ) ;
KeInitializeTimer ( & m_VsyncTimer ) ;
m_VsyncFiredCounter = 0 ;
m_bVsyncEnabled = FALSE ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " <--- %s \n " , __FUNCTION__ ) ) ;
}
QxlDod : : ~ QxlDod ( void )
{
PAGED_CODE ( ) ;
CleanUp ( ) ;
delete m_pHWDevice ;
m_pHWDevice = NULL ;
}
NTSTATUS QxlDod : : CheckHardware ( )
{
PAGED_CODE ( ) ;
NTSTATUS Status ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
// Get the Vendor & Device IDs on PCI system
PCI_COMMON_HEADER Header = { 0 } ;
ULONG BytesRead ;
Status = m_DxgkInterface . DxgkCbReadDeviceSpace ( m_DxgkInterface . DeviceHandle ,
DXGK_WHICHSPACE_CONFIG ,
& Header ,
0 ,
sizeof ( Header ) ,
& BytesRead ) ;
if ( ! NT_SUCCESS ( Status ) )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " DxgkCbReadDeviceSpace failed with status 0x%X \n " , Status ) ) ;
return Status ;
}
Status = STATUS_GRAPHICS_DRIVER_MISMATCH ;
if ( Header . VendorID = = REDHAT_PCI_VENDOR_ID & &
Header . DeviceID = = 0x0100 & &
2016-09-07 16:22:53 +02:00
Header . RevisionID > = 4 )
2014-09-02 09:36:27 +02:00
{
Status = STATUS_SUCCESS ;
}
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " <--- %s returned with status 0x%X \n " , __FUNCTION__ , Status ) ) ;
return Status ;
}
NTSTATUS QxlDod : : StartDevice ( _In_ DXGK_START_INFO * pDxgkStartInfo ,
_In_ DXGKRNL_INTERFACE * pDxgkInterface ,
_Out_ ULONG * pNumberOfViews ,
_Out_ ULONG * pNumberOfChildren )
{
PAGED_CODE ( ) ;
QXL_ASSERT ( pDxgkStartInfo ! = NULL ) ;
QXL_ASSERT ( pDxgkInterface ! = NULL ) ;
QXL_ASSERT ( pNumberOfViews ! = NULL ) ;
QXL_ASSERT ( pNumberOfChildren ! = NULL ) ;
//CHECK ME!!!!!!!!!!!!!
RtlCopyMemory ( & m_DxgkInterface , pDxgkInterface , sizeof ( m_DxgkInterface ) ) ;
RtlZeroMemory ( m_CurrentModes , sizeof ( m_CurrentModes ) ) ;
//CHECK ME!!!!!!!!!!!!!
m_CurrentModes [ 0 ] . DispInfo . TargetId = D3DDDI_ID_UNINITIALIZED ;
// Get device information from OS.
NTSTATUS Status = m_DxgkInterface . DxgkCbGetDeviceInformation ( m_DxgkInterface . DeviceHandle , & m_DeviceInfo ) ;
if ( ! NT_SUCCESS ( Status ) )
{
QXL_LOG_ASSERTION1 ( " DxgkCbGetDeviceInformation failed with status 0x%X \n " ,
Status ) ;
return Status ;
}
Status = CheckHardware ( ) ;
if ( NT_SUCCESS ( Status ) )
{
2015-03-24 06:41:58 +01:00
m_pHWDevice = new ( NonPagedPoolNx ) QxlDevice ( this ) ;
2014-09-02 09:36:27 +02:00
}
else
{
2015-03-24 06:41:58 +01:00
m_pHWDevice = new ( NonPagedPoolNx ) VgaDevice ( this ) ;
}
if ( ! m_pHWDevice )
{
Status = STATUS_NO_MEMORY ;
DbgPrint ( TRACE_LEVEL_ERROR , ( " HWInit failed to allocate memory \n " ) ) ;
return Status ;
2014-09-02 09:36:27 +02:00
}
Status = m_pHWDevice - > HWInit ( m_DeviceInfo . TranslatedResourceList , & m_CurrentModes [ 0 ] . DispInfo ) ;
if ( ! NT_SUCCESS ( Status ) )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " HWInit failed with status 0x%X \n " , Status ) ) ;
return Status ;
}
2014-12-05 23:20:04 +01:00
Status = RegisterHWInfo ( m_pHWDevice - > GetId ( ) ) ;
if ( ! NT_SUCCESS ( Status ) )
{
QXL_LOG_ASSERTION1 ( " RegisterHWInfo failed with status 0x%X \n " ,
Status ) ;
return Status ;
}
2014-09-02 09:36:27 +02:00
* pNumberOfViews = MAX_VIEWS ;
* pNumberOfChildren = MAX_CHILDREN ;
m_Flags . DriverStarted = TRUE ;
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return STATUS_SUCCESS ;
}
NTSTATUS QxlDod : : StopDevice ( VOID )
{
PAGED_CODE ( ) ;
m_Flags . DriverStarted = FALSE ;
2017-02-16 15:31:01 +01:00
EnableVsync ( FALSE ) ;
2014-09-02 09:36:27 +02:00
return STATUS_SUCCESS ;
}
VOID QxlDod : : CleanUp ( VOID )
{
PAGED_CODE ( ) ;
for ( UINT Source = 0 ; Source < MAX_VIEWS ; + + Source )
{
if ( m_CurrentModes [ Source ] . FrameBuffer . Ptr )
{
2016-09-26 15:00:07 +02:00
m_pHWDevice - > ReleaseFrameBuffer ( & m_CurrentModes [ Source ] ) ;
2014-09-02 09:36:27 +02:00
}
}
}
NTSTATUS QxlDod : : DispatchIoRequest ( _In_ ULONG VidPnSourceId ,
_In_ VIDEO_REQUEST_PACKET * pVideoRequestPacket )
{
PAGED_CODE ( ) ;
UNREFERENCED_PARAMETER ( VidPnSourceId ) ;
UNREFERENCED_PARAMETER ( pVideoRequestPacket ) ;
2015-02-18 10:57:00 +01:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
2014-09-02 09:36:27 +02:00
return STATUS_SUCCESS ;
}
PCHAR
DbgDevicePowerString (
__in DEVICE_POWER_STATE Type
)
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
switch ( Type )
{
case PowerDeviceUnspecified :
return " PowerDeviceUnspecified " ;
case PowerDeviceD0 :
return " PowerDeviceD0 " ;
case PowerDeviceD1 :
return " PowerDeviceD1 " ;
case PowerDeviceD2 :
return " PowerDeviceD2 " ;
case PowerDeviceD3 :
return " PowerDeviceD3 " ;
case PowerDeviceMaximum :
return " PowerDeviceMaximum " ;
default :
return " UnKnown Device Power State " ;
}
}
PCHAR
DbgPowerActionString (
__in POWER_ACTION Type
)
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
switch ( Type )
{
case PowerActionNone :
return " PowerActionNone " ;
case PowerActionReserved :
return " PowerActionReserved " ;
case PowerActionSleep :
return " PowerActionSleep " ;
case PowerActionHibernate :
return " PowerActionHibernate " ;
case PowerActionShutdown :
return " PowerActionShutdown " ;
case PowerActionShutdownReset :
return " PowerActionShutdownReset " ;
case PowerActionShutdownOff :
return " PowerActionShutdownOff " ;
case PowerActionWarmEject :
return " PowerActionWarmEject " ;
default :
return " UnKnown Device Power State " ;
}
}
NTSTATUS QxlDod : : SetPowerState ( _In_ ULONG HardwareUid ,
_In_ DEVICE_POWER_STATE DevicePowerState ,
_In_ POWER_ACTION ActionType )
{
2016-09-04 15:40:56 +02:00
NTSTATUS Status ( STATUS_SUCCESS ) ;
2014-09-02 09:36:27 +02:00
PAGED_CODE ( ) ;
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " ---> %s HardwareUid = 0x%x ActionType = %s DevicePowerState = %s AdapterPowerState = %s \n " , __FUNCTION__ , HardwareUid , DbgPowerActionString ( ActionType ) , DbgDevicePowerString ( DevicePowerState ) , DbgDevicePowerString ( m_AdapterPowerState ) ) ) ;
if ( HardwareUid = = DISPLAY_ADAPTER_HW_ID )
{
2016-09-04 15:40:56 +02:00
// There is nothing to do to specifically power up/down the display adapter
Status = m_pHWDevice - > SetPowerState ( DevicePowerState , & ( m_CurrentModes [ 0 ] . DispInfo ) ) ;
if ( NT_SUCCESS ( Status ) & & DevicePowerState = = PowerDeviceD0 )
2014-09-02 09:36:27 +02:00
{
// When returning from D3 the device visibility defined to be off for all targets
if ( m_AdapterPowerState = = PowerDeviceD3 )
{
DXGKARG_SETVIDPNSOURCEVISIBILITY Visibility ;
Visibility . VidPnSourceId = D3DDDI_ID_ALL ;
Visibility . Visible = FALSE ;
SetVidPnSourceVisibility ( & Visibility ) ;
}
2016-09-04 15:40:56 +02:00
// Store new adapter power state
m_AdapterPowerState = DevicePowerState ;
2014-09-02 09:36:27 +02:00
}
}
// TODO: This is where the specified monitor should be powered up/down
2016-09-04 15:40:56 +02:00
return Status ;
2014-09-02 09:36:27 +02:00
}
NTSTATUS QxlDod : : QueryChildRelations ( _Out_writes_bytes_ ( ChildRelationsSize ) DXGK_CHILD_DESCRIPTOR * pChildRelations ,
_In_ ULONG ChildRelationsSize )
{
PAGED_CODE ( ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
QXL_ASSERT ( pChildRelations ! = NULL ) ;
// The last DXGK_CHILD_DESCRIPTOR in the array of pChildRelations must remain zeroed out, so we subtract this from the count
ULONG ChildRelationsCount = ( ChildRelationsSize / sizeof ( DXGK_CHILD_DESCRIPTOR ) ) - 1 ;
2014-12-06 05:44:28 +01:00
ULONG DeviceId = m_pHWDevice - > GetId ( ) ;
2014-09-02 09:36:27 +02:00
QXL_ASSERT ( ChildRelationsCount < = MAX_CHILDREN ) ;
for ( UINT ChildIndex = 0 ; ChildIndex < ChildRelationsCount ; + + ChildIndex )
{
pChildRelations [ ChildIndex ] . ChildDeviceType = TypeVideoOutput ;
2014-12-06 05:44:28 +01:00
pChildRelations [ ChildIndex ] . ChildCapabilities . HpdAwareness = ( DeviceId = = 0 ) ? HpdAwarenessAlwaysConnected : HpdAwarenessInterruptible ;
2016-10-19 18:01:45 +02:00
pChildRelations [ ChildIndex ] . ChildCapabilities . Type . VideoOutput . InterfaceTechnology = D3DKMDT_VOT_HD15 ;
2014-09-02 09:36:27 +02:00
pChildRelations [ ChildIndex ] . ChildCapabilities . Type . VideoOutput . MonitorOrientationAwareness = D3DKMDT_MOA_NONE ;
pChildRelations [ ChildIndex ] . ChildCapabilities . Type . VideoOutput . SupportsSdtvModes = FALSE ;
// TODO: Replace 0 with the actual ACPI ID of the child device, if available
pChildRelations [ ChildIndex ] . AcpiUid = 0 ;
pChildRelations [ ChildIndex ] . ChildUid = ChildIndex ;
}
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return STATUS_SUCCESS ;
}
NTSTATUS QxlDod : : QueryChildStatus ( _Inout_ DXGK_CHILD_STATUS * pChildStatus ,
_In_ BOOLEAN NonDestructiveOnly )
{
PAGED_CODE ( ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
UNREFERENCED_PARAMETER ( NonDestructiveOnly ) ;
QXL_ASSERT ( pChildStatus ! = NULL ) ;
QXL_ASSERT ( pChildStatus - > ChildUid < MAX_CHILDREN ) ;
switch ( pChildStatus - > Type )
{
case StatusConnection :
{
// HpdAwarenessInterruptible was reported since HpdAwarenessNone is deprecated.
// However, BDD has no knowledge of HotPlug events, so just always return connected.
pChildStatus - > HotPlug . Connected = IsDriverActive ( ) ;
return STATUS_SUCCESS ;
}
case StatusRotation :
{
// D3DKMDT_MOA_NONE was reported, so this should never be called
DbgPrint ( TRACE_LEVEL_ERROR , ( " Child status being queried for StatusRotation even though D3DKMDT_MOA_NONE was reported " ) ) ;
return STATUS_INVALID_PARAMETER ;
}
default :
{
DbgPrint ( TRACE_LEVEL_WARNING , ( " Unknown pChildStatus->Type (0x%I64x) requested. " , pChildStatus - > Type ) ) ;
return STATUS_NOT_SUPPORTED ;
}
}
}
2017-02-16 15:30:57 +01:00
/* edid-decode:
Extracted contents :
header : 00 ff ff ff ff ff ff 00
serial number : 47 0 c 01 00 41 fa 38 78 01 1 b
version : 01 04
basic params : 6 a 22 1 b 78 ea
chroma info : 32 31 a3 57 4 c 9 d 25 11 50 54
established : 04 43 00
standard : 31 4f 45 4f 61 4f 81 4f 01 01 01 01 01 01 01 01
descriptor 1 : ba 2 c 00 a0 50 00 25 40 30 20 37 00 54 0 e 11 00 00 1 e
descriptor 2 : 00 00 00 fd 00 38 50 1 e 53 0f 00 00 00 00 00 00 00 00
descriptor 3 : 00 00 00 fc 00 51 58 4 c 30 30 30 31 0 a 20 20 20 20 20
descriptor 4 : 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00
extensions : 01
checksum : d5
Manufacturer : QXL Model 1 Serial Number 2017000001
Made week 1 of 2017
EDID version : 1.4
Analog display , Input voltage level : 0.7 / 0.7 V
Blank level equals black level
Sync : Separate SyncOnGreen
Maximum image size : 34 cm x 27 cm
Gamma : 2.20
DPMS levels : Standby Suspend Off
RGB color display
First detailed timing is preferred timing
Established timings supported :
640 x480 @ 75 Hz
800 x600 @ 75 Hz
1024 x768 @ 75 Hz
1280 x1024 @ 75 Hz
Standard timings supported :
640 x480 @ 75 Hz
800 x600 @ 75 Hz
1024 x768 @ 75 Hz
1280 x960 @ 75 Hz
Detailed mode : Clock 114.500 MHz , 340 mm x 270 mm
1280 1328 1360 1440 hborder 0
1024 1027 1034 1061 vborder 0
+ hsync + vsync
Monitor ranges : 56 - 80 HZ vertical , 30 - 83 kHz horizontal , max dotclock 150 MHz
Monitor name : QXL0001
Dummy block
Has 1 extension blocks
Checksum : 0xd5
CEA extension block
Extension version : 3
0 bytes of CEA data
0 native detailed modes
Checksum : 0xf7
*/
static const UCHAR edid [ 256 ] =
{
0x00 , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0x00 ,
0x47 , 0x0C , 0x01 , 0x00 , 0x41 , 0xFA , 0x38 , 0x78 ,
0x01 , 0x1B , 0x01 , 0x04 , 0x6A , 0x22 , 0x1B , 0x78 ,
0xEA , 0x32 , 0x31 , 0xA3 , 0x57 , 0x4C , 0x9D , 0x25 ,
0x11 , 0x50 , 0x54 , 0x04 , 0x43 , 0x00 , 0x31 , 0x4F ,
0x45 , 0x4F , 0x61 , 0x4F , 0x81 , 0x4F , 0x01 , 0x01 ,
0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0xBA , 0x2C ,
0x00 , 0xA0 , 0x50 , 0x00 , 0x25 , 0x40 , 0x30 , 0x20 ,
0x37 , 0x00 , 0x54 , 0x0E , 0x11 , 0x00 , 0x00 , 0x1E ,
0x00 , 0x00 , 0x00 , 0xFD , 0x00 , 0x38 , 0x50 , 0x1E ,
0x53 , 0x0F , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0xFC , 0x00 , 0x51 ,
0x58 , 0x4C , 0x30 , 0x30 , 0x30 , 0x31 , 0x0A , 0x20 ,
0x20 , 0x20 , 0x20 , 0x20 , 0x00 , 0x00 , 0x00 , 0x10 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x01 , 0xD5 ,
0x02 , 0x03 , 0x04 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0xF7 ,
} ;
2014-09-02 09:36:27 +02:00
// EDID retrieval
NTSTATUS QxlDod : : QueryDeviceDescriptor ( _In_ ULONG ChildUid ,
_Inout_ DXGK_DEVICE_DESCRIPTOR * pDeviceDescriptor )
{
PAGED_CODE ( ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
QXL_ASSERT ( pDeviceDescriptor ! = NULL ) ;
QXL_ASSERT ( ChildUid < MAX_CHILDREN ) ;
2017-02-16 15:30:57 +01:00
if ( pDeviceDescriptor - > DescriptorOffset > = sizeof ( edid ) )
{
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s out of area \n " , __FUNCTION__ ) ) ;
return STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA ;
}
else
{
const VOID * src = edid + pDeviceDescriptor - > DescriptorOffset ;
ULONG len = sizeof ( edid ) - pDeviceDescriptor - > DescriptorOffset ;
len = min ( len , pDeviceDescriptor - > DescriptorLength ) ;
RtlMoveMemory ( pDeviceDescriptor - > DescriptorBuffer , src , len ) ;
pDeviceDescriptor - > DescriptorLength = len ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s (%d copied) \n " , __FUNCTION__ , len ) ) ;
return STATUS_SUCCESS ;
}
2014-09-02 09:36:27 +02:00
}
NTSTATUS QxlDod : : QueryAdapterInfo ( _In_ CONST DXGKARG_QUERYADAPTERINFO * pQueryAdapterInfo )
{
PAGED_CODE ( ) ;
QXL_ASSERT ( pQueryAdapterInfo ! = NULL ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
switch ( pQueryAdapterInfo - > Type )
{
case DXGKQAITYPE_DRIVERCAPS :
{
if ( ! pQueryAdapterInfo - > OutputDataSize /* < sizeof(DXGK_DRIVERCAPS)*/ )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " pQueryAdapterInfo->OutputDataSize (0x%u) is smaller than sizeof(DXGK_DRIVERCAPS) (0x%u) \n " , pQueryAdapterInfo - > OutputDataSize , sizeof ( DXGK_DRIVERCAPS ) ) ) ;
return STATUS_BUFFER_TOO_SMALL ;
}
DXGK_DRIVERCAPS * pDriverCaps = ( DXGK_DRIVERCAPS * ) pQueryAdapterInfo - > pOutputData ;
2014-09-07 13:12:24 +02:00
RtlZeroMemory ( pDriverCaps , pQueryAdapterInfo - > OutputDataSize /*sizeof(DXGK_DRIVERCAPS)*/ ) ;
2014-09-02 09:36:27 +02:00
pDriverCaps - > WDDMVersion = DXGKDDI_WDDMv1_2 ;
pDriverCaps - > HighestAcceptableAddress . QuadPart = - 1 ;
2016-11-18 14:49:56 +01:00
pDriverCaps - > MaxPointerWidth = POINTER_SIZE ;
pDriverCaps - > MaxPointerHeight = POINTER_SIZE ;
pDriverCaps - > PointerCaps . Monochrome = 1 ;
pDriverCaps - > PointerCaps . Color = 1 ;
2016-09-07 16:26:06 +02:00
2017-01-25 16:55:36 +01:00
pDriverCaps - > SupportNonVGA = m_pHWDevice - > IsBIOSCompatible ( ) ;
2017-02-16 15:31:01 +01:00
pDriverCaps - > SchedulingCaps . VSyncPowerSaveAware = g_bSupportVSync ;
2016-09-07 16:26:06 +02:00
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s 1 \n " , __FUNCTION__ ) ) ;
return STATUS_SUCCESS ;
}
default :
{
// BDD does not need to support any other adapter information types
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return STATUS_NOT_SUPPORTED ;
}
}
}
NTSTATUS QxlDod : : SetPointerPosition ( _In_ CONST DXGKARG_SETPOINTERPOSITION * pSetPointerPosition )
{
PAGED_CODE ( ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
QXL_ASSERT ( pSetPointerPosition ! = NULL ) ;
QXL_ASSERT ( pSetPointerPosition - > VidPnSourceId < MAX_VIEWS ) ;
return m_pHWDevice - > SetPointerPosition ( pSetPointerPosition ) ;
}
// Basic Sample Display Driver does not support hardware cursors, and reports such
// in QueryAdapterInfo. Therefore this function should never be called.
NTSTATUS QxlDod : : SetPointerShape ( _In_ CONST DXGKARG_SETPOINTERSHAPE * pSetPointerShape )
{
PAGED_CODE ( ) ;
QXL_ASSERT ( pSetPointerShape ! = NULL ) ;
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " <---> %s Height = %d, Width = %d, XHot= %d, YHot = %d SourceId = %d \n " ,
__FUNCTION__ , pSetPointerShape - > Height , pSetPointerShape - > Width , pSetPointerShape - > XHot , pSetPointerShape - > YHot , pSetPointerShape - > VidPnSourceId ) ) ;
return m_pHWDevice - > SetPointerShape ( pSetPointerShape ) ;
}
NTSTATUS QxlDod : : Escape ( _In_ CONST DXGKARG_ESCAPE * pEscape )
{
PAGED_CODE ( ) ;
2015-02-18 10:57:00 +01:00
NTSTATUS Status = STATUS_SUCCESS ;
2014-09-02 09:36:27 +02:00
QXL_ASSERT ( pEscape ! = NULL ) ;
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <---> %s Flags = %d \n " , __FUNCTION__ , pEscape - > Flags . Value ) ) ;
2014-09-02 09:36:27 +02:00
2015-02-18 10:57:00 +01:00
Status = m_pHWDevice - > Escape ( pEscape ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <---> %s Status = %x \n " , __FUNCTION__ , Status ) ) ;
return Status ;
2014-09-02 09:36:27 +02:00
}
NTSTATUS QxlDod : : PresentDisplayOnly ( _In_ CONST DXGKARG_PRESENT_DISPLAYONLY * pPresentDisplayOnly )
{
PAGED_CODE ( ) ;
NTSTATUS Status = STATUS_SUCCESS ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
QXL_ASSERT ( pPresentDisplayOnly ! = NULL ) ;
QXL_ASSERT ( pPresentDisplayOnly - > VidPnSourceId < MAX_VIEWS ) ;
if ( pPresentDisplayOnly - > BytesPerPixel < 4 )
{
// Only >=32bpp modes are reported, therefore this Present should never pass anything less than 4 bytes per pixel
DbgPrint ( TRACE_LEVEL_ERROR , ( " pPresentDisplayOnly->BytesPerPixel is 0x%d, which is lower than the allowed. \n " , pPresentDisplayOnly - > BytesPerPixel ) ) ;
return STATUS_INVALID_PARAMETER ;
}
// If it is in monitor off state or source is not supposed to be visible, don't present anything to the screen
if ( ( m_MonitorPowerState > PowerDeviceD0 ) | |
( m_CurrentModes [ pPresentDisplayOnly - > VidPnSourceId ] . Flags . SourceNotVisible ) )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return STATUS_SUCCESS ;
}
2016-09-26 15:00:08 +02:00
// If actual pixels are coming through, will need to completely zero out physical address next time in BlackOutScreen
m_CurrentModes [ pPresentDisplayOnly - > VidPnSourceId ] . ZeroedOutStart . QuadPart = 0 ;
m_CurrentModes [ pPresentDisplayOnly - > VidPnSourceId ] . ZeroedOutEnd . QuadPart = 0 ;
D3DKMDT_VIDPN_PRESENT_PATH_ROTATION RotationNeededByFb = pPresentDisplayOnly - > Flags . Rotate ?
m_CurrentModes [ pPresentDisplayOnly - > VidPnSourceId ] . Rotation :
D3DKMDT_VPPR_IDENTITY ;
BYTE * pDst = ( BYTE * ) m_CurrentModes [ pPresentDisplayOnly - > VidPnSourceId ] . FrameBuffer . Ptr ;
UINT DstBitPerPixel = BPPFromPixelFormat ( m_CurrentModes [ pPresentDisplayOnly - > VidPnSourceId ] . DispInfo . ColorFormat ) ;
if ( m_CurrentModes [ pPresentDisplayOnly - > VidPnSourceId ] . Scaling = = D3DKMDT_VPPS_CENTERED )
{
UINT CenterShift = ( m_CurrentModes [ pPresentDisplayOnly - > VidPnSourceId ] . DispInfo . Height -
m_CurrentModes [ pPresentDisplayOnly - > VidPnSourceId ] . SrcModeHeight ) * m_CurrentModes [ pPresentDisplayOnly - > VidPnSourceId ] . DispInfo . Pitch ;
CenterShift + = ( m_CurrentModes [ pPresentDisplayOnly - > VidPnSourceId ] . DispInfo . Width -
m_CurrentModes [ pPresentDisplayOnly - > VidPnSourceId ] . SrcModeWidth ) * DstBitPerPixel / 8 ;
pDst + = ( int ) CenterShift / 2 ;
}
Status = m_pHWDevice - > ExecutePresentDisplayOnly (
pDst ,
DstBitPerPixel ,
( BYTE * ) pPresentDisplayOnly - > pSource ,
pPresentDisplayOnly - > BytesPerPixel ,
pPresentDisplayOnly - > Pitch ,
pPresentDisplayOnly - > NumMoves ,
pPresentDisplayOnly - > pMoves ,
pPresentDisplayOnly - > NumDirtyRects ,
pPresentDisplayOnly - > pDirtyRect ,
RotationNeededByFb ,
& m_CurrentModes [ 0 ] ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return Status ;
}
NTSTATUS QxlDod : : QueryInterface ( _In_ CONST PQUERY_INTERFACE pQueryInterface )
{
PAGED_CODE ( ) ;
QXL_ASSERT ( pQueryInterface ! = NULL ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <---> %s Version = %d \n " , __FUNCTION__ , pQueryInterface - > Version ) ) ;
2015-03-24 06:41:58 +01:00
return STATUS_NOT_SUPPORTED ;
2014-09-02 09:36:27 +02:00
}
NTSTATUS QxlDod : : StopDeviceAndReleasePostDisplayOwnership ( _In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId ,
_Out_ DXGK_DISPLAY_INFORMATION * pDisplayInfo )
{
PAGED_CODE ( ) ;
UNREFERENCED_PARAMETER ( pDisplayInfo ) ;
QXL_ASSERT ( TargetId < MAX_CHILDREN ) ;
D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId = FindSourceForTarget ( TargetId , TRUE ) ;
// In case BDD is the next driver to run, the monitor should not be off, since
// this could cause the BIOS to hang when the EDID is retrieved on Start.
if ( m_MonitorPowerState > PowerDeviceD0 )
{
SetPowerState ( TargetId , PowerDeviceD0 , PowerActionNone ) ;
}
// The driver has to black out the display and ensure it is visible when releasing ownership
m_pHWDevice - > BlackOutScreen ( & m_CurrentModes [ SourceId ] ) ;
* pDisplayInfo = m_CurrentModes [ SourceId ] . DispInfo ;
return StopDevice ( ) ;
}
NTSTATUS QxlDod : : QueryVidPnHWCapability ( _Inout_ DXGKARG_QUERYVIDPNHWCAPABILITY * pVidPnHWCaps )
{
PAGED_CODE ( ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
QXL_ASSERT ( pVidPnHWCaps ! = NULL ) ;
QXL_ASSERT ( pVidPnHWCaps - > SourceId < MAX_VIEWS ) ;
QXL_ASSERT ( pVidPnHWCaps - > TargetId < MAX_CHILDREN ) ;
pVidPnHWCaps - > VidPnHWCaps . DriverRotation = 1 ; // BDD does rotation in software
pVidPnHWCaps - > VidPnHWCaps . DriverScaling = 0 ; // BDD does not support scaling
pVidPnHWCaps - > VidPnHWCaps . DriverCloning = 0 ; // BDD does not support clone
pVidPnHWCaps - > VidPnHWCaps . DriverColorConvert = 1 ; // BDD does color conversions in software
pVidPnHWCaps - > VidPnHWCaps . DriverLinkedAdapaterOutput = 0 ; // BDD does not support linked adapters
pVidPnHWCaps - > VidPnHWCaps . DriverRemoteDisplay = 0 ; // BDD does not support remote displays
2016-06-24 23:31:18 +02:00
pVidPnHWCaps - > VidPnHWCaps . Reserved = 0 ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return STATUS_SUCCESS ;
}
// TODO: Need to also check pinned modes and the path parameters, not just topology
NTSTATUS QxlDod : : IsSupportedVidPn ( _Inout_ DXGKARG_ISSUPPORTEDVIDPN * pIsSupportedVidPn )
{
PAGED_CODE ( ) ;
2016-09-11 15:05:21 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s %d \n " , __FUNCTION__ , m_pHWDevice - > GetId ( ) ) ) ;
2014-09-02 09:36:27 +02:00
QXL_ASSERT ( pIsSupportedVidPn ! = NULL ) ;
if ( pIsSupportedVidPn - > hDesiredVidPn = = 0 )
{
// A null desired VidPn is supported
pIsSupportedVidPn - > IsVidPnSupported = TRUE ;
return STATUS_SUCCESS ;
}
// Default to not supported, until shown it is supported
pIsSupportedVidPn - > IsVidPnSupported = FALSE ;
CONST DXGK_VIDPN_INTERFACE * pVidPnInterface ;
NTSTATUS Status = m_DxgkInterface . DxgkCbQueryVidPnInterface ( pIsSupportedVidPn - > hDesiredVidPn , DXGK_VIDPN_INTERFACE_VERSION_V1 , & pVidPnInterface ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " DxgkCbQueryVidPnInterface failed with Status = 0x%X, hDesiredVidPn = 0x%p \n " , Status , pIsSupportedVidPn - > hDesiredVidPn ) ) ;
2014-09-02 09:36:27 +02:00
return Status ;
}
D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology ;
CONST DXGK_VIDPNTOPOLOGY_INTERFACE * pVidPnTopologyInterface ;
Status = pVidPnInterface - > pfnGetTopology ( pIsSupportedVidPn - > hDesiredVidPn , & hVidPnTopology , & pVidPnTopologyInterface ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnGetTopology failed with Status = 0x%X, hDesiredVidPn = 0x%p \n " , Status , pIsSupportedVidPn - > hDesiredVidPn ) ) ;
2014-09-02 09:36:27 +02:00
return Status ;
}
// For every source in this topology, make sure they don't have more paths than there are targets
for ( D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId = 0 ; SourceId < MAX_VIEWS ; + + SourceId )
{
SIZE_T NumPathsFromSource = 0 ;
Status = pVidPnTopologyInterface - > pfnGetNumPathsFromSource ( hVidPnTopology , SourceId , & NumPathsFromSource ) ;
if ( Status = = STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY )
{
continue ;
}
else if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnGetNumPathsFromSource failed with Status = 0x%X hVidPnTopology = 0x%p, SourceId = 0x%x " ,
2014-09-02 09:36:27 +02:00
Status , hVidPnTopology , SourceId ) ) ;
return Status ;
}
else if ( NumPathsFromSource > MAX_CHILDREN )
{
// This VidPn is not supported, which has already been set as the default
return STATUS_SUCCESS ;
}
}
// All sources succeeded so this VidPn is supported
pIsSupportedVidPn - > IsVidPnSupported = TRUE ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return STATUS_SUCCESS ;
}
NTSTATUS QxlDod : : RecommendFunctionalVidPn ( _In_ CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN * CONST pRecommendFunctionalVidPn )
{
PAGED_CODE ( ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <---> %s \n " , __FUNCTION__ ) ) ;
QXL_ASSERT ( pRecommendFunctionalVidPn = = NULL ) ;
return STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN ;
}
NTSTATUS QxlDod : : RecommendVidPnTopology ( _In_ CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY * CONST pRecommendVidPnTopology )
{
PAGED_CODE ( ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <---> %s \n " , __FUNCTION__ ) ) ;
QXL_ASSERT ( pRecommendVidPnTopology = = NULL ) ;
return STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN ;
}
NTSTATUS QxlDod : : RecommendMonitorModes ( _In_ CONST DXGKARG_RECOMMENDMONITORMODES * CONST pRecommendMonitorModes )
{
PAGED_CODE ( ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
return AddSingleMonitorMode ( pRecommendMonitorModes ) ;
}
NTSTATUS QxlDod : : AddSingleSourceMode ( _In_ CONST DXGK_VIDPNSOURCEMODESET_INTERFACE * pVidPnSourceModeSetInterface ,
D3DKMDT_HVIDPNSOURCEMODESET hVidPnSourceModeSet ,
D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId )
{
PAGED_CODE ( ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
UNREFERENCED_PARAMETER ( SourceId ) ;
// There is only one source format supported by display-only drivers, but more can be added in a
// full WDDM driver if the hardware supports them
for ( ULONG idx = 0 ; idx < m_pHWDevice - > GetModeCount ( ) ; + + idx )
{
// Create new mode info that will be populated
D3DKMDT_VIDPN_SOURCE_MODE * pVidPnSourceModeInfo = NULL ;
PVIDEO_MODE_INFORMATION pModeInfo = m_pHWDevice - > GetModeInfo ( idx ) ;
NTSTATUS Status = pVidPnSourceModeSetInterface - > pfnCreateNewModeInfo ( hVidPnSourceModeSet , & pVidPnSourceModeInfo ) ;
if ( ! NT_SUCCESS ( Status ) )
{
// If failed to create a new mode info, mode doesn't need to be released since it was never created
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnCreateNewModeInfo failed with Status = 0x%X, hVidPnSourceModeSet = 0x%p " , Status , hVidPnSourceModeSet ) ) ;
2014-09-02 09:36:27 +02:00
return Status ;
}
// Populate mode info with values from current mode and hard-coded values
// Always report 32 bpp format, this will be color converted during the present if the mode is < 32bpp
pVidPnSourceModeInfo - > Type = D3DKMDT_RMT_GRAPHICS ;
pVidPnSourceModeInfo - > Format . Graphics . PrimSurfSize . cx = pModeInfo - > VisScreenWidth ;
pVidPnSourceModeInfo - > Format . Graphics . PrimSurfSize . cy = pModeInfo - > VisScreenHeight ;
pVidPnSourceModeInfo - > Format . Graphics . VisibleRegionSize = pVidPnSourceModeInfo - > Format . Graphics . PrimSurfSize ;
pVidPnSourceModeInfo - > Format . Graphics . Stride = pModeInfo - > ScreenStride ;
pVidPnSourceModeInfo - > Format . Graphics . PixelFormat = D3DDDIFMT_A8R8G8B8 ;
pVidPnSourceModeInfo - > Format . Graphics . ColorBasis = D3DKMDT_CB_SCRGB ;
pVidPnSourceModeInfo - > Format . Graphics . PixelValueAccessMode = D3DKMDT_PVAM_DIRECT ;
// Add the mode to the source mode set
Status = pVidPnSourceModeSetInterface - > pfnAddMode ( hVidPnSourceModeSet , pVidPnSourceModeInfo ) ;
if ( ! NT_SUCCESS ( Status ) )
{
// If adding the mode failed, release the mode, if this doesn't work there is nothing that can be done, some memory will get leaked
NTSTATUS TempStatus = pVidPnSourceModeSetInterface - > pfnReleaseModeInfo ( hVidPnSourceModeSet , pVidPnSourceModeInfo ) ;
UNREFERENCED_PARAMETER ( TempStatus ) ;
NT_ASSERT ( NT_SUCCESS ( TempStatus ) ) ;
if ( Status ! = STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnAddMode failed with Status = 0x%X, hVidPnSourceModeSet = 0x%p, pVidPnSourceModeInfo = %p " , Status , hVidPnSourceModeSet , pVidPnSourceModeInfo ) ) ;
2014-09-02 09:36:27 +02:00
return Status ;
}
}
}
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return STATUS_SUCCESS ;
}
2017-02-16 15:30:58 +01:00
static VOID FillSignalInfo ( D3DKMDT_VIDEO_SIGNAL_INFO & SignalInfo , const VIDEO_MODE_INFORMATION * pVideoModeInfo , LPCSTR caller )
{
PAGED_CODE ( ) ;
SignalInfo . VideoStandard = D3DKMDT_VSS_OTHER ;
SignalInfo . TotalSize . cx = pVideoModeInfo - > VisScreenWidth ;
SignalInfo . TotalSize . cy = pVideoModeInfo - > VisScreenHeight ;
SignalInfo . ActiveSize = SignalInfo . TotalSize ;
if ( g_bSupportVSync )
{
UINT val ;
SignalInfo . VSyncFreq . Numerator = VSYNC_RATE ;
SignalInfo . VSyncFreq . Denominator = 1 ;
val =
SignalInfo . VSyncFreq . Numerator *
pVideoModeInfo - > VisScreenWidth *
pVideoModeInfo - > VisScreenHeight ;
SignalInfo . PixelRate = val ;
SignalInfo . HSyncFreq . Numerator = val / pVideoModeInfo - > VisScreenHeight ;
SignalInfo . HSyncFreq . Denominator = 1 ;
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " by %s: filling with frequency data for %dx%d \n " , caller , pVideoModeInfo - > VisScreenWidth , pVideoModeInfo - > VisScreenHeight ) ) ;
}
else
{
SignalInfo . VSyncFreq . Numerator = D3DKMDT_FREQUENCY_NOTSPECIFIED ;
SignalInfo . VSyncFreq . Denominator = D3DKMDT_FREQUENCY_NOTSPECIFIED ;
SignalInfo . HSyncFreq . Numerator = D3DKMDT_FREQUENCY_NOTSPECIFIED ;
SignalInfo . HSyncFreq . Denominator = D3DKMDT_FREQUENCY_NOTSPECIFIED ;
SignalInfo . PixelRate = D3DKMDT_FREQUENCY_NOTSPECIFIED ;
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " by %s: filling without frequency data for %dx%d \n " , caller , pVideoModeInfo - > VisScreenWidth , pVideoModeInfo - > VisScreenHeight ) ) ;
}
SignalInfo . ScanLineOrdering = D3DDDI_VSSLO_PROGRESSIVE ;
}
2014-09-02 09:36:27 +02:00
// Add the current mode information (acquired from the POST frame buffer) as the target mode.
NTSTATUS QxlDod : : AddSingleTargetMode ( _In_ CONST DXGK_VIDPNTARGETMODESET_INTERFACE * pVidPnTargetModeSetInterface ,
D3DKMDT_HVIDPNTARGETMODESET hVidPnTargetModeSet ,
_In_opt_ CONST D3DKMDT_VIDPN_SOURCE_MODE * pVidPnPinnedSourceModeInfo ,
D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId )
{
PAGED_CODE ( ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
UNREFERENCED_PARAMETER ( pVidPnPinnedSourceModeInfo ) ;
D3DKMDT_VIDPN_TARGET_MODE * pVidPnTargetModeInfo = NULL ;
NTSTATUS Status = STATUS_SUCCESS ;
for ( UINT ModeIndex = 0 ; ModeIndex < m_pHWDevice - > GetModeCount ( ) ; + + ModeIndex )
{
PVIDEO_MODE_INFORMATION pModeInfo = m_pHWDevice - > GetModeInfo ( SourceId ) ;
pVidPnTargetModeInfo = NULL ;
Status = pVidPnTargetModeSetInterface - > pfnCreateNewModeInfo ( hVidPnTargetModeSet , & pVidPnTargetModeInfo ) ;
if ( ! NT_SUCCESS ( Status ) )
{
// If failed to create a new mode info, mode doesn't need to be released since it was never created
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnCreateNewModeInfo failed with Status = 0x%X, hVidPnTargetModeSet = 0x%p " , Status , hVidPnTargetModeSet ) ) ;
2014-09-02 09:36:27 +02:00
return Status ;
}
2017-02-16 15:30:58 +01:00
FillSignalInfo ( pVidPnTargetModeInfo - > VideoSignalInfo , pModeInfo , __FUNCTION__ ) ;
2014-09-02 09:36:27 +02:00
// We add this as PREFERRED since it is the only supported target
pVidPnTargetModeInfo - > Preference = D3DKMDT_MP_NOTPREFERRED ; // TODO: another logic for prefferred mode. Maybe the pinned source mode
Status = pVidPnTargetModeSetInterface - > pfnAddMode ( hVidPnTargetModeSet , pVidPnTargetModeInfo ) ;
if ( ! NT_SUCCESS ( Status ) )
{
if ( Status ! = STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnAddMode failed with Status = 0x%X, hVidPnTargetModeSet = 0x%p, pVidPnTargetModeInfo = %p " , Status , hVidPnTargetModeSet , pVidPnTargetModeInfo ) ) ;
2014-09-02 09:36:27 +02:00
}
// If adding the mode failed, release the mode, if this doesn't work there is nothing that can be done, some memory will get leaked
Status = pVidPnTargetModeSetInterface - > pfnReleaseModeInfo ( hVidPnTargetModeSet , pVidPnTargetModeInfo ) ;
NT_ASSERT ( NT_SUCCESS ( Status ) ) ;
}
}
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return STATUS_SUCCESS ;
}
NTSTATUS QxlDod : : AddSingleMonitorMode ( _In_ CONST DXGKARG_RECOMMENDMONITORMODES * CONST pRecommendMonitorModes )
{
PAGED_CODE ( ) ;
NTSTATUS Status = STATUS_SUCCESS ;
D3DKMDT_MONITOR_SOURCE_MODE * pMonitorSourceMode = NULL ;
PVIDEO_MODE_INFORMATION pVbeModeInfo = NULL ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
Status = pRecommendMonitorModes - > pMonitorSourceModeSetInterface - > pfnCreateNewModeInfo ( pRecommendMonitorModes - > hMonitorSourceModeSet , & pMonitorSourceMode ) ;
if ( ! NT_SUCCESS ( Status ) )
{
// If failed to create a new mode info, mode doesn't need to be released since it was never created
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnCreateNewModeInfo failed with Status = 0x%X, hMonitorSourceModeSet = 0x%p " , Status , pRecommendMonitorModes - > hMonitorSourceModeSet ) ) ;
2014-09-02 09:36:27 +02:00
return Status ;
}
pVbeModeInfo = m_pHWDevice - > GetModeInfo ( m_pHWDevice - > GetCurrentModeIndex ( ) ) ;
// Since we don't know the real monitor timing information, just use the current display mode (from the POST device) with unknown frequencies
2017-02-16 15:30:58 +01:00
FillSignalInfo ( pMonitorSourceMode - > VideoSignalInfo , pVbeModeInfo , __FUNCTION__ ) ;
2014-09-02 09:36:27 +02:00
// We set the preference to PREFERRED since this is the only supported mode
pMonitorSourceMode - > Origin = D3DKMDT_MCO_DRIVER ;
pMonitorSourceMode - > Preference = D3DKMDT_MP_PREFERRED ;
pMonitorSourceMode - > ColorBasis = D3DKMDT_CB_SRGB ;
pMonitorSourceMode - > ColorCoeffDynamicRanges . FirstChannel = 8 ;
pMonitorSourceMode - > ColorCoeffDynamicRanges . SecondChannel = 8 ;
pMonitorSourceMode - > ColorCoeffDynamicRanges . ThirdChannel = 8 ;
pMonitorSourceMode - > ColorCoeffDynamicRanges . FourthChannel = 8 ;
Status = pRecommendMonitorModes - > pMonitorSourceModeSetInterface - > pfnAddMode ( pRecommendMonitorModes - > hMonitorSourceModeSet , pMonitorSourceMode ) ;
if ( ! NT_SUCCESS ( Status ) )
{
if ( Status ! = STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnAddMode failed with Status = 0x%X, hMonitorSourceModeSet = 0x%p, pMonitorSourceMode = 0x%p " ,
2014-09-02 09:36:27 +02:00
Status , pRecommendMonitorModes - > hMonitorSourceModeSet , pMonitorSourceMode ) ) ;
}
else
{
Status = STATUS_SUCCESS ;
}
// If adding the mode failed, release the mode, if this doesn't work there is nothing that can be done, some memory will get leaked
NTSTATUS TempStatus = pRecommendMonitorModes - > pMonitorSourceModeSetInterface - > pfnReleaseModeInfo ( pRecommendMonitorModes - > hMonitorSourceModeSet , pMonitorSourceMode ) ;
UNREFERENCED_PARAMETER ( TempStatus ) ;
NT_ASSERT ( NT_SUCCESS ( TempStatus ) ) ;
return Status ;
}
// If AddMode succeeded with something other than STATUS_SUCCESS treat it as such anyway when propagating up
for ( UINT Idx = 0 ; Idx < m_pHWDevice - > GetModeCount ( ) ; + + Idx )
{
// There is only one source format supported by display-only drivers, but more can be added in a
// full WDDM driver if the hardware supports them
pVbeModeInfo = m_pHWDevice - > GetModeInfo ( Idx ) ;
// TODO: add routine for filling Monitor modepMonitorSourceMode = NULL;
Status = pRecommendMonitorModes - > pMonitorSourceModeSetInterface - > pfnCreateNewModeInfo ( pRecommendMonitorModes - > hMonitorSourceModeSet , & pMonitorSourceMode ) ;
if ( ! NT_SUCCESS ( Status ) )
{
// If failed to create a new mode info, mode doesn't need to be released since it was never created
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnCreateNewModeInfo failed with Status = 0x%X, hMonitorSourceModeSet = 0x%p " , Status , pRecommendMonitorModes - > hMonitorSourceModeSet ) ) ;
2014-09-02 09:36:27 +02:00
return Status ;
}
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " %s: add pref mode, dimensions %ux%u, taken from DxgkCbAcquirePostDisplayOwnership at StartDevice \n " , __FUNCTION__ ,
pVbeModeInfo - > VisScreenWidth , pVbeModeInfo - > VisScreenHeight ) ) ;
// Since we don't know the real monitor timing information, just use the current display mode (from the POST device) with unknown frequencies
2017-02-16 15:30:58 +01:00
FillSignalInfo ( pMonitorSourceMode - > VideoSignalInfo , pVbeModeInfo , __FUNCTION__ ) ;
2014-09-02 09:36:27 +02:00
2015-03-24 07:22:45 +01:00
pMonitorSourceMode - > Origin = D3DKMDT_MCO_DRIVER ;
pMonitorSourceMode - > Preference = D3DKMDT_MP_NOTPREFERRED ;
pMonitorSourceMode - > ColorBasis = D3DKMDT_CB_SRGB ;
2014-09-02 09:36:27 +02:00
pMonitorSourceMode - > ColorCoeffDynamicRanges . FirstChannel = 8 ;
pMonitorSourceMode - > ColorCoeffDynamicRanges . SecondChannel = 8 ;
pMonitorSourceMode - > ColorCoeffDynamicRanges . ThirdChannel = 8 ;
pMonitorSourceMode - > ColorCoeffDynamicRanges . FourthChannel = 8 ;
Status = pRecommendMonitorModes - > pMonitorSourceModeSetInterface - > pfnAddMode ( pRecommendMonitorModes - > hMonitorSourceModeSet , pMonitorSourceMode ) ;
if ( ! NT_SUCCESS ( Status ) )
{
if ( Status ! = STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnAddMode failed with Status = 0x%X, hMonitorSourceModeSet = 0x%p, pMonitorSourceMode = 0x%p " ,
2014-09-02 09:36:27 +02:00
Status , pRecommendMonitorModes - > hMonitorSourceModeSet , pMonitorSourceMode ) ) ;
}
// If adding the mode failed, release the mode, if this doesn't work there is nothing that can be done, some memory will get leaked
Status = pRecommendMonitorModes - > pMonitorSourceModeSetInterface - > pfnReleaseModeInfo ( pRecommendMonitorModes - > hMonitorSourceModeSet , pMonitorSourceMode ) ;
NT_ASSERT ( NT_SUCCESS ( Status ) ) ;
}
}
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return Status ;
}
// Tell DMM about all the modes, etc. that are supported
NTSTATUS QxlDod : : EnumVidPnCofuncModality ( _In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY * CONST pEnumCofuncModality )
{
PAGED_CODE ( ) ;
QXL_ASSERT ( pEnumCofuncModality ! = NULL ) ;
2016-09-11 15:05:21 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s device %d \n " , __FUNCTION__ , m_pHWDevice - > GetId ( ) ) ) ;
2014-09-02 09:36:27 +02:00
D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology = 0 ;
D3DKMDT_HVIDPNSOURCEMODESET hVidPnSourceModeSet = 0 ;
D3DKMDT_HVIDPNTARGETMODESET hVidPnTargetModeSet = 0 ;
CONST DXGK_VIDPN_INTERFACE * pVidPnInterface = NULL ;
CONST DXGK_VIDPNTOPOLOGY_INTERFACE * pVidPnTopologyInterface = NULL ;
CONST DXGK_VIDPNSOURCEMODESET_INTERFACE * pVidPnSourceModeSetInterface = NULL ;
CONST DXGK_VIDPNTARGETMODESET_INTERFACE * pVidPnTargetModeSetInterface = NULL ;
CONST D3DKMDT_VIDPN_PRESENT_PATH * pVidPnPresentPath = NULL ;
2015-03-24 07:22:45 +01:00
CONST D3DKMDT_VIDPN_PRESENT_PATH * pVidPnPresentPathTemp = NULL ;
2014-09-02 09:36:27 +02:00
CONST D3DKMDT_VIDPN_SOURCE_MODE * pVidPnPinnedSourceModeInfo = NULL ;
CONST D3DKMDT_VIDPN_TARGET_MODE * pVidPnPinnedTargetModeInfo = NULL ;
// Get the VidPn Interface so we can get the 'Source Mode Set', 'Target Mode Set' and 'VidPn Topology' interfaces
NTSTATUS Status = m_DxgkInterface . DxgkCbQueryVidPnInterface ( pEnumCofuncModality - > hConstrainingVidPn , DXGK_VIDPN_INTERFACE_VERSION_V1 , & pVidPnInterface ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " DxgkCbQueryVidPnInterface failed with Status = 0x%X, hFunctionalVidPn = 0x%p " , Status , pEnumCofuncModality - > hConstrainingVidPn ) ) ;
2014-09-02 09:36:27 +02:00
return Status ;
}
// Get the VidPn Topology interface so we can enumerate all paths
Status = pVidPnInterface - > pfnGetTopology ( pEnumCofuncModality - > hConstrainingVidPn , & hVidPnTopology , & pVidPnTopologyInterface ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnGetTopology failed with Status = 0x%X, hFunctionalVidPn = 0x%p " , Status , pEnumCofuncModality - > hConstrainingVidPn ) ) ;
2014-09-02 09:36:27 +02:00
return Status ;
}
// Get the first path before we start looping through them
Status = pVidPnTopologyInterface - > pfnAcquireFirstPathInfo ( hVidPnTopology , & pVidPnPresentPath ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnAcquireFirstPathInfo failed with Status =0x%X, hVidPnTopology = 0x%p " , Status , hVidPnTopology ) ) ;
2014-09-02 09:36:27 +02:00
return Status ;
}
// Loop through all available paths.
while ( Status ! = STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET )
{
// Get the Source Mode Set interface so the pinned mode can be retrieved
Status = pVidPnInterface - > pfnAcquireSourceModeSet ( pEnumCofuncModality - > hConstrainingVidPn ,
pVidPnPresentPath - > VidPnSourceId ,
& hVidPnSourceModeSet ,
& pVidPnSourceModeSetInterface ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnAcquireSourceModeSet failed with Status = 0x%X, hConstrainingVidPn = 0x%p, SourceId = 0x%x " ,
2014-09-02 09:36:27 +02:00
Status , pEnumCofuncModality - > hConstrainingVidPn , pVidPnPresentPath - > VidPnSourceId ) ) ;
break ;
}
// Get the pinned mode, needed when VidPnSource isn't pivot, and when VidPnTarget isn't pivot
Status = pVidPnSourceModeSetInterface - > pfnAcquirePinnedModeInfo ( hVidPnSourceModeSet , & pVidPnPinnedSourceModeInfo ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnAcquirePinnedModeInfo failed with Status = 0x%X, hVidPnSourceModeSet = 0x%p " , Status , hVidPnSourceModeSet ) ) ;
2014-09-02 09:36:27 +02:00
break ;
}
// SOURCE MODES: If this source mode isn't the pivot point, do work on the source mode set
if ( ! ( ( pEnumCofuncModality - > EnumPivotType = = D3DKMDT_EPT_VIDPNSOURCE ) & &
( pEnumCofuncModality - > EnumPivot . VidPnSourceId = = pVidPnPresentPath - > VidPnSourceId ) ) )
{
// If there's no pinned source add possible modes (otherwise they've already been added)
if ( pVidPnPinnedSourceModeInfo = = NULL )
{
// Release the acquired source mode set, since going to create a new one to put all modes in
Status = pVidPnInterface - > pfnReleaseSourceModeSet ( pEnumCofuncModality - > hConstrainingVidPn , hVidPnSourceModeSet ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnReleaseSourceModeSet failed with Status = 0x%X, hConstrainingVidPn = 0x%p, hVidPnSourceModeSet = 0x%p " ,
2014-09-02 09:36:27 +02:00
Status , pEnumCofuncModality - > hConstrainingVidPn , hVidPnSourceModeSet ) ) ;
break ;
}
hVidPnSourceModeSet = 0 ; // Successfully released it
// Create a new source mode set which will be added to the constraining VidPn with all the possible modes
Status = pVidPnInterface - > pfnCreateNewSourceModeSet ( pEnumCofuncModality - > hConstrainingVidPn ,
pVidPnPresentPath - > VidPnSourceId ,
& hVidPnSourceModeSet ,
& pVidPnSourceModeSetInterface ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnCreateNewSourceModeSet failed with Status = 0x%X, hConstrainingVidPn = 0x%p, SourceId = 0x%x " ,
2014-09-02 09:36:27 +02:00
Status , pEnumCofuncModality - > hConstrainingVidPn , pVidPnPresentPath - > VidPnSourceId ) ) ;
break ;
}
// Add the appropriate modes to the source mode set
{
Status = AddSingleSourceMode ( pVidPnSourceModeSetInterface , hVidPnSourceModeSet , pVidPnPresentPath - > VidPnSourceId ) ;
}
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " AddSingleSourceMode failed with Status = 0x%X, hFunctionalVidPn = 0x%p " , Status , pEnumCofuncModality - > hConstrainingVidPn ) ) ;
2014-09-02 09:36:27 +02:00
break ;
}
// Give DMM back the source modes just populated
Status = pVidPnInterface - > pfnAssignSourceModeSet ( pEnumCofuncModality - > hConstrainingVidPn , pVidPnPresentPath - > VidPnSourceId , hVidPnSourceModeSet ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnAssignSourceModeSet failed with Status = 0x%X, hConstrainingVidPn = 0x%p, SourceId = 0x%x, hVidPnSourceModeSet = 0x%p " ,
2014-09-02 09:36:27 +02:00
Status , pEnumCofuncModality - > hConstrainingVidPn , pVidPnPresentPath - > VidPnSourceId , hVidPnSourceModeSet ) ) ;
break ;
}
hVidPnSourceModeSet = 0 ; // Successfully assigned it (equivalent to releasing it)
}
} // End: SOURCE MODES
// TARGET MODES: If this target mode isn't the pivot point, do work on the target mode set
if ( ! ( ( pEnumCofuncModality - > EnumPivotType = = D3DKMDT_EPT_VIDPNTARGET ) & &
( pEnumCofuncModality - > EnumPivot . VidPnTargetId = = pVidPnPresentPath - > VidPnTargetId ) ) )
{
// Get the Target Mode Set interface so modes can be added if necessary
Status = pVidPnInterface - > pfnAcquireTargetModeSet ( pEnumCofuncModality - > hConstrainingVidPn ,
pVidPnPresentPath - > VidPnTargetId ,
& hVidPnTargetModeSet ,
& pVidPnTargetModeSetInterface ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnAcquireTargetModeSet failed with Status = 0x%X, hConstrainingVidPn = 0x%p, TargetId = 0x%x " ,
2014-09-02 09:36:27 +02:00
Status , pEnumCofuncModality - > hConstrainingVidPn , pVidPnPresentPath - > VidPnTargetId ) ) ;
break ;
}
Status = pVidPnTargetModeSetInterface - > pfnAcquirePinnedModeInfo ( hVidPnTargetModeSet , & pVidPnPinnedTargetModeInfo ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnAcquirePinnedModeInfo failed with Status = 0x%X, hVidPnTargetModeSet = 0x%p " , Status , hVidPnTargetModeSet ) ) ;
2014-09-02 09:36:27 +02:00
break ;
}
// If there's no pinned target add possible modes (otherwise they've already been added)
if ( pVidPnPinnedTargetModeInfo = = NULL )
{
// Release the acquired target mode set, since going to create a new one to put all modes in
Status = pVidPnInterface - > pfnReleaseTargetModeSet ( pEnumCofuncModality - > hConstrainingVidPn , hVidPnTargetModeSet ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnReleaseTargetModeSet failed with Status = 0x%X, hConstrainingVidPn = 0x%p, hVidPnTargetModeSet = 0x%p " ,
2014-09-02 09:36:27 +02:00
Status , pEnumCofuncModality - > hConstrainingVidPn , hVidPnTargetModeSet ) ) ;
break ;
}
hVidPnTargetModeSet = 0 ; // Successfully released it
// Create a new target mode set which will be added to the constraining VidPn with all the possible modes
Status = pVidPnInterface - > pfnCreateNewTargetModeSet ( pEnumCofuncModality - > hConstrainingVidPn ,
pVidPnPresentPath - > VidPnTargetId ,
& hVidPnTargetModeSet ,
& pVidPnTargetModeSetInterface ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnCreateNewTargetModeSet failed with Status = 0x%X, hConstrainingVidPn = 0x%p, TargetId = 0x%x " ,
2014-09-02 09:36:27 +02:00
Status , pEnumCofuncModality - > hConstrainingVidPn , pVidPnPresentPath - > VidPnTargetId ) ) ;
break ;
}
Status = AddSingleTargetMode ( pVidPnTargetModeSetInterface , hVidPnTargetModeSet , pVidPnPinnedSourceModeInfo , pVidPnPresentPath - > VidPnSourceId ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " AddSingleTargetMode failed with Status = 0x%X, hFunctionalVidPn = 0x%p " , Status , pEnumCofuncModality - > hConstrainingVidPn ) ) ;
2014-09-02 09:36:27 +02:00
break ;
}
// Give DMM back the source modes just populated
Status = pVidPnInterface - > pfnAssignTargetModeSet ( pEnumCofuncModality - > hConstrainingVidPn , pVidPnPresentPath - > VidPnTargetId , hVidPnTargetModeSet ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnAssignTargetModeSet failed with Status = 0x%X, hConstrainingVidPn = 0x%p, TargetId = 0x%x, hVidPnTargetModeSet = 0x%p " ,
2014-09-02 09:36:27 +02:00
Status , pEnumCofuncModality - > hConstrainingVidPn , pVidPnPresentPath - > VidPnTargetId , hVidPnTargetModeSet ) ) ;
break ;
}
hVidPnTargetModeSet = 0 ; // Successfully assigned it (equivalent to releasing it)
}
else
{
// Release the pinned target as there's no other work to do
Status = pVidPnTargetModeSetInterface - > pfnReleaseModeInfo ( hVidPnTargetModeSet , pVidPnPinnedTargetModeInfo ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnReleaseModeInfo failed with Status = 0x%X, hVidPnTargetModeSet = 0x%p, pVidPnPinnedTargetModeInfo = %p " ,
2014-09-02 09:36:27 +02:00
Status , hVidPnTargetModeSet , pVidPnPinnedTargetModeInfo ) ) ;
break ;
}
pVidPnPinnedTargetModeInfo = NULL ; // Successfully released it
// Release the acquired target mode set, since it is no longer needed
Status = pVidPnInterface - > pfnReleaseTargetModeSet ( pEnumCofuncModality - > hConstrainingVidPn , hVidPnTargetModeSet ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnReleaseTargetModeSet failed with Status = 0x%X, hConstrainingVidPn = 0x%p, hVidPnTargetModeSet = 0x%p " ,
2014-09-02 09:36:27 +02:00
Status , pEnumCofuncModality - > hConstrainingVidPn , hVidPnTargetModeSet ) ) ;
break ;
}
hVidPnTargetModeSet = 0 ; // Successfully released it
}
} // End: TARGET MODES
// Nothing else needs the pinned source mode so release it
if ( pVidPnPinnedSourceModeInfo ! = NULL )
{
Status = pVidPnSourceModeSetInterface - > pfnReleaseModeInfo ( hVidPnSourceModeSet , pVidPnPinnedSourceModeInfo ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnReleaseModeInfo failed with Status = 0x%X, hVidPnSourceModeSet = 0x%p, pVidPnPinnedSourceModeInfo = %p " ,
2014-09-02 09:36:27 +02:00
Status , hVidPnSourceModeSet , pVidPnPinnedSourceModeInfo ) ) ;
break ;
}
pVidPnPinnedSourceModeInfo = NULL ; // Successfully released it
}
// With the pinned source mode now released, if the source mode set hasn't been released, release that as well
if ( hVidPnSourceModeSet ! = 0 )
{
Status = pVidPnInterface - > pfnReleaseSourceModeSet ( pEnumCofuncModality - > hConstrainingVidPn , hVidPnSourceModeSet ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnReleaseSourceModeSet failed with Status = 0x%X, hConstrainingVidPn = 0x%p, hVidPnSourceModeSet = 0x%p " ,
2014-09-02 09:36:27 +02:00
Status , pEnumCofuncModality - > hConstrainingVidPn , hVidPnSourceModeSet ) ) ;
break ;
}
hVidPnSourceModeSet = 0 ; // Successfully released it
}
// If modifying support fields, need to modify a local version of a path structure since the retrieved one is const
D3DKMDT_VIDPN_PRESENT_PATH LocalVidPnPresentPath = * pVidPnPresentPath ;
BOOLEAN SupportFieldsModified = FALSE ;
// SCALING: If this path's scaling isn't the pivot point, do work on the scaling support
if ( ! ( ( pEnumCofuncModality - > EnumPivotType = = D3DKMDT_EPT_SCALING ) & &
( pEnumCofuncModality - > EnumPivot . VidPnSourceId = = pVidPnPresentPath - > VidPnSourceId ) & &
( pEnumCofuncModality - > EnumPivot . VidPnTargetId = = pVidPnPresentPath - > VidPnTargetId ) ) )
{
// If the scaling is unpinned, then modify the scaling support field
if ( pVidPnPresentPath - > ContentTransformation . Scaling = = D3DKMDT_VPPS_UNPINNED )
{
// Identity and centered scaling are supported, but not any stretch modes
RtlZeroMemory ( & ( LocalVidPnPresentPath . ContentTransformation . ScalingSupport ) , sizeof ( D3DKMDT_VIDPN_PRESENT_PATH_SCALING_SUPPORT ) ) ;
LocalVidPnPresentPath . ContentTransformation . ScalingSupport . Identity = 1 ;
LocalVidPnPresentPath . ContentTransformation . ScalingSupport . Centered = 1 ;
SupportFieldsModified = TRUE ;
}
} // End: SCALING
// ROTATION: If this path's rotation isn't the pivot point, do work on the rotation support
if ( ! ( ( pEnumCofuncModality - > EnumPivotType ! = D3DKMDT_EPT_ROTATION ) & &
( pEnumCofuncModality - > EnumPivot . VidPnSourceId = = pVidPnPresentPath - > VidPnSourceId ) & &
( pEnumCofuncModality - > EnumPivot . VidPnTargetId = = pVidPnPresentPath - > VidPnTargetId ) ) )
{
// If the rotation is unpinned, then modify the rotation support field
if ( pVidPnPresentPath - > ContentTransformation . Rotation = = D3DKMDT_VPPR_UNPINNED )
{
LocalVidPnPresentPath . ContentTransformation . RotationSupport . Identity = 1 ;
// Sample supports only Rotate90
LocalVidPnPresentPath . ContentTransformation . RotationSupport . Rotate90 = 1 ;
LocalVidPnPresentPath . ContentTransformation . RotationSupport . Rotate180 = 0 ;
LocalVidPnPresentPath . ContentTransformation . RotationSupport . Rotate270 = 0 ;
SupportFieldsModified = TRUE ;
}
} // End: ROTATION
if ( SupportFieldsModified )
{
// The correct path will be found by this function and the appropriate fields updated
Status = pVidPnTopologyInterface - > pfnUpdatePathSupportInfo ( hVidPnTopology , & LocalVidPnPresentPath ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnUpdatePathSupportInfo failed with Status = 0x%X, hVidPnTopology = 0x%p " , Status , hVidPnTopology ) ) ;
2014-09-02 09:36:27 +02:00
break ;
}
}
// Get the next path...
// (NOTE: This is the value of Status that will return STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET when it's time to quit the loop)
pVidPnPresentPathTemp = pVidPnPresentPath ;
Status = pVidPnTopologyInterface - > pfnAcquireNextPathInfo ( hVidPnTopology , pVidPnPresentPathTemp , & pVidPnPresentPath ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnAcquireNextPathInfo failed with Status = 0x%X, hVidPnTopology = 0x%p, pVidPnPresentPathTemp = %p " , Status , hVidPnTopology , pVidPnPresentPathTemp ) ) ;
2014-09-02 09:36:27 +02:00
break ;
}
// ...and release the last path
NTSTATUS TempStatus = pVidPnTopologyInterface - > pfnReleasePathInfo ( hVidPnTopology , pVidPnPresentPathTemp ) ;
if ( ! NT_SUCCESS ( TempStatus ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnReleasePathInfo failed with Status = 0x%X, hVidPnTopology = 0x%p, pVidPnPresentPathTemp = %p " , TempStatus , hVidPnTopology , pVidPnPresentPathTemp ) ) ;
2014-09-02 09:36:27 +02:00
Status = TempStatus ;
break ;
}
pVidPnPresentPathTemp = NULL ; // Successfully released it
} // End: while loop for paths in topology
// If quit the while loop normally, set the return value to success
if ( Status = = STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET )
{
Status = STATUS_SUCCESS ;
}
// Release any resources hanging around because the loop was quit early.
// Since in normal execution everything should be released by this point, TempStatus is initialized to a bogus error to be used as an
// assertion that if anything had to be released now (TempStatus changing) Status isn't successful.
NTSTATUS TempStatus = STATUS_NOT_FOUND ;
if ( ( pVidPnSourceModeSetInterface ! = NULL ) & &
( pVidPnPinnedSourceModeInfo ! = NULL ) )
{
TempStatus = pVidPnSourceModeSetInterface - > pfnReleaseModeInfo ( hVidPnSourceModeSet , pVidPnPinnedSourceModeInfo ) ;
QXL_ASSERT_CHK ( NT_SUCCESS ( TempStatus ) ) ;
}
if ( ( pVidPnTargetModeSetInterface ! = NULL ) & &
( pVidPnPinnedTargetModeInfo ! = NULL ) )
{
TempStatus = pVidPnTargetModeSetInterface - > pfnReleaseModeInfo ( hVidPnTargetModeSet , pVidPnPinnedTargetModeInfo ) ;
QXL_ASSERT_CHK ( NT_SUCCESS ( TempStatus ) ) ;
}
if ( pVidPnPresentPath ! = NULL )
{
TempStatus = pVidPnTopologyInterface - > pfnReleasePathInfo ( hVidPnTopology , pVidPnPresentPath ) ;
QXL_ASSERT_CHK ( NT_SUCCESS ( TempStatus ) ) ;
}
if ( pVidPnPresentPathTemp ! = NULL )
{
TempStatus = pVidPnTopologyInterface - > pfnReleasePathInfo ( hVidPnTopology , pVidPnPresentPathTemp ) ;
QXL_ASSERT_CHK ( NT_SUCCESS ( TempStatus ) ) ;
}
if ( hVidPnSourceModeSet ! = 0 )
{
TempStatus = pVidPnInterface - > pfnReleaseSourceModeSet ( pEnumCofuncModality - > hConstrainingVidPn , hVidPnSourceModeSet ) ;
QXL_ASSERT_CHK ( NT_SUCCESS ( TempStatus ) ) ;
}
if ( hVidPnTargetModeSet ! = 0 )
{
TempStatus = pVidPnInterface - > pfnReleaseTargetModeSet ( pEnumCofuncModality - > hConstrainingVidPn , hVidPnTargetModeSet ) ;
QXL_ASSERT_CHK ( NT_SUCCESS ( TempStatus ) ) ;
}
QXL_ASSERT_CHK ( TempStatus = = STATUS_NOT_FOUND | | Status ! = STATUS_SUCCESS ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return Status ;
}
NTSTATUS QxlDod : : SetVidPnSourceVisibility ( _In_ CONST DXGKARG_SETVIDPNSOURCEVISIBILITY * pSetVidPnSourceVisibility )
{
PAGED_CODE ( ) ;
2016-09-11 15:05:21 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s %d \n " , __FUNCTION__ , m_pHWDevice - > GetId ( ) ) ) ;
2014-09-02 09:36:27 +02:00
QXL_ASSERT ( pSetVidPnSourceVisibility ! = NULL ) ;
QXL_ASSERT ( ( pSetVidPnSourceVisibility - > VidPnSourceId < MAX_VIEWS ) | |
( pSetVidPnSourceVisibility - > VidPnSourceId = = D3DDDI_ID_ALL ) ) ;
UINT StartVidPnSourceId = ( pSetVidPnSourceVisibility - > VidPnSourceId = = D3DDDI_ID_ALL ) ? 0 : pSetVidPnSourceVisibility - > VidPnSourceId ;
UINT MaxVidPnSourceId = ( pSetVidPnSourceVisibility - > VidPnSourceId = = D3DDDI_ID_ALL ) ? MAX_VIEWS : pSetVidPnSourceVisibility - > VidPnSourceId + 1 ;
for ( UINT SourceId = StartVidPnSourceId ; SourceId < MaxVidPnSourceId ; + + SourceId )
{
if ( pSetVidPnSourceVisibility - > Visible )
{
m_CurrentModes [ SourceId ] . Flags . FullscreenPresent = TRUE ;
}
else
{
m_pHWDevice - > BlackOutScreen ( & m_CurrentModes [ SourceId ] ) ;
}
// Store current visibility so it can be dealt with during Present call
m_CurrentModes [ SourceId ] . Flags . SourceNotVisible = ! ( pSetVidPnSourceVisibility - > Visible ) ;
}
2015-03-24 07:22:45 +01:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
2014-09-02 09:36:27 +02:00
return STATUS_SUCCESS ;
}
// NOTE: The value of pCommitVidPn->MonitorConnectivityChecks is ignored, since BDD is unable to recognize whether a monitor is connected or not
// The value of pCommitVidPn->hPrimaryAllocation is also ignored, since BDD is a display only driver and does not deal with allocations
NTSTATUS QxlDod : : CommitVidPn ( _In_ CONST DXGKARG_COMMITVIDPN * CONST pCommitVidPn )
{
PAGED_CODE ( ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
QXL_ASSERT ( pCommitVidPn ! = NULL ) ;
QXL_ASSERT ( pCommitVidPn - > AffectedVidPnSourceId < MAX_VIEWS ) ;
NTSTATUS Status ;
SIZE_T NumPaths = 0 ;
D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology = 0 ;
D3DKMDT_HVIDPNSOURCEMODESET hVidPnSourceModeSet = 0 ;
CONST DXGK_VIDPN_INTERFACE * pVidPnInterface = NULL ;
CONST DXGK_VIDPNTOPOLOGY_INTERFACE * pVidPnTopologyInterface = NULL ;
CONST DXGK_VIDPNSOURCEMODESET_INTERFACE * pVidPnSourceModeSetInterface = NULL ;
CONST D3DKMDT_VIDPN_PRESENT_PATH * pVidPnPresentPath = NULL ;
CONST D3DKMDT_VIDPN_SOURCE_MODE * pPinnedVidPnSourceModeInfo = NULL ;
// Check this CommitVidPn is for the mode change notification when monitor is in power off state.
if ( pCommitVidPn - > Flags . PathPoweredOff )
{
// Ignore the commitVidPn call for the mode change notification when monitor is in power off state.
Status = STATUS_SUCCESS ;
goto CommitVidPnExit ;
}
// Get the VidPn Interface so we can get the 'Source Mode Set' and 'VidPn Topology' interfaces
Status = m_DxgkInterface . DxgkCbQueryVidPnInterface ( pCommitVidPn - > hFunctionalVidPn , DXGK_VIDPN_INTERFACE_VERSION_V1 , & pVidPnInterface ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " DxgkCbQueryVidPnInterface failed with Status = 0x%X, hFunctionalVidPn = 0x%p " , Status , pCommitVidPn - > hFunctionalVidPn ) ) ;
2014-09-02 09:36:27 +02:00
goto CommitVidPnExit ;
}
// Get the VidPn Topology interface so can enumerate paths from source
Status = pVidPnInterface - > pfnGetTopology ( pCommitVidPn - > hFunctionalVidPn , & hVidPnTopology , & pVidPnTopologyInterface ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnGetTopology failed with Status = 0x%X, hFunctionalVidPn = 0x%p " , Status , pCommitVidPn - > hFunctionalVidPn ) ) ;
2014-09-02 09:36:27 +02:00
goto CommitVidPnExit ;
}
// Find out the number of paths now, if it's 0 don't bother with source mode set and pinned mode, just clear current and then quit
Status = pVidPnTopologyInterface - > pfnGetNumPaths ( hVidPnTopology , & NumPaths ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnGetNumPaths failed with Status = 0x%X, hVidPnTopology = 0x%p " , Status , hVidPnTopology ) ) ;
2014-09-02 09:36:27 +02:00
goto CommitVidPnExit ;
}
if ( NumPaths ! = 0 )
{
// Get the Source Mode Set interface so we can get the pinned mode
Status = pVidPnInterface - > pfnAcquireSourceModeSet ( pCommitVidPn - > hFunctionalVidPn ,
pCommitVidPn - > AffectedVidPnSourceId ,
& hVidPnSourceModeSet ,
& pVidPnSourceModeSetInterface ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnAcquireSourceModeSet failed with Status = 0x%X, hFunctionalVidPn = 0x%p, SourceId = 0x%x " , Status , pCommitVidPn - > hFunctionalVidPn , pCommitVidPn - > AffectedVidPnSourceId ) ) ;
2014-09-02 09:36:27 +02:00
goto CommitVidPnExit ;
}
// Get the mode that is being pinned
Status = pVidPnSourceModeSetInterface - > pfnAcquirePinnedModeInfo ( hVidPnSourceModeSet , & pPinnedVidPnSourceModeInfo ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnAcquirePinnedModeInfo failed with Status = 0x%X, hFunctionalVidPn = 0x%p " , Status , pCommitVidPn - > hFunctionalVidPn ) ) ;
2014-09-02 09:36:27 +02:00
goto CommitVidPnExit ;
}
}
else
{
// This will cause the successful quit below
pPinnedVidPnSourceModeInfo = NULL ;
}
if ( m_CurrentModes [ pCommitVidPn - > AffectedVidPnSourceId ] . FrameBuffer . Ptr & &
! m_CurrentModes [ pCommitVidPn - > AffectedVidPnSourceId ] . Flags . DoNotMapOrUnmap )
{
2016-09-26 15:00:07 +02:00
Status = m_pHWDevice - > ReleaseFrameBuffer ( & m_CurrentModes [ pCommitVidPn - > AffectedVidPnSourceId ] ) ;
2014-09-02 09:36:27 +02:00
if ( ! NT_SUCCESS ( Status ) )
{
goto CommitVidPnExit ;
}
}
if ( pPinnedVidPnSourceModeInfo = = NULL )
{
// There is no mode to pin on this source, any old paths here have already been cleared
Status = STATUS_SUCCESS ;
goto CommitVidPnExit ;
}
Status = IsVidPnSourceModeFieldsValid ( pPinnedVidPnSourceModeInfo ) ;
if ( ! NT_SUCCESS ( Status ) )
{
goto CommitVidPnExit ;
}
// Get the number of paths from this source so we can loop through all paths
SIZE_T NumPathsFromSource = 0 ;
Status = pVidPnTopologyInterface - > pfnGetNumPathsFromSource ( hVidPnTopology , pCommitVidPn - > AffectedVidPnSourceId , & NumPathsFromSource ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnGetNumPathsFromSource failed with Status = 0x%X, hVidPnTopology = 0x%p " , Status , hVidPnTopology ) ) ;
2014-09-02 09:36:27 +02:00
goto CommitVidPnExit ;
}
// Loop through all paths to set this mode
for ( SIZE_T PathIndex = 0 ; PathIndex < NumPathsFromSource ; + + PathIndex )
{
// Get the target id for this path
D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId = D3DDDI_ID_UNINITIALIZED ;
Status = pVidPnTopologyInterface - > pfnEnumPathTargetsFromSource ( hVidPnTopology , pCommitVidPn - > AffectedVidPnSourceId , PathIndex , & TargetId ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnEnumPathTargetsFromSource failed with Status = 0x%X, hVidPnTopology = 0x%p, SourceId = 0x%x, PathIndex = 0x%I64x " ,
2014-09-02 09:36:27 +02:00
Status , hVidPnTopology , pCommitVidPn - > AffectedVidPnSourceId , PathIndex ) ) ;
goto CommitVidPnExit ;
}
// Get the actual path info
Status = pVidPnTopologyInterface - > pfnAcquirePathInfo ( hVidPnTopology , pCommitVidPn - > AffectedVidPnSourceId , TargetId , & pVidPnPresentPath ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnAcquirePathInfo failed with Status = 0x%X, hVidPnTopology = 0x%p, SourceId = 0x%x, TargetId = 0x%x " ,
2014-09-02 09:36:27 +02:00
Status , hVidPnTopology , pCommitVidPn - > AffectedVidPnSourceId , TargetId ) ) ;
goto CommitVidPnExit ;
}
Status = IsVidPnPathFieldsValid ( pVidPnPresentPath ) ;
if ( ! NT_SUCCESS ( Status ) )
{
goto CommitVidPnExit ;
}
Status = SetSourceModeAndPath ( pPinnedVidPnSourceModeInfo , pVidPnPresentPath ) ;
if ( ! NT_SUCCESS ( Status ) )
{
goto CommitVidPnExit ;
}
Status = pVidPnTopologyInterface - > pfnReleasePathInfo ( hVidPnTopology , pVidPnPresentPath ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " pfnReleasePathInfo failed with Status = 0x%X, hVidPnTopoogy = 0x%p, pVidPnPresentPath = %p " ,
2014-09-02 09:36:27 +02:00
Status , hVidPnTopology , pVidPnPresentPath ) ) ;
goto CommitVidPnExit ;
}
pVidPnPresentPath = NULL ; // Successfully released it
}
CommitVidPnExit :
2016-09-28 13:09:27 +02:00
NTSTATUS TempStatus ( STATUS_SUCCESS ) ;
2014-09-02 09:36:27 +02:00
UNREFERENCED_PARAMETER ( TempStatus ) ;
if ( ( pVidPnSourceModeSetInterface ! = NULL ) & &
( hVidPnSourceModeSet ! = 0 ) & &
( pPinnedVidPnSourceModeInfo ! = NULL ) )
{
TempStatus = pVidPnSourceModeSetInterface - > pfnReleaseModeInfo ( hVidPnSourceModeSet , pPinnedVidPnSourceModeInfo ) ;
NT_ASSERT ( NT_SUCCESS ( TempStatus ) ) ;
}
if ( ( pVidPnInterface ! = NULL ) & &
( pCommitVidPn - > hFunctionalVidPn ! = 0 ) & &
( hVidPnSourceModeSet ! = 0 ) )
{
TempStatus = pVidPnInterface - > pfnReleaseSourceModeSet ( pCommitVidPn - > hFunctionalVidPn , hVidPnSourceModeSet ) ;
NT_ASSERT ( NT_SUCCESS ( TempStatus ) ) ;
}
if ( ( pVidPnTopologyInterface ! = NULL ) & &
( hVidPnTopology ! = 0 ) & &
( pVidPnPresentPath ! = NULL ) )
{
TempStatus = pVidPnTopologyInterface - > pfnReleasePathInfo ( hVidPnTopology , pVidPnPresentPath ) ;
NT_ASSERT ( NT_SUCCESS ( TempStatus ) ) ;
}
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return Status ;
}
NTSTATUS QxlDod : : SetSourceModeAndPath ( CONST D3DKMDT_VIDPN_SOURCE_MODE * pSourceMode ,
CONST D3DKMDT_VIDPN_PRESENT_PATH * pPath )
{
PAGED_CODE ( ) ;
NTSTATUS Status = STATUS_SUCCESS ;
CURRENT_BDD_MODE * pCurrentBddMode = & m_CurrentModes [ pPath - > VidPnSourceId ] ;
pCurrentBddMode - > Scaling = pPath - > ContentTransformation . Scaling ;
pCurrentBddMode - > SrcModeWidth = pSourceMode - > Format . Graphics . VisibleRegionSize . cx ;
pCurrentBddMode - > SrcModeHeight = pSourceMode - > Format . Graphics . VisibleRegionSize . cy ;
pCurrentBddMode - > Rotation = pPath - > ContentTransformation . Rotation ;
pCurrentBddMode - > DispInfo . Width = pSourceMode - > Format . Graphics . PrimSurfSize . cx ;
pCurrentBddMode - > DispInfo . Height = pSourceMode - > Format . Graphics . PrimSurfSize . cy ;
pCurrentBddMode - > DispInfo . Pitch = pSourceMode - > Format . Graphics . PrimSurfSize . cx * BPPFromPixelFormat ( pCurrentBddMode - > DispInfo . ColorFormat ) / BITS_PER_BYTE ;
2016-09-26 15:00:07 +02:00
Status = m_pHWDevice - > AcquireFrameBuffer ( pCurrentBddMode ) ;
2014-09-02 09:36:27 +02:00
if ( NT_SUCCESS ( Status ) )
{
// Mark that the next present should be fullscreen so the screen doesn't go from black to actual pixels one dirty rect at a time.
pCurrentBddMode - > Flags . FullscreenPresent = TRUE ;
for ( USHORT ModeIndex = 0 ; ModeIndex < m_pHWDevice - > GetModeCount ( ) ; + + ModeIndex )
{
PVIDEO_MODE_INFORMATION pModeInfo = m_pHWDevice - > GetModeInfo ( ModeIndex ) ;
if ( pCurrentBddMode - > DispInfo . Width = = pModeInfo - > VisScreenWidth & &
pCurrentBddMode - > DispInfo . Height = = pModeInfo - > VisScreenHeight )
{
Status = m_pHWDevice - > SetCurrentMode ( m_pHWDevice - > GetModeNumber ( ModeIndex ) ) ;
if ( NT_SUCCESS ( Status ) )
{
m_pHWDevice - > SetCurrentModeIndex ( ModeIndex ) ;
}
break ;
}
}
}
return Status ;
}
NTSTATUS QxlDod : : IsVidPnPathFieldsValid ( CONST D3DKMDT_VIDPN_PRESENT_PATH * pPath ) const
{
PAGED_CODE ( ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
if ( pPath - > VidPnSourceId > = MAX_VIEWS )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " VidPnSourceId is 0x%I64x is too high (MAX_VIEWS is 0x%I64x) " ,
pPath - > VidPnSourceId , MAX_VIEWS ) ) ;
return STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE ;
}
else if ( pPath - > VidPnTargetId > = MAX_CHILDREN )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " VidPnTargetId is 0x%I64x is too high (MAX_CHILDREN is 0x%I64x) " ,
pPath - > VidPnTargetId , MAX_CHILDREN ) ) ;
return STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET ;
}
else if ( pPath - > GammaRamp . Type ! = D3DDDI_GAMMARAMP_DEFAULT )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " pPath contains a gamma ramp (0x%I64x) " , pPath - > GammaRamp . Type ) ) ;
return STATUS_GRAPHICS_GAMMA_RAMP_NOT_SUPPORTED ;
}
else if ( ( pPath - > ContentTransformation . Scaling ! = D3DKMDT_VPPS_IDENTITY ) & &
( pPath - > ContentTransformation . Scaling ! = D3DKMDT_VPPS_CENTERED ) & &
( pPath - > ContentTransformation . Scaling ! = D3DKMDT_VPPS_NOTSPECIFIED ) & &
( pPath - > ContentTransformation . Scaling ! = D3DKMDT_VPPS_UNINITIALIZED ) )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " pPath contains a non-identity scaling (0x%I64x) " , pPath - > ContentTransformation . Scaling ) ) ;
return STATUS_GRAPHICS_VIDPN_MODALITY_NOT_SUPPORTED ;
}
else if ( ( pPath - > ContentTransformation . Rotation ! = D3DKMDT_VPPR_IDENTITY ) & &
( pPath - > ContentTransformation . Rotation ! = D3DKMDT_VPPR_ROTATE90 ) & &
( pPath - > ContentTransformation . Rotation ! = D3DKMDT_VPPR_NOTSPECIFIED ) & &
( pPath - > ContentTransformation . Rotation ! = D3DKMDT_VPPR_UNINITIALIZED ) )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " pPath contains a not-supported rotation (0x%I64x) " , pPath - > ContentTransformation . Rotation ) ) ;
return STATUS_GRAPHICS_VIDPN_MODALITY_NOT_SUPPORTED ;
}
else if ( ( pPath - > VidPnTargetColorBasis ! = D3DKMDT_CB_SCRGB ) & &
( pPath - > VidPnTargetColorBasis ! = D3DKMDT_CB_UNINITIALIZED ) )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " pPath has a non-linear RGB color basis (0x%I64x) " , pPath - > VidPnTargetColorBasis ) ) ;
return STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE ;
}
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return STATUS_SUCCESS ;
}
NTSTATUS QxlDod : : IsVidPnSourceModeFieldsValid ( CONST D3DKMDT_VIDPN_SOURCE_MODE * pSourceMode ) const
{
PAGED_CODE ( ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
if ( pSourceMode - > Type ! = D3DKMDT_RMT_GRAPHICS )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " pSourceMode is a non-graphics mode (0x%I64x) " , pSourceMode - > Type ) ) ;
return STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE ;
}
else if ( ( pSourceMode - > Format . Graphics . ColorBasis ! = D3DKMDT_CB_SCRGB ) & &
( pSourceMode - > Format . Graphics . ColorBasis ! = D3DKMDT_CB_UNINITIALIZED ) )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " pSourceMode has a non-linear RGB color basis (0x%I64x) " , pSourceMode - > Format . Graphics . ColorBasis ) ) ;
return STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE ;
}
else if ( pSourceMode - > Format . Graphics . PixelValueAccessMode ! = D3DKMDT_PVAM_DIRECT )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " pSourceMode has a palettized access mode (0x%I64x) " , pSourceMode - > Format . Graphics . PixelValueAccessMode ) ) ;
return STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE ;
}
else
{
if ( pSourceMode - > Format . Graphics . PixelFormat = = D3DDDIFMT_A8R8G8B8 )
{
return STATUS_SUCCESS ;
}
}
DbgPrint ( TRACE_LEVEL_ERROR , ( " pSourceMode has an unknown pixel format (0x%I64x) " , pSourceMode - > Format . Graphics . PixelFormat ) ) ;
return STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE ;
}
NTSTATUS QxlDod : : UpdateActiveVidPnPresentPath ( _In_ CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH * CONST pUpdateActiveVidPnPresentPath )
{
PAGED_CODE ( ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
QXL_ASSERT ( pUpdateActiveVidPnPresentPath ! = NULL ) ;
NTSTATUS Status = IsVidPnPathFieldsValid ( & ( pUpdateActiveVidPnPresentPath - > VidPnPresentPathInfo ) ) ;
if ( ! NT_SUCCESS ( Status ) )
{
return Status ;
}
// Mark the next present as fullscreen to make sure the full rotation comes through
m_CurrentModes [ pUpdateActiveVidPnPresentPath - > VidPnPresentPathInfo . VidPnSourceId ] . Flags . FullscreenPresent = TRUE ;
m_CurrentModes [ pUpdateActiveVidPnPresentPath - > VidPnPresentPathInfo . VidPnSourceId ] . Rotation = pUpdateActiveVidPnPresentPath - > VidPnPresentPathInfo . ContentTransformation . Rotation ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return STATUS_SUCCESS ;
}
//
// Non-Paged Code
//
2016-09-13 00:02:01 +02:00
QXL_NON_PAGED
2014-09-02 09:36:27 +02:00
VOID QxlDod : : DpcRoutine ( VOID )
{
2017-04-01 18:40:32 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
2014-09-02 09:36:27 +02:00
m_pHWDevice - > DpcRoutine ( & m_DxgkInterface ) ;
m_DxgkInterface . DxgkCbNotifyDpc ( ( HANDLE ) m_DxgkInterface . DeviceHandle ) ;
2017-04-01 18:40:32 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
2014-09-02 09:36:27 +02:00
}
2016-09-13 00:02:01 +02:00
QXL_NON_PAGED
2014-09-02 09:36:27 +02:00
BOOLEAN QxlDod : : InterruptRoutine ( _In_ ULONG MessageNumber )
{
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " <--> 0 %s \n " , __FUNCTION__ ) ) ;
2016-09-26 15:00:11 +02:00
if ( m_Flags . DriverStarted & & m_pHWDevice ) {
return m_pHWDevice - > InterruptRoutine ( & m_DxgkInterface , MessageNumber ) ;
}
return FALSE ;
2014-09-02 09:36:27 +02:00
}
2016-09-13 00:02:01 +02:00
QXL_NON_PAGED
2014-09-02 09:36:27 +02:00
VOID QxlDod : : ResetDevice ( VOID )
{
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <---> %s \n " , __FUNCTION__ ) ) ;
m_pHWDevice - > ResetDevice ( ) ;
}
// Must be Non-Paged, as it sets up the display for a bugcheck
2016-09-13 00:02:01 +02:00
QXL_NON_PAGED
2014-09-02 09:36:27 +02:00
NTSTATUS QxlDod : : SystemDisplayEnable ( _In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId ,
_In_ PDXGKARG_SYSTEM_DISPLAY_ENABLE_FLAGS Flags ,
_Out_ UINT * pWidth ,
_Out_ UINT * pHeight ,
_Out_ D3DDDIFORMAT * pColorFormat )
{
UNREFERENCED_PARAMETER ( Flags ) ;
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " ---> %s \n " , __FUNCTION__ ) ) ;
m_SystemDisplaySourceId = D3DDDI_ID_UNINITIALIZED ;
QXL_ASSERT ( ( TargetId < MAX_CHILDREN ) | | ( TargetId = = D3DDDI_ID_UNINITIALIZED ) ) ;
// Find the frame buffer for displaying the bugcheck, if it was successfully mapped
if ( TargetId = = D3DDDI_ID_UNINITIALIZED )
{
for ( UINT SourceIdx = 0 ; SourceIdx < MAX_VIEWS ; + + SourceIdx )
{
if ( m_CurrentModes [ SourceIdx ] . FrameBuffer . Ptr ! = NULL )
{
m_SystemDisplaySourceId = SourceIdx ;
break ;
}
}
}
else
{
m_SystemDisplaySourceId = FindSourceForTarget ( TargetId , FALSE ) ;
}
if ( m_SystemDisplaySourceId = = D3DDDI_ID_UNINITIALIZED )
{
{
return STATUS_UNSUCCESSFUL ;
}
}
if ( ( m_CurrentModes [ m_SystemDisplaySourceId ] . Rotation = = D3DKMDT_VPPR_ROTATE90 ) | |
( m_CurrentModes [ m_SystemDisplaySourceId ] . Rotation = = D3DKMDT_VPPR_ROTATE270 ) )
{
* pHeight = m_CurrentModes [ m_SystemDisplaySourceId ] . DispInfo . Width ;
* pWidth = m_CurrentModes [ m_SystemDisplaySourceId ] . DispInfo . Height ;
}
else
{
* pWidth = m_CurrentModes [ m_SystemDisplaySourceId ] . DispInfo . Width ;
* pHeight = m_CurrentModes [ m_SystemDisplaySourceId ] . DispInfo . Height ;
}
* pColorFormat = m_CurrentModes [ m_SystemDisplaySourceId ] . DispInfo . ColorFormat ;
return STATUS_SUCCESS ;
}
// Must be Non-Paged, as it is called to display the bugcheck screen
2016-09-13 00:02:01 +02:00
QXL_NON_PAGED
2014-09-02 09:36:27 +02:00
VOID QxlDod : : SystemDisplayWrite ( _In_reads_bytes_ ( SourceHeight * SourceStride ) VOID * pSource ,
_In_ UINT SourceWidth ,
_In_ UINT SourceHeight ,
_In_ UINT SourceStride ,
_In_ INT PositionX ,
_In_ INT PositionY )
{
UNREFERENCED_PARAMETER ( pSource ) ;
UNREFERENCED_PARAMETER ( SourceStride ) ;
// Rect will be Offset by PositionX/Y in the src to reset it back to 0
RECT Rect ;
Rect . left = PositionX ;
Rect . top = PositionY ;
Rect . right = Rect . left + SourceWidth ;
Rect . bottom = Rect . top + SourceHeight ;
// Set up destination blt info
BLT_INFO DstBltInfo ;
DstBltInfo . pBits = m_CurrentModes [ m_SystemDisplaySourceId ] . FrameBuffer . Ptr ;
DstBltInfo . Pitch = m_CurrentModes [ m_SystemDisplaySourceId ] . DispInfo . Pitch ;
DstBltInfo . BitsPerPel = BPPFromPixelFormat ( m_CurrentModes [ m_SystemDisplaySourceId ] . DispInfo . ColorFormat ) ;
DstBltInfo . Offset . x = 0 ;
DstBltInfo . Offset . y = 0 ;
DstBltInfo . Rotation = m_CurrentModes [ m_SystemDisplaySourceId ] . Rotation ;
DstBltInfo . Width = m_CurrentModes [ m_SystemDisplaySourceId ] . DispInfo . Width ;
DstBltInfo . Height = m_CurrentModes [ m_SystemDisplaySourceId ] . DispInfo . Height ;
// Set up source blt info
BLT_INFO SrcBltInfo ;
SrcBltInfo . pBits = pSource ;
SrcBltInfo . Pitch = SourceStride ;
SrcBltInfo . BitsPerPel = 32 ;
SrcBltInfo . Offset . x = - PositionX ;
SrcBltInfo . Offset . y = - PositionY ;
SrcBltInfo . Rotation = D3DKMDT_VPPR_IDENTITY ;
SrcBltInfo . Width = SourceWidth ;
SrcBltInfo . Height = SourceHeight ;
BltBits ( & DstBltInfo ,
& SrcBltInfo ,
2015-03-24 07:22:45 +01:00
1 ,
2014-09-02 09:36:27 +02:00
& Rect ) ;
}
2016-09-13 00:02:01 +02:00
// End Non-Paged Code
2014-09-02 09:36:27 +02:00
NTSTATUS QxlDod : : WriteHWInfoStr ( _In_ HANDLE DevInstRegKeyHandle , _In_ PCWSTR pszwValueName , _In_ PCSTR pszValue )
{
PAGED_CODE ( ) ;
NTSTATUS Status ;
ANSI_STRING AnsiStrValue ;
UNICODE_STRING UnicodeStrValue ;
UNICODE_STRING UnicodeStrValueName ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
// ZwSetValueKey wants the ValueName as a UNICODE_STRING
RtlInitUnicodeString ( & UnicodeStrValueName , pszwValueName ) ;
// REG_SZ is for WCHARs, there is no equivalent for CHARs
// Use the ansi/unicode conversion functions to get from PSTR to PWSTR
RtlInitAnsiString ( & AnsiStrValue , pszValue ) ;
Status = RtlAnsiStringToUnicodeString ( & UnicodeStrValue , & AnsiStrValue , TRUE ) ;
if ( ! NT_SUCCESS ( Status ) )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " RtlAnsiStringToUnicodeString failed with Status: 0x%X \n " , Status ) ) ;
return Status ;
}
// Write the value to the registry
Status = ZwSetValueKey ( DevInstRegKeyHandle ,
& UnicodeStrValueName ,
0 ,
REG_SZ ,
UnicodeStrValue . Buffer ,
UnicodeStrValue . MaximumLength ) ;
// Free the earlier allocated unicode string
RtlFreeUnicodeString ( & UnicodeStrValue ) ;
if ( ! NT_SUCCESS ( Status ) )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " ZwSetValueKey failed with Status: 0x%X \n " , Status ) ) ;
}
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return Status ;
}
2016-09-28 13:09:27 +02:00
NTSTATUS QxlDod : : RegisterHWInfo ( _In_ ULONG Id )
2014-09-02 09:36:27 +02:00
{
PAGED_CODE ( ) ;
NTSTATUS Status ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
PCSTR StrHWInfoChipType = " QEMU QXL " ;
PCSTR StrHWInfoDacType = " QXL 1B36 " ;
PCSTR StrHWInfoAdapterString = " QXL " ;
PCSTR StrHWInfoBiosString = " SEABIOS QXL " ;
HANDLE DevInstRegKeyHandle ;
Status = IoOpenDeviceRegistryKey ( m_pPhysicalDevice , PLUGPLAY_REGKEY_DRIVER , KEY_SET_VALUE , & DevInstRegKeyHandle ) ;
if ( ! NT_SUCCESS ( Status ) )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " IoOpenDeviceRegistryKey failed for PDO: 0x%p, Status: 0x%X " , m_pPhysicalDevice , Status ) ) ;
2014-09-02 09:36:27 +02:00
return Status ;
}
Status = WriteHWInfoStr ( DevInstRegKeyHandle , L " HardwareInformation.ChipType " , StrHWInfoChipType ) ;
if ( ! NT_SUCCESS ( Status ) )
{
return Status ;
}
Status = WriteHWInfoStr ( DevInstRegKeyHandle , L " HardwareInformation.DacType " , StrHWInfoDacType ) ;
if ( ! NT_SUCCESS ( Status ) )
{
return Status ;
}
Status = WriteHWInfoStr ( DevInstRegKeyHandle , L " HardwareInformation.AdapterString " , StrHWInfoAdapterString ) ;
if ( ! NT_SUCCESS ( Status ) )
{
return Status ;
}
Status = WriteHWInfoStr ( DevInstRegKeyHandle , L " HardwareInformation.BiosString " , StrHWInfoBiosString ) ;
if ( ! NT_SUCCESS ( Status ) )
{
return Status ;
}
// MemorySize is a ULONG, unlike the others which are all strings
UNICODE_STRING ValueNameMemorySize ;
RtlInitUnicodeString ( & ValueNameMemorySize , L " HardwareInformation.MemorySize " ) ;
DWORD MemorySize = 0 ; // BDD has no access to video memory
Status = ZwSetValueKey ( DevInstRegKeyHandle ,
& ValueNameMemorySize ,
0 ,
REG_DWORD ,
& MemorySize ,
sizeof ( MemorySize ) ) ;
if ( ! NT_SUCCESS ( Status ) )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " ZwSetValueKey for MemorySize failed with Status: 0x%X \n " , Status ) ) ;
return Status ;
}
2014-12-05 23:20:04 +01:00
UNICODE_STRING ValueQxlDeviceID ;
RtlInitUnicodeString ( & ValueQxlDeviceID , L " QxlDeviceID " ) ;
DWORD DeviceId = Id ; // BDD has no access to video memory
Status = ZwSetValueKey ( DevInstRegKeyHandle ,
& ValueQxlDeviceID ,
0 ,
REG_BINARY ,
& DeviceId ,
sizeof ( DeviceId ) ) ;
if ( ! NT_SUCCESS ( Status ) )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " ZwSetValueKey for MemorySize failed with Status: 0x%X \n " , Status ) ) ;
return Status ;
}
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return Status ;
}
2016-09-13 00:02:01 +02:00
QXL_NON_PAGED
2014-09-02 09:36:27 +02:00
D3DDDI_VIDEO_PRESENT_SOURCE_ID QxlDod : : FindSourceForTarget ( D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId , BOOLEAN DefaultToZero )
{
UNREFERENCED_PARAMETER ( TargetId ) ;
for ( UINT SourceId = 0 ; SourceId < MAX_VIEWS ; + + SourceId )
{
if ( m_CurrentModes [ SourceId ] . FrameBuffer . Ptr ! = NULL )
{
return SourceId ;
}
}
return DefaultToZero ? 0 : D3DDDI_ID_UNINITIALIZED ;
}
//
// Frame buffer map/unmap
//
NTSTATUS
MapFrameBuffer (
_In_ PHYSICAL_ADDRESS PhysicalAddress ,
_In_ ULONG Length ,
_Outptr_result_bytebuffer_ ( Length ) VOID * * VirtualAddress )
{
PAGED_CODE ( ) ;
//
// Check for parameters
//
if ( ( PhysicalAddress . QuadPart = = ( ULONGLONG ) 0 ) | |
( Length = = 0 ) | |
( VirtualAddress = = NULL ) )
{
2015-03-30 13:57:12 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " One of PhysicalAddress.QuadPart (0x%I64x), Length (%lu), VirtualAddress (%p) is NULL or 0 \n " ,
2014-09-02 09:36:27 +02:00
PhysicalAddress . QuadPart , Length , VirtualAddress ) ) ;
return STATUS_INVALID_PARAMETER ;
}
2016-09-28 13:31:04 +02:00
* VirtualAddress = MapIoSpace ( PhysicalAddress ,
Length ,
MmWriteCombined ,
PAGE_WRITECOMBINE | PAGE_READWRITE ) ;
2014-09-02 09:36:27 +02:00
if ( * VirtualAddress = = NULL )
{
// The underlying call to MmMapIoSpace failed. This may be because, MmWriteCombined
// isn't supported, so try again with MmNonCached
2016-09-28 13:31:04 +02:00
* VirtualAddress = MapIoSpace ( PhysicalAddress ,
Length ,
MmNonCached ,
PAGE_NOCACHE | PAGE_READWRITE ) ;
2014-09-02 09:36:27 +02:00
if ( * VirtualAddress = = NULL )
{
2015-03-30 13:57:12 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " MmMapIoSpace returned a NULL buffer when trying to allocate %lu bytes " , Length ) ) ;
2014-09-02 09:36:27 +02:00
return STATUS_NO_MEMORY ;
}
}
return STATUS_SUCCESS ;
}
NTSTATUS
UnmapFrameBuffer (
_In_reads_bytes_ ( Length ) VOID * VirtualAddress ,
_In_ ULONG Length )
{
PAGED_CODE ( ) ;
//
// Check for parameters
//
if ( ( VirtualAddress = = NULL ) & & ( Length = = 0 ) )
{
// Allow this function to be called when there's no work to do, and treat as successful
return STATUS_SUCCESS ;
}
else if ( ( VirtualAddress = = NULL ) | | ( Length = = 0 ) )
{
2015-03-30 13:57:12 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " Only one of Length (%lu), VirtualAddress (%p) is NULL or 0 " ,
2014-09-02 09:36:27 +02:00
Length , VirtualAddress ) ) ;
return STATUS_INVALID_PARAMETER ;
}
MmUnmapIoSpace ( VirtualAddress ,
Length ) ;
return STATUS_SUCCESS ;
}
// HW specific code
2016-09-13 00:02:01 +02:00
QXL_NON_PAGED
2014-09-02 09:36:27 +02:00
VOID GetPitches ( _In_ CONST BLT_INFO * pBltInfo , _Out_ LONG * pPixelPitch , _Out_ LONG * pRowPitch )
{
switch ( pBltInfo - > Rotation )
{
case D3DKMDT_VPPR_IDENTITY :
{
* pPixelPitch = ( pBltInfo - > BitsPerPel / BITS_PER_BYTE ) ;
* pRowPitch = pBltInfo - > Pitch ;
return ;
}
case D3DKMDT_VPPR_ROTATE90 :
{
* pPixelPitch = - ( ( LONG ) pBltInfo - > Pitch ) ;
* pRowPitch = ( pBltInfo - > BitsPerPel / BITS_PER_BYTE ) ;
return ;
}
case D3DKMDT_VPPR_ROTATE180 :
{
* pPixelPitch = - ( ( LONG ) pBltInfo - > BitsPerPel / BITS_PER_BYTE ) ;
* pRowPitch = - ( ( LONG ) pBltInfo - > Pitch ) ;
return ;
}
case D3DKMDT_VPPR_ROTATE270 :
{
* pPixelPitch = pBltInfo - > Pitch ;
* pRowPitch = - ( ( LONG ) pBltInfo - > BitsPerPel / BITS_PER_BYTE ) ;
return ;
}
default :
{
QXL_LOG_ASSERTION1 ( " Invalid rotation (0x%I64x) specified " , pBltInfo - > Rotation ) ;
* pPixelPitch = 0 ;
* pRowPitch = 0 ;
return ;
}
}
}
2016-09-13 00:02:01 +02:00
QXL_NON_PAGED
2014-09-02 09:36:27 +02:00
BYTE * GetRowStart ( _In_ CONST BLT_INFO * pBltInfo , CONST RECT * pRect )
{
BYTE * pRet = NULL ;
LONG OffLeft = pRect - > left + pBltInfo - > Offset . x ;
LONG OffTop = pRect - > top + pBltInfo - > Offset . y ;
LONG BytesPerPixel = ( pBltInfo - > BitsPerPel / BITS_PER_BYTE ) ;
switch ( pBltInfo - > Rotation )
{
case D3DKMDT_VPPR_IDENTITY :
{
pRet = ( ( BYTE * ) pBltInfo - > pBits +
OffTop * pBltInfo - > Pitch +
OffLeft * BytesPerPixel ) ;
break ;
}
case D3DKMDT_VPPR_ROTATE90 :
{
pRet = ( ( BYTE * ) pBltInfo - > pBits +
( pBltInfo - > Height - 1 - OffLeft ) * pBltInfo - > Pitch +
OffTop * BytesPerPixel ) ;
break ;
}
case D3DKMDT_VPPR_ROTATE180 :
{
pRet = ( ( BYTE * ) pBltInfo - > pBits +
( pBltInfo - > Height - 1 - OffTop ) * pBltInfo - > Pitch +
( pBltInfo - > Width - 1 - OffLeft ) * BytesPerPixel ) ;
break ;
}
case D3DKMDT_VPPR_ROTATE270 :
{
pRet = ( ( BYTE * ) pBltInfo - > pBits +
OffLeft * pBltInfo - > Pitch +
( pBltInfo - > Width - 1 - OffTop ) * BytesPerPixel ) ;
break ;
}
default :
{
QXL_LOG_ASSERTION1 ( " Invalid rotation (0x%I64x) specified " , pBltInfo - > Rotation ) ;
break ;
}
}
return pRet ;
}
/****************************Internal*Routine******************************\
* CopyBitsGeneric
*
*
* Blt function which can handle a rotated dst / src , offset rects in dst / src
* and bpp combinations of :
* dst | src
* 32 | 32 // For identity rotation this is much faster in CopyBits32_32
* 32 | 24
* 32 | 16
* 24 | 32
* 16 | 32
* 8 | 32
* 24 | 24 // untested
*
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-09-13 00:02:01 +02:00
QXL_NON_PAGED
2014-09-02 09:36:27 +02:00
VOID CopyBitsGeneric (
BLT_INFO * pDst ,
CONST BLT_INFO * pSrc ,
UINT NumRects ,
_In_reads_ ( NumRects ) CONST RECT * pRects )
{
LONG DstPixelPitch = 0 ;
LONG DstRowPitch = 0 ;
LONG SrcPixelPitch = 0 ;
LONG SrcRowPitch = 0 ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s NumRects = %d Dst = %p Src = %p \n " , __FUNCTION__ , NumRects , pDst - > pBits , pSrc - > pBits ) ) ;
GetPitches ( pDst , & DstPixelPitch , & DstRowPitch ) ;
GetPitches ( pSrc , & SrcPixelPitch , & SrcRowPitch ) ;
for ( UINT iRect = 0 ; iRect < NumRects ; iRect + + )
{
CONST RECT * pRect = & pRects [ iRect ] ;
NT_ASSERT ( pRect - > right > = pRect - > left ) ;
NT_ASSERT ( pRect - > bottom > = pRect - > top ) ;
UINT NumPixels = pRect - > right - pRect - > left ;
UINT NumRows = pRect - > bottom - pRect - > top ;
BYTE * pDstRow = GetRowStart ( pDst , pRect ) ;
CONST BYTE * pSrcRow = GetRowStart ( pSrc , pRect ) ;
for ( UINT y = 0 ; y < NumRows ; y + + )
{
BYTE * pDstPixel = pDstRow ;
CONST BYTE * pSrcPixel = pSrcRow ;
for ( UINT x = 0 ; x < NumPixels ; x + + )
{
if ( ( pDst - > BitsPerPel = = 24 ) | |
( pSrc - > BitsPerPel = = 24 ) )
{
pDstPixel [ 0 ] = pSrcPixel [ 0 ] ;
pDstPixel [ 1 ] = pSrcPixel [ 1 ] ;
pDstPixel [ 2 ] = pSrcPixel [ 2 ] ;
// pPixel[3] is the alpha channel and is ignored for whichever of Src/Dst is 32bpp
}
else if ( pDst - > BitsPerPel = = 32 )
{
if ( pSrc - > BitsPerPel = = 32 )
{
UINT32 * pDstPixelAs32 = ( UINT32 * ) pDstPixel ;
UINT32 * pSrcPixelAs32 = ( UINT32 * ) pSrcPixel ;
* pDstPixelAs32 = * pSrcPixelAs32 ;
}
else if ( pSrc - > BitsPerPel = = 16 )
{
UINT32 * pDstPixelAs32 = ( UINT32 * ) pDstPixel ;
UINT16 * pSrcPixelAs16 = ( UINT16 * ) pSrcPixel ;
* pDstPixelAs32 = CONVERT_16BPP_TO_32BPP ( * pSrcPixelAs16 ) ;
}
else
{
// Invalid pSrc->BitsPerPel on a pDst->BitsPerPel of 32
NT_ASSERT ( FALSE ) ;
}
}
else if ( pDst - > BitsPerPel = = 16 )
{
NT_ASSERT ( pSrc - > BitsPerPel = = 32 ) ;
UINT16 * pDstPixelAs16 = ( UINT16 * ) pDstPixel ;
* pDstPixelAs16 = CONVERT_32BPP_TO_16BPP ( pSrcPixel ) ;
}
else if ( pDst - > BitsPerPel = = 8 )
{
NT_ASSERT ( pSrc - > BitsPerPel = = 32 ) ;
* pDstPixel = CONVERT_32BPP_TO_8BPP ( pSrcPixel ) ;
}
else
{
// Invalid pDst->BitsPerPel
NT_ASSERT ( FALSE ) ;
}
pDstPixel + = DstPixelPitch ;
pSrcPixel + = SrcPixelPitch ;
}
pDstRow + = DstRowPitch ;
pSrcRow + = SrcRowPitch ;
}
}
}
2016-09-13 00:02:01 +02:00
QXL_NON_PAGED
2014-09-02 09:36:27 +02:00
VOID CopyBits32_32 (
BLT_INFO * pDst ,
CONST BLT_INFO * pSrc ,
UINT NumRects ,
_In_reads_ ( NumRects ) CONST RECT * pRects )
{
NT_ASSERT ( ( pDst - > BitsPerPel = = 32 ) & &
( pSrc - > BitsPerPel = = 32 ) ) ;
NT_ASSERT ( ( pDst - > Rotation = = D3DKMDT_VPPR_IDENTITY ) & &
( pSrc - > Rotation = = D3DKMDT_VPPR_IDENTITY ) ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
for ( UINT iRect = 0 ; iRect < NumRects ; iRect + + )
{
CONST RECT * pRect = & pRects [ iRect ] ;
NT_ASSERT ( pRect - > right > = pRect - > left ) ;
NT_ASSERT ( pRect - > bottom > = pRect - > top ) ;
UINT NumPixels = pRect - > right - pRect - > left ;
UINT NumRows = pRect - > bottom - pRect - > top ;
UINT BytesToCopy = NumPixels * 4 ;
BYTE * pStartDst = ( ( BYTE * ) pDst - > pBits +
( pRect - > top + pDst - > Offset . y ) * pDst - > Pitch +
( pRect - > left + pDst - > Offset . x ) * 4 ) ;
CONST BYTE * pStartSrc = ( ( BYTE * ) pSrc - > pBits +
( pRect - > top + pSrc - > Offset . y ) * pSrc - > Pitch +
( pRect - > left + pSrc - > Offset . x ) * 4 ) ;
for ( UINT i = 0 ; i < NumRows ; + + i )
{
RtlCopyMemory ( pStartDst , pStartSrc , BytesToCopy ) ;
pStartDst + = pDst - > Pitch ;
pStartSrc + = pSrc - > Pitch ;
}
}
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
}
2016-09-13 00:02:01 +02:00
QXL_NON_PAGED
2014-09-02 09:36:27 +02:00
VOID BltBits (
BLT_INFO * pDst ,
CONST BLT_INFO * pSrc ,
UINT NumRects ,
_In_reads_ ( NumRects ) CONST RECT * pRects )
{
// pSrc->pBits might be coming from user-mode. User-mode addresses when accessed by kernel need to be protected by a __try/__except.
// This usage is redundant in the sample driver since it is already being used for MmProbeAndLockPages. However, it is very important
// to have this in place and to make sure developers don't miss it, it is in these two locations.
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
__try
{
if ( pDst - > BitsPerPel = = 32 & &
pSrc - > BitsPerPel = = 32 & &
pDst - > Rotation = = D3DKMDT_VPPR_IDENTITY & &
pSrc - > Rotation = = D3DKMDT_VPPR_IDENTITY )
{
// This is by far the most common copy function being called
CopyBits32_32 ( pDst , pSrc , NumRects , pRects ) ;
}
else
{
CopyBitsGeneric ( pDst , pSrc , NumRects , pRects ) ;
}
}
# pragma prefast(suppress: __WARNING_EXCEPTIONEXECUTEHANDLER, "try / except is only able to protect against user-mode errors and these are the only errors we try to catch here");
__except ( EXCEPTION_EXECUTE_HANDLER )
{
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " Either dst (0x%p) or src (0x%p) bits encountered exception during access. \n " , pDst - > pBits , pSrc - > pBits ) ) ;
2014-09-02 09:36:27 +02:00
}
}
VgaDevice : : VgaDevice ( _In_ QxlDod * pQxlDod )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
m_pQxlDod = pQxlDod ;
m_ModeInfo = NULL ;
m_ModeCount = 0 ;
m_ModeNumbers = NULL ;
m_CurrentMode = 0 ;
2014-12-05 23:20:04 +01:00
m_Id = 0 ;
2014-09-02 09:36:27 +02:00
}
VgaDevice : : ~ VgaDevice ( void )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2015-03-30 13:57:12 +02:00
HWClose ( ) ;
2016-09-08 15:43:32 +02:00
delete [ ] m_ModeInfo ;
2016-09-08 15:40:08 +02:00
delete [ ] m_ModeNumbers ;
2014-09-02 09:36:27 +02:00
m_ModeInfo = NULL ;
m_ModeNumbers = NULL ;
m_CurrentMode = 0 ;
m_ModeCount = 0 ;
2014-12-05 23:20:04 +01:00
m_Id = 0 ;
2014-09-02 09:36:27 +02:00
}
BOOL VgaDevice : : SetVideoModeInfo ( UINT Idx , PVBE_MODEINFO pModeInfo )
{
PVIDEO_MODE_INFORMATION pMode = NULL ;
PAGED_CODE ( ) ;
pMode = & m_ModeInfo [ Idx ] ;
pMode - > Length = sizeof ( VIDEO_MODE_INFORMATION ) ;
2015-03-24 07:22:45 +01:00
pMode - > ModeIndex = Idx ;
2014-09-02 09:36:27 +02:00
pMode - > VisScreenWidth = pModeInfo - > XResolution ;
pMode - > VisScreenHeight = pModeInfo - > YResolution ;
pMode - > ScreenStride = pModeInfo - > LinBytesPerScanLine ;
pMode - > NumberOfPlanes = pModeInfo - > NumberOfPlanes ;
pMode - > BitsPerPlane = pModeInfo - > BitsPerPixel / pModeInfo - > NumberOfPlanes ;
pMode - > Frequency = 60 ;
pMode - > XMillimeter = pModeInfo - > XResolution * 254 / 720 ;
pMode - > YMillimeter = pModeInfo - > YResolution * 254 / 720 ;
if ( pModeInfo - > BitsPerPixel = = 15 & & pModeInfo - > NumberOfPlanes = = 1 )
{
pMode - > BitsPerPlane = 16 ;
}
pMode - > NumberRedBits = pModeInfo - > LinRedMaskSize ;
pMode - > NumberGreenBits = pModeInfo - > LinGreenMaskSize ;
pMode - > NumberBlueBits = pModeInfo - > LinBlueMaskSize ;
pMode - > RedMask = ( ( 1 < < pModeInfo - > LinRedMaskSize ) - 1 ) < < pModeInfo - > LinRedFieldPosition ;
pMode - > GreenMask = ( ( 1 < < pModeInfo - > LinGreenMaskSize ) - 1 ) < < pModeInfo - > LinGreenFieldPosition ;
pMode - > BlueMask = ( ( 1 < < pModeInfo - > LinBlueMaskSize ) - 1 ) < < pModeInfo - > LinBlueFieldPosition ;
pMode - > AttributeFlags = VIDEO_MODE_COLOR | VIDEO_MODE_GRAPHICS | VIDEO_MODE_NO_OFF_SCREEN ;
pMode - > VideoMemoryBitmapWidth = pModeInfo - > XResolution ;
pMode - > VideoMemoryBitmapHeight = pModeInfo - > YResolution ;
pMode - > DriverSpecificAttributeFlags = 0 ;
return TRUE ;
}
NTSTATUS VgaDevice : : GetModeList ( DXGK_DISPLAY_INFORMATION * pDispInfo )
{
PAGED_CODE ( ) ;
USHORT m_Segment ;
USHORT m_Offset ;
USHORT ModeCount ;
ULONG SuitableModeCount ;
USHORT ModeTemp ;
USHORT CurrentMode ;
VBE_INFO VbeInfo = { 0 } ;
ULONG Length ;
VBE_MODEINFO tmpModeInfo ;
2015-02-19 11:07:24 +01:00
UINT Height = pDispInfo - > Height ;
UINT Width = pDispInfo - > Width ;
UINT BitsPerPixel = BPPFromPixelFormat ( pDispInfo - > ColorFormat ) ;
2014-09-02 09:36:27 +02:00
NTSTATUS Status = STATUS_SUCCESS ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
Length = 0x400 ;
Status = x86BiosAllocateBuffer ( & Length , & m_Segment , & m_Offset ) ;
if ( ! NT_SUCCESS ( Status ) )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " x86BiosAllocateBuffer failed with Status: 0x%X \n " , Status ) ) ;
return Status ;
}
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " x86BiosAllocateBuffer 0x%x (%x.%x) \n " , VbeInfo . VideoModePtr , m_Segment , m_Offset ) ) ;
Status = x86BiosWriteMemory ( m_Segment , m_Offset , " VBE2 " , 4 ) ;
if ( ! NT_SUCCESS ( Status ) )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " x86BiosWriteMemory failed with Status: 0x%X \n " , Status ) ) ;
return Status ;
}
X86BIOS_REGISTERS regs = { 0 } ;
regs . SegEs = m_Segment ;
regs . Edi = m_Offset ;
regs . Eax = 0x4F00 ;
if ( ! x86BiosCall ( 0x10 , & regs ) /* || (regs.Eax & 0xFF00) != 0x4F00 */ )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " x86BiosCall failed \n " ) ) ;
return STATUS_UNSUCCESSFUL ;
}
Status = x86BiosReadMemory ( m_Segment , m_Offset , & VbeInfo , sizeof ( VbeInfo ) ) ;
if ( ! NT_SUCCESS ( Status ) )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " x86BiosReadMemory failed with Status: 0x%X \n " , Status ) ) ;
return Status ;
}
if ( ! RtlEqualMemory ( VbeInfo . Signature , " VESA " , 4 ) )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " No VBE BIOS present \n " ) ) ;
return STATUS_UNSUCCESSFUL ;
}
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " VBE BIOS Present (%d.%d, %8ld Kb) \n " , VbeInfo . Version / 0x100 , VbeInfo . Version & 0xFF , VbeInfo . TotalMemory * 64 ) ) ;
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " Capabilities = 0x%x \n " , VbeInfo . Capabilities ) ) ;
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " VideoModePtr = 0x%x (0x%x.0x%x) \n " , VbeInfo . VideoModePtr , HIWORD ( VbeInfo . VideoModePtr ) , LOWORD ( VbeInfo . VideoModePtr ) ) ) ;
2015-02-19 11:07:24 +01:00
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " pDispInfo = %p %dx%d@%d \n " , pDispInfo , Width , Height , BitsPerPixel ) ) ;
2014-09-02 09:36:27 +02:00
for ( ModeCount = 0 ; ; ModeCount + + )
{
2016-09-12 23:59:07 +02:00
/* Read the VBE mode number. */
2014-09-02 09:36:27 +02:00
Status = x86BiosReadMemory (
HIWORD ( VbeInfo . VideoModePtr ) ,
LOWORD ( VbeInfo . VideoModePtr ) + ( ModeCount < < 1 ) ,
& ModeTemp ,
sizeof ( ModeTemp ) ) ;
if ( ! NT_SUCCESS ( Status ) )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " x86BiosReadMemory failed with Status: 0x%X \n " , Status ) ) ;
break ;
}
2016-09-12 23:59:07 +02:00
/* End of list? */
2014-09-02 09:36:27 +02:00
if ( ModeTemp = = 0xFFFF | | ModeTemp = = 0 )
{
break ;
}
2016-09-12 23:59:07 +02:00
}
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " ModeCount %d \n " , ModeCount ) ) ;
2016-09-08 15:43:32 +02:00
delete [ ] m_ModeInfo ;
2016-09-08 15:40:08 +02:00
delete [ ] m_ModeNumbers ;
2015-03-30 13:57:12 +02:00
m_ModeInfo = NULL ;
m_ModeNumbers = NULL ;
2016-09-08 15:43:32 +02:00
m_ModeInfo = new ( PagedPool ) VIDEO_MODE_INFORMATION [ ModeCount ] ;
2015-03-24 06:41:58 +01:00
if ( ! m_ModeInfo )
{
Status = STATUS_NO_MEMORY ;
DbgPrint ( TRACE_LEVEL_ERROR , ( " VgaDevice::GetModeList failed to allocate m_ModeInfo memory \n " ) ) ;
return Status ;
}
RtlZeroMemory ( m_ModeInfo , sizeof ( VIDEO_MODE_INFORMATION ) * ModeCount ) ;
2016-09-08 15:40:08 +02:00
m_ModeNumbers = new ( PagedPool ) USHORT [ ModeCount ] ;
2015-03-24 06:41:58 +01:00
if ( ! m_ModeNumbers )
{
Status = STATUS_NO_MEMORY ;
DbgPrint ( TRACE_LEVEL_ERROR , ( " VgaDevice::GetModeList failed to allocate m_ModeNumbers memory \n " ) ) ;
return Status ;
}
RtlZeroMemory ( m_ModeNumbers , sizeof ( USHORT ) * ModeCount ) ;
2014-09-02 09:36:27 +02:00
m_CurrentMode = 0 ;
2015-02-19 11:07:24 +01:00
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " m_ModeInfo = 0x%p, m_ModeNumbers = 0x%p \n " , m_ModeInfo , m_ModeNumbers ) ) ;
2014-09-02 09:36:27 +02:00
for ( CurrentMode = 0 , SuitableModeCount = 0 ;
CurrentMode < ModeCount ;
CurrentMode + + )
{
Status = x86BiosReadMemory (
HIWORD ( VbeInfo . VideoModePtr ) ,
LOWORD ( VbeInfo . VideoModePtr ) + ( CurrentMode < < 1 ) ,
& ModeTemp ,
sizeof ( ModeTemp ) ) ;
if ( ! NT_SUCCESS ( Status ) )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " x86BiosReadMemory failed with Status: 0x%X \n " , Status ) ) ;
break ;
}
RtlZeroMemory ( & regs , sizeof ( regs ) ) ;
regs . Eax = 0x4F01 ;
regs . Ecx = ModeTemp ;
regs . Edi = m_Offset + sizeof ( VbeInfo ) ;
regs . SegEs = m_Segment ;
if ( ! x86BiosCall ( 0x10 , & regs ) )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " x86BiosCall failed \n " ) ) ;
return STATUS_UNSUCCESSFUL ;
}
Status = x86BiosReadMemory (
m_Segment ,
m_Offset + sizeof ( VbeInfo ) ,
& tmpModeInfo ,
sizeof ( VBE_MODEINFO ) ) ;
2015-02-19 11:07:24 +01:00
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " ModeTemp = 0x%X %dx%d@%d \n " , ModeTemp , tmpModeInfo . XResolution , tmpModeInfo . YResolution , tmpModeInfo . BitsPerPixel ) ) ;
2014-09-02 09:36:27 +02:00
2017-02-16 15:30:59 +01:00
if ( tmpModeInfo . XResolution > = MIN_WIDTH_SIZE & &
tmpModeInfo . YResolution > = MIN_HEIGHT_SIZE & &
2014-09-02 09:36:27 +02:00
tmpModeInfo . BitsPerPixel = = BitsPerPixel & &
tmpModeInfo . PhysBasePtr ! = 0 )
{
m_ModeNumbers [ SuitableModeCount ] = ModeTemp ;
SetVideoModeInfo ( SuitableModeCount , & tmpModeInfo ) ;
2014-12-06 05:44:28 +01:00
if ( tmpModeInfo . XResolution = = MIN_WIDTH_SIZE & &
tmpModeInfo . YResolution = = MIN_HEIGHT_SIZE )
2014-09-02 09:36:27 +02:00
{
m_CurrentMode = ( USHORT ) SuitableModeCount ;
}
SuitableModeCount + + ;
}
}
if ( SuitableModeCount = = 0 )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " No video modes supported \n " ) ) ;
Status = STATUS_UNSUCCESSFUL ;
}
m_ModeCount = SuitableModeCount ;
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " ModeCount filtered %d \n " , m_ModeCount ) ) ;
for ( ULONG idx = 0 ; idx < m_ModeCount ; idx + + )
{
2015-02-18 10:57:00 +01:00
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " type %x, XRes = %d, YRes = %d, BPP = %d \n " ,
2014-09-02 09:36:27 +02:00
m_ModeNumbers [ idx ] ,
m_ModeInfo [ idx ] . VisScreenWidth ,
m_ModeInfo [ idx ] . VisScreenHeight ,
m_ModeInfo [ idx ] . BitsPerPlane ) ) ;
}
if ( m_Segment ! = 0 )
{
x86BiosFreeBuffer ( m_Segment , m_Offset ) ;
}
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return Status ;
}
NTSTATUS VgaDevice : : QueryCurrentMode ( PVIDEO_MODE RequestedMode )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
NTSTATUS Status = STATUS_SUCCESS ;
UNREFERENCED_PARAMETER ( RequestedMode ) ;
return Status ;
}
NTSTATUS VgaDevice : : SetCurrentMode ( ULONG Mode )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
NTSTATUS Status = STATUS_SUCCESS ;
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " ---> %s Mode = %x \n " , __FUNCTION__ , Mode ) ) ;
X86BIOS_REGISTERS regs = { 0 } ;
regs . Eax = 0x4F02 ;
regs . Ebx = Mode | 0x000 ;
if ( ! x86BiosCall ( 0x10 , & regs ) )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " x86BiosCall failed \n " ) ) ;
return STATUS_UNSUCCESSFUL ;
}
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return Status ;
}
NTSTATUS VgaDevice : : GetCurrentMode ( ULONG * pMode )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
NTSTATUS Status = STATUS_SUCCESS ;
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " ---> %s \n " , __FUNCTION__ ) ) ;
X86BIOS_REGISTERS regs = { 0 } ;
regs . Eax = 0x4F03 ;
if ( ! x86BiosCall ( 0x10 , & regs ) )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " x86BiosCall failed \n " ) ) ;
return STATUS_UNSUCCESSFUL ;
}
* pMode = regs . Ebx ;
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " <---> EAX = %x, EBX = %x Mode = %x \n " , regs . Eax , regs . Ebx , * pMode ) ) ;
return Status ;
}
2017-02-06 23:29:20 +01:00
static LONGLONG GetVgaFrameBuffer ( const CM_RESOURCE_LIST & resList )
{
PAGED_CODE ( ) ;
for ( ULONG i = 0 ; i < resList . Count ; + + i )
{
const CM_PARTIAL_RESOURCE_DESCRIPTOR * prd = resList . List [ i ] . PartialResourceList . PartialDescriptors ;
for ( ULONG j = 0 ; j < resList . List [ i ] . PartialResourceList . Count ; + + j )
{
if ( prd [ j ] . Type = = CmResourceTypeMemory )
{
// bar 0 is VGA area
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " %s: found %I64x \n " , __FUNCTION__ , prd [ j ] . u . Memory . Start . QuadPart ) ) ;
return prd [ j ] . u . Memory . Start . QuadPart ;
}
}
}
DbgPrint ( TRACE_LEVEL_ERROR , ( " %s: not found in resources \n " , __FUNCTION__ ) ) ;
return 0 ;
}
2014-09-02 09:36:27 +02:00
NTSTATUS VgaDevice : : HWInit ( PCM_RESOURCE_LIST pResList , DXGK_DISPLAY_INFORMATION * pDispInfo )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
UNREFERENCED_PARAMETER ( pResList ) ;
2016-10-13 15:29:17 +02:00
AcquireDisplayInfo ( * ( pDispInfo ) ) ;
2017-02-06 23:29:20 +01:00
// it is possible that the OS does not have current display information
// in this case the driver uses defaults, but physical address
// is still not initialized
if ( ! pDispInfo - > PhysicAddress . QuadPart )
{
pDispInfo - > PhysicAddress . QuadPart = GetVgaFrameBuffer ( * pResList ) ;
}
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return GetModeList ( pDispInfo ) ;
}
NTSTATUS VgaDevice : : HWClose ( void )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return STATUS_SUCCESS ;
}
2016-09-11 15:05:23 +02:00
NTSTATUS VgaDevice : : SetPowerState ( DEVICE_POWER_STATE DevicePowerState , DXGK_DISPLAY_INFORMATION * pDispInfo )
2014-09-02 09:36:27 +02:00
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " ---> %s \n " , __FUNCTION__ ) ) ;
X86BIOS_REGISTERS regs = { 0 } ;
regs . Eax = 0x4F10 ;
regs . Ebx = 0 ;
switch ( DevicePowerState )
{
case PowerDeviceUnspecified :
2016-10-13 15:29:18 +02:00
case PowerDeviceD0 :
regs . Ebx | = 0x1 ;
AcquireDisplayInfo ( * ( pDispInfo ) ) ;
break ;
2014-09-02 09:36:27 +02:00
case PowerDeviceD1 :
case PowerDeviceD2 :
case PowerDeviceD3 : regs . Ebx | = 0x400 ; break ;
}
if ( ! x86BiosCall ( 0x10 , & regs ) )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " x86BiosCall failed \n " ) ) ;
return STATUS_UNSUCCESSFUL ;
}
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return STATUS_SUCCESS ;
}
NTSTATUS
VgaDevice : : ExecutePresentDisplayOnly (
_In_ BYTE * DstAddr ,
_In_ UINT DstBitPerPixel ,
_In_ BYTE * SrcAddr ,
_In_ UINT SrcBytesPerPixel ,
_In_ LONG SrcPitch ,
_In_ ULONG NumMoves ,
_In_ D3DKMT_MOVE_RECT * Moves ,
_In_ ULONG NumDirtyRects ,
_In_ RECT * DirtyRect ,
_In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation ,
_In_ const CURRENT_BDD_MODE * pModeCur )
/*++
Routine Description :
The method creates present worker thread and provides context
for it filled with present commands
Arguments :
DstAddr - address of destination surface
DstBitPerPixel - color depth of destination surface
SrcAddr - address of source surface
SrcBytesPerPixel - bytes per pixel of source surface
SrcPitch - source surface pitch ( bytes in a row )
NumMoves - number of moves to be copied
Moves - moves ' data
NumDirtyRects - number of rectangles to be copied
DirtyRect - rectangles ' data
Rotation - roatation to be performed when executing copy
CallBack - callback for present worker thread to report execution status
Return Value :
Status
- - */
{
PAGED_CODE ( ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
NTSTATUS Status = STATUS_SUCCESS ;
SIZE_T sizeMoves = NumMoves * sizeof ( D3DKMT_MOVE_RECT ) ;
SIZE_T sizeRects = NumDirtyRects * sizeof ( RECT ) ;
SIZE_T size = sizeof ( DoPresentMemory ) + sizeMoves + sizeRects ;
DoPresentMemory * ctx = reinterpret_cast < DoPresentMemory * >
( new ( NonPagedPoolNx ) BYTE [ size ] ) ;
if ( ! ctx )
{
return STATUS_NO_MEMORY ;
}
RtlZeroMemory ( ctx , size ) ;
ctx - > DstAddr = DstAddr ;
ctx - > DstBitPerPixel = DstBitPerPixel ;
ctx - > DstStride = pModeCur - > DispInfo . Pitch ;
ctx - > SrcWidth = pModeCur - > SrcModeWidth ;
ctx - > SrcHeight = pModeCur - > SrcModeHeight ;
ctx - > SrcAddr = NULL ;
ctx - > SrcPitch = SrcPitch ;
ctx - > Rotation = Rotation ;
ctx - > NumMoves = NumMoves ;
ctx - > Moves = Moves ;
ctx - > NumDirtyRects = NumDirtyRects ;
ctx - > DirtyRect = DirtyRect ;
ctx - > Mdl = NULL ;
ctx - > DisplaySource = this ;
// Alternate between synch and asynch execution, for demonstrating
// that a real hardware implementation can do either
{
// Map Source into kernel space, as Blt will be executed by system worker thread
UINT sizeToMap = SrcBytesPerPixel * ctx - > SrcWidth * ctx - > SrcHeight ;
PMDL mdl = IoAllocateMdl ( ( PVOID ) SrcAddr , sizeToMap , FALSE , FALSE , NULL ) ;
if ( ! mdl )
{
return STATUS_INSUFFICIENT_RESOURCES ;
}
KPROCESSOR_MODE AccessMode = static_cast < KPROCESSOR_MODE > ( ( SrcAddr < =
( BYTE * const ) MM_USER_PROBE_ADDRESS ) ? UserMode : KernelMode ) ;
__try
{
// Probe and lock the pages of this buffer in physical memory.
// We need only IoReadAccess.
MmProbeAndLockPages ( mdl , AccessMode , IoReadAccess ) ;
}
# pragma prefast(suppress: __WARNING_EXCEPTIONEXECUTEHANDLER, "try / except is only able to protect against user-mode errors and these are the only errors we try to catch here");
__except ( EXCEPTION_EXECUTE_HANDLER )
{
Status = GetExceptionCode ( ) ;
IoFreeMdl ( mdl ) ;
return Status ;
}
// Map the physical pages described by the MDL into system space.
// Note: double mapping the buffer this way causes lot of system
// overhead for large size buffers.
ctx - > SrcAddr = reinterpret_cast < BYTE * >
2015-10-21 17:54:37 +02:00
( MmGetSystemAddressForMdlSafe ( mdl , NormalPagePriority | MdlMappingNoExecute ) ) ;
2014-09-02 09:36:27 +02:00
if ( ! ctx - > SrcAddr ) {
Status = STATUS_INSUFFICIENT_RESOURCES ;
MmUnlockPages ( mdl ) ;
IoFreeMdl ( mdl ) ;
return Status ;
}
// Save Mdl to unmap and unlock the pages in worker thread
ctx - > Mdl = mdl ;
}
BYTE * rects = reinterpret_cast < BYTE * > ( ctx + 1 ) ;
// copy moves and update pointer
if ( Moves )
{
memcpy ( rects , Moves , sizeMoves ) ;
ctx - > Moves = reinterpret_cast < D3DKMT_MOVE_RECT * > ( rects ) ;
rects + = sizeMoves ;
}
// copy dirty rects and update pointer
if ( DirtyRect )
{
memcpy ( rects , DirtyRect , sizeRects ) ;
ctx - > DirtyRect = reinterpret_cast < RECT * > ( rects ) ;
}
// Set up destination blt info
BLT_INFO DstBltInfo ;
DstBltInfo . pBits = ctx - > DstAddr ;
DstBltInfo . Pitch = ctx - > DstStride ;
DstBltInfo . BitsPerPel = ctx - > DstBitPerPixel ;
DstBltInfo . Offset . x = 0 ;
DstBltInfo . Offset . y = 0 ;
DstBltInfo . Rotation = ctx - > Rotation ;
DstBltInfo . Width = ctx - > SrcWidth ;
DstBltInfo . Height = ctx - > SrcHeight ;
// Set up source blt info
BLT_INFO SrcBltInfo ;
SrcBltInfo . pBits = ctx - > SrcAddr ;
SrcBltInfo . Pitch = ctx - > SrcPitch ;
SrcBltInfo . BitsPerPel = 32 ;
SrcBltInfo . Offset . x = 0 ;
SrcBltInfo . Offset . y = 0 ;
SrcBltInfo . Rotation = D3DKMDT_VPPR_IDENTITY ;
if ( ctx - > Rotation = = D3DKMDT_VPPR_ROTATE90 | |
ctx - > Rotation = = D3DKMDT_VPPR_ROTATE270 )
{
SrcBltInfo . Width = DstBltInfo . Height ;
SrcBltInfo . Height = DstBltInfo . Width ;
}
else
{
SrcBltInfo . Width = DstBltInfo . Width ;
SrcBltInfo . Height = DstBltInfo . Height ;
}
// Copy all the scroll rects from source image to video frame buffer.
for ( UINT i = 0 ; i < ctx - > NumMoves ; i + + )
{
RECT * pDestRect = & ctx - > Moves [ i ] . DestRect ;
BltBits ( & DstBltInfo ,
& SrcBltInfo ,
1 , // NumRects
pDestRect ) ;
}
// Copy all the dirty rects from source image to video frame buffer.
for ( UINT i = 0 ; i < ctx - > NumDirtyRects ; i + + )
{
RECT * pDirtyRect = & ctx - > DirtyRect [ i ] ;
BltBits ( & DstBltInfo ,
& SrcBltInfo ,
1 , // NumRects
pDirtyRect ) ;
}
// Unmap unmap and unlock the pages.
if ( ctx - > Mdl )
{
MmUnlockPages ( ctx - > Mdl ) ;
IoFreeMdl ( ctx - > Mdl ) ;
}
delete [ ] reinterpret_cast < BYTE * > ( ctx ) ;
return STATUS_SUCCESS ;
}
VOID VgaDevice : : BlackOutScreen ( CURRENT_BDD_MODE * pCurrentBddMod )
{
PAGED_CODE ( ) ;
UINT ScreenHeight = pCurrentBddMod - > DispInfo . Height ;
UINT ScreenPitch = pCurrentBddMod - > DispInfo . Pitch ;
PHYSICAL_ADDRESS NewPhysAddrStart = pCurrentBddMod - > DispInfo . PhysicAddress ;
PHYSICAL_ADDRESS NewPhysAddrEnd ;
NewPhysAddrEnd . QuadPart = NewPhysAddrStart . QuadPart + ( ScreenHeight * ScreenPitch ) ;
if ( pCurrentBddMod - > Flags . FrameBufferIsActive )
{
BYTE * MappedAddr = reinterpret_cast < BYTE * > ( pCurrentBddMod - > FrameBuffer . Ptr ) ;
// Zero any memory at the start that hasn't been zeroed recently
if ( NewPhysAddrStart . QuadPart < pCurrentBddMod - > ZeroedOutStart . QuadPart )
{
if ( NewPhysAddrEnd . QuadPart < pCurrentBddMod - > ZeroedOutStart . QuadPart )
{
// No overlap
RtlZeroMemory ( MappedAddr , ScreenHeight * ScreenPitch ) ;
}
else
{
RtlZeroMemory ( MappedAddr , ( UINT ) ( pCurrentBddMod - > ZeroedOutStart . QuadPart - NewPhysAddrStart . QuadPart ) ) ;
}
}
// Zero any memory at the end that hasn't been zeroed recently
if ( NewPhysAddrEnd . QuadPart > pCurrentBddMod - > ZeroedOutEnd . QuadPart )
{
if ( NewPhysAddrStart . QuadPart > pCurrentBddMod - > ZeroedOutEnd . QuadPart )
{
// No overlap
// NOTE: When actual pixels were the most recent thing drawn, ZeroedOutStart & ZeroedOutEnd will both be 0
// and this is the path that will be used to black out the current screen.
RtlZeroMemory ( MappedAddr , ScreenHeight * ScreenPitch ) ;
}
else
{
RtlZeroMemory ( MappedAddr , ( UINT ) ( NewPhysAddrEnd . QuadPart - pCurrentBddMod - > ZeroedOutEnd . QuadPart ) ) ;
}
}
}
pCurrentBddMod - > ZeroedOutStart . QuadPart = NewPhysAddrStart . QuadPart ;
pCurrentBddMod - > ZeroedOutEnd . QuadPart = NewPhysAddrEnd . QuadPart ;
}
2016-09-13 00:02:01 +02:00
QXL_NON_PAGED
2014-09-02 09:36:27 +02:00
BOOLEAN VgaDevice : : InterruptRoutine ( _In_ PDXGKRNL_INTERFACE pDxgkInterface , _In_ ULONG MessageNumber )
{
UNREFERENCED_PARAMETER ( pDxgkInterface ) ;
UNREFERENCED_PARAMETER ( MessageNumber ) ;
return FALSE ;
}
2016-09-13 00:02:01 +02:00
QXL_NON_PAGED
2014-09-02 09:36:27 +02:00
VOID VgaDevice : : DpcRoutine ( PVOID )
{
}
2016-09-13 00:02:01 +02:00
QXL_NON_PAGED
2014-09-02 09:36:27 +02:00
VOID VgaDevice : : ResetDevice ( VOID )
{
}
2016-09-26 15:00:07 +02:00
NTSTATUS VgaDevice : : AcquireFrameBuffer ( CURRENT_BDD_MODE * pCurrentBddMode )
{
2016-09-13 00:01:21 +02:00
PAGED_CODE ( ) ;
2016-09-26 15:00:08 +02:00
if ( pCurrentBddMode - > Flags . DoNotMapOrUnmap ) {
return STATUS_UNSUCCESSFUL ;
}
2016-09-26 15:00:07 +02:00
// Map the new frame buffer
QXL_ASSERT ( pCurrentBddMode - > FrameBuffer . Ptr = = NULL ) ;
NTSTATUS status = MapFrameBuffer ( pCurrentBddMode - > DispInfo . PhysicAddress ,
pCurrentBddMode - > DispInfo . Pitch * pCurrentBddMode - > DispInfo . Height ,
& ( pCurrentBddMode - > FrameBuffer . Ptr ) ) ;
2016-09-26 15:00:08 +02:00
if ( NT_SUCCESS ( status ) )
{
pCurrentBddMode - > Flags . FrameBufferIsActive = TRUE ;
}
2016-09-26 15:00:07 +02:00
return status ;
}
NTSTATUS VgaDevice : : ReleaseFrameBuffer ( CURRENT_BDD_MODE * pCurrentBddMode )
{
2016-09-13 00:01:21 +02:00
PAGED_CODE ( ) ;
2016-09-26 15:00:07 +02:00
NTSTATUS status = UnmapFrameBuffer ( pCurrentBddMode - > FrameBuffer . Ptr , pCurrentBddMode - > DispInfo . Height * pCurrentBddMode - > DispInfo . Pitch ) ;
pCurrentBddMode - > FrameBuffer . Ptr = NULL ;
pCurrentBddMode - > Flags . FrameBufferIsActive = FALSE ;
return status ;
}
2014-09-02 09:36:27 +02:00
NTSTATUS VgaDevice : : SetPointerShape ( _In_ CONST DXGKARG_SETPOINTERSHAPE * pSetPointerShape )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-12-15 10:31:09 +01:00
UNREFERENCED_PARAMETER ( pSetPointerShape ) ;
2014-09-02 09:36:27 +02:00
return STATUS_NOT_SUPPORTED ;
}
NTSTATUS VgaDevice : : SetPointerPosition ( _In_ CONST DXGKARG_SETPOINTERPOSITION * pSetPointerPosition )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-12-15 10:31:09 +01:00
UNREFERENCED_PARAMETER ( pSetPointerPosition ) ;
2014-09-02 09:36:27 +02:00
return STATUS_SUCCESS ;
}
2015-02-08 11:04:39 +01:00
NTSTATUS VgaDevice : : Escape ( _In_ CONST DXGKARG_ESCAPE * pEscap )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2015-02-08 11:04:39 +01:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return STATUS_NOT_IMPLEMENTED ;
}
2014-09-02 09:36:27 +02:00
QxlDevice : : QxlDevice ( _In_ QxlDod * pQxlDod )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
m_pQxlDod = pQxlDod ;
m_ModeInfo = NULL ;
m_ModeCount = 0 ;
m_ModeNumbers = NULL ;
m_CurrentMode = 0 ;
2015-02-08 11:04:39 +01:00
m_CustomMode = 0 ;
2014-09-02 09:36:27 +02:00
m_FreeOutputs = 0 ;
m_Pending = 0 ;
2017-04-01 18:40:28 +02:00
m_PresentThread = NULL ;
2017-04-08 12:46:50 +02:00
m_bActive = FALSE ;
2014-09-02 09:36:27 +02:00
}
QxlDevice : : ~ QxlDevice ( void )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2015-03-30 13:57:12 +02:00
HWClose ( ) ;
2016-09-08 15:43:32 +02:00
delete [ ] m_ModeInfo ;
2016-09-08 15:40:08 +02:00
delete [ ] m_ModeNumbers ;
2014-09-02 09:36:27 +02:00
m_ModeInfo = NULL ;
m_ModeNumbers = NULL ;
m_CurrentMode = 0 ;
m_ModeCount = 0 ;
}
BOOL QxlDevice : : SetVideoModeInfo ( UINT Idx , QXLMode * pModeInfo )
{
PVIDEO_MODE_INFORMATION pMode = NULL ;
ULONG color_bits ;
PAGED_CODE ( ) ;
pMode = & m_ModeInfo [ Idx ] ;
pMode - > Length = sizeof ( VIDEO_MODE_INFORMATION ) ;
2015-03-24 07:22:45 +01:00
pMode - > ModeIndex = Idx ;
2014-09-02 09:36:27 +02:00
pMode - > VisScreenWidth = pModeInfo - > x_res ;
pMode - > VisScreenHeight = pModeInfo - > y_res ;
pMode - > ScreenStride = pModeInfo - > stride ;
pMode - > NumberOfPlanes = 1 ;
pMode - > BitsPerPlane = pModeInfo - > bits ;
pMode - > Frequency = 100 ;
pMode - > XMillimeter = pModeInfo - > x_mili ;
pMode - > YMillimeter = pModeInfo - > y_mili ;
color_bits = ( pModeInfo - > bits = = 16 ) ? 5 : 8 ;
pMode - > NumberRedBits = color_bits ;
pMode - > NumberGreenBits = color_bits ;
pMode - > NumberBlueBits = color_bits ;
pMode - > BlueMask = ( 1 < < color_bits ) - 1 ;
pMode - > GreenMask = pMode - > BlueMask < < color_bits ;
pMode - > RedMask = pMode - > GreenMask < < color_bits ;
pMode - > AttributeFlags = VIDEO_MODE_COLOR | VIDEO_MODE_GRAPHICS ;
pMode - > VideoMemoryBitmapWidth = pModeInfo - > x_res ;
pMode - > VideoMemoryBitmapHeight = pModeInfo - > y_res ;
pMode - > DriverSpecificAttributeFlags = pModeInfo - > orientation ;
return TRUE ;
}
2015-02-18 10:57:00 +01:00
void QxlDevice : : UpdateVideoModeInfo ( UINT Idx , UINT xres , UINT yres , UINT bpp )
2015-02-08 11:04:39 +01:00
{
PVIDEO_MODE_INFORMATION pMode = NULL ;
2016-09-08 13:03:56 +02:00
UINT bytes_pp = ( bpp + 7 ) / 8 ;
2015-02-08 11:04:39 +01:00
ULONG color_bits ;
PAGED_CODE ( ) ;
2016-09-08 13:03:56 +02:00
2015-02-08 11:04:39 +01:00
pMode = & m_ModeInfo [ Idx ] ;
pMode - > VisScreenWidth = xres ;
pMode - > VisScreenHeight = yres ;
pMode - > ScreenStride = ( xres * bytes_pp + 3 ) & ~ 0x3 ;
pMode - > BitsPerPlane = bpp ;
color_bits = ( bpp = = 16 ) ? 5 : 8 ;
pMode - > NumberRedBits = color_bits ;
pMode - > NumberGreenBits = color_bits ;
pMode - > NumberBlueBits = color_bits ;
pMode - > BlueMask = ( 1 < < color_bits ) - 1 ;
pMode - > GreenMask = pMode - > BlueMask < < color_bits ;
pMode - > RedMask = pMode - > GreenMask < < color_bits ;
}
2014-09-02 09:36:27 +02:00
NTSTATUS QxlDevice : : GetModeList ( DXGK_DISPLAY_INFORMATION * pDispInfo )
{
PAGED_CODE ( ) ;
NTSTATUS Status = STATUS_SUCCESS ;
QXLModes * modes ;
ULONG ModeCount ;
2015-02-08 11:04:39 +01:00
USHORT SuitableModeCount ;
2014-09-02 09:36:27 +02:00
USHORT CurrentMode ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
modes = ( QXLModes * ) ( ( UCHAR * ) m_RomHdr + m_RomHdr - > modes_offset ) ;
if ( m_RomSize < m_RomHdr - > modes_offset + sizeof ( QXLModes ) | |
( ModeCount = modes - > n_modes ) = = 0 | | m_RomSize <
m_RomHdr - > modes_offset + sizeof ( QXLModes ) + ModeCount * sizeof ( QXLMode ) ) {
DbgPrint ( TRACE_LEVEL_ERROR , ( " %s: bad rom size \n " , __FUNCTION__ ) ) ;
return STATUS_UNSUCCESSFUL ;
}
2016-09-08 15:43:32 +02:00
delete [ ] m_ModeInfo ;
2016-09-08 15:40:08 +02:00
delete [ ] m_ModeNumbers ;
2015-03-30 13:57:12 +02:00
m_ModeInfo = NULL ;
m_ModeNumbers = NULL ;
2014-09-02 09:36:27 +02:00
ModeCount + = 2 ;
2016-09-08 15:43:32 +02:00
m_ModeInfo = new ( PagedPool ) VIDEO_MODE_INFORMATION [ ModeCount ] ;
2015-03-24 06:41:58 +01:00
if ( ! m_ModeInfo )
{
Status = STATUS_NO_MEMORY ;
DbgPrint ( TRACE_LEVEL_ERROR , ( " QxlDevice::GetModeList failed to allocate m_ModeInfo memory \n " ) ) ;
return Status ;
}
RtlZeroMemory ( m_ModeInfo , sizeof ( VIDEO_MODE_INFORMATION ) * ModeCount ) ;
2016-09-08 15:40:08 +02:00
m_ModeNumbers = new ( PagedPool ) USHORT [ ModeCount ] ;
2015-03-24 06:41:58 +01:00
if ( ! m_ModeNumbers )
{
Status = STATUS_NO_MEMORY ;
DbgPrint ( TRACE_LEVEL_ERROR , ( " QxlDevice::GetModeList failed to allocate m_ModeNumbers memory \n " ) ) ;
return Status ;
}
RtlZeroMemory ( m_ModeNumbers , sizeof ( USHORT ) * ModeCount ) ;
2014-09-02 09:36:27 +02:00
m_CurrentMode = 0 ;
UINT Height = pDispInfo - > Height ;
UINT Width = pDispInfo - > Width ;
UINT BitsPerPixel = BPPFromPixelFormat ( pDispInfo - > ColorFormat ) ;
2015-02-19 11:07:24 +01:00
if ( Width = = 0 | | Height = = 0 | | BitsPerPixel ! = QXL_BPP )
{
Width = MIN_WIDTH_SIZE ;
Height = MIN_HEIGHT_SIZE ;
BitsPerPixel = QXL_BPP ;
}
2014-09-02 09:36:27 +02:00
for ( CurrentMode = 0 , SuitableModeCount = 0 ;
2015-02-08 11:04:39 +01:00
CurrentMode < modes - > n_modes ;
2014-09-02 09:36:27 +02:00
CurrentMode + + )
{
QXLMode * tmpModeInfo = & modes - > modes [ CurrentMode ] ;
2015-02-18 10:57:00 +01:00
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " %s: modes[%d] x_res = %d, y_res = %d, bits = %d BitsPerPixel = %d \n " , __FUNCTION__ , CurrentMode , tmpModeInfo - > x_res , tmpModeInfo - > y_res , tmpModeInfo - > bits , BitsPerPixel ) ) ;
2014-09-02 09:36:27 +02:00
2017-02-16 15:30:59 +01:00
if ( tmpModeInfo - > x_res > = MIN_WIDTH_SIZE & &
tmpModeInfo - > y_res > = MIN_HEIGHT_SIZE & &
2015-02-18 10:57:00 +01:00
tmpModeInfo - > bits = = QXL_BPP )
2014-09-02 09:36:27 +02:00
{
2015-02-23 12:21:14 +01:00
m_ModeNumbers [ SuitableModeCount ] = SuitableModeCount ;
2014-09-02 09:36:27 +02:00
SetVideoModeInfo ( SuitableModeCount , tmpModeInfo ) ;
2014-12-06 05:44:28 +01:00
if ( tmpModeInfo - > x_res = = MIN_WIDTH_SIZE & &
tmpModeInfo - > y_res = = MIN_HEIGHT_SIZE )
2014-09-02 09:36:27 +02:00
{
2015-02-08 11:04:39 +01:00
m_CurrentMode = SuitableModeCount ;
2014-09-02 09:36:27 +02:00
}
SuitableModeCount + + ;
}
}
if ( SuitableModeCount = = 0 )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " No video modes supported \n " ) ) ;
Status = STATUS_UNSUCCESSFUL ;
}
2015-02-08 11:04:39 +01:00
m_CustomMode = SuitableModeCount ;
for ( CurrentMode = SuitableModeCount ;
CurrentMode < SuitableModeCount + 2 ;
CurrentMode + + )
{
m_ModeNumbers [ CurrentMode ] = CurrentMode ;
memcpy ( & m_ModeInfo [ CurrentMode ] , & m_ModeInfo [ m_CurrentMode ] , sizeof ( VIDEO_MODE_INFORMATION ) ) ;
}
m_ModeCount = SuitableModeCount + 2 ;
2015-02-18 10:57:00 +01:00
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " ModeCount filtered %d \n " , m_ModeCount ) ) ;
2015-02-08 11:04:39 +01:00
for ( ULONG idx = 0 ; idx < GetModeCount ( ) ; idx + + )
2014-09-02 09:36:27 +02:00
{
2015-02-18 10:57:00 +01:00
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " type %x, XRes = %d, YRes = %d, BPP = %d \n " ,
2014-09-02 09:36:27 +02:00
m_ModeNumbers [ idx ] ,
m_ModeInfo [ idx ] . VisScreenWidth ,
m_ModeInfo [ idx ] . VisScreenHeight ,
m_ModeInfo [ idx ] . BitsPerPlane ) ) ;
}
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return Status ;
}
NTSTATUS QxlDevice : : QueryCurrentMode ( PVIDEO_MODE RequestedMode )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
NTSTATUS Status = STATUS_SUCCESS ;
UNREFERENCED_PARAMETER ( RequestedMode ) ;
return Status ;
}
2017-05-05 13:54:58 +02:00
template < typename Closure >
class QxlGenericOperation : public QxlPresentOperation
{
public :
QxlGenericOperation ( const Closure & _closure ) : closure ( _closure ) { PAGED_CODE ( ) ; }
void Run ( ) override { PAGED_CODE ( ) ; closure ( ) ; }
private :
Closure closure ;
} ;
template < typename Closure >
__forceinline QxlPresentOperation * BuildQxlOperation ( Closure & & closure )
{
return new ( PagedPool ) QxlGenericOperation < Closure > ( closure ) ;
}
2014-09-02 09:36:27 +02:00
NTSTATUS QxlDevice : : SetCurrentMode ( ULONG Mode )
{
2016-09-11 15:05:21 +02:00
PAGED_CODE ( ) ;
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " ---> %s - %d: Mode = %d \n " , __FUNCTION__ , m_Id , Mode ) ) ;
2015-02-08 11:04:39 +01:00
for ( ULONG idx = 0 ; idx < GetModeCount ( ) ; idx + + )
2014-09-02 09:36:27 +02:00
{
if ( Mode = = m_ModeNumbers [ idx ] )
{
2017-05-05 13:54:58 +02:00
if ( ! m_PresentThread )
break ;
2016-09-11 15:05:21 +02:00
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " %s device %d: setting current mode %d (%d x %d) \n " ,
__FUNCTION__ , m_Id , Mode , m_ModeInfo [ idx ] . VisScreenWidth ,
m_ModeInfo [ idx ] . VisScreenHeight ) ) ;
2017-05-05 13:54:58 +02:00
// execute the operation in the worker thread to avoiding
// executing drawing commands while changing resolution
KEVENT finishEvent ;
KeInitializeEvent ( & finishEvent , SynchronizationEvent , FALSE ) ;
+ + m_DrawGeneration ;
QxlPresentOperation * operation = BuildQxlOperation ( [ = , this , & finishEvent ] ( ) {
PAGED_CODE ( ) ;
DestroyPrimarySurface ( ) ;
CreatePrimarySurface ( & m_ModeInfo [ idx ] ) ;
KeSetEvent ( & finishEvent , IO_NO_INCREMENT , FALSE ) ;
} ) ;
if ( ! operation )
return STATUS_NO_MEMORY ;
PostToWorkerThread ( operation ) ;
WaitForObject ( & finishEvent , NULL ) ;
2014-09-02 09:36:27 +02:00
return STATUS_SUCCESS ;
}
}
2016-09-11 15:05:21 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s failed \n " , __FUNCTION__ ) ) ;
2014-09-02 09:36:27 +02:00
return STATUS_UNSUCCESSFUL ;
}
NTSTATUS QxlDevice : : GetCurrentMode ( ULONG * pMode )
{
2016-09-11 15:05:21 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
NTSTATUS Status = STATUS_SUCCESS ;
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " ---> %s \n " , __FUNCTION__ ) ) ;
UNREFERENCED_PARAMETER ( pMode ) ;
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return Status ;
}
2016-09-28 13:09:27 +02:00
NTSTATUS QxlDevice : : SetPowerState ( DEVICE_POWER_STATE DevicePowerState , DXGK_DISPLAY_INFORMATION * pDispInfo )
2014-09-02 09:36:27 +02:00
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
switch ( DevicePowerState )
{
case PowerDeviceUnspecified :
2014-12-05 23:20:04 +01:00
case PowerDeviceD0 : QxlInit ( pDispInfo ) ; break ;
2014-09-02 09:36:27 +02:00
case PowerDeviceD1 :
case PowerDeviceD2 :
case PowerDeviceD3 : QxlClose ( ) ; break ;
}
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return STATUS_SUCCESS ;
}
NTSTATUS QxlDevice : : HWInit ( PCM_RESOURCE_LIST pResList , DXGK_DISPLAY_INFORMATION * pDispInfo )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
2016-09-11 15:05:20 +02:00
PDXGKRNL_INTERFACE pDxgkInterface = m_pQxlDod - > GetDxgkInterface ( ) ;
2014-09-02 09:36:27 +02:00
UINT pci_range = QXL_RAM_RANGE_INDEX ;
for ( ULONG i = 0 ; i < pResList - > Count ; + + i )
{
PCM_FULL_RESOURCE_DESCRIPTOR pFullResDescriptor = & pResList - > List [ i ] ;
for ( ULONG j = 0 ; j < pFullResDescriptor - > PartialResourceList . Count ; + + j )
{
PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDescriptor = & pFullResDescriptor - > PartialResourceList . PartialDescriptors [ j ] ;
switch ( pResDescriptor - > Type )
{
case CmResourceTypePort :
{
PVOID IoBase = NULL ;
ULONG IoLength = pResDescriptor - > u . Port . Length ;
NTSTATUS Status = STATUS_SUCCESS ;
2015-03-30 13:57:12 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " IO Port Info [%08I64X-%08I64X] \n " ,
2014-09-02 09:36:27 +02:00
pResDescriptor - > u . Port . Start . QuadPart ,
pResDescriptor - > u . Port . Start . QuadPart +
pResDescriptor - > u . Port . Length ) ) ;
m_IoMapped = ( pResDescriptor - > Flags & CM_RESOURCE_PORT_IO ) ? FALSE : TRUE ;
if ( m_IoMapped )
{
Status = pDxgkInterface - > DxgkCbMapMemory ( pDxgkInterface - > DeviceHandle ,
pResDescriptor - > u . Port . Start ,
IoLength ,
TRUE , /* IN BOOLEAN InIoSpace */
FALSE , /* IN BOOLEAN MapToUserMode */
MmNonCached , /* IN MEMORY_CACHING_TYPE CacheType */
& IoBase /*OUT PVOID *VirtualAddress*/
) ;
if ( Status = = STATUS_SUCCESS )
{
m_IoBase = ( PUCHAR ) IoBase ;
m_IoSize = IoLength ;
}
else
{
2015-03-30 13:57:12 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " DxgkCbMapMemor (CmResourceTypePort) failed with status 0x%X \n " , Status ) ) ;
2014-09-02 09:36:27 +02:00
}
}
else
{
m_IoBase = ( PUCHAR ) ( ULONG_PTR ) pResDescriptor - > u . Port . Start . QuadPart ;
m_IoSize = pResDescriptor - > u . Port . Length ;
}
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " io_base [%p-%p] \n " ,
2014-09-02 09:36:27 +02:00
m_IoBase ,
m_IoBase +
m_IoSize ) ) ;
}
break ;
case CmResourceTypeInterrupt :
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " Interrupt level: 0x%0x, Vector: 0x%0x \n " ,
pResDescriptor - > u . Interrupt . Level ,
pResDescriptor - > u . Interrupt . Vector ) ) ;
break ;
case CmResourceTypeMemory :
{
PVOID MemBase = NULL ;
ULONG MemLength = pResDescriptor - > u . Memory . Length ;
NTSTATUS Status = STATUS_SUCCESS ;
2015-03-30 13:57:12 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " Memory mapped: (%x:%x) Length:(%x) \n " ,
2014-09-02 09:36:27 +02:00
pResDescriptor - > u . Memory . Start . LowPart ,
pResDescriptor - > u . Memory . Start . HighPart ,
pResDescriptor - > u . Memory . Length ) ) ;
Status = pDxgkInterface - > DxgkCbMapMemory ( pDxgkInterface - > DeviceHandle ,
pResDescriptor - > u . Memory . Start ,
MemLength ,
FALSE , /* IN BOOLEAN InIoSpace */
FALSE , /* IN BOOLEAN MapToUserMode */
MmNonCached , /* IN MEMORY_CACHING_TYPE CacheType */
& MemBase /*OUT PVOID *VirtualAddress*/
) ;
if ( Status = = STATUS_SUCCESS )
{
switch ( pci_range )
{
case QXL_RAM_RANGE_INDEX :
m_RamPA = pResDescriptor - > u . Memory . Start ;
m_RamStart = ( UINT8 * ) MemBase ;
m_RamSize = MemLength ;
2014-12-06 05:44:28 +01:00
if ( pDispInfo - > PhysicAddress . QuadPart = = 0L ) {
pDispInfo - > PhysicAddress . QuadPart = m_RamPA . QuadPart ;
}
2014-09-02 09:36:27 +02:00
pci_range = QXL_VRAM_RANGE_INDEX ;
break ;
case QXL_VRAM_RANGE_INDEX :
m_VRamPA = pResDescriptor - > u . Memory . Start ;
m_VRamStart = ( UINT8 * ) MemBase ;
m_VRamSize = MemLength ;
pci_range = QXL_ROM_RANGE_INDEX ;
break ;
case QXL_ROM_RANGE_INDEX :
m_RomHdr = ( QXLRom * ) MemBase ;
m_RomSize = MemLength ;
pci_range = QXL_PCI_RANGES ;
break ;
default :
2017-05-25 15:06:38 +02:00
DbgPrint ( TRACE_LEVEL_WARNING , ( " Unused memory range found \n " ) ) ;
pDxgkInterface - > DxgkCbUnmapMemory ( pDxgkInterface - > DeviceHandle , MemBase ) ;
2014-09-02 09:36:27 +02:00
break ;
}
}
2015-03-30 13:57:12 +02:00
else
{
2017-05-25 15:06:39 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " DxgkCbMapMemory (CmResourceTypeMemory) failed with status 0x%X \n " , Status ) ) ;
2015-03-30 13:57:12 +02:00
}
2014-09-02 09:36:27 +02:00
}
break ;
case CmResourceTypeDma :
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " Dma \n " ) ) ;
break ;
case CmResourceTypeDeviceSpecific :
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " Device Specific \n " ) ) ;
break ;
case CmResourceTypeBusNumber :
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " Bus number \n " ) ) ;
break ;
default :
break ;
}
}
}
if ( m_IoBase = = NULL | | m_IoSize = = 0 | |
m_RomHdr = = NULL | | m_RomSize = = 0 | |
m_RomHdr - > magic ! = QXL_ROM_MAGIC | |
m_RamStart = = NULL | | m_RamSize = = 0 | |
m_VRamStart = = NULL | | m_VRamSize = = 0 | |
( m_RamHdr = ( QXLRam * ) ( m_RamStart + m_RomHdr - > ram_header_offset ) ) = = NULL | |
m_RamHdr - > magic ! = QXL_RAM_MAGIC )
{
UnmapMemory ( ) ;
2017-05-25 15:06:39 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " %s failed initializing HW resources \n " , __FUNCTION__ ) ) ;
2014-09-02 09:36:27 +02:00
return STATUS_UNSUCCESSFUL ;
}
m_LogBuf = m_RamHdr - > log_buf ;
m_LogPort = m_IoBase + QXL_IO_LOG ;
2014-12-05 23:20:04 +01:00
m_Id = m_RomHdr - > id ;
2014-09-02 09:36:27 +02:00
CreateEvents ( ) ;
return QxlInit ( pDispInfo ) ;
}
2017-04-01 18:40:28 +02:00
NTSTATUS QxlDevice : : StartPresentThread ( )
{
PAGED_CODE ( ) ;
OBJECT_ATTRIBUTES ObjectAttributes ;
NTSTATUS Status ;
InitializeObjectAttributes ( & ObjectAttributes , NULL , OBJ_KERNEL_HANDLE , NULL , NULL ) ;
Status = PsCreateSystemThread (
& m_PresentThread ,
THREAD_ALL_ACCESS ,
& ObjectAttributes ,
NULL ,
NULL ,
PresentThreadRoutineWrapper ,
this ) ;
return Status ;
}
2014-09-02 09:36:27 +02:00
NTSTATUS QxlDevice : : QxlInit ( DXGK_DISPLAY_INFORMATION * pDispInfo )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
NTSTATUS Status = STATUS_SUCCESS ;
if ( ! InitMemSlots ( ) ) {
2014-12-05 23:20:04 +01:00
DestroyMemSlots ( ) ;
2015-03-30 13:57:12 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " %s failed init mem slots \n " , __FUNCTION__ ) ) ;
2014-12-05 23:20:04 +01:00
return STATUS_UNSUCCESSFUL ;
}
2014-09-02 09:36:27 +02:00
2014-12-05 23:20:04 +01:00
Status = GetModeList ( pDispInfo ) ;
2014-09-02 09:36:27 +02:00
if ( ! NT_SUCCESS ( Status ) )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " GetModeList failed with status 0x%X \n " ,
Status ) ) ;
return Status ;
}
WRITE_PORT_UCHAR ( ( PUCHAR ) ( m_IoBase + QXL_IO_RESET ) , 0 ) ;
CreateRings ( ) ;
2016-09-04 16:12:33 +02:00
m_RamHdr - > int_mask = WIN_QXL_INT_MASK ;
2014-09-02 09:36:27 +02:00
CreateMemSlots ( ) ;
InitDeviceMemoryResources ( ) ;
2017-04-08 12:46:50 +02:00
Status = InitMonitorConfig ( ) ;
if ( ! NT_SUCCESS ( Status ) )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " InitMonitorConfig failed with status 0x%X \n " , Status ) ) ;
return Status ;
}
2016-10-13 15:29:17 +02:00
Status = AcquireDisplayInfo ( * ( pDispInfo ) ) ;
2017-04-01 18:40:28 +02:00
if ( NT_SUCCESS ( Status ) )
{
2017-04-08 12:46:50 +02:00
m_bActive = TRUE ;
2017-04-01 18:40:28 +02:00
Status = StartPresentThread ( ) ;
}
2017-04-08 12:46:50 +02:00
if ( ! NT_SUCCESS ( Status ) ) {
m_bActive = FALSE ;
}
2014-09-02 09:36:27 +02:00
return Status ;
}
void QxlDevice : : QxlClose ( )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2017-04-08 12:46:50 +02:00
m_bActive = FALSE ;
2017-04-01 18:40:28 +02:00
StopPresentThread ( ) ;
2014-09-02 09:36:27 +02:00
DestroyMemSlots ( ) ;
}
void QxlDevice : : UnmapMemory ( void )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2016-09-11 15:05:20 +02:00
PDXGKRNL_INTERFACE pDxgkInterface = m_pQxlDod - > GetDxgkInterface ( ) ;
2014-09-02 09:36:27 +02:00
if ( m_IoMapped & & m_IoBase )
{
2017-05-25 15:06:37 +02:00
pDxgkInterface - > DxgkCbUnmapMemory ( pDxgkInterface - > DeviceHandle , m_IoBase ) ;
2014-09-02 09:36:27 +02:00
}
m_IoBase = NULL ;
if ( m_RomHdr )
{
2017-05-25 15:06:37 +02:00
pDxgkInterface - > DxgkCbUnmapMemory ( pDxgkInterface - > DeviceHandle , m_RomHdr ) ;
2014-09-02 09:36:27 +02:00
m_RomHdr = NULL ;
}
if ( m_RamStart )
{
2017-05-25 15:06:37 +02:00
pDxgkInterface - > DxgkCbUnmapMemory ( pDxgkInterface - > DeviceHandle , m_RamStart ) ;
2014-09-02 09:36:27 +02:00
m_RamStart = NULL ;
}
if ( m_VRamStart )
{
2017-05-25 15:06:37 +02:00
pDxgkInterface - > DxgkCbUnmapMemory ( pDxgkInterface - > DeviceHandle , m_VRamStart ) ;
2014-09-02 09:36:27 +02:00
m_VRamStart = NULL ;
}
}
BOOL QxlDevice : : InitMemSlots ( void )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
m_SlotGenBits = m_RomHdr - > slot_gen_bits ;
m_SlotIdBits = m_RomHdr - > slot_id_bits ;
m_VaSlotMask = ( ~ ( uint64_t ) 0 ) > > ( m_SlotIdBits + m_SlotGenBits ) ;
2017-04-10 16:50:54 +02:00
RtlZeroMemory ( m_MemSlots , sizeof ( m_MemSlots ) ) ;
return TRUE ;
2014-09-02 09:36:27 +02:00
}
void QxlDevice : : DestroyMemSlots ( void )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
}
void QxlDevice : : CreatePrimarySurface ( PVIDEO_MODE_INFORMATION pModeInfo )
{
2016-09-11 15:05:21 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
QXLSurfaceCreate * primary_surface_create ;
2016-09-11 15:05:21 +02:00
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " ---> %s - %d: (%d x %d) \n " , __FUNCTION__ , m_Id ,
pModeInfo - > VisScreenWidth , pModeInfo - > VisScreenHeight ) ) ;
2014-09-02 09:36:27 +02:00
primary_surface_create = & m_RamHdr - > create_surface ;
primary_surface_create - > format = pModeInfo - > BitsPerPlane ;
primary_surface_create - > width = pModeInfo - > VisScreenWidth ;
primary_surface_create - > height = pModeInfo - > VisScreenHeight ;
primary_surface_create - > stride = pModeInfo - > ScreenStride ;
2017-04-10 17:02:47 +02:00
primary_surface_create - > mem = PA ( m_RamStart ) ;
2014-09-02 09:36:27 +02:00
2016-06-22 12:34:45 +02:00
primary_surface_create - > flags = 0 ;
2014-09-02 09:36:27 +02:00
primary_surface_create - > type = QXL_SURF_TYPE_PRIMARY ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--> %s format = %d, width = %d, height = %d, stride = %d \n " , __FUNCTION__ , pModeInfo - > BitsPerPlane , pModeInfo - > VisScreenWidth , pModeInfo - > VisScreenHeight ,
pModeInfo - > ScreenStride ) ) ;
// AsyncIo(QXL_IO_CREATE_PRIMARY_ASYNC, 0);
SyncIo ( QXL_IO_CREATE_PRIMARY , 0 ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
}
void QxlDevice : : DestroyPrimarySurface ( void )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
// AsyncIo(QXL_IO_DESTROY_PRIMARY_ASYNC, 0);
SyncIo ( QXL_IO_DESTROY_PRIMARY , 0 ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
}
2017-04-10 17:04:18 +02:00
inline QXLPHYSICAL QxlDevice : : PA ( PVOID virt )
2014-09-02 09:36:27 +02:00
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--> %s \n " , __FUNCTION__ ) ) ;
2017-04-10 17:02:47 +02:00
const MemSlot * pSlot = m_MemSlots ;
if ( virt < pSlot - > start_virt_addr | | virt > pSlot - > last_virt_addr )
+ + pSlot ;
2017-04-10 16:59:15 +02:00
return pSlot - > high_bits | ( ( UINT8 * ) virt - pSlot - > start_virt_addr ) ;
2014-09-02 09:36:27 +02:00
}
2017-04-10 17:04:18 +02:00
inline UINT8 * QxlDevice : : VA ( QXLPHYSICAL paddr )
2014-09-02 09:36:27 +02:00
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
2017-04-10 17:02:47 +02:00
UINT8 slot_id = UINT8 ( paddr > > ( 64 - m_SlotIdBits ) ) - m_RomHdr - > slots_start ;
const MemSlot * pSlot = & m_MemSlots [ slot_id & 1 ] ;
return pSlot - > start_virt_addr + ( paddr & m_VaSlotMask ) ;
2014-09-02 09:36:27 +02:00
}
void QxlDevice : : SetupHWSlot ( UINT8 Idx , MemSlot * pSlot )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
m_RamHdr - > mem_slot . mem_start = pSlot - > start_phys_addr ;
m_RamHdr - > mem_slot . mem_end = pSlot - > end_phys_addr ;
WRITE_PORT_UCHAR ( ( PUCHAR ) ( m_IoBase + QXL_IO_MEMSLOT_ADD ) , Idx ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <---> %s \n " , __FUNCTION__ ) ) ;
}
BOOL QxlDevice : : CreateEvents ( )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
KeInitializeEvent ( & m_DisplayEvent ,
SynchronizationEvent ,
FALSE ) ;
KeInitializeEvent ( & m_CursorEvent ,
SynchronizationEvent ,
FALSE ) ;
KeInitializeEvent ( & m_IoCmdEvent ,
SynchronizationEvent ,
FALSE ) ;
2017-04-01 18:40:28 +02:00
KeInitializeEvent ( & m_PresentEvent ,
SynchronizationEvent ,
FALSE ) ;
KeInitializeEvent ( & m_PresentThreadReadyEvent ,
SynchronizationEvent ,
FALSE ) ;
2017-03-28 19:59:46 +02:00
KeInitializeMutex ( & m_MemLock , 0 ) ;
KeInitializeMutex ( & m_CmdLock , 0 ) ;
KeInitializeMutex ( & m_IoLock , 0 ) ;
KeInitializeMutex ( & m_CrsLock , 0 ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return TRUE ;
}
BOOL QxlDevice : : CreateRings ( )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
m_CommandRing = & ( m_RamHdr - > cmd_ring ) ;
m_CursorRing = & ( m_RamHdr - > cursor_ring ) ;
m_ReleaseRing = & ( m_RamHdr - > release_ring ) ;
2017-04-01 18:40:28 +02:00
SPICE_RING_INIT ( m_PresentRing ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return TRUE ;
}
void QxlDevice : : AsyncIo ( UCHAR Port , UCHAR Value )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
LARGE_INTEGER timeout ;
2015-03-24 06:41:58 +01:00
BOOLEAN locked = FALSE ;
locked = WaitForObject ( & m_IoLock , NULL ) ;
2014-09-02 09:36:27 +02:00
WRITE_PORT_UCHAR ( m_IoBase + Port , Value ) ;
timeout . QuadPart = - 60000L * 1000 * 10 ;
2015-03-24 06:41:58 +01:00
WaitForObject ( & m_IoCmdEvent , & timeout ) ;
ReleaseMutex ( & m_IoLock , locked ) ;
2014-09-02 09:36:27 +02:00
}
void QxlDevice : : SyncIo ( UCHAR Port , UCHAR Value )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2015-03-24 06:41:58 +01:00
BOOLEAN locked = FALSE ;
locked = WaitForObject ( & m_IoLock , NULL ) ;
2014-09-02 09:36:27 +02:00
WRITE_PORT_UCHAR ( m_IoBase + Port , Value ) ;
2015-03-24 06:41:58 +01:00
ReleaseMutex ( & m_IoLock , locked ) ;
2014-09-02 09:36:27 +02:00
}
2017-04-10 16:59:15 +02:00
void QxlDevice : : SetupMemSlot ( UINT8 Idx , UINT64 pastart , UINT64 paend , UINT8 * vastart , UINT8 * valast )
2014-09-02 09:36:27 +02:00
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
UINT64 high_bits ;
MemSlot * pSlot ;
UINT8 slot_index ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
slot_index = m_RomHdr - > slots_start + Idx ;
2017-04-10 16:50:54 +02:00
pSlot = & m_MemSlots [ Idx ] ;
2014-09-02 09:36:27 +02:00
pSlot - > start_phys_addr = pastart ;
pSlot - > end_phys_addr = paend ;
pSlot - > start_virt_addr = vastart ;
2017-04-10 16:59:15 +02:00
pSlot - > last_virt_addr = valast ;
2014-09-02 09:36:27 +02:00
SetupHWSlot ( Idx + 1 , pSlot ) ;
high_bits = slot_index < < m_SlotGenBits ;
2016-09-12 17:06:25 +02:00
high_bits | = m_RomHdr - > slot_generation ;
2014-09-02 09:36:27 +02:00
high_bits < < = ( 64 - ( m_SlotGenBits + m_SlotIdBits ) ) ;
pSlot - > high_bits = high_bits ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
}
BOOL QxlDevice : : CreateMemSlots ( void )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s 3 \n " , __FUNCTION__ ) ) ;
UINT64 len = m_RomHdr - > surface0_area_size + m_RomHdr - > num_pages * PAGE_SIZE ;
2017-04-10 16:50:54 +02:00
SetupMemSlot ( m_MainMemSlot ,
2017-04-10 16:59:15 +02:00
( UINT64 ) m_RamPA . QuadPart ,
2017-04-10 16:50:54 +02:00
( UINT64 ) ( m_RamPA . QuadPart + len ) ,
2017-04-10 16:59:15 +02:00
m_RamStart ,
m_RamStart + len - 1 ) ;
2014-09-02 09:36:27 +02:00
len = m_VRamSize ;
2017-04-10 16:50:54 +02:00
SetupMemSlot ( m_SurfaceMemSlot ,
( UINT64 ) m_VRamPA . QuadPart ,
( UINT64 ) ( m_VRamPA . QuadPart + len ) ,
2017-04-10 16:59:15 +02:00
m_VRamStart ,
m_VRamStart + len - 1 ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return TRUE ;
}
void QxlDevice : : InitDeviceMemoryResources ( void )
{
2016-09-11 15:05:21 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s num_pages = %d \n " , __FUNCTION__ , m_RomHdr - > num_pages ) ) ;
InitMspace ( MSPACE_TYPE_DEVRAM , ( m_RamStart + m_RomHdr - > surface0_area_size ) , ( size_t ) ( m_RomHdr - > num_pages * PAGE_SIZE ) ) ;
InitMspace ( MSPACE_TYPE_VRAM , m_VRamStart , m_VRamSize ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
}
2017-04-08 12:46:50 +02:00
NTSTATUS QxlDevice : : InitMonitorConfig ( void )
2016-09-11 15:05:21 +02:00
{
PAGED_CODE ( ) ;
size_t config_size = sizeof ( QXLMonitorsConfig ) + sizeof ( QXLHead ) ;
m_monitor_config = ( QXLMonitorsConfig * ) AllocMem ( MSPACE_TYPE_DEVRAM , config_size , TRUE ) ;
2017-04-08 12:46:50 +02:00
if ( m_monitor_config ) {
RtlZeroMemory ( m_monitor_config , config_size ) ;
m_monitor_config_pa = & m_RamHdr - > monitors_config ;
2017-04-10 17:02:47 +02:00
* m_monitor_config_pa = PA ( m_monitor_config ) ;
2017-04-08 12:46:50 +02:00
}
return m_monitor_config ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL ;
2016-09-11 15:05:21 +02:00
}
2014-09-02 09:36:27 +02:00
void QxlDevice : : InitMspace ( UINT32 mspace_type , UINT8 * start , size_t capacity )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s type = %d, start = %p, capacity = %d \n " , __FUNCTION__ , mspace_type , start , capacity ) ) ;
m_MSInfo [ mspace_type ] . _mspace = create_mspace_with_base ( start , capacity , 0 , this ) ;
m_MSInfo [ mspace_type ] . mspace_start = start ;
m_MSInfo [ mspace_type ] . mspace_end = start + capacity ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s _mspace = %p \n " , __FUNCTION__ , m_MSInfo [ mspace_type ] . _mspace ) ) ;
}
2016-09-13 00:02:01 +02:00
QXL_NON_PAGED
2014-09-02 09:36:27 +02:00
void QxlDevice : : ResetDevice ( void )
{
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
m_RamHdr - > int_mask = ~ 0 ;
WRITE_PORT_UCHAR ( m_IoBase + QXL_IO_MEMSLOT_ADD , 0 ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
}
NTSTATUS
QxlDevice : : ExecutePresentDisplayOnly (
_In_ BYTE * DstAddr ,
_In_ UINT DstBitPerPixel ,
_In_ BYTE * SrcAddr ,
_In_ UINT SrcBytesPerPixel ,
_In_ LONG SrcPitch ,
_In_ ULONG NumMoves ,
_In_ D3DKMT_MOVE_RECT * Moves ,
_In_ ULONG NumDirtyRects ,
_In_ RECT * DirtyRect ,
_In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation ,
_In_ const CURRENT_BDD_MODE * pModeCur )
{
PAGED_CODE ( ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
NTSTATUS Status = STATUS_SUCCESS ;
2017-04-01 18:40:29 +02:00
QXLDrawable * * pDrawables = new ( NonPagedPoolNx ) QXLDrawable * [ NumDirtyRects + NumMoves + 1 ] ;
UINT nIndex = 0 ;
2014-09-02 09:36:27 +02:00
2017-04-01 18:40:29 +02:00
if ( ! pDrawables )
2014-09-02 09:36:27 +02:00
{
return STATUS_NO_MEMORY ;
}
2017-04-01 18:40:29 +02:00
DoPresentMemory ctx [ 1 ] ;
RtlZeroMemory ( ctx , sizeof ( ctx ) ) ;
2014-09-02 09:36:27 +02:00
ctx - > DstAddr = DstAddr ;
ctx - > DstBitPerPixel = DstBitPerPixel ;
ctx - > DstStride = pModeCur - > DispInfo . Pitch ;
ctx - > SrcWidth = pModeCur - > SrcModeWidth ;
ctx - > SrcHeight = pModeCur - > SrcModeHeight ;
ctx - > SrcAddr = NULL ;
ctx - > SrcPitch = SrcPitch ;
ctx - > Rotation = Rotation ;
ctx - > NumMoves = NumMoves ;
ctx - > Moves = Moves ;
ctx - > NumDirtyRects = NumDirtyRects ;
ctx - > DirtyRect = DirtyRect ;
ctx - > Mdl = NULL ;
ctx - > DisplaySource = this ;
2016-09-28 13:09:28 +02:00
// Source bitmap is in user mode, must be locked under __try/__except
// and mapped to kernel space before use.
2014-09-02 09:36:27 +02:00
{
2017-01-27 11:02:40 +01:00
LONG maxHeight = GetMaxSourceMappingHeight ( ctx - > DirtyRect , ctx - > NumDirtyRects ) ;
2016-09-28 13:09:28 +02:00
UINT sizeToMap = ctx - > SrcPitch * maxHeight ;
2014-09-02 09:36:27 +02:00
PMDL mdl = IoAllocateMdl ( ( PVOID ) SrcAddr , sizeToMap , FALSE , FALSE , NULL ) ;
if ( ! mdl )
{
2017-04-01 18:40:29 +02:00
delete [ ] pDrawables ;
2014-09-02 09:36:27 +02:00
return STATUS_INSUFFICIENT_RESOURCES ;
}
KPROCESSOR_MODE AccessMode = static_cast < KPROCESSOR_MODE > ( ( SrcAddr < =
( BYTE * const ) MM_USER_PROBE_ADDRESS ) ? UserMode : KernelMode ) ;
__try
{
// Probe and lock the pages of this buffer in physical memory.
// We need only IoReadAccess.
MmProbeAndLockPages ( mdl , AccessMode , IoReadAccess ) ;
}
# pragma prefast(suppress: __WARNING_EXCEPTIONEXECUTEHANDLER, "try / except is only able to protect against user-mode errors and these are the only errors we try to catch here");
__except ( EXCEPTION_EXECUTE_HANDLER )
{
Status = GetExceptionCode ( ) ;
IoFreeMdl ( mdl ) ;
2017-04-01 18:40:29 +02:00
delete [ ] pDrawables ;
2014-09-02 09:36:27 +02:00
return Status ;
}
// Map the physical pages described by the MDL into system space.
// Note: double mapping the buffer this way causes lot of system
// overhead for large size buffers.
ctx - > SrcAddr = reinterpret_cast < BYTE * >
2015-10-21 17:54:37 +02:00
( MmGetSystemAddressForMdlSafe ( mdl , NormalPagePriority | MdlMappingNoExecute ) ) ;
2014-09-02 09:36:27 +02:00
if ( ! ctx - > SrcAddr ) {
Status = STATUS_INSUFFICIENT_RESOURCES ;
MmUnlockPages ( mdl ) ;
IoFreeMdl ( mdl ) ;
2017-04-01 18:40:29 +02:00
delete [ ] pDrawables ;
2014-09-02 09:36:27 +02:00
return Status ;
}
// Save Mdl to unmap and unlock the pages in worker thread
ctx - > Mdl = mdl ;
}
// Set up destination blt info
BLT_INFO DstBltInfo ;
DstBltInfo . pBits = ctx - > DstAddr ;
DstBltInfo . Pitch = ctx - > DstStride ;
DstBltInfo . BitsPerPel = ctx - > DstBitPerPixel ;
DstBltInfo . Offset . x = 0 ;
DstBltInfo . Offset . y = 0 ;
DstBltInfo . Rotation = ctx - > Rotation ;
DstBltInfo . Width = ctx - > SrcWidth ;
DstBltInfo . Height = ctx - > SrcHeight ;
// Set up source blt info
BLT_INFO SrcBltInfo ;
SrcBltInfo . pBits = ctx - > SrcAddr ;
SrcBltInfo . Pitch = ctx - > SrcPitch ;
SrcBltInfo . BitsPerPel = 32 ;
SrcBltInfo . Offset . x = 0 ;
SrcBltInfo . Offset . y = 0 ;
SrcBltInfo . Rotation = D3DKMDT_VPPR_IDENTITY ;
if ( ctx - > Rotation = = D3DKMDT_VPPR_ROTATE90 | |
ctx - > Rotation = = D3DKMDT_VPPR_ROTATE270 )
{
SrcBltInfo . Width = DstBltInfo . Height ;
SrcBltInfo . Height = DstBltInfo . Width ;
}
else
{
SrcBltInfo . Width = DstBltInfo . Width ;
SrcBltInfo . Height = DstBltInfo . Height ;
}
2017-05-05 13:54:58 +02:00
uint16_t currentGeneration = m_DrawGeneration ;
QxlPresentOperation * operation = BuildQxlOperation ( [ = , this ] ( ) {
PAGED_CODE ( ) ;
ULONG delayed = 0 ;
for ( UINT i = 0 ; pDrawables [ i ] ; + + i )
{
ULONG n = PrepareDrawable ( pDrawables [ i ] ) ;
// only reason why drawables[i] is zeroed is stop flow
if ( pDrawables [ i ] ) {
delayed + = n ;
if ( currentGeneration = = m_DrawGeneration )
PushDrawable ( pDrawables [ i ] ) ;
else
DiscardDrawable ( pDrawables [ i ] ) ;
}
}
delete [ ] pDrawables ;
if ( delayed ) {
DbgPrint ( TRACE_LEVEL_WARNING , ( " %s: %d delayed chunks \n " , __FUNCTION__ , delayed ) ) ;
}
} ) ;
if ( ! operation ) {
MmUnlockPages ( ctx - > Mdl ) ;
IoFreeMdl ( ctx - > Mdl ) ;
delete [ ] pDrawables ;
return STATUS_NO_MEMORY ;
}
2014-09-02 09:36:27 +02:00
// Copy all the scroll rects from source image to video frame buffer.
for ( UINT i = 0 ; i < ctx - > NumMoves ; i + + )
{
POINT * pSourcePoint = & ctx - > Moves [ i ] . SourcePoint ;
RECT * pDestRect = & ctx - > Moves [ i ] . DestRect ;
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " --- %d SourcePoint.x = %ld, SourcePoint.y = %ld, DestRect.bottom = %ld, DestRect.left = %ld, DestRect.right = %ld, DestRect.top = %ld \n " ,
i , pSourcePoint - > x , pSourcePoint - > y , pDestRect - > bottom , pDestRect - > left , pDestRect - > right , pDestRect - > top ) ) ;
2017-04-01 18:40:29 +02:00
pDrawables [ nIndex ] = PrepareCopyBits ( * pDestRect , * pSourcePoint ) ;
if ( pDrawables [ nIndex ] ) nIndex + + ;
2014-09-02 09:36:27 +02:00
}
// Copy all the dirty rects from source image to video frame buffer.
for ( UINT i = 0 ; i < ctx - > NumDirtyRects ; i + + )
{
RECT * pDirtyRect = & ctx - > DirtyRect [ i ] ;
2016-06-16 16:04:50 +02:00
POINT sourcePoint ;
sourcePoint . x = pDirtyRect - > left ;
sourcePoint . y = pDirtyRect - > top ;
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " --- %d pDirtyRect->bottom = %ld, pDirtyRect->left = %ld, pDirtyRect->right = %ld, pDirtyRect->top = %ld \n " ,
2014-09-02 09:36:27 +02:00
i , pDirtyRect - > bottom , pDirtyRect - > left , pDirtyRect - > right , pDirtyRect - > top ) ) ;
2017-04-01 18:40:29 +02:00
pDrawables [ nIndex ] = PrepareBltBits ( & DstBltInfo ,
2014-09-02 09:36:27 +02:00
& SrcBltInfo ,
2015-03-24 07:22:45 +01:00
1 ,
2016-06-16 16:04:50 +02:00
pDirtyRect ,
& sourcePoint ) ;
2017-04-01 18:40:29 +02:00
if ( pDrawables [ nIndex ] ) nIndex + + ;
2014-09-02 09:36:27 +02:00
}
// Unmap unmap and unlock the pages.
if ( ctx - > Mdl )
{
MmUnlockPages ( ctx - > Mdl ) ;
IoFreeMdl ( ctx - > Mdl ) ;
}
2017-04-01 18:40:29 +02:00
pDrawables [ nIndex ] = NULL ;
2017-05-05 13:54:58 +02:00
PostToWorkerThread ( operation ) ;
2014-09-02 09:36:27 +02:00
return STATUS_SUCCESS ;
}
void QxlDevice : : WaitForReleaseRing ( void )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
int wait ;
2017-04-08 12:46:50 +02:00
BOOLEAN locked ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " --->%s \n " , __FUNCTION__ ) ) ;
2017-04-08 12:46:50 +02:00
locked = WaitForObject ( & m_MemLock , NULL ) ;
2014-09-02 09:36:27 +02:00
for ( ; ; ) {
LARGE_INTEGER timeout ;
if ( SPICE_RING_IS_EMPTY ( m_ReleaseRing ) ) {
2017-04-08 12:46:50 +02:00
ReleaseMutex ( & m_MemLock , locked ) ;
2014-09-02 09:36:27 +02:00
QXL_SLEEP ( 10 ) ;
2017-04-08 12:46:50 +02:00
locked = WaitForObject ( & m_MemLock , NULL ) ;
2014-09-02 09:36:27 +02:00
if ( ! SPICE_RING_IS_EMPTY ( m_ReleaseRing ) ) {
break ;
}
SyncIo ( QXL_IO_NOTIFY_OOM , 0 ) ;
}
SPICE_RING_CONS_WAIT ( m_ReleaseRing , wait ) ;
2017-04-08 12:46:50 +02:00
if ( ! wait | | ! m_bActive ) {
2014-09-02 09:36:27 +02:00
break ;
}
2017-04-08 12:46:50 +02:00
ReleaseMutex ( & m_MemLock , locked ) ;
2014-09-02 09:36:27 +02:00
timeout . QuadPart = - 30 * 1000 * 10 ; //30ms
2015-03-24 06:41:58 +01:00
WaitForObject ( & m_DisplayEvent , & timeout ) ;
2017-04-08 12:46:50 +02:00
locked = WaitForObject ( & m_MemLock , NULL ) ;
2014-09-02 09:36:27 +02:00
if ( SPICE_RING_IS_EMPTY ( m_ReleaseRing ) ) {
SyncIo ( QXL_IO_NOTIFY_OOM , 0 ) ;
}
}
2017-04-08 12:46:50 +02:00
ReleaseMutex ( & m_MemLock , locked ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " %s: <--- \n " , __FUNCTION__ ) ) ;
}
void QxlDevice : : FlushReleaseRing ( )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
UINT64 output ;
int notify ;
int num_to_release = 50 ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
output = m_FreeOutputs ;
while ( 1 ) {
while ( output ! = 0 ) {
output = ReleaseOutput ( output ) ;
if ( - - num_to_release = = 0 ) {
break ;
}
}
if ( output ! = 0 | |
SPICE_RING_IS_EMPTY ( m_ReleaseRing ) ) {
break ;
}
output = * SPICE_RING_CONS_ITEM ( m_ReleaseRing ) ;
SPICE_RING_POP ( m_ReleaseRing , notify ) ;
}
m_FreeOutputs = output ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
}
UINT64 QxlDevice : : ReleaseOutput ( UINT64 output_id )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
QXLOutput * output = ( QXLOutput * ) output_id ;
Resource * * now ;
Resource * * end ;
UINT64 next ;
ASSERT ( output_id ) ;
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " --->%s 0x%p \n " , __FUNCTION__ , output ) ) ;
2014-09-02 09:36:27 +02:00
for ( now = output - > resources , end = now + output - > num_res ; now < end ; now + + ) {
RELEASE_RES ( * now ) ;
}
2016-09-13 00:00:26 +02:00
next = ( ( QXLReleaseInfo * ) output - > data ) - > next ;
2017-04-10 15:30:56 +02:00
FreeMem ( output ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <---%s \n " , __FUNCTION__ ) ) ;
return next ;
}
void * QxlDevice : : AllocMem ( UINT32 mspace_type , size_t size , BOOL force )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
PVOID ptr ;
2015-03-24 06:41:58 +01:00
BOOLEAN locked = FALSE ;
2014-09-02 09:36:27 +02:00
ASSERT ( m_MSInfo [ mspace_type ] . _mspace ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " --->%s: %p(%d) size %u \n " , __FUNCTION__ ,
m_MSInfo [ mspace_type ] . _mspace ,
mspace_footprint ( m_MSInfo [ mspace_type ] . _mspace ) ,
size ) ) ;
# ifdef DBG
mspace_malloc_stats ( m_MSInfo [ mspace_type ] . _mspace ) ;
# endif
2017-04-08 12:46:50 +02:00
if ( force )
locked = WaitForObject ( & m_MemLock , NULL ) ;
else {
LARGE_INTEGER doNotWait ;
doNotWait . QuadPart = 0 ;
locked = WaitForObject ( & m_MemLock , & doNotWait ) ;
if ( ! locked ) {
return NULL ;
}
}
2014-09-02 09:36:27 +02:00
while ( 1 ) {
/* Release lots of queued resources, before allocating, as we
want to release early to minimize fragmentation risks . */
FlushReleaseRing ( ) ;
ptr = mspace_malloc ( m_MSInfo [ mspace_type ] . _mspace , size ) ;
2017-04-12 15:26:30 +02:00
if ( ! ptr & & mspace_type = = MSPACE_TYPE_VRAM & &
( ptr = mspace_malloc ( m_MSInfo [ MSPACE_TYPE_DEVRAM ] . _mspace , size ) ) ) {
/* for proper address check at the end of the procedure */
mspace_type = MSPACE_TYPE_DEVRAM ;
}
2014-09-02 09:36:27 +02:00
if ( ptr ) {
break ;
}
if ( m_FreeOutputs ! = 0 | |
! SPICE_RING_IS_EMPTY ( m_ReleaseRing ) ) {
/* We have more things to free, try that */
continue ;
}
2017-04-08 12:46:50 +02:00
if ( force & & m_bActive ) {
2014-09-02 09:36:27 +02:00
/* Ask spice to free some stuff */
2017-04-08 12:46:50 +02:00
ReleaseMutex ( & m_MemLock , locked ) ;
2014-09-02 09:36:27 +02:00
WaitForReleaseRing ( ) ;
2017-04-08 12:46:50 +02:00
locked = WaitForObject ( & m_MemLock , NULL ) ;
2014-09-02 09:36:27 +02:00
} else {
/* Fail */
break ;
}
}
2017-04-08 12:46:50 +02:00
2015-03-24 06:41:58 +01:00
ReleaseMutex ( & m_MemLock , locked ) ;
2014-09-02 09:36:27 +02:00
2017-04-08 12:46:50 +02:00
ASSERT ( ( ! ptr & & ( ! force | | ! m_bActive ) ) | | ( ptr > = m_MSInfo [ mspace_type ] . mspace_start & &
2014-09-02 09:36:27 +02:00
ptr < m_MSInfo [ mspace_type ] . mspace_end ) ) ;
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <---%s: ptr 0x%p \n " , __FUNCTION__ , ptr ) ) ;
2014-09-02 09:36:27 +02:00
return ptr ;
}
2017-04-10 15:30:56 +02:00
void QxlDevice : : FreeMem ( void * ptr )
2014-09-02 09:36:27 +02:00
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
2017-04-10 15:30:56 +02:00
for ( const MspaceInfo * info = m_MSInfo ; ; + + info )
{
if ( info = = m_MSInfo + _countof ( m_MSInfo ) )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " ASSERT failed @ %s, %p not in device memory \n " ,
__FUNCTION__ , ptr ) ) ;
break ;
}
if ( info - > _mspace & & ptr > = info - > mspace_start & & ptr < info - > mspace_end )
{
BOOLEAN locked = WaitForObject ( & m_MemLock , NULL ) ;
mspace_free ( info - > _mspace , ptr ) ;
ReleaseMutex ( & m_MemLock , locked ) ;
break ;
}
2014-09-02 09:36:27 +02:00
}
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
}
QXLDrawable * QxlDevice : : GetDrawable ( )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
QXLOutput * output ;
2017-04-10 17:18:53 +02:00
// commands must be allocated into Bar0 (DEVRAM)
output = ( QXLOutput * ) AllocMem ( MSPACE_TYPE_DEVRAM , sizeof ( QXLOutput ) + sizeof ( QXLDrawable ) , TRUE ) ;
2017-04-08 12:46:50 +02:00
if ( ! output ) {
return NULL ;
}
2014-09-02 09:36:27 +02:00
output - > num_res = 0 ;
RESOURCE_TYPE ( output , RESOURCE_TYPE_DRAWABLE ) ;
( ( QXLDrawable * ) output - > data ) - > release_info . id = ( UINT64 ) output ;
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--> %s 0x%p \n " , __FUNCTION__ , output ) ) ;
2014-09-02 09:36:27 +02:00
return ( QXLDrawable * ) output - > data ;
}
QXLCursorCmd * QxlDevice : : CursorCmd ( )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
QXLCursorCmd * cursor_cmd ;
QXLOutput * output ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
2017-04-10 17:18:53 +02:00
// commands must be allocated into Bar0 (DEVRAM)
output = ( QXLOutput * ) AllocMem ( MSPACE_TYPE_DEVRAM , sizeof ( QXLOutput ) + sizeof ( QXLCursorCmd ) , TRUE ) ;
2017-04-08 12:46:50 +02:00
if ( ! output ) {
return NULL ;
}
2014-09-02 09:36:27 +02:00
output - > num_res = 0 ;
RESOURCE_TYPE ( output , RESOURCE_TYPE_CURSOR ) ;
cursor_cmd = ( QXLCursorCmd * ) output - > data ;
cursor_cmd - > release_info . id = ( UINT64 ) output ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return cursor_cmd ;
}
BOOL QxlDevice : : SetClip ( const RECT * clip , QXLDrawable * drawable )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
Resource * rects_res ;
if ( clip = = NULL ) {
drawable - > clip . type = SPICE_CLIP_TYPE_NONE ;
2017-04-01 18:40:32 +02:00
// currently we always with NULL clip parameter
2014-09-02 09:36:27 +02:00
return TRUE ;
}
QXLClipRects * rects ;
2016-09-11 15:05:24 +02:00
rects_res = ( Resource * ) AllocMem ( MSPACE_TYPE_VRAM , sizeof ( Resource ) + sizeof ( QXLClipRects ) +
2014-09-02 09:36:27 +02:00
sizeof ( QXLRect ) , TRUE ) ;
2017-04-08 12:46:50 +02:00
if ( rects_res = = NULL ) {
return FALSE ;
}
2014-09-02 09:36:27 +02:00
rects_res - > refs = 1 ;
rects_res - > free = FreeClipRectsEx ;
rects_res - > ptr = this ;
rects = ( QXLClipRects * ) rects_res - > res ;
rects - > num_rects = 1 ;
rects - > chunk . data_size = sizeof ( QXLRect ) ;
rects - > chunk . prev_chunk = 0 ;
rects - > chunk . next_chunk = 0 ;
CopyRect ( ( QXLRect * ) rects - > chunk . data , clip ) ;
DrawableAddRes ( drawable , rects_res ) ;
drawable - > clip . type = SPICE_CLIP_TYPE_RECTS ;
2017-04-10 17:02:47 +02:00
drawable - > clip . data = PA ( rects_res - > res ) ;
2014-09-02 09:36:27 +02:00
return TRUE ;
}
void QxlDevice : : AddRes ( QXLOutput * output , Resource * res )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
res - > refs + + ;
output - > resources [ output - > num_res + + ] = res ;
}
void QxlDevice : : DrawableAddRes ( QXLDrawable * drawable , Resource * res )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
QXLOutput * output ;
output = ( QXLOutput * ) ( ( UINT8 * ) drawable - sizeof ( QXLOutput ) ) ;
AddRes ( output , res ) ;
}
2017-04-08 12:46:55 +02:00
static FORCEINLINE PLIST_ENTRY DelayedList ( QXLDrawable * pd )
{
QXLOutput * output ;
output = ( QXLOutput * ) ( ( UINT8 * ) pd - sizeof ( QXLOutput ) ) ;
return & output - > list ;
}
2014-09-02 09:36:27 +02:00
void QxlDevice : : CursorCmdAddRes ( QXLCursorCmd * cmd , Resource * res )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
QXLOutput * output ;
output = ( QXLOutput * ) ( ( UINT8 * ) cmd - sizeof ( QXLOutput ) ) ;
AddRes ( output , res ) ;
}
void QxlDevice : : FreeClipRectsEx ( Resource * res )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--> %s \n " , __FUNCTION__ ) ) ;
QxlDevice * pqxl = ( QxlDevice * ) res - > ptr ;
pqxl - > FreeClipRects ( res ) ;
}
void QxlDevice : : FreeClipRects ( Resource * res )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
QXLPHYSICAL chunk_phys ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
chunk_phys = ( ( QXLClipRects * ) res - > res ) - > chunk . next_chunk ;
while ( chunk_phys ) {
2017-04-10 17:02:47 +02:00
QXLDataChunk * chunk = ( QXLDataChunk * ) VA ( chunk_phys ) ;
2014-09-02 09:36:27 +02:00
chunk_phys = chunk - > next_chunk ;
2017-04-10 15:30:56 +02:00
FreeMem ( chunk ) ;
2014-09-02 09:36:27 +02:00
}
2017-04-10 15:30:56 +02:00
FreeMem ( res ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
}
void QxlDevice : : FreeBitmapImageEx ( Resource * res )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--> %s \n " , __FUNCTION__ ) ) ;
QxlDevice * pqxl = ( QxlDevice * ) res - > ptr ;
pqxl - > FreeBitmapImage ( res ) ;
}
void QxlDevice : : FreeBitmapImage ( Resource * res )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
InternalImage * internal ;
QXLPHYSICAL chunk_phys ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
internal = ( InternalImage * ) res - > res ;
chunk_phys = ( ( QXLDataChunk * ) ( & internal - > image . bitmap + 1 ) ) - > next_chunk ;
while ( chunk_phys ) {
2017-04-10 17:02:47 +02:00
QXLDataChunk * chunk = ( QXLDataChunk * ) VA ( chunk_phys ) ;
2014-09-02 09:36:27 +02:00
chunk_phys = chunk - > next_chunk ;
2017-04-10 15:30:56 +02:00
FreeMem ( chunk ) ;
2014-09-02 09:36:27 +02:00
}
2017-04-10 15:30:56 +02:00
FreeMem ( res ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
}
void QxlDevice : : FreeCursorEx ( Resource * res )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--> %s \n " , __FUNCTION__ ) ) ;
QxlDevice * pqxl = ( QxlDevice * ) res - > ptr ;
pqxl - > FreeCursor ( res ) ;
}
void QxlDevice : : FreeCursor ( Resource * res )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
QXLPHYSICAL chunk_phys ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
chunk_phys = ( ( InternalCursor * ) res - > res ) - > cursor . chunk . next_chunk ;
while ( chunk_phys ) {
2017-04-10 17:02:47 +02:00
QXLDataChunk * chunk = ( QXLDataChunk * ) VA ( chunk_phys ) ;
2014-09-02 09:36:27 +02:00
chunk_phys = chunk - > next_chunk ;
2017-04-10 15:30:56 +02:00
FreeMem ( chunk ) ;
2014-09-02 09:36:27 +02:00
}
2017-04-10 15:30:56 +02:00
FreeMem ( res ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
}
QXLDrawable * QxlDevice : : Drawable ( UINT8 type , CONST RECT * area , CONST RECT * clip , UINT32 surface_id )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
QXLDrawable * drawable ;
ASSERT ( area ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
drawable = GetDrawable ( ) ;
2017-04-08 12:46:50 +02:00
if ( ! drawable ) {
return NULL ;
}
2014-09-02 09:36:27 +02:00
drawable - > surface_id = surface_id ;
drawable - > type = type ;
drawable - > effect = QXL_EFFECT_OPAQUE ;
drawable - > self_bitmap = 0 ;
drawable - > mm_time = m_RomHdr - > mm_clock ;
drawable - > surfaces_dest [ 0 ] = - 1 ;
drawable - > surfaces_dest [ 1 ] = - 1 ;
drawable - > surfaces_dest [ 2 ] = - 1 ;
CopyRect ( & drawable - > bbox , area ) ;
2017-04-08 12:46:55 +02:00
InitializeListHead ( DelayedList ( drawable ) ) ;
2014-09-02 09:36:27 +02:00
if ( ! SetClip ( clip , drawable ) ) {
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " %s: set clip failed \n " , __FUNCTION__ ) ) ;
ReleaseOutput ( drawable - > release_info . id ) ;
drawable = NULL ;
}
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return drawable ;
}
2016-09-28 13:09:27 +02:00
void QxlDevice : : PushDrawable ( QXLDrawable * drawable )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
QXLCommand * cmd ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
2015-03-24 06:41:58 +01:00
BOOLEAN locked = FALSE ;
locked = WaitForObject ( & m_CmdLock , NULL ) ;
2014-09-02 09:36:27 +02:00
WaitForCmdRing ( ) ;
cmd = SPICE_RING_PROD_ITEM ( m_CommandRing ) ;
cmd - > type = QXL_CMD_DRAW ;
2017-04-10 17:02:47 +02:00
cmd - > data = PA ( drawable ) ;
2014-09-02 09:36:27 +02:00
PushCmd ( ) ;
2015-03-24 06:41:58 +01:00
ReleaseMutex ( & m_CmdLock , locked ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
}
void QxlDevice : : PushCursorCmd ( QXLCursorCmd * cursor_cmd )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
QXLCommand * cmd ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
2015-03-24 06:41:58 +01:00
BOOLEAN locked = FALSE ;
locked = WaitForObject ( & m_CrsLock , NULL ) ;
2014-09-02 09:36:27 +02:00
WaitForCursorRing ( ) ;
cmd = SPICE_RING_PROD_ITEM ( m_CursorRing ) ;
cmd - > type = QXL_CMD_CURSOR ;
2017-04-10 17:02:47 +02:00
cmd - > data = PA ( cursor_cmd ) ;
2014-09-02 09:36:27 +02:00
PushCursor ( ) ;
2015-03-24 06:41:58 +01:00
ReleaseMutex ( & m_CrsLock , locked ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
}
VOID QxlDevice : : SetImageId ( InternalImage * internal ,
BOOL cache_me ,
LONG width ,
LONG height ,
UINT8 format , UINT32 key )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
UINT32 image_info = IMAGE_HASH_INIT_VAL ( width , height , format ) ;
if ( cache_me ) {
QXL_SET_IMAGE_ID ( & internal - > image , ( ( UINT32 ) QXL_IMAGE_GROUP_DRIVER < < 30 ) |
image_info , key ) ;
internal - > image . descriptor . flags = QXL_IMAGE_CACHE ;
} else {
QXL_SET_IMAGE_ID ( & internal - > image , ( ( UINT32 ) QXL_IMAGE_GROUP_DRIVER_DONT_CACHE < < 30 ) |
image_info , key ) ;
internal - > image . descriptor . flags = 0 ;
}
}
2017-04-01 18:40:29 +02:00
QXLDrawable * QxlDevice : : PrepareCopyBits ( const RECT & rect , const POINT & sourcePoint )
2016-12-06 07:10:46 +01:00
{
PAGED_CODE ( ) ;
QXLDrawable * drawable ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s device %d \n " , __FUNCTION__ , m_Id ) ) ;
if ( ! ( drawable = Drawable ( QXL_COPY_BITS , & rect , NULL , 0 ) ) ) {
DbgPrint ( TRACE_LEVEL_ERROR , ( " Cannot get Drawable. \n " ) ) ;
2017-04-01 18:40:29 +02:00
return NULL ;
2016-12-06 07:10:46 +01:00
}
drawable - > u . copy_bits . src_pos . x = sourcePoint . x ;
drawable - > u . copy_bits . src_pos . y = sourcePoint . y ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
2017-04-01 18:40:29 +02:00
return drawable ;
2016-12-06 07:10:46 +01:00
}
2017-04-08 12:46:54 +02:00
BOOLEAN QxlDevice : : AttachNewBitmap ( QXLDrawable * drawable , UINT8 * src , UINT8 * src_end , INT pitch , BOOLEAN bForce )
2017-04-08 12:46:53 +02:00
{
PAGED_CODE ( ) ;
LONG width , height ;
size_t alloc_size ;
UINT32 line_size ;
Resource * image_res ;
InternalImage * internal ;
QXLDataChunk * chunk ;
2017-04-08 12:46:55 +02:00
PLIST_ENTRY pDelayedList = bForce ? NULL : DelayedList ( drawable ) ;
2017-04-08 12:46:53 +02:00
UINT8 * dest , * dest_end ;
height = drawable - > u . copy . src_area . bottom ;
width = drawable - > u . copy . src_area . right ;
line_size = width * 4 ;
alloc_size = BITMAP_ALLOC_BASE + BITS_BUF_MAX - BITS_BUF_MAX % line_size ;
alloc_size = MIN ( BITMAP_ALLOC_BASE + height * line_size , alloc_size ) ;
2017-04-08 12:46:54 +02:00
image_res = ( Resource * ) AllocMem ( MSPACE_TYPE_VRAM , alloc_size , bForce ) ;
2017-04-08 12:46:53 +02:00
if ( image_res ) {
image_res - > refs = 1 ;
image_res - > free = FreeBitmapImageEx ;
image_res - > ptr = this ;
internal = ( InternalImage * ) image_res - > res ;
SetImageId ( internal , FALSE , width , height , SPICE_BITMAP_FMT_32BIT , 0 ) ;
internal - > image . descriptor . flags = 0 ;
internal - > image . descriptor . type = SPICE_IMAGE_TYPE_BITMAP ;
chunk = ( QXLDataChunk * ) ( & internal - > image . bitmap + 1 ) ;
chunk - > data_size = 0 ;
chunk - > prev_chunk = 0 ;
chunk - > next_chunk = 0 ;
2017-04-10 17:02:47 +02:00
internal - > image . bitmap . data = PA ( chunk ) ;
2017-04-08 12:46:53 +02:00
internal - > image . bitmap . flags = 0 ;
internal - > image . descriptor . width = internal - > image . bitmap . x = width ;
internal - > image . descriptor . height = internal - > image . bitmap . y = height ;
internal - > image . bitmap . format = SPICE_BITMAP_FMT_RGBA ;
internal - > image . bitmap . stride = line_size ;
internal - > image . bitmap . palette = 0 ;
dest = chunk - > data ;
dest_end = ( UINT8 * ) image_res + alloc_size ;
2017-04-10 17:02:47 +02:00
drawable - > u . copy . src_bitmap = PA ( & internal - > image ) ;
2017-04-08 12:46:53 +02:00
DrawableAddRes ( drawable , image_res ) ;
RELEASE_RES ( image_res ) ;
alloc_size = height * line_size ;
2017-04-08 12:46:54 +02:00
} else if ( ! bForce ) {
alloc_size = height * line_size ;
// allocate delayed chunck for entire bitmap without limitation
DelayedChunk * pChunk = ( DelayedChunk * ) new ( PagedPool ) BYTE [ alloc_size + sizeof ( DelayedChunk ) ] ;
if ( pChunk ) {
// add it to delayed list
InsertTailList ( pDelayedList , & pChunk - > list ) ;
// PutBytesAlign do not need to allocate additional memory
pDelayedList = NULL ;
chunk = & pChunk - > chunk ;
chunk - > data_size = 0 ;
chunk - > prev_chunk = 0 ;
chunk - > next_chunk = 0 ;
// set dest and dest_end
dest = chunk - > data ;
dest_end = chunk - > data + alloc_size ;
} else {
// can't allocate memory
DbgPrint ( TRACE_LEVEL_ERROR , ( " Cannot allocate delayed bitmap for drawable \n " ) ) ;
return FALSE ;
}
2017-04-08 12:46:53 +02:00
} else {
// can't allocate memory (forced), driver abort flow
DbgPrint ( TRACE_LEVEL_ERROR , ( " Cannot get bitmap for drawable (stopping) \n " ) ) ;
return FALSE ;
}
for ( ; src ! = src_end ; src - = pitch , alloc_size - = line_size ) {
2017-04-08 12:46:55 +02:00
if ( ! PutBytesAlign ( & chunk , & dest , & dest_end , src , line_size , alloc_size , pDelayedList ) ) {
if ( pitch < 0 & & bForce ) {
DbgPrint ( TRACE_LEVEL_WARNING , ( " %s: aborting copy of lines (forced) \n " , __FUNCTION__ ) ) ;
} else {
DbgPrint ( TRACE_LEVEL_WARNING , ( " %s: unexpected aborting copy of lines (force %d, pitch %d) \n " , __FUNCTION__ , bForce , pitch ) ) ;
}
2017-04-08 12:46:53 +02:00
return FALSE ;
}
}
return TRUE ;
}
2017-04-16 21:43:01 +02:00
void QxlDevice : : DiscardDrawable ( QXLDrawable * drawable )
{
PAGED_CODE ( ) ;
PLIST_ENTRY pDelayedList = DelayedList ( drawable ) ;
// if some delayed chunks were allocated, free them
while ( ! IsListEmpty ( pDelayedList ) ) {
DelayedChunk * pdc = ( DelayedChunk * ) RemoveHeadList ( pDelayedList ) ;
delete [ ] reinterpret_cast < BYTE * > ( pdc ) ;
}
ReleaseOutput ( drawable - > release_info . id ) ;
DbgPrint ( TRACE_LEVEL_WARNING , ( " %s \n " , __FUNCTION__ ) ) ;
}
2017-04-01 18:40:29 +02:00
QXLDrawable * QxlDevice : : PrepareBltBits (
2014-09-02 09:36:27 +02:00
BLT_INFO * pDst ,
CONST BLT_INFO * pSrc ,
UINT NumRects ,
2016-06-16 16:04:50 +02:00
_In_reads_ ( NumRects ) CONST RECT * pRects ,
POINT * pSourcePoint )
2014-09-02 09:36:27 +02:00
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
QXLDrawable * drawable ;
LONG width ;
LONG height ;
2016-09-11 15:05:21 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s device %d \n " , __FUNCTION__ , m_Id ) ) ;
2014-12-15 10:31:09 +01:00
UNREFERENCED_PARAMETER ( NumRects ) ;
UNREFERENCED_PARAMETER ( pDst ) ;
2014-09-02 09:36:27 +02:00
if ( ! ( drawable = Drawable ( QXL_DRAW_COPY , pRects , NULL , 0 ) ) ) {
DbgPrint ( TRACE_LEVEL_ERROR , ( " Cannot get Drawable. \n " ) ) ;
2017-04-01 18:40:29 +02:00
return NULL ;
2014-09-02 09:36:27 +02:00
}
CONST RECT * pRect = & pRects [ 0 ] ;
drawable - > u . copy . scale_mode = SPICE_IMAGE_SCALE_MODE_NEAREST ;
drawable - > u . copy . mask . bitmap = 0 ;
drawable - > u . copy . rop_descriptor = SPICE_ROPD_OP_PUT ;
drawable - > surfaces_dest [ 0 ] = 0 ;
CopyRect ( & drawable - > surfaces_rects [ 0 ] , pRect ) ;
drawable - > self_bitmap = TRUE ;
CopyRect ( & drawable - > self_bitmap_area , pRect ) ;
height = pRect - > bottom - pRect - > top ;
width = pRect - > right - pRect - > left ;
drawable - > u . copy . src_area . bottom = height ;
drawable - > u . copy . src_area . left = 0 ;
drawable - > u . copy . src_area . top = 0 ;
drawable - > u . copy . src_area . right = width ;
2017-04-08 12:46:53 +02:00
CopyRect ( & drawable - > surfaces_rects [ 1 ] , pRect ) ;
2014-09-02 09:36:27 +02:00
2017-04-08 12:46:53 +02:00
UINT8 * src = ( UINT8 * ) pSrc - > pBits +
( pSourcePoint - > y ) * pSrc - > Pitch +
( pSourcePoint - > x * 4 ) ;
2014-09-02 09:36:27 +02:00
UINT8 * src_end = src - pSrc - > Pitch ;
src + = pSrc - > Pitch * ( height - 1 ) ;
2017-04-08 12:46:55 +02:00
if ( ! AttachNewBitmap ( drawable , src , src_end , ( INT ) pSrc - > Pitch , ! g_bSupportVSync ) ) {
2017-04-16 21:43:01 +02:00
DiscardDrawable ( drawable ) ;
2017-04-08 12:46:53 +02:00
drawable = NULL ;
} else {
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " %s drawable= %p type = %d, effect = %d Dest right(%d) left(%d) top(%d) bottom(%d) src_bitmap= %I64x. \n " , __FUNCTION__ ,
2017-04-08 12:46:53 +02:00
drawable , drawable - > type , drawable - > effect , drawable - > surfaces_rects [ 0 ] . right , drawable - > surfaces_rects [ 0 ] . left ,
drawable - > surfaces_rects [ 0 ] . top , drawable - > surfaces_rects [ 0 ] . bottom ,
drawable - > u . copy . src_bitmap ) ) ;
}
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
2017-04-01 18:40:29 +02:00
return drawable ;
2014-09-02 09:36:27 +02:00
}
2017-04-08 12:46:51 +02:00
// can work in 2 modes:
// forced - as before, when pDelayed not provided or if VSync is not in use
// non-forced, if VSync is active and pDelayed provided. In this case, if memory
// can't be allocated immediately, allocates 'delayed chunk' and copies data
// to it. Further, before send to the device, this 'delayed chunk' should be processed,
// regular chunk allocated from device memory and the data copied to it
2017-04-08 12:46:50 +02:00
BOOLEAN QxlDevice : : PutBytesAlign ( QXLDataChunk * * chunk_ptr , UINT8 * * now_ptr ,
2014-09-02 09:36:27 +02:00
UINT8 * * end_ptr , UINT8 * src , int size ,
2018-03-09 06:56:29 +01:00
size_t alloc_size , PLIST_ENTRY pDelayed , BOOLEAN bDevRam )
2014-09-02 09:36:27 +02:00
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2017-04-08 12:46:51 +02:00
BOOLEAN bResult = TRUE ;
2018-03-09 06:56:29 +01:00
UINT32 memSpace = bDevRam ? MSPACE_TYPE_DEVRAM : MSPACE_TYPE_VRAM ;
2017-04-08 12:46:51 +02:00
BOOLEAN bForced = ! g_bSupportVSync | | ! pDelayed ;
2014-09-02 09:36:27 +02:00
QXLDataChunk * chunk = * chunk_ptr ;
UINT8 * now = * now_ptr ;
UINT8 * end = * end_ptr ;
2017-04-08 12:46:51 +02:00
size_t maxAllocSize = BITS_BUF_MAX - BITS_BUF_MAX % size ;
2017-04-08 12:46:52 +02:00
alloc_size = MIN ( alloc_size , maxAllocSize ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
while ( size ) {
int cp_size = ( int ) MIN ( end - now , size ) ;
if ( ! cp_size ) {
2018-03-09 06:56:29 +01:00
void * ptr = ( bForced | | IsListEmpty ( pDelayed ) ) ? AllocMem ( memSpace , alloc_size + sizeof ( QXLDataChunk ) , bForced ) : NULL ;
2017-04-08 12:46:51 +02:00
if ( ptr ) {
2017-04-10 17:02:47 +02:00
chunk - > next_chunk = PA ( ptr ) ;
( ( QXLDataChunk * ) ptr ) - > prev_chunk = PA ( chunk ) ;
2017-04-08 12:46:51 +02:00
chunk = ( QXLDataChunk * ) ptr ;
chunk - > next_chunk = 0 ;
}
if ( ! ptr & & pDelayed ) {
ptr = new ( PagedPool ) BYTE [ alloc_size + sizeof ( DelayedChunk ) ] ;
if ( ptr ) {
DelayedChunk * pChunk = ( DelayedChunk * ) ptr ;
InsertTailList ( pDelayed , & pChunk - > list ) ;
pChunk - > chunk . prev_chunk = ( QXLPHYSICAL ) chunk ;
chunk = & pChunk - > chunk ;
}
}
if ( ptr ) {
chunk - > data_size = 0 ;
now = chunk - > data ;
end = now + alloc_size ;
cp_size = ( int ) MIN ( end - now , size ) ;
} else {
bResult = FALSE ;
break ;
2017-04-08 12:46:50 +02:00
}
2014-09-02 09:36:27 +02:00
}
RtlCopyMemory ( now , src , cp_size ) ;
src + = cp_size ;
now + = cp_size ;
chunk - > data_size + = cp_size ;
size - = cp_size ;
}
* chunk_ptr = chunk ;
* now_ptr = now ;
* end_ptr = end ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
2017-04-08 12:46:51 +02:00
return bResult ;
2014-09-02 09:36:27 +02:00
}
VOID QxlDevice : : BlackOutScreen ( CURRENT_BDD_MODE * pCurrentBddMod )
{
QXLDrawable * drawable ;
RECT Rect ;
PAGED_CODE ( ) ;
2016-09-26 15:00:08 +02:00
Rect . bottom = pCurrentBddMod - > SrcModeHeight ;
Rect . top = 0 ;
Rect . left = 0 ;
Rect . right = pCurrentBddMod - > SrcModeWidth ;
if ( ! ( drawable = Drawable ( QXL_DRAW_FILL , & Rect , NULL , 0 ) ) )
2015-02-19 11:07:24 +01:00
{
2016-09-26 15:00:08 +02:00
DbgPrint ( TRACE_LEVEL_ERROR , ( " Cannot get Drawable. \n " ) ) ;
return ;
2014-09-02 09:36:27 +02:00
}
2016-09-26 15:00:08 +02:00
drawable - > u . fill . brush . type = SPICE_BRUSH_TYPE_SOLID ;
drawable - > u . fill . brush . u . color = 0 ;
drawable - > u . fill . rop_descriptor = SPICE_ROPD_OP_PUT ;
drawable - > u . fill . mask . flags = 0 ;
drawable - > u . fill . mask . pos . x = 0 ;
drawable - > u . fill . mask . pos . y = 0 ;
drawable - > u . fill . mask . bitmap = 0 ;
PushDrawable ( drawable ) ;
2014-09-02 09:36:27 +02:00
}
NTSTATUS QxlDevice : : HWClose ( void )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
QxlClose ( ) ;
UnmapMemory ( ) ;
return STATUS_SUCCESS ;
}
NTSTATUS QxlDevice : : SetPointerShape ( _In_ CONST DXGKARG_SETPOINTERSHAPE * pSetPointerShape )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s flag = %x \n " , __FUNCTION__ , pSetPointerShape - > Flags . Value ) ) ;
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " <--> %s flag = %d pitch = %d, pixels = %p, id = %d, w = %d, h = %d, x = %d, y = %d \n " , __FUNCTION__ ,
pSetPointerShape - > Flags . Value ,
pSetPointerShape - > Pitch ,
pSetPointerShape - > pPixels ,
pSetPointerShape - > VidPnSourceId ,
pSetPointerShape - > Width ,
pSetPointerShape - > Height ,
pSetPointerShape - > XHot ,
pSetPointerShape - > YHot ) ) ;
2016-11-18 14:49:56 +01:00
if ( ! pSetPointerShape - > Flags . Monochrome & & ! pSetPointerShape - > Flags . Color )
2014-09-02 09:36:27 +02:00
return STATUS_UNSUCCESSFUL ;
QXLCursorCmd * cursor_cmd ;
InternalCursor * internal ;
QXLCursor * cursor ;
Resource * res ;
QXLDataChunk * chunk ;
UINT8 * src ;
UINT8 * src_end ;
UINT8 * now ;
UINT8 * end ;
int line_size ;
2016-09-07 14:15:53 +02:00
int num_images = 1 ;
2014-09-02 09:36:27 +02:00
cursor_cmd = CursorCmd ( ) ;
2017-04-08 12:46:50 +02:00
if ( ! cursor_cmd ) {
DbgPrint ( TRACE_LEVEL_ERROR , ( " %s: Failed to allocate cursor command \n " , __FUNCTION__ ) ) ;
return STATUS_INSUFFICIENT_RESOURCES ;
}
2014-09-02 09:36:27 +02:00
cursor_cmd - > type = QXL_CURSOR_SET ;
cursor_cmd - > u . set . visible = TRUE ;
cursor_cmd - > u . set . position . x = 0 ;
cursor_cmd - > u . set . position . y = 0 ;
2018-03-09 06:56:29 +01:00
res = ( Resource * ) AllocMem ( MSPACE_TYPE_DEVRAM , CURSOR_ALLOC_SIZE , TRUE ) ;
2017-04-08 12:46:50 +02:00
if ( ! res ) {
DbgPrint ( TRACE_LEVEL_ERROR , ( " %s: Failed to allocate cursor data \n " , __FUNCTION__ ) ) ;
ReleaseOutput ( cursor_cmd - > release_info . id ) ;
return STATUS_INSUFFICIENT_RESOURCES ;
}
2014-09-02 09:36:27 +02:00
res - > refs = 1 ;
res - > free = FreeCursorEx ;
res - > ptr = this ;
RESOURCE_TYPE ( res , RESOURCE_TYPE_CURSOR ) ;
internal = ( InternalCursor * ) res - > res ;
cursor = & internal - > cursor ;
cursor - > header . type = pSetPointerShape - > Flags . Monochrome ? SPICE_CURSOR_TYPE_MONO : SPICE_CURSOR_TYPE_ALPHA ;
cursor - > header . unique = 0 ;
cursor - > header . width = ( UINT16 ) pSetPointerShape - > Width ;
cursor - > header . height = ( UINT16 ) pSetPointerShape - > Height ;
if ( cursor - > header . type = = SPICE_CURSOR_TYPE_MONO ) {
line_size = ALIGN ( cursor - > header . width , 8 ) > > 3 ;
2016-09-07 14:15:53 +02:00
cursor - > data_size = line_size * pSetPointerShape - > Height * 2 ;
num_images = 2 ;
2014-09-02 09:36:27 +02:00
} else {
line_size = cursor - > header . width < < 2 ;
2016-09-07 14:15:53 +02:00
cursor - > data_size = line_size * pSetPointerShape - > Height ;
2014-09-02 09:36:27 +02:00
}
cursor - > header . hot_spot_x = ( UINT16 ) pSetPointerShape - > XHot ;
cursor - > header . hot_spot_y = ( UINT16 ) pSetPointerShape - > YHot ;
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " <--> %s %d::%d::%d::%d::%d \n " , __FUNCTION__ , cursor - > header . width , cursor - > header . height , cursor - > header . hot_spot_x , cursor - > header . hot_spot_y , cursor - > data_size ) ) ;
chunk = & cursor - > chunk ;
chunk - > data_size = 0 ;
chunk - > prev_chunk = 0 ;
chunk - > next_chunk = 0 ;
src = ( UINT8 * ) pSetPointerShape - > pPixels ;
now = chunk - > data ;
end = ( UINT8 * ) res + CURSOR_ALLOC_SIZE ;
2016-09-07 14:15:53 +02:00
src_end = src + ( pSetPointerShape - > Pitch * pSetPointerShape - > Height * num_images ) ;
2014-09-02 09:36:27 +02:00
for ( ; src ! = src_end ; src + = pSetPointerShape - > Pitch ) {
2018-03-09 06:56:29 +01:00
if ( ! PutBytesAlign ( & chunk , & now , & end , src , line_size , PAGE_SIZE - PAGE_SIZE % line_size , NULL , TRUE ) ) {
2017-04-08 12:46:51 +02:00
// we have a chance to get here only with color cursor bigger than 45*45
// and only if we modify this procedure to use non-forced allocation
DbgPrint ( TRACE_LEVEL_ERROR , ( " %s: failed to push part of shape \n " , __FUNCTION__ ) ) ;
break ;
2017-04-08 12:46:50 +02:00
}
2014-09-02 09:36:27 +02:00
}
CursorCmdAddRes ( cursor_cmd , res ) ;
RELEASE_RES ( res ) ;
2017-04-10 17:02:47 +02:00
cursor_cmd - > u . set . shape = PA ( & internal - > cursor ) ;
2014-09-02 09:36:27 +02:00
PushCursorCmd ( cursor_cmd ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return STATUS_SUCCESS ;
}
NTSTATUS QxlDevice : : SetPointerPosition ( _In_ CONST DXGKARG_SETPOINTERPOSITION * pSetPointerPosition )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " <--> %s flag = %d id = %d, x = %d, y = %d \n " , __FUNCTION__ ,
pSetPointerPosition - > Flags . Value ,
pSetPointerPosition - > VidPnSourceId ,
pSetPointerPosition - > X ,
pSetPointerPosition - > Y ) ) ;
2016-11-18 14:49:56 +01:00
QXLCursorCmd * cursor_cmd = CursorCmd ( ) ;
2017-04-08 12:46:50 +02:00
if ( ! cursor_cmd ) {
DbgPrint ( TRACE_LEVEL_ERROR , ( " %s: Failed to allocate cursor command \n " , __FUNCTION__ ) ) ;
return STATUS_INSUFFICIENT_RESOURCES ;
}
2016-02-10 11:45:14 +01:00
if ( pSetPointerPosition - > X < 0 | | ! pSetPointerPosition - > Flags . Visible ) {
2016-11-18 14:49:56 +01:00
cursor_cmd - > type = QXL_CURSOR_HIDE ;
} else {
cursor_cmd - > type = QXL_CURSOR_MOVE ;
cursor_cmd - > u . position . x = ( INT16 ) pSetPointerPosition - > X ;
cursor_cmd - > u . position . y = ( INT16 ) pSetPointerPosition - > Y ;
2014-09-02 09:36:27 +02:00
}
2016-11-18 14:49:56 +01:00
PushCursorCmd ( cursor_cmd ) ;
2014-09-02 09:36:27 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
return STATUS_SUCCESS ;
}
2016-09-11 15:05:21 +02:00
NTSTATUS QxlDevice : : UpdateChildStatus ( BOOLEAN connect )
2015-02-08 11:04:39 +01:00
{
2016-09-11 15:05:21 +02:00
PAGED_CODE ( ) ;
NTSTATUS Status ( STATUS_SUCCESS ) ;
DXGK_CHILD_STATUS ChildStatus ;
PDXGKRNL_INTERFACE pDXGKInterface ( m_pQxlDod - > GetDxgkInterface ( ) ) ;
ChildStatus . Type = StatusConnection ;
ChildStatus . ChildUid = 0 ;
ChildStatus . HotPlug . Connected = connect ;
Status = pDXGKInterface - > DxgkCbIndicateChildStatus ( pDXGKInterface - > DeviceHandle , & ChildStatus ) ;
return Status ;
}
2015-02-08 11:04:39 +01:00
2016-09-11 15:05:21 +02:00
NTSTATUS QxlDevice : : SetCustomDisplay ( QXLEscapeSetCustomDisplay * custom_display )
{
PAGED_CODE ( ) ;
NTSTATUS status ;
UINT xres = custom_display - > xres ;
UINT yres = custom_display - > yres ;
UINT bpp = QXL_BPP ;
DbgPrint ( TRACE_LEVEL_WARNING , ( " %s - %d (%dx%d#%d) \n " , __FUNCTION__ , m_Id , xres , yres , bpp ) ) ;
if ( xres < MIN_WIDTH_SIZE | | yres < MIN_HEIGHT_SIZE ) {
2017-07-09 09:54:22 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " %s: (%dx%d#%d) less than (%dx%d) \n " , __FUNCTION__ ,
2016-09-11 15:05:21 +02:00
xres , yres , bpp , MIN_WIDTH_SIZE , MIN_HEIGHT_SIZE ) ) ;
2016-09-08 13:03:56 +02:00
}
2016-09-11 15:05:21 +02:00
m_CustomMode = ( USHORT ) ( ( m_CustomMode = = m_ModeCount - 1 ) ? m_ModeCount - 2 : m_ModeCount - 1 ) ;
2016-09-08 13:03:56 +02:00
if ( ( xres * yres * bpp / 8 ) > m_RomHdr - > surface0_area_size ) {
DbgPrint ( TRACE_LEVEL_ERROR , ( " %s: Mode (%dx%d#%d) doesn't fit in memory (%d) \n " ,
__FUNCTION__ , xres , yres , bpp , m_RomHdr - > surface0_area_size ) ) ;
2016-09-11 15:05:21 +02:00
return ERROR_NOT_ENOUGH_MEMORY ;
2016-09-08 13:03:56 +02:00
}
UpdateVideoModeInfo ( m_CustomMode , xres , yres , bpp ) ;
2016-09-11 15:05:21 +02:00
status = UpdateChildStatus ( TRUE ) ;
return status ;
}
void QxlDevice : : SetMonitorConfig ( QXLHead * monitor_config )
{
PAGED_CODE ( ) ;
m_monitor_config - > count = 1 ;
m_monitor_config - > max_allowed = 1 ;
memcpy ( & m_monitor_config - > heads [ 0 ] , monitor_config , sizeof ( QXLHead ) ) ;
m_monitor_config - > heads [ 0 ] . id = 0 ;
m_monitor_config - > heads [ 0 ] . surface_id = 0 ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " %s:%d configuring monitor at (%d, %d) (%dx%d) \n " , __FUNCTION__ , m_Id ,
m_monitor_config - > heads [ 0 ] . x , m_monitor_config - > heads [ 0 ] . y ,
m_monitor_config - > heads [ 0 ] . width , m_monitor_config - > heads [ 0 ] . height ) ) ;
AsyncIo ( QXL_IO_MONITORS_CONFIG_ASYNC , 0 ) ;
}
2017-01-27 11:02:40 +01:00
LONG QxlDevice : : GetMaxSourceMappingHeight ( RECT * DirtyRects , ULONG NumDirtyRects )
2016-09-28 13:09:28 +02:00
{
2016-09-13 00:01:21 +02:00
PAGED_CODE ( ) ;
2016-09-28 13:09:28 +02:00
LONG maxHeight = 0 ;
if ( DirtyRects ! = NULL ) {
for ( UINT i = 0 ; i < NumDirtyRects ; i + + ) {
const RECT & pDirtyRect = DirtyRects [ i ] ;
maxHeight = MAX ( maxHeight , pDirtyRect . bottom ) ;
}
}
return maxHeight ;
}
2016-09-11 15:05:21 +02:00
NTSTATUS QxlDevice : : Escape ( _In_ CONST DXGKARG_ESCAPE * pEscape )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2016-09-11 15:05:21 +02:00
size_t data_size ( sizeof ( uint32_t ) ) ;
QXLEscape * pQXLEscape ( ( QXLEscape * ) pEscape - > pPrivateDriverData ) ;
NTSTATUS status ( STATUS_SUCCESS ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
switch ( pQXLEscape - > ioctl ) {
case QXL_ESCAPE_SET_CUSTOM_DISPLAY : {
data_size + = sizeof ( QXLEscapeSetCustomDisplay ) ;
if ( pEscape - > PrivateDriverDataSize ! = data_size ) {
status = STATUS_INVALID_BUFFER_SIZE ;
break ;
}
status = SetCustomDisplay ( & pQXLEscape - > custom_display ) ;
break ;
}
case QXL_ESCAPE_MONITOR_CONFIG : {
data_size + = sizeof ( QXLHead ) ;
if ( pEscape - > PrivateDriverDataSize ! = data_size ) {
status = STATUS_INVALID_BUFFER_SIZE ;
break ;
}
SetMonitorConfig ( & pQXLEscape - > monitor_config ) ;
status = STATUS_SUCCESS ;
break ;
}
default :
DbgPrint ( TRACE_LEVEL_ERROR , ( " %s: invalid Escape 0x%x \n " , __FUNCTION__ , pQXLEscape - > ioctl ) ) ;
status = STATUS_INVALID_PARAMETER ;
}
if ( status = = STATUS_INVALID_BUFFER_SIZE ) {
DbgPrint ( TRACE_LEVEL_ERROR , ( " %s invalid buffer size of %d, should be %d \n " , __FUNCTION__ ,
pEscape - > PrivateDriverDataSize , data_size ) ) ;
}
return status ;
2015-02-08 11:04:39 +01:00
}
2014-09-02 09:36:27 +02:00
VOID QxlDevice : : WaitForCmdRing ( )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
int wait ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
for ( ; ; ) {
SPICE_RING_PROD_WAIT ( m_CommandRing , wait ) ;
if ( ! wait ) {
break ;
}
2015-03-24 06:41:58 +01:00
WaitForObject ( & m_DisplayEvent , NULL ) ;
2014-09-02 09:36:27 +02:00
}
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
}
VOID QxlDevice : : PushCmd ( )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
int notify ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
SPICE_RING_PUSH ( m_CommandRing , notify ) ;
if ( notify ) {
SyncIo ( QXL_IO_NOTIFY_CMD , 0 ) ;
}
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s notify = %d \n " , __FUNCTION__ , notify ) ) ;
}
VOID QxlDevice : : WaitForCursorRing ( VOID )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
int wait ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
for ( ; ; ) {
SPICE_RING_PROD_WAIT ( m_CursorRing , wait ) ;
if ( ! wait ) {
break ;
}
LARGE_INTEGER timeout ; // 1 => 100 nanoseconds
timeout . QuadPart = - 1 * ( 1000 * 1000 * 10 ) ; //negative => relative // 1s
2015-03-24 06:41:58 +01:00
WaitForObject ( & m_CursorEvent , & timeout ) ;
2014-09-02 09:36:27 +02:00
if ( SPICE_RING_IS_FULL ( m_CursorRing ) ) {
DbgPrint ( TRACE_LEVEL_ERROR , ( " %s: timeout \n " , __FUNCTION__ ) ) ;
}
}
}
VOID QxlDevice : : PushCursor ( VOID )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
int notify ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
SPICE_RING_PUSH ( m_CursorRing , notify ) ;
if ( notify ) {
SyncIo ( QXL_IO_NOTIFY_CURSOR , 0 ) ;
}
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s notify = %d \n " , __FUNCTION__ , notify ) ) ;
}
2016-09-13 00:02:01 +02:00
QXL_NON_PAGED
2014-09-02 09:36:27 +02:00
BOOLEAN QxlDevice : : InterruptRoutine ( _In_ PDXGKRNL_INTERFACE pDxgkInterface , _In_ ULONG MessageNumber )
{
UNREFERENCED_PARAMETER ( MessageNumber ) ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
if ( ! ( m_RamHdr - > int_pending & m_RamHdr - > int_mask ) ) {
return FALSE ;
}
2017-02-16 15:31:00 +01:00
m_Pending | = InterlockedExchange ( ( LONG * ) & m_RamHdr - > int_pending , 0 ) ;
2014-09-02 09:36:27 +02:00
WRITE_PORT_UCHAR ( ( PUCHAR ) ( m_IoBase + QXL_IO_UPDATE_IRQ ) , 0 ) ;
2017-02-16 15:31:00 +01:00
// QXL_IO_UPDATE_IRQ sets interrupt level to m_RamHdr->int_pending & m_RamHdr->int_mask
// so it will be dropped if interrupt status is not modified after clear
2014-09-02 09:36:27 +02:00
if ( ! pDxgkInterface - > DxgkCbQueueDpc ( pDxgkInterface - > DeviceHandle ) ) {
2017-02-16 15:31:00 +01:00
// DPC already queued and will process m_Pending when called
DbgPrint ( TRACE_LEVEL_WARNING , ( " ---> %s can't queue Dpc for %X \n " , __FUNCTION__ , m_Pending ) ) ;
2014-09-02 09:36:27 +02:00
}
2016-09-04 16:12:33 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
2014-09-02 09:36:27 +02:00
return TRUE ;
}
2017-02-16 15:31:01 +01:00
QXL_NON_PAGED
VOID QxlDevice : : VSyncInterruptPostProcess ( _In_ PDXGKRNL_INTERFACE pDxgkInterface )
{
if ( ! pDxgkInterface - > DxgkCbQueueDpc ( pDxgkInterface - > DeviceHandle ) ) {
DbgPrint ( TRACE_LEVEL_WARNING , ( " ---> %s can't enqueue DPC, pending interrupts %X \n " , __FUNCTION__ , m_Pending ) ) ;
}
}
2016-09-13 00:02:01 +02:00
QXL_NON_PAGED
2017-02-16 15:31:00 +01:00
VOID QxlDevice : : DpcRoutine ( PVOID )
2014-09-02 09:36:27 +02:00
{
2017-02-16 15:31:00 +01:00
LONG intStatus = InterlockedExchange ( & m_Pending , 0 ) ;
2017-04-01 18:40:32 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " ---> %s \n " , __FUNCTION__ ) ) ;
2017-02-16 15:31:00 +01:00
if ( intStatus & QXL_INTERRUPT_DISPLAY ) {
2015-02-18 10:57:00 +01:00
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " ---> %s m_DisplayEvent \n " , __FUNCTION__ ) ) ;
2014-09-02 09:36:27 +02:00
KeSetEvent ( & m_DisplayEvent , IO_NO_INCREMENT , FALSE ) ;
}
2017-02-16 15:31:00 +01:00
if ( intStatus & QXL_INTERRUPT_CURSOR ) {
2015-02-18 10:57:00 +01:00
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " ---> %s m_CursorEvent \n " , __FUNCTION__ ) ) ;
2014-09-02 09:36:27 +02:00
KeSetEvent ( & m_CursorEvent , IO_NO_INCREMENT , FALSE ) ;
}
2017-02-16 15:31:00 +01:00
if ( intStatus & QXL_INTERRUPT_IO_CMD ) {
2015-02-18 10:57:00 +01:00
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " ---> %s m_IoCmdEvent \n " , __FUNCTION__ ) ) ;
2014-09-02 09:36:27 +02:00
KeSetEvent ( & m_IoCmdEvent , IO_NO_INCREMENT , FALSE ) ;
}
2017-04-01 18:40:32 +02:00
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
2014-09-02 09:36:27 +02:00
}
2016-09-13 00:02:01 +02:00
QXL_NON_PAGED
2014-09-02 09:36:27 +02:00
UINT BPPFromPixelFormat ( D3DDDIFORMAT Format )
{
switch ( Format )
{
case D3DDDIFMT_UNKNOWN : return 0 ;
case D3DDDIFMT_P8 : return 8 ;
case D3DDDIFMT_R5G6B5 : return 16 ;
case D3DDDIFMT_R8G8B8 : return 24 ;
case D3DDDIFMT_X8R8G8B8 : // fall through
case D3DDDIFMT_A8R8G8B8 : return 32 ;
default : QXL_LOG_ASSERTION1 ( " Unknown D3DDDIFORMAT 0x%I64x " , Format ) ; return 0 ;
}
}
// Given bits per pixel, return the pixel format at the same bpp
2016-09-13 00:02:01 +02:00
QXL_NON_PAGED
2014-09-02 09:36:27 +02:00
D3DDDIFORMAT PixelFormatFromBPP ( UINT BPP )
{
switch ( BPP )
{
case 8 : return D3DDDIFMT_P8 ;
case 16 : return D3DDDIFMT_R5G6B5 ;
case 24 : return D3DDDIFMT_R8G8B8 ;
case 32 : return D3DDDIFMT_X8R8G8B8 ;
default : QXL_LOG_ASSERTION1 ( " A bit per pixel of 0x%I64x is not supported. " , BPP ) ; return D3DDDIFMT_UNKNOWN ;
}
}
UINT SpiceFromPixelFormat ( D3DDDIFORMAT Format )
{
2016-09-28 13:09:25 +02:00
PAGED_CODE ( ) ;
2014-09-02 09:36:27 +02:00
switch ( Format )
{
case D3DDDIFMT_UNKNOWN :
case D3DDDIFMT_P8 : QXL_LOG_ASSERTION1 ( " Bad format type 0x%I64x " , Format ) ; return 0 ;
case D3DDDIFMT_R5G6B5 : return SPICE_SURFACE_FMT_16_555 ;
case D3DDDIFMT_R8G8B8 :
case D3DDDIFMT_X8R8G8B8 :
case D3DDDIFMT_A8R8G8B8 : return SPICE_SURFACE_FMT_32_xRGB ;
default : QXL_LOG_ASSERTION1 ( " Unknown D3DDDIFORMAT 0x%I64x " , Format ) ; return 0 ;
}
}
2016-10-13 15:29:17 +02:00
NTSTATUS HwDeviceInterface : : AcquireDisplayInfo ( DXGK_DISPLAY_INFORMATION & DispInfo )
{
2017-04-01 18:40:28 +02:00
PAGED_CODE ( ) ;
2016-10-13 15:29:17 +02:00
NTSTATUS Status = STATUS_SUCCESS ;
if ( GetId ( ) = = 0 )
{
Status = m_pQxlDod - > AcquireDisplayInfo ( DispInfo ) ;
}
if ( ! NT_SUCCESS ( Status ) )
{
DbgPrint ( TRACE_LEVEL_ERROR , ( " QxlDod::AcquireDisplayInfo failed with status 0x%X Width = %d \n " ,
Status , DispInfo . Width ) ) ;
return STATUS_UNSUCCESSFUL ;
}
if ( DispInfo . Width = = 0 )
{
2017-02-04 17:00:23 +01:00
DispInfo . ColorFormat = D3DDDIFMT_A8R8G8B8 ;
2016-10-13 15:29:17 +02:00
DispInfo . Width = MIN_WIDTH_SIZE ;
DispInfo . Height = MIN_HEIGHT_SIZE ;
2017-02-04 17:00:22 +01:00
DispInfo . Pitch = DispInfo . Width * BPPFromPixelFormat ( DispInfo . ColorFormat ) / BITS_PER_BYTE ;
2016-10-13 15:29:17 +02:00
DispInfo . TargetId = 0 ;
}
return Status ;
}
2017-02-16 15:31:01 +01:00
// Vga device does not generate interrupts
QXL_NON_PAGED VOID VgaDevice : : VSyncInterruptPostProcess ( _In_ PDXGKRNL_INTERFACE pxface )
{
pxface - > DxgkCbQueueDpc ( pxface - > DeviceHandle ) ;
}
QXL_NON_PAGED VOID QxlDod : : IndicateVSyncInterrupt ( )
{
DXGKARGCB_NOTIFY_INTERRUPT_DATA data = { } ;
data . InterruptType = DXGK_INTERRUPT_DISPLAYONLY_VSYNC ;
m_DxgkInterface . DxgkCbNotifyInterrupt ( m_DxgkInterface . DeviceHandle , & data ) ;
m_pHWDevice - > VSyncInterruptPostProcess ( & m_DxgkInterface ) ;
}
QXL_NON_PAGED BOOLEAN QxlDod : : VsyncTimerSynchRoutine ( PVOID context )
{
QxlDod * pQxl = reinterpret_cast < QxlDod * > ( context ) ;
pQxl - > IndicateVSyncInterrupt ( ) ;
return FALSE ;
}
QXL_NON_PAGED VOID QxlDod : : VsyncTimerProc ( )
{
BOOLEAN bDummy ;
DbgPrint ( TRACE_LEVEL_VERBOSE , ( " <--- %s \n " , __FUNCTION__ ) ) ;
if ( m_bVsyncEnabled & & m_AdapterPowerState = = PowerDeviceD0 )
{
m_DxgkInterface . DxgkCbSynchronizeExecution (
m_DxgkInterface . DeviceHandle ,
VsyncTimerSynchRoutine ,
this ,
0 ,
& bDummy
) ;
INCREMENT_VSYNC_COUNTER ( & m_VsyncFiredCounter ) ;
}
}
VOID QxlDod : : EnableVsync ( BOOLEAN bEnable )
{
PAGED_CODE ( ) ;
if ( g_bSupportVSync )
{
m_bVsyncEnabled = bEnable ;
if ( ! m_bVsyncEnabled )
{
DbgPrint ( TRACE_LEVEL_WARNING , ( " Disabled VSync(fired %d) \n " , InterlockedExchange ( & m_VsyncFiredCounter , 0 ) ) ) ;
KeCancelTimer ( & m_VsyncTimer ) ;
}
else
{
LARGE_INTEGER li ;
2017-04-01 18:40:34 +02:00
LONG period = VSYNC_PERIOD ;
if ( ! period ) period = 1000 / VSYNC_RATE ;
DbgPrint ( TRACE_LEVEL_WARNING , ( " Enabled VSync %d ms(fired %d) \n " , period , m_VsyncFiredCounter ) ) ;
2017-02-16 15:31:01 +01:00
li . QuadPart = - 10000000 / VSYNC_RATE ;
KeSetTimerEx ( & m_VsyncTimer , li , period , & m_VsyncTimerDpc ) ;
}
}
}
QXL_NON_PAGED VOID QxlDod : : VsyncTimerProcGate ( _In_ _KDPC * dpc , _In_ PVOID context , _In_ PVOID arg1 , _In_ PVOID arg2 )
{
QxlDod * pQxl = reinterpret_cast < QxlDod * > ( context ) ;
pQxl - > VsyncTimerProc ( ) ;
}
2017-04-01 18:40:28 +02:00
void QxlDevice : : StopPresentThread ( )
{
PAGED_CODE ( ) ;
PVOID pDispatcherObject ;
if ( m_PresentThread )
{
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " ---> %s \n " , __FUNCTION__ ) ) ;
2017-05-05 13:54:58 +02:00
// this cause pending drawing operation to be discarded instead
// of executed, there's no reason to execute them if we are
// destroying the device
+ + m_DrawGeneration ;
2017-04-01 18:40:28 +02:00
PostToWorkerThread ( NULL ) ;
NTSTATUS Status = ObReferenceObjectByHandle (
m_PresentThread , 0 , NULL , KernelMode , & pDispatcherObject , NULL ) ;
if ( NT_SUCCESS ( Status ) )
{
WaitForObject ( pDispatcherObject , NULL ) ;
ObDereferenceObject ( pDispatcherObject ) ;
}
ZwClose ( m_PresentThread ) ;
m_PresentThread = NULL ;
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " <--- %s \n " , __FUNCTION__ ) ) ;
}
}
2017-04-08 12:46:55 +02:00
QXLDataChunk * QxlDevice : : MakeChunk ( DelayedChunk * pdc )
{
PAGED_CODE ( ) ;
QXLDataChunk * chunk = ( QXLDataChunk * ) AllocMem ( MSPACE_TYPE_VRAM , pdc - > chunk . data_size + sizeof ( QXLDataChunk ) , TRUE ) ;
if ( chunk )
{
chunk - > data_size = pdc - > chunk . data_size ;
chunk - > next_chunk = 0 ;
RtlCopyMemory ( chunk - > data , pdc - > chunk . data , chunk - > data_size ) ;
}
return chunk ;
}
ULONG QxlDevice : : PrepareDrawable ( QXLDrawable * & drawable )
{
PAGED_CODE ( ) ;
ULONG n = 0 ;
BOOLEAN bFail ;
PLIST_ENTRY pe = DelayedList ( drawable ) ;
QXLDataChunk * chunk , * lastchunk = NULL ;
bFail = ! m_bActive ;
while ( ! IsListEmpty ( pe ) ) {
DelayedChunk * pdc = ( DelayedChunk * ) RemoveHeadList ( pe ) ;
if ( ! lastchunk ) {
lastchunk = ( QXLDataChunk * ) pdc - > chunk . prev_chunk ;
}
if ( ! bFail & & ! lastchunk ) {
// bitmap was not allocated, this is single delayed chunk
QXL_ASSERT ( IsListEmpty ( pe ) ) ;
if ( AttachNewBitmap (
drawable ,
pdc - > chunk . data ,
pdc - > chunk . data + pdc - > chunk . data_size ,
- ( drawable - > u . copy . src_area . right * 4 ) ,
TRUE ) ) {
+ + n ;
} else {
bFail = TRUE ;
}
}
if ( ! bFail & & lastchunk ) {
// some chunks were not allocated
chunk = MakeChunk ( pdc ) ;
if ( chunk ) {
2017-04-10 17:02:47 +02:00
chunk - > prev_chunk = PA ( lastchunk ) ;
lastchunk - > next_chunk = PA ( chunk ) ;
2017-04-08 12:46:55 +02:00
lastchunk = chunk ;
+ + n ;
} else {
bFail = TRUE ;
}
}
delete [ ] reinterpret_cast < BYTE * > ( pdc ) ;
}
if ( bFail ) {
ReleaseOutput ( drawable - > release_info . id ) ;
drawable = NULL ;
}
return n ;
}
2017-04-01 18:40:28 +02:00
void QxlDevice : : PresentThreadRoutine ( )
{
PAGED_CODE ( ) ;
int wait ;
int notify ;
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " --->%s \n " , __FUNCTION__ ) ) ;
while ( 1 )
{
2017-05-05 13:54:58 +02:00
// Pop an operation from the ring
2017-04-01 18:40:28 +02:00
// No need for a mutex, only one consumer thread
SPICE_RING_CONS_WAIT ( m_PresentRing , wait ) ;
while ( wait ) {
2017-04-01 18:40:31 +02:00
// we do not want indication of long wait on this event
DoWaitForObject ( & m_PresentEvent , NULL , NULL ) ;
2017-04-01 18:40:28 +02:00
SPICE_RING_CONS_WAIT ( m_PresentRing , wait ) ;
}
2017-05-05 13:54:58 +02:00
QxlPresentOperation * operation = * SPICE_RING_CONS_ITEM ( m_PresentRing ) ;
2017-04-01 18:40:28 +02:00
SPICE_RING_POP ( m_PresentRing , notify ) ;
if ( notify ) {
KeSetEvent ( & m_PresentThreadReadyEvent , 0 , FALSE ) ;
}
2017-05-05 13:54:58 +02:00
if ( ! operation ) {
2017-04-01 18:40:28 +02:00
DbgPrint ( TRACE_LEVEL_WARNING , ( " %s is being terminated \n " , __FUNCTION__ ) ) ;
break ;
}
2017-05-05 13:54:58 +02:00
operation - > Run ( ) ;
delete operation ;
2017-04-01 18:40:28 +02:00
}
}
2017-05-05 13:54:58 +02:00
void QxlDevice : : PostToWorkerThread ( QxlPresentOperation * operation )
2017-04-01 18:40:28 +02:00
{
PAGED_CODE ( ) ;
// Push drawables into PresentRing and notify worker thread
int notify , wait ;
SPICE_RING_PROD_WAIT ( m_PresentRing , wait ) ;
while ( wait ) {
WaitForObject ( & m_PresentThreadReadyEvent , NULL ) ;
SPICE_RING_PROD_WAIT ( m_PresentRing , wait ) ;
}
2017-05-05 13:54:58 +02:00
* SPICE_RING_PROD_ITEM ( m_PresentRing ) = operation ;
2017-04-01 18:40:28 +02:00
SPICE_RING_PUSH ( m_PresentRing , notify ) ;
if ( notify ) {
KeSetEvent ( & m_PresentEvent , 0 , FALSE ) ;
}
DbgPrint ( TRACE_LEVEL_INFORMATION , ( " <--- %s \n " , __FUNCTION__ ) ) ;
}