summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYonit Halperin <yhalperi@redhat.com>2013-03-21 12:26:42 -0400
committerYonit Halperin <yhalperi@redhat.com>2013-03-21 12:26:42 -0400
commit2bdea610e40481b13eb1f8f25dfc80eb7261f2de (patch)
tree5f91aa0d5e8bbef30b01e6d5692e1bdc8896d8d7
start
-rw-r--r--C++/KMDOD.sln44
-rw-r--r--C++/Package/package.VcxProj93
-rw-r--r--C++/Package/package.VcxProj.Filters21
-rw-r--r--C++/Sample/SampleDisplay.vcxproj119
-rw-r--r--C++/Sample/SampleDisplay.vcxproj.Filters21
-rw-r--r--C++/Sample/sampledisplay.infbin0 -> 5224 bytes
-rw-r--r--C++/bdd.cxx830
-rw-r--r--C++/bdd.hxx647
-rw-r--r--C++/bdd_ddi.cxx578
-rw-r--r--C++/bdd_dmm.cxx1080
-rw-r--r--C++/bdd_errorlog.hxx84
-rw-r--r--C++/bdd_util.cxx115
-rw-r--r--C++/bltfuncs.cxx346
-rw-r--r--C++/blthw.cxx556
-rw-r--r--C++/memory.cxx78
-rw-r--r--C++/readme.htm46
-rw-r--r--C++/sampledisplay.rc30
-rw-r--r--description.html245
-rw-r--r--description/84ada392-ed9e-43d3-9c3e-f99f948be6cbBrand.css245
-rw-r--r--description/Brand.css3625
-rw-r--r--description/Combined.css0
-rw-r--r--description/Galleries.css418
-rw-r--r--description/Layout.css147
-rw-r--r--description/d0a480a2-d1c4-4159-af59-5aa4abd59cb0Combined.css0
-rw-r--r--description/iframedescription.css179
-rw-r--r--description/offline.js52
-rw-r--r--license.rtf25
27 files changed, 9624 insertions, 0 deletions
diff --git a/C++/KMDOD.sln b/C++/KMDOD.sln
new file mode 100644
index 0000000..f836684
--- /dev/null
+++ b/C++/KMDOD.sln
@@ -0,0 +1,44 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 11
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Package", "Package", "{80C7563F-F645-43DE-A00B-23C24BF5698F}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sample", "Sample", "{16B7D4DC-5693-4EC3-BD5F-ED60E27D2009}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "package", "Package\package.VcxProj", "{7F99CD16-400B-4B3A-B34A-A6140D4354B2}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleDisplay", "Sample\SampleDisplay.vcxproj", "{967F9D3D-5122-41FF-95F8-F0891EBA3D9E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Win8 Debug|Win32 = Win8 Debug|Win32
+ Win8 Debug|x64 = Win8 Debug|x64
+ Win8 Release|Win32 = Win8 Release|Win32
+ Win8 Release|x64 = Win8 Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {7F99CD16-400B-4B3A-B34A-A6140D4354B2}.Win8 Debug|Win32.ActiveCfg = Win8 Debug|Win32
+ {7F99CD16-400B-4B3A-B34A-A6140D4354B2}.Win8 Debug|Win32.Build.0 = Win8 Debug|Win32
+ {7F99CD16-400B-4B3A-B34A-A6140D4354B2}.Win8 Debug|x64.ActiveCfg = Win8 Debug|x64
+ {7F99CD16-400B-4B3A-B34A-A6140D4354B2}.Win8 Debug|x64.Build.0 = Win8 Debug|x64
+ {7F99CD16-400B-4B3A-B34A-A6140D4354B2}.Win8 Release|Win32.ActiveCfg = Win8 Release|Win32
+ {7F99CD16-400B-4B3A-B34A-A6140D4354B2}.Win8 Release|Win32.Build.0 = Win8 Release|Win32
+ {7F99CD16-400B-4B3A-B34A-A6140D4354B2}.Win8 Release|x64.ActiveCfg = Win8 Release|x64
+ {7F99CD16-400B-4B3A-B34A-A6140D4354B2}.Win8 Release|x64.Build.0 = Win8 Release|x64
+ {967F9D3D-5122-41FF-95F8-F0891EBA3D9E}.Win8 Debug|Win32.ActiveCfg = Win8 Debug|Win32
+ {967F9D3D-5122-41FF-95F8-F0891EBA3D9E}.Win8 Debug|Win32.Build.0 = Win8 Debug|Win32
+ {967F9D3D-5122-41FF-95F8-F0891EBA3D9E}.Win8 Debug|x64.ActiveCfg = Win8 Debug|x64
+ {967F9D3D-5122-41FF-95F8-F0891EBA3D9E}.Win8 Debug|x64.Build.0 = Win8 Debug|x64
+ {967F9D3D-5122-41FF-95F8-F0891EBA3D9E}.Win8 Release|Win32.ActiveCfg = Win8 Release|Win32
+ {967F9D3D-5122-41FF-95F8-F0891EBA3D9E}.Win8 Release|Win32.Build.0 = Win8 Release|Win32
+ {967F9D3D-5122-41FF-95F8-F0891EBA3D9E}.Win8 Release|x64.ActiveCfg = Win8 Release|x64
+ {967F9D3D-5122-41FF-95F8-F0891EBA3D9E}.Win8 Release|x64.Build.0 = Win8 Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {7F99CD16-400B-4B3A-B34A-A6140D4354B2} = {80C7563F-F645-43DE-A00B-23C24BF5698F}
+ {967F9D3D-5122-41FF-95F8-F0891EBA3D9E} = {16B7D4DC-5693-4EC3-BD5F-ED60E27D2009}
+ EndGlobalSection
+EndGlobal
diff --git a/C++/Package/package.VcxProj b/C++/Package/package.VcxProj
new file mode 100644
index 0000000..3f355db
--- /dev/null
+++ b/C++/Package/package.VcxProj
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Win8 Debug|Win32">
+ <Configuration>Win8 Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Win8 Release|Win32">
+ <Configuration>Win8 Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Win8 Debug|x64">
+ <Configuration>Win8 Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Win8 Release|x64">
+ <Configuration>Win8 Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="PropertySheets">
+ <PlatformToolset>WindowsKernelModeDriver8.0</PlatformToolset>
+ <ConfigurationType>Utility</ConfigurationType>
+ <DriverType>Package</DriverType>
+ <DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
+ <Configuration>Win8 Debug</Configuration>
+ </PropertyGroup>
+ <PropertyGroup Label="Globals">
+ <VCTargetsPath Condition="'$(VCTargetsPath11)' != '' and '$(VisualStudioVersion)' == '11.0'">$(VCTargetsPath11)</VCTargetsPath>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{7F99CD16-400B-4B3A-B34A-A6140D4354B2}</ProjectGuid>
+ <SampleGuid>{B42947DC-A8BB-406B-9611-7EAA2D3F44A7}</SampleGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Debug|Win32'" Label="Configuration">
+ <TargetVersion>Windows8</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Release|Win32'" Label="Configuration">
+ <TargetVersion>Windows8</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Debug|x64'" Label="Configuration">
+ <TargetVersion>Windows8</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Release|x64'" Label="Configuration">
+ <TargetVersion>Windows8</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup />
+ <PropertyGroup>
+ <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
+ <EnableDeployment>False</EnableDeployment>
+ <ImportToStore>False</ImportToStore>
+ <InstallMode>None</InstallMode>
+ <HardwareIdString />
+ <CommandLine />
+ <ScriptPath />
+ <DeployFiles />
+ <ScriptName />
+ <ScriptDeviceQuery>%PathToInf%</ScriptDeviceQuery>
+ <EnableVerifier>False</EnableVerifier>
+ <AllDrivers>False</AllDrivers>
+ <VerifyProjectOutput>True</VerifyProjectOutput>
+ <VerifyDrivers />
+ <VerifyFlags>133563</VerifyFlags>
+ <PackageDir>$(OutDir)Package</PackageDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <!--Inf Include="DriverInf.inv" /-->
+ <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Sample\SampleDisplay.vcxproj">
+ <Project>{967F9D3D-5122-41FF-95F8-F0891EBA3D9E}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/C++/Package/package.VcxProj.Filters b/C++/Package/package.VcxProj.Filters
new file mode 100644
index 0000000..bbcd0ea
--- /dev/null
+++ b/C++/Package/package.VcxProj.Filters
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ <UniqueIdentifier>{166FD30A-2F76-4770-B486-D13804DF324D}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{3918AB78-68B8-4E44-992D-D99C9C50422C}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Resource Files">
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ <UniqueIdentifier>{EF6CF794-5956-4F5B-B92D-C499C89AF08E}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Driver Files">
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ <UniqueIdentifier>{FBAD92ED-235B-4ECA-9B45-D6588E02FBA2}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/C++/Sample/SampleDisplay.vcxproj b/C++/Sample/SampleDisplay.vcxproj
new file mode 100644
index 0000000..02581a1
--- /dev/null
+++ b/C++/Sample/SampleDisplay.vcxproj
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Win8 Debug|Win32">
+ <Configuration>Win8 Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Win8 Release|Win32">
+ <Configuration>Win8 Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Win8 Debug|x64">
+ <Configuration>Win8 Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Win8 Release|x64">
+ <Configuration>Win8 Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="PropertySheets">
+ <DriverType>WDM</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver8.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Globals">
+ <VCTargetsPath Condition="'$(VCTargetsPath11)' != '' and '$(VisualStudioVersion)' == '11.0'">$(VCTargetsPath11)</VCTargetsPath>
+ <Configuration>Win8 Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <DebuggerFlavor Condition="'$(PlatformToolset)' == 'WindowsKernelModeDriver8.0'">DbgengKernelDebugger</DebuggerFlavor>
+ <DebuggerFlavor Condition="'$(PlatformToolset)' == 'WindowsUserModeDriver8.0'">DbgengRemoteDebugger</DebuggerFlavor>
+ <SampleGuid>{F63E0BD2-B6E0-485D-A780-B314E55ABB41}</SampleGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{967F9D3D-5122-41FF-95F8-F0891EBA3D9E}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Win8 Debug|Win32'">
+ <TargetVersion>Win8</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Win8 Release|Win32'">
+ <TargetVersion>Win8</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Win8 Debug|x64'">
+ <TargetVersion>Win8</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Win8 Release|x64'">
+ <TargetVersion>Win8</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <PropertyGroup>
+ <OutDir>$(IntDir)</OutDir>
+ </PropertyGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Win8 Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Win8 Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Win8 Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Win8 Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ItemGroup Label="WrappedTaskItems" />
+ <ItemDefinitionGroup>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\displib.lib;$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\hal.lib</AdditionalDependencies>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)</AdditionalIncludeDirectories>
+ </Midl>
+ </ItemDefinitionGroup>
+ <PropertyGroup>
+ <TargetName>SampleDisplay</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup>
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\BDD.cxx" />
+ <ClCompile Include="..\BDD_DDI.cxx" />
+ <ClCompile Include="..\BDD_DMM.cxx" />
+ <ClCompile Include="..\BDD_Util.cxx" />
+ <ClCompile Include="..\BltFuncs.cxx" />
+ <ClCompile Include="..\BltHw.cxx" />
+ <ClCompile Include="..\memory.cxx" />
+ <ResourceCompile Include="..\sampledisplay.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Exclude="@(Inf)" Include="*.inf" />
+ <FilesToPackage Include="$(TargetPath)" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Exclude="@(None)" Include="*.txt;*.htm;*.html" />
+ <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" />
+ <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project> \ No newline at end of file
diff --git a/C++/Sample/SampleDisplay.vcxproj.Filters b/C++/Sample/SampleDisplay.vcxproj.Filters
new file mode 100644
index 0000000..0fd4d5c
--- /dev/null
+++ b/C++/Sample/SampleDisplay.vcxproj.Filters
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ <UniqueIdentifier>{30064243-456F-446D-ABA8-B60188BA7A1C}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{0541BF12-46FE-4701-81BA-A909127FE4B5}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Resource Files">
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ <UniqueIdentifier>{940E2602-FF23-4E5B-9979-A6A716476C0B}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Driver Files">
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ <UniqueIdentifier>{A8015DF0-98D6-422C-A5D9-BAB52F04B5E7}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/C++/Sample/sampledisplay.inf b/C++/Sample/sampledisplay.inf
new file mode 100644
index 0000000..d913032
--- /dev/null
+++ b/C++/Sample/sampledisplay.inf
Binary files differ
diff --git a/C++/bdd.cxx b/C++/bdd.cxx
new file mode 100644
index 0000000..a0b4524
--- /dev/null
+++ b/C++/bdd.cxx
@@ -0,0 +1,830 @@
+/******************************Module*Header*******************************\
+* Module Name: bdd.cxx
+*
+* Basic Display Driver functions implementation
+*
+*
+* Copyright (c) 2010 Microsoft Corporation
+\**************************************************************************/
+
+
+#include "BDD.hxx"
+
+#pragma code_seg("PAGE")
+
+
+BASIC_DISPLAY_DRIVER::BASIC_DISPLAY_DRIVER(_In_ DEVICE_OBJECT* pPhysicalDeviceObject) : m_pPhysicalDevice(pPhysicalDeviceObject),
+ m_MonitorPowerState(PowerDeviceD0),
+ m_AdapterPowerState(PowerDeviceD0)
+{
+ PAGED_CODE();
+ *((UINT*)&m_Flags) = 0;
+ m_Flags._LastFlag = TRUE;
+ RtlZeroMemory(&m_DxgkInterface, sizeof(m_DxgkInterface));
+ RtlZeroMemory(&m_StartInfo, sizeof(m_StartInfo));
+ RtlZeroMemory(m_CurrentModes, sizeof(m_CurrentModes));
+ RtlZeroMemory(&m_DeviceInfo, sizeof(m_DeviceInfo));
+
+
+ for (UINT i=0;i<MAX_VIEWS;i++)
+ {
+ m_HardwareBlt[i].Initialize(this,i);
+ }
+}
+
+BASIC_DISPLAY_DRIVER::~BASIC_DISPLAY_DRIVER()
+{
+ PAGED_CODE();
+
+
+ CleanUp();
+}
+
+
+NTSTATUS BASIC_DISPLAY_DRIVER::StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo,
+ _In_ DXGKRNL_INTERFACE* pDxgkInterface,
+ _Out_ ULONG* pNumberOfViews,
+ _Out_ ULONG* pNumberOfChildren)
+{
+ PAGED_CODE();
+
+ BDD_ASSERT(pDxgkStartInfo != NULL);
+ BDD_ASSERT(pDxgkInterface != NULL);
+ BDD_ASSERT(pNumberOfViews != NULL);
+ BDD_ASSERT(pNumberOfChildren != NULL);
+
+ RtlCopyMemory(&m_StartInfo, pDxgkStartInfo, sizeof(m_StartInfo));
+ RtlCopyMemory(&m_DxgkInterface, pDxgkInterface, sizeof(m_DxgkInterface));
+ RtlZeroMemory(m_CurrentModes, sizeof(m_CurrentModes));
+ 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))
+ {
+ BDD_LOG_ASSERTION1("DxgkCbGetDeviceInformation failed with status 0x%I64x",
+ Status);
+ return Status;
+ }
+
+ // Ignore return value, since it's not the end of the world if we failed to write these values to the registry
+ RegisterHWInfo();
+
+ // TODO: Uncomment the line below after updating the TODOs in the function CheckHardware
+// Status = CheckHardware();
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ // This sample driver only uses the frame buffer of the POST device. DxgkCbAcquirePostDisplayOwnership
+ // gives you the frame buffer address and ensures that no one else is drawing to it. Be sure to give it back!
+ Status = m_DxgkInterface.DxgkCbAcquirePostDisplayOwnership(m_DxgkInterface.DeviceHandle, &(m_CurrentModes[0].DispInfo));
+ if (!NT_SUCCESS(Status) || m_CurrentModes[0].DispInfo.Width == 0)
+ {
+ // The most likely cause of failure is that the driver is simply not running on a POST device, or we are running
+ // after a pre-WDDM 1.2 driver. Since we can't draw anything, we should fail to start.
+ return STATUS_UNSUCCESSFUL;
+ }
+ m_Flags.DriverStarted = TRUE;
+ *pNumberOfViews = MAX_VIEWS;
+ *pNumberOfChildren = MAX_CHILDREN;
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS BASIC_DISPLAY_DRIVER::StopDevice(VOID)
+{
+ PAGED_CODE();
+
+ CleanUp();
+
+ m_Flags.DriverStarted = FALSE;
+
+ return STATUS_SUCCESS;
+}
+
+VOID BASIC_DISPLAY_DRIVER::CleanUp()
+{
+ PAGED_CODE();
+
+ for (UINT Source = 0; Source < MAX_VIEWS; ++Source)
+ {
+ if (m_CurrentModes[Source].FrameBuffer.Ptr)
+ {
+ UnmapFrameBuffer(m_CurrentModes[Source].FrameBuffer.Ptr, m_CurrentModes[Source].DispInfo.Height * m_CurrentModes[Source].DispInfo.Pitch);
+ m_CurrentModes[Source].FrameBuffer.Ptr = NULL;
+ m_CurrentModes[Source].Flags.FrameBufferIsActive = FALSE;
+ }
+ }
+}
+
+
+NTSTATUS BASIC_DISPLAY_DRIVER::DispatchIoRequest(_In_ ULONG VidPnSourceId,
+ _In_ VIDEO_REQUEST_PACKET* pVideoRequestPacket)
+{
+ PAGED_CODE();
+
+ BDD_ASSERT(pVideoRequestPacket != NULL);
+ BDD_ASSERT(VidPnSourceId < MAX_VIEWS);
+
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS BASIC_DISPLAY_DRIVER::SetPowerState(_In_ ULONG HardwareUid,
+ _In_ DEVICE_POWER_STATE DevicePowerState,
+ _In_ POWER_ACTION ActionType)
+{
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(ActionType);
+
+ BDD_ASSERT((HardwareUid < MAX_CHILDREN) || (HardwareUid == DISPLAY_ADAPTER_HW_ID));
+
+ if (HardwareUid == DISPLAY_ADAPTER_HW_ID)
+ {
+ if (DevicePowerState == PowerDeviceD0)
+ {
+
+ // 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);
+ }
+ }
+
+ // Store new adapter power state
+ m_AdapterPowerState = DevicePowerState;
+
+ // There is nothing to do to specifically power up/down the display adapter
+ return STATUS_SUCCESS;
+ }
+ else
+ {
+ // TODO: This is where the specified monitor should be powered up/down
+ NOTHING;
+ return STATUS_SUCCESS;
+ }
+}
+
+NTSTATUS BASIC_DISPLAY_DRIVER::QueryChildRelations(_Out_writes_bytes_(ChildRelationsSize) DXGK_CHILD_DESCRIPTOR* pChildRelations,
+ _In_ ULONG ChildRelationsSize)
+{
+ PAGED_CODE();
+
+ BDD_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;
+ BDD_ASSERT(ChildRelationsCount <= MAX_CHILDREN);
+
+ for (UINT ChildIndex = 0; ChildIndex < ChildRelationsCount; ++ChildIndex)
+ {
+ pChildRelations[ChildIndex].ChildDeviceType = TypeVideoOutput;
+ pChildRelations[ChildIndex].ChildCapabilities.HpdAwareness = m_CurrentModes[0].Flags.IsInternal ? HpdAwarenessAlwaysConnected : HpdAwarenessInterruptible;
+ pChildRelations[ChildIndex].ChildCapabilities.Type.VideoOutput.InterfaceTechnology = m_CurrentModes[0].Flags.IsInternal ? D3DKMDT_VOT_INTERNAL : D3DKMDT_VOT_OTHER;
+ 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;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS BASIC_DISPLAY_DRIVER::QueryChildStatus(_Inout_ DXGK_CHILD_STATUS* pChildStatus,
+ _In_ BOOLEAN NonDestructiveOnly)
+{
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(NonDestructiveOnly);
+ BDD_ASSERT(pChildStatus != NULL);
+ BDD_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
+ BDD_LOG_ERROR0("Child status being queried for StatusRotation even though D3DKMDT_MOA_NONE was reported");
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ default:
+ {
+ BDD_LOG_WARNING1("Unknown pChildStatus->Type (0x%I64x) requested.", pChildStatus->Type);
+ return STATUS_NOT_SUPPORTED;
+ }
+ }
+}
+
+// EDID retrieval
+NTSTATUS BASIC_DISPLAY_DRIVER::QueryDeviceDescriptor(_In_ ULONG ChildUid,
+ _Inout_ DXGK_DEVICE_DESCRIPTOR* pDeviceDescriptor)
+{
+ PAGED_CODE();
+
+ BDD_ASSERT(pDeviceDescriptor != NULL);
+ BDD_ASSERT(ChildUid < MAX_CHILDREN);
+
+ // If we haven't successfully retrieved an EDID yet (invalid ones are ok, so long as it was retrieved)
+ if (!m_Flags.EDID_Attempted)
+ {
+ GetEdid(ChildUid);
+
+ }
+
+ if (!m_Flags.EDID_Retrieved || !m_Flags.EDID_ValidHeader || !m_Flags.EDID_ValidChecksum)
+ {
+ // Report no EDID if a valid one wasn't retrieved
+ return STATUS_GRAPHICS_CHILD_DESCRIPTOR_NOT_SUPPORTED;
+ }
+ else if (pDeviceDescriptor->DescriptorOffset == 0)
+ {
+ // Only the base block is supported
+ RtlCopyMemory(pDeviceDescriptor->DescriptorBuffer,
+ m_EDIDs[ChildUid],
+ min(pDeviceDescriptor->DescriptorLength, EDID_V1_BLOCK_SIZE));
+
+ return STATUS_SUCCESS;
+ }
+ else
+ {
+ return STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA;
+ }
+}
+
+NTSTATUS BASIC_DISPLAY_DRIVER::QueryAdapterInfo(_In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAdapterInfo)
+{
+ PAGED_CODE();
+
+ BDD_ASSERT(pQueryAdapterInfo != NULL);
+
+ switch (pQueryAdapterInfo->Type)
+ {
+ case DXGKQAITYPE_DRIVERCAPS:
+ {
+ if (pQueryAdapterInfo->OutputDataSize < sizeof(DXGK_DRIVERCAPS))
+ {
+ BDD_LOG_ERROR2("pQueryAdapterInfo->OutputDataSize (0x%I64x) is smaller than sizeof(DXGK_DRIVERCAPS) (0x%I64x)", pQueryAdapterInfo->OutputDataSize, sizeof(DXGK_DRIVERCAPS));
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ DXGK_DRIVERCAPS* pDriverCaps = (DXGK_DRIVERCAPS*)pQueryAdapterInfo->pOutputData;
+
+ // Nearly all fields must be initialized to zero, so zero out to start and then change those that are non-zero.
+ // Fields are zero since BDD is Display-Only and therefore does not support any of the render related fields.
+ // It also doesn't support hardware interrupts, gamma ramps, etc.
+ RtlZeroMemory(pDriverCaps, sizeof(DXGK_DRIVERCAPS));
+
+ pDriverCaps->WDDMVersion = DXGKDDI_WDDMv1_2;
+ pDriverCaps->HighestAcceptableAddress.QuadPart = -1;
+
+ pDriverCaps->SupportNonVGA = TRUE;
+ pDriverCaps->SupportSmoothRotation = TRUE;
+
+ return STATUS_SUCCESS;
+ }
+
+ default:
+ {
+ // BDD does not need to support any other adapter information types
+ BDD_LOG_WARNING1("Unknown QueryAdapterInfo Type (0x%I64x) requested", pQueryAdapterInfo->Type);
+ return STATUS_NOT_SUPPORTED;
+ }
+ }
+}
+
+
+NTSTATUS BASIC_DISPLAY_DRIVER::CheckHardware()
+{
+ PAGED_CODE();
+
+ NTSTATUS Status;
+ ULONG VendorID;
+ ULONG DeviceID;
+
+// TODO: If developing a driver for PCI based hardware, then use the second method to retrieve Vendor/Device IDs.
+// If developing for non-PCI based hardware (i.e. ACPI based hardware), use the first method to retrieve the IDs.
+#if 1 // ACPI-based device
+
+ // Get the Vendor & Device IDs on non-PCI system
+ ACPI_EVAL_INPUT_BUFFER_COMPLEX AcpiInputBuffer = {0};
+ AcpiInputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_COMPLEX_SIGNATURE;
+ AcpiInputBuffer.MethodNameAsUlong = ACPI_METHOD_HARDWARE_ID;
+ AcpiInputBuffer.Size = 0;
+ AcpiInputBuffer.ArgumentCount = 0;
+
+ BYTE OutputBuffer[sizeof(ACPI_EVAL_OUTPUT_BUFFER) + 0x10];
+ RtlZeroMemory(OutputBuffer, sizeof(OutputBuffer));
+ ACPI_EVAL_OUTPUT_BUFFER* pAcpiOutputBuffer = reinterpret_cast<ACPI_EVAL_OUTPUT_BUFFER*>(&OutputBuffer);
+
+ Status = m_DxgkInterface.DxgkCbEvalAcpiMethod(m_DxgkInterface.DeviceHandle,
+ DISPLAY_ADAPTER_HW_ID,
+ &AcpiInputBuffer,
+ sizeof(AcpiInputBuffer),
+ pAcpiOutputBuffer,
+ sizeof(OutputBuffer));
+ if (!NT_SUCCESS(Status))
+ {
+ BDD_LOG_ERROR1("DxgkCbReadDeviceSpace failed to get hardware IDs with status 0x%I64x", Status);
+ return Status;
+ }
+
+ VendorID = ((ULONG*)(pAcpiOutputBuffer->Argument[0].Data))[0];
+ DeviceID = ((ULONG*)(pAcpiOutputBuffer->Argument[0].Data))[1];
+
+#else // PCI-based device
+
+ // 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))
+ {
+ BDD_LOG_ERROR1("DxgkCbReadDeviceSpace failed with status 0x%I64x", Status);
+ return Status;
+ }
+
+ VendorID = Header.VendorID;
+ DeviceID = Header.DeviceID;
+
+#endif
+
+ // TODO: Replace 0x1414 with your Vendor ID
+ if (VendorID == 0x1414)
+ {
+ switch (DeviceID)
+ {
+ // TODO: Replace the case statements below with the Device IDs supported by this driver
+ case 0x0000:
+ case 0xFFFF: return STATUS_SUCCESS;
+ }
+ }
+
+ return STATUS_GRAPHICS_DRIVER_MISMATCH;
+}
+
+// Even though Sample Basic Display Driver does not support hardware cursors, and reports such
+// in QueryAdapterInfo. This function can still be called to set the pointer to not visible
+NTSTATUS BASIC_DISPLAY_DRIVER::SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition)
+{
+ PAGED_CODE();
+
+ BDD_ASSERT(pSetPointerPosition != NULL);
+ BDD_ASSERT(pSetPointerPosition->VidPnSourceId < MAX_VIEWS);
+
+ if (!(pSetPointerPosition->Flags.Visible))
+ {
+ return STATUS_SUCCESS;
+ }
+ else
+ {
+ BDD_LOG_ASSERTION0("SetPointerPosition should never be called to set the pointer to visible since BDD doesn't support hardware cursors.");
+ return STATUS_UNSUCCESSFUL;
+ }
+}
+
+// Basic Sample Display Driver does not support hardware cursors, and reports such
+// in QueryAdapterInfo. Therefore this function should never be called.
+NTSTATUS BASIC_DISPLAY_DRIVER::SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape)
+{
+ PAGED_CODE();
+
+ BDD_ASSERT(pSetPointerShape != NULL);
+ BDD_LOG_ASSERTION0("SetPointerShape should never be called since BDD doesn't support hardware cursors.");
+
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+
+NTSTATUS BASIC_DISPLAY_DRIVER::PresentDisplayOnly(_In_ CONST DXGKARG_PRESENT_DISPLAYONLY* pPresentDisplayOnly)
+{
+ PAGED_CODE();
+
+ BDD_ASSERT(pPresentDisplayOnly != NULL);
+ BDD_ASSERT(pPresentDisplayOnly->VidPnSourceId < MAX_VIEWS);
+
+ if (pPresentDisplayOnly->BytesPerPixel < MIN_BYTES_PER_PIXEL_REPORTED)
+ {
+ // Only >=32bpp modes are reported, therefore this Present should never pass anything less than 4 bytes per pixel
+ BDD_LOG_ERROR1("pPresentDisplayOnly->BytesPerPixel is 0x%I64x, which is lower than the allowed.", 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))
+ {
+ return STATUS_SUCCESS;
+ }
+
+ // Present is only valid if the target is actively connected to this source
+ if (m_CurrentModes[pPresentDisplayOnly->VidPnSourceId].Flags.FrameBufferIsActive)
+ {
+
+ // 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;
+ }
+ return m_HardwareBlt[pPresentDisplayOnly->VidPnSourceId].ExecutePresentDisplayOnly(pDst,
+ DstBitPerPixel,
+ (BYTE*)pPresentDisplayOnly->pSource,
+ pPresentDisplayOnly->BytesPerPixel,
+ pPresentDisplayOnly->Pitch,
+ pPresentDisplayOnly->NumMoves,
+ pPresentDisplayOnly->pMoves,
+ pPresentDisplayOnly->NumDirtyRects,
+ pPresentDisplayOnly->pDirtyRect,
+ RotationNeededByFb);
+ }
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS BASIC_DISPLAY_DRIVER::StopDeviceAndReleasePostDisplayOwnership(_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
+ _Out_ DXGK_DISPLAY_INFORMATION* pDisplayInfo)
+{
+ PAGED_CODE();
+
+ BDD_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
+ BlackOutScreen(SourceId);
+
+ *pDisplayInfo = m_CurrentModes[SourceId].DispInfo;
+
+ return StopDevice();
+}
+
+NTSTATUS BASIC_DISPLAY_DRIVER::QueryVidPnHWCapability(_Inout_ DXGKARG_QUERYVIDPNHWCAPABILITY* pVidPnHWCaps)
+{
+ PAGED_CODE();
+
+ BDD_ASSERT(pVidPnHWCaps != NULL);
+ BDD_ASSERT(pVidPnHWCaps->SourceId < MAX_VIEWS);
+ BDD_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
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS BASIC_DISPLAY_DRIVER::GetEdid(D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId)
+{
+ PAGED_CODE();
+
+ BDD_ASSERT_CHK(!m_Flags.EDID_Attempted);
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ RtlZeroMemory(m_EDIDs[TargetId], sizeof(m_EDIDs[TargetId]));
+
+
+ m_Flags.EDID_Attempted = TRUE;
+
+ return Status;
+}
+
+
+VOID BASIC_DISPLAY_DRIVER::BlackOutScreen(D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId)
+{
+ PAGED_CODE();
+
+ UINT ScreenHeight = m_CurrentModes[SourceId].DispInfo.Height;
+ UINT ScreenPitch = m_CurrentModes[SourceId].DispInfo.Pitch;
+
+ PHYSICAL_ADDRESS NewPhysAddrStart = m_CurrentModes[SourceId].DispInfo.PhysicAddress;
+ PHYSICAL_ADDRESS NewPhysAddrEnd;
+ NewPhysAddrEnd.QuadPart = NewPhysAddrStart.QuadPart + (ScreenHeight * ScreenPitch);
+
+ if (m_CurrentModes[SourceId].Flags.FrameBufferIsActive)
+ {
+ BYTE* MappedAddr = reinterpret_cast<BYTE*>(m_CurrentModes[SourceId].FrameBuffer.Ptr);
+
+ // Zero any memory at the start that hasn't been zeroed recently
+ if (NewPhysAddrStart.QuadPart < m_CurrentModes[SourceId].ZeroedOutStart.QuadPart)
+ {
+ if (NewPhysAddrEnd.QuadPart < m_CurrentModes[SourceId].ZeroedOutStart.QuadPart)
+ {
+ // No overlap
+ RtlZeroMemory(MappedAddr, ScreenHeight * ScreenPitch);
+ }
+ else
+ {
+ RtlZeroMemory(MappedAddr, (UINT)(m_CurrentModes[SourceId].ZeroedOutStart.QuadPart - NewPhysAddrStart.QuadPart));
+ }
+ }
+
+ // Zero any memory at the end that hasn't been zeroed recently
+ if (NewPhysAddrEnd.QuadPart > m_CurrentModes[SourceId].ZeroedOutEnd.QuadPart)
+ {
+ if (NewPhysAddrStart.QuadPart > m_CurrentModes[SourceId].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 - m_CurrentModes[SourceId].ZeroedOutEnd.QuadPart));
+ }
+ }
+ }
+
+ m_CurrentModes[SourceId].ZeroedOutStart.QuadPart = NewPhysAddrStart.QuadPart;
+ m_CurrentModes[SourceId].ZeroedOutEnd.QuadPart = NewPhysAddrEnd.QuadPart;
+}
+
+NTSTATUS BASIC_DISPLAY_DRIVER::WriteHWInfoStr(_In_ HANDLE DevInstRegKeyHandle, _In_ PCWSTR pszwValueName, _In_ PCSTR pszValue)
+{
+ PAGED_CODE();
+
+ NTSTATUS Status;
+ ANSI_STRING AnsiStrValue;
+ UNICODE_STRING UnicodeStrValue;
+ UNICODE_STRING UnicodeStrValueName;
+
+ // 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))
+ {
+ BDD_LOG_ERROR1("RtlAnsiStringToUnicodeString failed with Status: 0x%I64x", 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))
+ {
+ BDD_LOG_ERROR1("ZwSetValueKey failed with Status: 0x%I64x", Status);
+ }
+
+ return Status;
+}
+
+NTSTATUS BASIC_DISPLAY_DRIVER::RegisterHWInfo()
+{
+ PAGED_CODE();
+
+ NTSTATUS Status;
+
+ // TODO: Replace these strings with proper information
+ PCSTR StrHWInfoChipType = "Replace with the chip name";
+ PCSTR StrHWInfoDacType = "Replace with the DAC name or identifier (ID)";
+ PCSTR StrHWInfoAdapterString = "Replace with the name of the adapter";
+ PCSTR StrHWInfoBiosString = "Replace with information about the BIOS";
+
+ HANDLE DevInstRegKeyHandle;
+ Status = IoOpenDeviceRegistryKey(m_pPhysicalDevice, PLUGPLAY_REGKEY_DRIVER, KEY_SET_VALUE, &DevInstRegKeyHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ BDD_LOG_ERROR2("IoOpenDeviceRegistryKey failed for PDO: 0x%I64x, Status: 0x%I64x", m_pPhysicalDevice, Status);
+ 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))
+ {
+ BDD_LOG_ERROR1("ZwSetValueKey for MemorySize failed with Status: 0x%I64x", Status);
+ return Status;
+ }
+
+ return Status;
+}
+
+//
+// Non-Paged Code
+//
+#pragma code_seg(push)
+#pragma code_seg()
+D3DDDI_VIDEO_PRESENT_SOURCE_ID BASIC_DISPLAY_DRIVER::FindSourceForTarget(D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId, BOOLEAN DefaultToZero)
+{
+ UNREFERENCED_PARAMETER(TargetId);
+ BDD_ASSERT_CHK(TargetId < MAX_CHILDREN);
+
+ for (UINT SourceId = 0; SourceId < MAX_VIEWS; ++SourceId)
+ {
+ if (m_CurrentModes[SourceId].FrameBuffer.Ptr != NULL)
+ {
+ return SourceId;
+ }
+ }
+
+ return DefaultToZero ? 0 : D3DDDI_ID_UNINITIALIZED;
+}
+
+VOID BASIC_DISPLAY_DRIVER::DpcRoutine(VOID)
+{
+ m_DxgkInterface.DxgkCbNotifyDpc((HANDLE)m_DxgkInterface.DeviceHandle);
+}
+
+BOOLEAN BASIC_DISPLAY_DRIVER::InterruptRoutine(_In_ ULONG MessageNumber)
+{
+ UNREFERENCED_PARAMETER(MessageNumber);
+
+ // BDD cannot handle interrupts
+ return FALSE;
+}
+
+VOID BASIC_DISPLAY_DRIVER::ResetDevice(VOID)
+{
+}
+
+// Must be Non-Paged, as it sets up the display for a bugcheck
+NTSTATUS BASIC_DISPLAY_DRIVER::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);
+
+ m_SystemDisplaySourceId = D3DDDI_ID_UNINITIALIZED;
+
+ BDD_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
+VOID BASIC_DISPLAY_DRIVER::SystemDisplayWrite(_In_reads_bytes_(SourceHeight * SourceStride) VOID* pSource,
+ _In_ UINT SourceWidth,
+ _In_ UINT SourceHeight,
+ _In_ UINT SourceStride,
+ _In_ INT PositionX,
+ _In_ INT PositionY)
+{
+
+ // 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,
+ 1, // NumRects
+ &Rect);
+}
+
+#pragma code_seg(pop) // End Non-Paged Code
+
diff --git a/C++/bdd.hxx b/C++/bdd.hxx
new file mode 100644
index 0000000..3c98664
--- /dev/null
+++ b/C++/bdd.hxx
@@ -0,0 +1,647 @@
+/******************************Module*Header*******************************\
+* Module Name: BDD.hxx
+*
+* Basic Display Driver header file
+*
+*
+* Copyright (c) 2010 Microsoft Corporation
+\**************************************************************************/
+
+#ifndef _BDD_HXX_
+#define _BDD_HXX_
+
+extern "C"
+{
+ #define __CPLUSPLUS
+
+ // Standard C-runtime headers
+ #include <stddef.h>
+ #include <string.h>
+ #include <stdarg.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+
+ #include <initguid.h>
+
+ // NTOS headers
+ #include <ntddk.h>
+
+ #ifndef FAR
+ #define FAR
+ #endif
+
+ // Windows headers
+ #include <windef.h>
+ #include <winerror.h>
+
+ // Windows GDI headers
+ #include <wingdi.h>
+
+ // Windows DDI headers
+ #include <winddi.h>
+ #include <ntddvdeo.h>
+
+ #include <d3dkmddi.h>
+ #include <d3dkmthk.h>
+
+ #include <ntstrsafe.h>
+ #include <ntintsafe.h>
+
+ #include <dispmprt.h>
+};
+#include "BDD_ErrorLog.hxx"
+
+#define MIN_WIDTH 640
+#define MIN_HEIGHT 480
+#define MIN_BITS_PER_PIXEL_ALLOWED 8
+#define MIN_BYTES_PER_PIXEL_REPORTED 4
+
+#define DEFAULT_WIDTH 1024
+#define DEFAULT_HEIGHT 768
+
+#define MAX_INVALID_INHERITED_WIDTH 1024
+#define MAX_INVALID_INHERITED_HEIGHT 768
+
+#define BITS_PER_BYTE 8
+#define EDID_V1_BLOCK_SIZE 128
+
+typedef struct _BLT_INFO
+{
+ PVOID pBits;
+ UINT Pitch;
+ UINT BitsPerPel;
+ POINT Offset; // To unrotated top-left of dirty rects
+ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation;
+ UINT Width; // For the unrotated image
+ UINT Height; // For the unrotated image
+} BLT_INFO;
+
+#define MAX_CHILDREN 1
+#define MAX_VIEWS 1
+
+typedef struct _BDD_FLAGS
+{
+ UINT DriverStarted : 1; // ( 1) 1 after StartDevice and 0 after StopDevice
+ UINT EDID_Retrieved : 1; // ( 2) EDID was successfully retrieved
+ UINT EDID_ValidChecksum : 1; // ( 3) Retrieved EDID has a valid checksum
+ UINT EDID_ValidHeader : 1; // ( 4) Retrieved EDID has a valid header
+ UINT EDID_Attempted : 1; // ( 5) 1 if an attempt was made to retrieve the EDID, successful or not
+
+ // IMPORTANT: All new flags must be added to just before _LastFlag (i.e. right above this comment), this allows different versions of diagnostics to still be useful.
+ UINT _LastFlag : 1; // ( 6) Always set to 1, is used to ensure that diagnostic version matches binary version
+ UINT Unused : 26;
+} BDD_FLAGS;
+
+// Represents the current mode, may not always be set (i.e. frame buffer mapped) if representing the mode passed in on single mode setups.
+typedef struct _CURRENT_BDD_MODE
+{
+ // The source mode currently set for HW Framebuffer
+ // For sample driver this info filled in StartDevice by the OS and never changed.
+ DXGK_DISPLAY_INFORMATION DispInfo;
+
+ // The rotation of the current mode. Rotation is performed in software during Present call
+ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation;
+
+ D3DKMDT_VIDPN_PRESENT_PATH_SCALING Scaling;
+ // This mode might be different from one which are supported for HW frame buffer
+ // Scaling/displasment might be needed (if supported)
+ UINT SrcModeWidth;
+ UINT SrcModeHeight;
+
+ // Various boolean flags the struct uses
+ struct _CURRENT_BDD_MODE_FLAGS
+ {
+ UINT SourceNotVisible : 1; // 0 if source is visible
+ UINT FullscreenPresent : 1; // 0 if should use dirty rects for present
+ UINT FrameBufferIsActive : 1; // 0 if not currently active (i.e. target not connected to source)
+ UINT DoNotMapOrUnmap : 1; // 1 if the FrameBuffer should not be (un)mapped during normal execution
+ UINT IsInternal : 1; // 1 if it was determined (i.e. through ACPI) that an internal panel is being driven
+ UINT Unused : 27;
+ } Flags;
+
+ // The start and end of physical memory known to be all zeroes. Used to optimize the BlackOutScreen function to not write
+ // zeroes to memory already known to be zero. (Physical address is located in DispInfo)
+ PHYSICAL_ADDRESS ZeroedOutStart;
+ PHYSICAL_ADDRESS ZeroedOutEnd;
+
+ // Linear frame buffer pointer
+ // A union with a ULONG64 is used here to ensure this struct looks the same on 32bit and 64bit builds
+ // since the size of a VOID* changes depending on the build.
+ union
+ {
+ VOID* Ptr;
+ ULONG64 Force8Bytes;
+ } FrameBuffer;
+} CURRENT_BDD_MODE;
+
+class BASIC_DISPLAY_DRIVER;
+
+class BDD_HWBLT
+{
+public:
+ D3DDDI_VIDEO_PRESENT_SOURCE_ID m_SourceId;
+ BASIC_DISPLAY_DRIVER* m_DevExt;
+ BOOLEAN m_SynchExecution;
+ HANDLE m_hPresentWorkerThread;
+ PVOID m_pPresentWorkerThread;
+
+ // Events to contol thread execution
+ KEVENT m_hThreadStartupEvent;
+ KEVENT m_hThreadSuspendEvent;
+
+ BDD_HWBLT();
+
+ ~BDD_HWBLT();
+
+ void Initialize(_In_ BASIC_DISPLAY_DRIVER* DevExt, _In_ UINT IdSrc) { m_DevExt = DevExt; m_SourceId = IdSrc; }
+ void SetPresentWorkerThreadInfo(HANDLE hWorkerThread);
+ NTSTATUS ExecutePresentDisplayOnly(_In_ BYTE* DstAddr,
+ _In_ UINT DstBitPerPixel,
+ _In_ BYTE* SrcAddr,
+ _In_ UINT SrcBytesPerPixel,
+ _In_ LONG SrcPitch,
+ _In_ ULONG NumMoves,
+ _In_ D3DKMT_MOVE_RECT* pMoves,
+ _In_ ULONG NumDirtyRects,
+ _In_ RECT* pDirtyRect,
+ _In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation);
+
+};
+
+class BASIC_DISPLAY_DRIVER
+{
+private:
+ DEVICE_OBJECT* m_pPhysicalDevice;
+ DXGKRNL_INTERFACE m_DxgkInterface;
+
+ // Information passed in by StartDevice DDI
+ DXGK_START_INFO m_StartInfo;
+
+
+ // Array of EDIDs, currently only supporting base block, hence EDID_V1_BLOCK_SIZE for size of each EDID
+ BYTE m_EDIDs[MAX_CHILDREN][EDID_V1_BLOCK_SIZE];
+
+ CURRENT_BDD_MODE m_CurrentModes[MAX_VIEWS];
+
+
+ BDD_HWBLT m_HardwareBlt[MAX_VIEWS];
+
+ // Current monitorpower state (this needs to be changed if MAX_CHILDREN != 1)
+ DEVICE_POWER_STATE m_MonitorPowerState;
+
+ // Current adapter power state
+ DEVICE_POWER_STATE m_AdapterPowerState;
+
+ // Source ID to be used by SystemDisplay functions
+ D3DDDI_VIDEO_PRESENT_SOURCE_ID m_SystemDisplaySourceId;
+
+ // Various boolean flags the class uses
+ BDD_FLAGS m_Flags;
+
+ // Device information
+ DXGK_DEVICE_INFO m_DeviceInfo;
+
+public:
+ BASIC_DISPLAY_DRIVER(_In_ DEVICE_OBJECT* pPhysicalDeviceObject);
+ ~BASIC_DISPLAY_DRIVER();
+
+#pragma code_seg(push)
+#pragma code_seg()
+ BOOLEAN IsDriverActive() const
+ {
+ return m_Flags.DriverStarted;
+ }
+#pragma code_seg(pop)
+
+ NTSTATUS StartDevice(_In_ DXGK_START_INFO* pDxgkStartInfo,
+ _In_ DXGKRNL_INTERFACE* pDxgkInterface,
+ _Out_ ULONG* pNumberOfViews,
+ _Out_ ULONG* pNumberOfChildren);
+
+ NTSTATUS StopDevice(VOID);
+
+ // Must be Non-Paged
+ VOID ResetDevice(VOID);
+
+
+ const CURRENT_BDD_MODE* GetCurrentMode(UINT SourceId) const
+ {
+ return (SourceId < MAX_VIEWS)?&m_CurrentModes[SourceId]:NULL;
+ }
+ const DXGKRNL_INTERFACE* GetDxgkInterface() const { return &m_DxgkInterface;}
+
+ // Not implemented since no IOCTLs currently handled.
+ NTSTATUS DispatchIoRequest(_In_ ULONG VidPnSourceId,
+ _In_ VIDEO_REQUEST_PACKET* pVideoRequestPacket);
+
+ // Used to either turn off/on monitor (if possible), or mark that system is going into hibernate
+ NTSTATUS SetPowerState(_In_ ULONG HardwareUid,
+ _In_ DEVICE_POWER_STATE DevicePowerState,
+ _In_ POWER_ACTION ActionType);
+
+ // Report back child capabilities
+ NTSTATUS QueryChildRelations(_Out_writes_bytes_(ChildRelationsSize) DXGK_CHILD_DESCRIPTOR* pChildRelations,
+ _In_ ULONG ChildRelationsSize);
+
+ NTSTATUS QueryChildStatus(_Inout_ DXGK_CHILD_STATUS* pChildStatus,
+ _In_ BOOLEAN NonDestructiveOnly);
+
+ // Return EDID if previously retrieved
+ NTSTATUS QueryDeviceDescriptor(_In_ ULONG ChildUid,
+ _Inout_ DXGK_DEVICE_DESCRIPTOR* pDeviceDescriptor);
+
+ // Must be Non-Paged
+ // BDD doesn't have interrupts, so just returns false
+ BOOLEAN InterruptRoutine(_In_ ULONG MessageNumber);
+
+ VOID DpcRoutine(VOID);
+
+ // Return DriverCaps, doesn't support other queries though
+ NTSTATUS QueryAdapterInfo(_In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAdapterInfo);
+
+ NTSTATUS SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition);
+
+ NTSTATUS SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape);
+
+ NTSTATUS PresentDisplayOnly(_In_ CONST DXGKARG_PRESENT_DISPLAYONLY* pPresentDisplayOnly);
+
+ NTSTATUS IsSupportedVidPn(_Inout_ DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPn);
+
+ NTSTATUS RecommendFunctionalVidPn(_In_ CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST pRecommendFunctionalVidPn);
+
+ NTSTATUS RecommendVidPnTopology(_In_ CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST pRecommendVidPnTopology);
+
+ NTSTATUS RecommendMonitorModes(_In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModes);
+
+ NTSTATUS EnumVidPnCofuncModality(_In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModality);
+
+ NTSTATUS SetVidPnSourceVisibility(_In_ CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility);
+
+ NTSTATUS CommitVidPn(_In_ CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPn);
+
+ NTSTATUS UpdateActiveVidPnPresentPath(_In_ CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPath);
+
+ NTSTATUS QueryVidPnHWCapability(_Inout_ DXGKARG_QUERYVIDPNHWCAPABILITY* pVidPnHWCaps);
+
+ // Part of PnPStop (PnP instance only), returns current mode information (which will be passed to fallback instance by dxgkrnl)
+ NTSTATUS StopDeviceAndReleasePostDisplayOwnership(_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
+ _Out_ DXGK_DISPLAY_INFORMATION* pDisplayInfo);
+
+ // Must be Non-Paged
+ // Call to initialize as part of bugcheck
+ NTSTATUS SystemDisplayEnable(_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
+ _In_ PDXGKARG_SYSTEM_DISPLAY_ENABLE_FLAGS Flags,
+ _Out_ UINT* pWidth,
+ _Out_ UINT* pHeight,
+ _Out_ D3DDDIFORMAT* pColorFormat);
+
+ // Must be Non-Paged
+ // Write out pixels as part of bugcheck
+ VOID SystemDisplayWrite(_In_reads_bytes_(SourceHeight * SourceStride) VOID* pSource,
+ _In_ UINT SourceWidth,
+ _In_ UINT SourceHeight,
+ _In_ UINT SourceStride,
+ _In_ INT PositionX,
+ _In_ INT PositionY);
+
+
+private:
+ VOID CleanUp();
+
+ NTSTATUS CommonStart();
+
+ NTSTATUS GetEdid(D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId);
+
+
+ // Given pixel format, give back the bits per pixel. Only supports pixel formats expected by BDD
+ // (i.e. the ones found below in PixelFormatFromBPP or that may come in from FallbackStart)
+ // This is because these two functions combine to allow BDD to store the bpp of a VBE mode in the
+ // ColorFormat field of a DispInfo
+ UINT BPPFromPixelFormat(D3DDDIFORMAT Format) const
+ {
+ 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: BDD_LOG_ASSERTION1("Unknown D3DDDIFORMAT 0x%I64x", Format); return 0;
+ }
+ }
+
+ // Given bits per pixel, return the pixel format at the same bpp
+ D3DDDIFORMAT PixelFormatFromBPP(UINT BPP) const
+ {
+ switch (BPP)
+ {
+ case 8: return D3DDDIFMT_P8;
+ case 16: return D3DDDIFMT_R5G6B5;
+ case 24: return D3DDDIFMT_R8G8B8;
+ case 32: return D3DDDIFMT_X8R8G8B8;
+ default: BDD_LOG_ASSERTION1("A bit per pixel of 0x%I64x is not supported.", BPP); return D3DDDIFMT_UNKNOWN;
+ }
+ }
+
+ // These two functions make checks on the values of some of the fields of their respective structures to ensure
+ // that the specified fields are supported by BDD, i.e. gamma ramp must be D3DDDI_GAMMARAMP_DEFAULT
+ NTSTATUS IsVidPnPathFieldsValid(CONST D3DKMDT_VIDPN_PRESENT_PATH* pPath) const;
+ NTSTATUS IsVidPnSourceModeFieldsValid(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMode) const;
+
+ VOID BlackOutScreen(D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId);
+
+ // Returns the index into gBddBiosData.BddModes of the VBE mode that matches the given VidPnSourceMode.
+ // If such a mode cannot be found, returns a number outside of [0, gBddBiosData.CountBddModes)
+ UINT FindMatchingVBEMode(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMode) const;
+
+ // Must be Non-Paged
+ // Returns the SourceId that has TargetId as a valid frame buffer or D3DDDI_ID_UNINITIALIZED if no such SourceId exists
+ D3DDDI_VIDEO_PRESENT_SOURCE_ID FindSourceForTarget(D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId, BOOLEAN DefaultToZero);
+
+ // Set the given source mode on the given path
+ NTSTATUS SetSourceModeAndPath(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMode,
+ CONST D3DKMDT_VIDPN_PRESENT_PATH* pPath);
+
+
+ // Add the current mode to the given monitor source mode set
+ NTSTATUS AddSingleMonitorMode(_In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModes);
+
+
+ // Add the current mode to the given VidPn source mode set
+ NTSTATUS AddSingleSourceMode(_In_ CONST DXGK_VIDPNSOURCEMODESET_INTERFACE* pVidPnSourceModeSetInterface,
+ D3DKMDT_HVIDPNSOURCEMODESET hVidPnSourceModeSet,
+ D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId);
+
+ // Add the current mode (or the matching to pinned source mode) to the give VidPn target mode set
+ NTSTATUS AddSingleTargetMode(_In_ CONST DXGK_VIDPNTARGETMODESET_INTERFACE* pVidPnTargetModeSetInterface,
+ D3DKMDT_HVIDPNTARGETMODESET hVidPnTargetModeSet,
+ _In_opt_ CONST D3DKMDT_VIDPN_SOURCE_MODE* pVidPnPinnedSourceModeInfo,
+ D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId);
+
+ // Check that the hardware the driver is running on is hardware it is capable of driving.
+ NTSTATUS CheckHardware();
+
+ // Helper function for RegisterHWInfo
+ NTSTATUS WriteHWInfoStr(_In_ HANDLE DevInstRegKeyHandle, _In_ PCWSTR pszwValueName, _In_ PCSTR pszValue);
+
+ // Set the information in the registry as described here: http://msdn.microsoft.com/en-us/library/windows/hardware/ff569240(v=vs.85).aspx
+ NTSTATUS RegisterHWInfo();
+};
+
+//
+// Blt functions
+//
+
+// Must be Non-Paged
+VOID BltBits(
+ BLT_INFO* pDst,
+ CONST BLT_INFO* pSrc,
+ UINT NumRects,
+ _In_reads_(NumRects) CONST RECT *pRects);
+
+//
+// Driver Entry point
+//
+
+extern "C"
+DRIVER_INITIALIZE DriverEntry;
+
+//
+// PnP DDIs
+//
+
+VOID
+BddDdiUnload(VOID);
+
+// If uncommenting ENABLE_DXGK_SAL in the sources file, all the below function prototypes should be updated to use
+// the function typedef's from the header files. Additionally, annotations on the function definitions can be removed
+// as they are inherited from the prototype definition here. As an example the entire 4-line prototype for BddDdiAddDevice
+// is replaced by the single commented line below:
+// DXGKDDI_ADD_DEVICE BddDdiAddDevice;
+NTSTATUS
+BddDdiAddDevice(
+ _In_ DEVICE_OBJECT* pPhysicalDeviceObject,
+ _Outptr_ PVOID* ppDeviceContext);
+
+NTSTATUS
+BddDdiRemoveDevice(
+ _In_ VOID* pDeviceContext);
+
+NTSTATUS
+BddDdiStartDevice(
+ _In_ VOID* pDeviceContext,
+ _In_ DXGK_START_INFO* pDxgkStartInfo,
+ _In_ DXGKRNL_INTERFACE* pDxgkInterface,
+ _Out_ ULONG* pNumberOfViews,
+ _Out_ ULONG* pNumberOfChildren);
+
+NTSTATUS
+BddDdiStopDevice(
+ _In_ VOID* pDeviceContext);
+
+VOID
+BddDdiResetDevice(
+ _In_ VOID* pDeviceContext);
+
+
+NTSTATUS
+BddDdiDispatchIoRequest(
+ _In_ VOID* pDeviceContext,
+ _In_ ULONG VidPnSourceId,
+ _In_ VIDEO_REQUEST_PACKET* pVideoRequestPacket);
+
+NTSTATUS
+BddDdiSetPowerState(
+ _In_ VOID* pDeviceContext,
+ _In_ ULONG HardwareUid,
+ _In_ DEVICE_POWER_STATE DevicePowerState,
+ _In_ POWER_ACTION ActionType);
+
+NTSTATUS
+BddDdiQueryChildRelations(
+ _In_ VOID* pDeviceContext,
+ _Out_writes_bytes_(ChildRelationsSize) DXGK_CHILD_DESCRIPTOR* pChildRelations,
+ _In_ ULONG ChildRelationsSize);
+
+NTSTATUS
+BddDdiQueryChildStatus(
+ _In_ VOID* pDeviceContext,
+ _Inout_ DXGK_CHILD_STATUS* pChildStatus,
+ _In_ BOOLEAN NonDestructiveOnly);
+
+NTSTATUS
+BddDdiQueryDeviceDescriptor(
+ _In_ VOID* pDeviceContext,
+ _In_ ULONG ChildUid,
+ _Inout_ DXGK_DEVICE_DESCRIPTOR* pDeviceDescriptor);
+
+// Must be Non-Paged
+BOOLEAN
+BddDdiInterruptRoutine(
+ _In_ VOID* pDeviceContext,
+ _In_ ULONG MessageNumber);
+
+VOID
+BddDdiDpcRoutine(
+ _In_ VOID* pDeviceContext);
+
+//
+// WDDM Display Only Driver DDIs
+//
+
+NTSTATUS
+APIENTRY
+BddDdiQueryAdapterInfo(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAdapterInfo);
+
+NTSTATUS
+APIENTRY
+BddDdiSetPointerPosition(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition);
+
+NTSTATUS
+APIENTRY
+BddDdiSetPointerShape(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape);
+
+NTSTATUS
+APIENTRY
+BddDdiPresentDisplayOnly(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_PRESENT_DISPLAYONLY* pPresentDisplayOnly);
+
+NTSTATUS
+APIENTRY
+BddDdiIsSupportedVidPn(
+ _In_ CONST HANDLE hAdapter,
+ _Inout_ DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPn);
+
+NTSTATUS
+APIENTRY
+BddDdiRecommendFunctionalVidPn(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST pRecommendFunctionalVidPn);
+
+NTSTATUS
+APIENTRY
+BddDdiRecommendVidPnTopology(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST pRecommendVidPnTopology);
+
+NTSTATUS
+APIENTRY
+BddDdiRecommendMonitorModes(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModes);
+
+NTSTATUS
+APIENTRY
+BddDdiEnumVidPnCofuncModality(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModality);
+
+NTSTATUS
+APIENTRY
+BddDdiSetVidPnSourceVisibility(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility);
+
+NTSTATUS
+APIENTRY
+BddDdiCommitVidPn(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPn);
+
+NTSTATUS
+APIENTRY
+BddDdiUpdateActiveVidPnPresentPath(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPath);
+
+NTSTATUS
+APIENTRY
+BddDdiQueryVidPnHWCapability(
+ _In_ CONST HANDLE hAdapter,
+ _Inout_ DXGKARG_QUERYVIDPNHWCAPABILITY* pVidPnHWCaps);
+
+NTSTATUS
+APIENTRY
+BddDdiStopDeviceAndReleasePostDisplayOwnership(
+ _In_ VOID* pDeviceContext,
+ _In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
+ _Out_ DXGK_DISPLAY_INFORMATION* DisplayInfo);
+
+// Must be Non-Paged
+NTSTATUS
+APIENTRY
+BddDdiSystemDisplayEnable(
+ _In_ VOID* pDeviceContext,
+ _In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
+ _In_ PDXGKARG_SYSTEM_DISPLAY_ENABLE_FLAGS Flags,
+ _Out_ UINT* Width,
+ _Out_ UINT* Height,
+ _Out_ D3DDDIFORMAT* ColorFormat);
+
+// Must be Non-Paged
+VOID
+APIENTRY
+BddDdiSystemDisplayWrite(
+ _In_ VOID* pDeviceContext,
+ _In_ VOID* Source,
+ _In_ UINT SourceWidth,
+ _In_ UINT SourceHeight,
+ _In_ UINT SourceStride,
+ _In_ UINT PositionX,
+ _In_ UINT PositionY);
+
+//
+// Frame buffer map/unmap
+//
+
+NTSTATUS
+MapFrameBuffer(
+ _In_ PHYSICAL_ADDRESS PhysicalAddress,
+ _In_ ULONG Length,
+ _Outptr_result_bytebuffer_(Length) VOID** VirtualAddress);
+
+NTSTATUS
+UnmapFrameBuffer(
+ _In_reads_bytes_(Length) VOID* VirtualAddress,
+ _In_ ULONG Length);
+
+
+BOOLEAN
+IsEdidHeaderValid(_In_reads_bytes_(EDID_V1_BLOCK_SIZE) const BYTE* pEdid);
+
+BOOLEAN
+IsEdidChecksumValid(_In_reads_bytes_(EDID_V1_BLOCK_SIZE) const BYTE* pEdid);
+
+//
+// Memory handling
+//
+
+// Defaulting the value of PoolType means that any call to new Foo()
+// will raise a compiler error for being ambiguous. This is to help keep
+// any calls to allocate memory from accidentally NOT going through
+// these functions.
+_When_((PoolType & NonPagedPoolMustSucceed) != 0,
+ __drv_reportError("Must succeed pool allocations are forbidden. "
+ "Allocation failures cause a system crash"))
+void* __cdecl operator new(size_t Size, POOL_TYPE PoolType = PagedPool);
+_When_((PoolType & NonPagedPoolMustSucceed) != 0,
+ __drv_reportError("Must succeed pool allocations are forbidden. "
+ "Allocation failures cause a system crash"))
+void* __cdecl operator new[](size_t Size, POOL_TYPE PoolType = PagedPool);
+void __cdecl operator delete(void* pObject);
+void __cdecl operator delete[](void* pObject);
+
+// Pool allocation tag for the Sample Display Driver. All allocations use this tag.
+#define BDDTAG 'DDBS'
+
+#endif // _BDD_HXX_
+
+
diff --git a/C++/bdd_ddi.cxx b/C++/bdd_ddi.cxx
new file mode 100644
index 0000000..544ba22
--- /dev/null
+++ b/C++/bdd_ddi.cxx
@@ -0,0 +1,578 @@
+/******************************Module*Header*******************************\
+* Module Name: BDD_DDI.cxx
+*
+* Basic Display Driver DDI entry points redirects
+*
+*
+* Copyright (c) 2010 Microsoft Corporation
+\**************************************************************************/
+
+#include "BDD.hxx"
+
+
+#pragma code_seg(push)
+#pragma code_seg("INIT")
+// BEGIN: Init Code
+
+//
+// Driver Entry point
+//
+
+extern "C"
+NTSTATUS
+DriverEntry(
+ _In_ DRIVER_OBJECT* pDriverObject,
+ _In_ UNICODE_STRING* pRegistryPath)
+{
+ PAGED_CODE();
+
+
+ // Initialize DDI function pointers and dxgkrnl
+ KMDDOD_INITIALIZATION_DATA InitialData = {0};
+
+ InitialData.Version = DXGKDDI_INTERFACE_VERSION_WIN8;
+
+ InitialData.DxgkDdiAddDevice = BddDdiAddDevice;
+ InitialData.DxgkDdiStartDevice = BddDdiStartDevice;
+ InitialData.DxgkDdiStopDevice = BddDdiStopDevice;
+ InitialData.DxgkDdiResetDevice = BddDdiResetDevice;
+ InitialData.DxgkDdiRemoveDevice = BddDdiRemoveDevice;
+ InitialData.DxgkDdiDispatchIoRequest = BddDdiDispatchIoRequest;
+ InitialData.DxgkDdiInterruptRoutine = BddDdiInterruptRoutine;
+ InitialData.DxgkDdiDpcRoutine = BddDdiDpcRoutine;
+ InitialData.DxgkDdiQueryChildRelations = BddDdiQueryChildRelations;
+ InitialData.DxgkDdiQueryChildStatus = BddDdiQueryChildStatus;
+ InitialData.DxgkDdiQueryDeviceDescriptor = BddDdiQueryDeviceDescriptor;
+ InitialData.DxgkDdiSetPowerState = BddDdiSetPowerState;
+ InitialData.DxgkDdiUnload = BddDdiUnload;
+ InitialData.DxgkDdiQueryAdapterInfo = BddDdiQueryAdapterInfo;
+ InitialData.DxgkDdiSetPointerPosition = BddDdiSetPointerPosition;
+ InitialData.DxgkDdiSetPointerShape = BddDdiSetPointerShape;
+ InitialData.DxgkDdiIsSupportedVidPn = BddDdiIsSupportedVidPn;
+ InitialData.DxgkDdiRecommendFunctionalVidPn = BddDdiRecommendFunctionalVidPn;
+ InitialData.DxgkDdiEnumVidPnCofuncModality = BddDdiEnumVidPnCofuncModality;
+ InitialData.DxgkDdiSetVidPnSourceVisibility = BddDdiSetVidPnSourceVisibility;
+ InitialData.DxgkDdiCommitVidPn = BddDdiCommitVidPn;
+ InitialData.DxgkDdiUpdateActiveVidPnPresentPath = BddDdiUpdateActiveVidPnPresentPath;
+ InitialData.DxgkDdiRecommendMonitorModes = BddDdiRecommendMonitorModes;
+ InitialData.DxgkDdiQueryVidPnHWCapability = BddDdiQueryVidPnHWCapability;
+ InitialData.DxgkDdiPresentDisplayOnly = BddDdiPresentDisplayOnly;
+ InitialData.DxgkDdiStopDeviceAndReleasePostDisplayOwnership = BddDdiStopDeviceAndReleasePostDisplayOwnership;
+ InitialData.DxgkDdiSystemDisplayEnable = BddDdiSystemDisplayEnable;
+ InitialData.DxgkDdiSystemDisplayWrite = BddDdiSystemDisplayWrite;
+
+ NTSTATUS Status = DxgkInitializeDisplayOnlyDriver(pDriverObject, pRegistryPath, &InitialData);
+ if (!NT_SUCCESS(Status))
+ {
+ BDD_LOG_ERROR1("DxgkInitializeDisplayOnlyDriver failed with Status: 0x%I64x", Status);
+ }
+
+
+ return Status;
+}
+// END: Init Code
+#pragma code_seg(pop)
+
+#pragma code_seg(push)
+#pragma code_seg("PAGE")
+
+//
+// PnP DDIs
+//
+
+VOID
+BddDdiUnload(VOID)
+{
+ PAGED_CODE();
+}
+
+NTSTATUS
+BddDdiAddDevice(
+ _In_ DEVICE_OBJECT* pPhysicalDeviceObject,
+ _Outptr_ PVOID* ppDeviceContext)
+{
+ PAGED_CODE();
+
+ if ((pPhysicalDeviceObject == NULL) ||
+ (ppDeviceContext == NULL))
+ {
+ BDD_LOG_ERROR2("One of pPhysicalDeviceObject (0x%I64x), ppDeviceContext (0x%I64x) is NULL",
+ pPhysicalDeviceObject, ppDeviceContext);
+ return STATUS_INVALID_PARAMETER;
+ }
+ *ppDeviceContext = NULL;
+
+ BASIC_DISPLAY_DRIVER* pBDD = new(NonPagedPoolNx) BASIC_DISPLAY_DRIVER(pPhysicalDeviceObject);
+ if (pBDD == NULL)
+ {
+ BDD_LOG_LOW_RESOURCE0("pBDD failed to be allocated");
+ return STATUS_NO_MEMORY;
+ }
+
+ *ppDeviceContext = pBDD;
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+BddDdiRemoveDevice(
+ _In_ VOID* pDeviceContext)
+{
+ PAGED_CODE();
+
+ BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
+
+ if (pBDD)
+ {
+ delete pBDD;
+ pBDD = NULL;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+BddDdiStartDevice(
+ _In_ VOID* pDeviceContext,
+ _In_ DXGK_START_INFO* pDxgkStartInfo,
+ _In_ DXGKRNL_INTERFACE* pDxgkInterface,
+ _Out_ ULONG* pNumberOfViews,
+ _Out_ ULONG* pNumberOfChildren)
+{
+ PAGED_CODE();
+ BDD_ASSERT_CHK(pDeviceContext != NULL);
+
+ BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
+ return pBDD->StartDevice(pDxgkStartInfo, pDxgkInterface, pNumberOfViews, pNumberOfChildren);
+}
+
+NTSTATUS
+BddDdiStopDevice(
+ _In_ VOID* pDeviceContext)
+{
+ PAGED_CODE();
+ BDD_ASSERT_CHK(pDeviceContext != NULL);
+
+ BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
+ return pBDD->StopDevice();
+}
+
+
+NTSTATUS
+BddDdiDispatchIoRequest(
+ _In_ VOID* pDeviceContext,
+ _In_ ULONG VidPnSourceId,
+ _In_ VIDEO_REQUEST_PACKET* pVideoRequestPacket)
+{
+ PAGED_CODE();
+ BDD_ASSERT_CHK(pDeviceContext != NULL);
+
+ BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
+ if (!pBDD->IsDriverActive())
+ {
+ BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return pBDD->DispatchIoRequest(VidPnSourceId, pVideoRequestPacket);
+}
+
+NTSTATUS
+BddDdiSetPowerState(
+ _In_ VOID* pDeviceContext,
+ _In_ ULONG HardwareUid,
+ _In_ DEVICE_POWER_STATE DevicePowerState,
+ _In_ POWER_ACTION ActionType)
+{
+ PAGED_CODE();
+ BDD_ASSERT_CHK(pDeviceContext != NULL);
+
+ BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
+ if (!pBDD->IsDriverActive())
+ {
+ // If the driver isn't active, SetPowerState can still be called, however in BDD's case
+ // this shouldn't do anything, as it could for instance be called on BDD Fallback after
+ // Fallback has been stopped and BDD PnP is being started. Fallback doesn't have control
+ // of the hardware in this case.
+ return STATUS_SUCCESS;
+ }
+ return pBDD->SetPowerState(HardwareUid, DevicePowerState, ActionType);
+}
+
+NTSTATUS
+BddDdiQueryChildRelations(
+ _In_ VOID* pDeviceContext,
+ _Out_writes_bytes_(ChildRelationsSize) DXGK_CHILD_DESCRIPTOR* pChildRelations,
+ _In_ ULONG ChildRelationsSize)
+{
+ PAGED_CODE();
+ BDD_ASSERT_CHK(pDeviceContext != NULL);
+
+ BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
+ return pBDD->QueryChildRelations(pChildRelations, ChildRelationsSize);
+}
+
+NTSTATUS
+BddDdiQueryChildStatus(
+ _In_ VOID* pDeviceContext,
+ _Inout_ DXGK_CHILD_STATUS* pChildStatus,
+ _In_ BOOLEAN NonDestructiveOnly)
+{
+ PAGED_CODE();
+ BDD_ASSERT_CHK(pDeviceContext != NULL);
+
+ BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
+ return pBDD->QueryChildStatus(pChildStatus, NonDestructiveOnly);
+}
+
+NTSTATUS
+BddDdiQueryDeviceDescriptor(
+ _In_ VOID* pDeviceContext,
+ _In_ ULONG ChildUid,
+ _Inout_ DXGK_DEVICE_DESCRIPTOR* pDeviceDescriptor)
+{
+ PAGED_CODE();
+ BDD_ASSERT_CHK(pDeviceContext != NULL);
+
+ BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
+ if (!pBDD->IsDriverActive())
+ {
+ // During stress testing of PnPStop, it is possible for BDD Fallback to get called to start then stop in quick succession.
+ // The first call queues a worker thread item indicating that it now has a child device, the second queues a worker thread
+ // item that it no longer has any child device. This function gets called based on the first worker thread item, but after
+ // the driver has been stopped. Therefore instead of asserting like other functions, we only warn.
+ BDD_LOG_WARNING1("BDD (0x%I64x) is being called when not active!", pBDD);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return pBDD->QueryDeviceDescriptor(ChildUid, pDeviceDescriptor);
+}
+
+
+//
+// WDDM Display Only Driver DDIs
+//
+
+NTSTATUS
+APIENTRY
+BddDdiQueryAdapterInfo(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAdapterInfo)
+{
+ PAGED_CODE();
+ BDD_ASSERT_CHK(hAdapter != NULL);
+
+ BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
+ return pBDD->QueryAdapterInfo(pQueryAdapterInfo);
+}
+
+NTSTATUS
+APIENTRY
+BddDdiSetPointerPosition(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition)
+{
+ PAGED_CODE();
+ BDD_ASSERT_CHK(hAdapter != NULL);
+
+ BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
+ if (!pBDD->IsDriverActive())
+ {
+ BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return pBDD->SetPointerPosition(pSetPointerPosition);
+}
+
+NTSTATUS
+APIENTRY
+BddDdiSetPointerShape(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape)
+{
+ PAGED_CODE();
+ BDD_ASSERT_CHK(hAdapter != NULL);
+
+ BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
+ if (!pBDD->IsDriverActive())
+ {
+ BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return pBDD->SetPointerShape(pSetPointerShape);
+}
+
+
+NTSTATUS
+APIENTRY
+BddDdiPresentDisplayOnly(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_PRESENT_DISPLAYONLY* pPresentDisplayOnly)
+{
+ PAGED_CODE();
+ BDD_ASSERT_CHK(hAdapter != NULL);
+
+ BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
+ if (!pBDD->IsDriverActive())
+ {
+ BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return pBDD->PresentDisplayOnly(pPresentDisplayOnly);
+}
+
+NTSTATUS
+APIENTRY
+BddDdiStopDeviceAndReleasePostDisplayOwnership(
+ _In_ VOID* pDeviceContext,
+ _In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
+ _Out_ DXGK_DISPLAY_INFORMATION* DisplayInfo)
+{
+ PAGED_CODE();
+ BDD_ASSERT_CHK(pDeviceContext != NULL);
+
+ BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
+ return pBDD->StopDeviceAndReleasePostDisplayOwnership(TargetId, DisplayInfo);
+}
+
+NTSTATUS
+APIENTRY
+BddDdiIsSupportedVidPn(
+ _In_ CONST HANDLE hAdapter,
+ _Inout_ DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPn)
+{
+ PAGED_CODE();
+ BDD_ASSERT_CHK(hAdapter != NULL);
+
+ BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
+ if (!pBDD->IsDriverActive())
+ {
+ // This path might hit because win32k/dxgport doesn't check that an adapter is active when taking the adapter lock.
+ // The adapter lock is the main thing BDD Fallback relies on to not be called while it's inactive. It is still a rare
+ // timing issue around PnpStart/Stop and isn't expected to have any effect on the stability of the system.
+ BDD_LOG_WARNING1("BDD (0x%I64x) is being called when not active!", pBDD);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return pBDD->IsSupportedVidPn(pIsSupportedVidPn);
+}
+
+NTSTATUS
+APIENTRY
+BddDdiRecommendFunctionalVidPn(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST pRecommendFunctionalVidPn)
+{
+ PAGED_CODE();
+ BDD_ASSERT_CHK(hAdapter != NULL);
+
+ BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
+ if (!pBDD->IsDriverActive())
+ {
+ BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return pBDD->RecommendFunctionalVidPn(pRecommendFunctionalVidPn);
+}
+
+NTSTATUS
+APIENTRY
+BddDdiRecommendVidPnTopology(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST pRecommendVidPnTopology)
+{
+ PAGED_CODE();
+ BDD_ASSERT_CHK(hAdapter != NULL);
+
+ BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
+ if (!pBDD->IsDriverActive())
+ {
+ BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return pBDD->RecommendVidPnTopology(pRecommendVidPnTopology);
+}
+
+NTSTATUS
+APIENTRY
+BddDdiRecommendMonitorModes(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModes)
+{
+ PAGED_CODE();
+ BDD_ASSERT_CHK(hAdapter != NULL);
+
+ BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
+ if (!pBDD->IsDriverActive())
+ {
+ BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return pBDD->RecommendMonitorModes(pRecommendMonitorModes);
+}
+
+NTSTATUS
+APIENTRY
+BddDdiEnumVidPnCofuncModality(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModality)
+{
+ PAGED_CODE();
+ BDD_ASSERT_CHK(hAdapter != NULL);
+
+ BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
+ if (!pBDD->IsDriverActive())
+ {
+ BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return pBDD->EnumVidPnCofuncModality(pEnumCofuncModality);
+}
+
+NTSTATUS
+APIENTRY
+BddDdiSetVidPnSourceVisibility(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility)
+{
+ PAGED_CODE();
+ BDD_ASSERT_CHK(hAdapter != NULL);
+
+ BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
+ if (!pBDD->IsDriverActive())
+ {
+ BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return pBDD->SetVidPnSourceVisibility(pSetVidPnSourceVisibility);
+}
+
+NTSTATUS
+APIENTRY
+BddDdiCommitVidPn(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPn)
+{
+ PAGED_CODE();
+ BDD_ASSERT_CHK(hAdapter != NULL);
+
+ BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
+ if (!pBDD->IsDriverActive())
+ {
+ BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return pBDD->CommitVidPn(pCommitVidPn);
+}
+
+NTSTATUS
+APIENTRY
+BddDdiUpdateActiveVidPnPresentPath(
+ _In_ CONST HANDLE hAdapter,
+ _In_ CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPath)
+{
+ PAGED_CODE();
+ BDD_ASSERT_CHK(hAdapter != NULL);
+
+ BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
+ if (!pBDD->IsDriverActive())
+ {
+ BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return pBDD->UpdateActiveVidPnPresentPath(pUpdateActiveVidPnPresentPath);
+}
+
+NTSTATUS
+APIENTRY
+BddDdiQueryVidPnHWCapability(
+ _In_ CONST HANDLE hAdapter,
+ _Inout_ DXGKARG_QUERYVIDPNHWCAPABILITY* pVidPnHWCaps)
+{
+ PAGED_CODE();
+ BDD_ASSERT_CHK(hAdapter != NULL);
+
+ BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(hAdapter);
+ if (!pBDD->IsDriverActive())
+ {
+ BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
+ return STATUS_UNSUCCESSFUL;
+ }
+ return pBDD->QueryVidPnHWCapability(pVidPnHWCaps);
+}
+//END: Paged Code
+#pragma code_seg(pop)
+
+#pragma code_seg(push)
+#pragma code_seg()
+// BEGIN: Non-Paged Code
+
+VOID
+BddDdiDpcRoutine(
+ _In_ VOID* pDeviceContext)
+{
+ BDD_ASSERT_CHK(pDeviceContext != NULL);
+
+ BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
+ if (!pBDD->IsDriverActive())
+ {
+ BDD_LOG_ASSERTION1("BDD (0x%I64x) is being called when not active!", pBDD);
+ return;
+ }
+ pBDD->DpcRoutine();
+}
+
+BOOLEAN
+BddDdiInterruptRoutine(
+ _In_ VOID* pDeviceContext,
+ _In_ ULONG MessageNumber)
+{
+ BDD_ASSERT_CHK(pDeviceContext != NULL);
+
+ BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
+ return pBDD->InterruptRoutine(MessageNumber);
+}
+
+VOID
+BddDdiResetDevice(
+ _In_ VOID* pDeviceContext)
+{
+ BDD_ASSERT_CHK(pDeviceContext != NULL);
+
+ BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
+ pBDD->ResetDevice();
+}
+
+NTSTATUS
+APIENTRY
+BddDdiSystemDisplayEnable(
+ _In_ VOID* pDeviceContext,
+ _In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
+ _In_ PDXGKARG_SYSTEM_DISPLAY_ENABLE_FLAGS Flags,
+ _Out_ UINT* Width,
+ _Out_ UINT* Height,
+ _Out_ D3DDDIFORMAT* ColorFormat)
+{
+ BDD_ASSERT_CHK(pDeviceContext != NULL);
+
+ BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
+ return pBDD->SystemDisplayEnable(TargetId, Flags, Width, Height, ColorFormat);
+}
+
+VOID
+APIENTRY
+BddDdiSystemDisplayWrite(
+ _In_ VOID* pDeviceContext,
+ _In_ VOID* Source,
+ _In_ UINT SourceWidth,
+ _In_ UINT SourceHeight,
+ _In_ UINT SourceStride,
+ _In_ UINT PositionX,
+ _In_ UINT PositionY)
+{
+ BDD_ASSERT_CHK(pDeviceContext != NULL);
+
+ BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
+ pBDD->SystemDisplayWrite(Source, SourceWidth, SourceHeight, SourceStride, PositionX, PositionY);
+}
+
+// END: Non-Paged Code
+#pragma code_seg(pop)
+
diff --git a/C++/bdd_dmm.cxx b/C++/bdd_dmm.cxx
new file mode 100644
index 0000000..6ffec82
--- /dev/null
+++ b/C++/bdd_dmm.cxx
@@ -0,0 +1,1080 @@
+/******************************Module*Header*******************************\
+* Module Name: bdd_dmm.hxx
+*
+* Basic Display Driver display-mode management (DMM) function implementations
+*
+*
+* Copyright (c) 2010 Microsoft Corporation
+\**************************************************************************/
+
+#include "BDD.hxx"
+
+#pragma code_seg("PAGE")
+
+// Display-Only Devices can only return display modes of D3DDDIFMT_A8R8G8B8.
+// Color conversion takes place if the app's fullscreen backbuffer has different format.
+// Full display drivers can add more if the hardware supports them.
+D3DDDIFORMAT gBddPixelFormats[] = {
+ D3DDDIFMT_A8R8G8B8
+};
+
+// TODO: Need to also check pinned modes and the path parameters, not just topology
+NTSTATUS BASIC_DISPLAY_DRIVER::IsSupportedVidPn(_Inout_ DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPn)
+{
+ PAGED_CODE();
+
+ BDD_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))
+ {
+ BDD_LOG_ERROR2("DxgkCbQueryVidPnInterface failed with Status = 0x%I64x, hDesiredVidPn = 0x%I64x", Status, pIsSupportedVidPn->hDesiredVidPn);
+ return Status;
+ }
+
+ D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
+ CONST DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
+ Status = pVidPnInterface->pfnGetTopology(pIsSupportedVidPn->hDesiredVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
+ if (!NT_SUCCESS(Status))
+ {
+ BDD_LOG_ERROR2("pfnGetTopology failed with Status = 0x%I64x, hDesiredVidPn = 0x%I64x", Status, pIsSupportedVidPn->hDesiredVidPn);
+ 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))
+ {
+ BDD_LOG_ERROR3("pfnGetNumPathsFromSource failed with Status = 0x%I64x. hVidPnTopology = 0x%I64x, SourceId = 0x%I64x",
+ 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;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS BASIC_DISPLAY_DRIVER::RecommendFunctionalVidPn(_In_ CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST pRecommendFunctionalVidPn)
+{
+ PAGED_CODE();
+
+ BDD_ASSERT(pRecommendFunctionalVidPn == NULL);
+
+ return STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN;
+}
+
+NTSTATUS BASIC_DISPLAY_DRIVER::RecommendVidPnTopology(_In_ CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST pRecommendVidPnTopology)
+{
+ PAGED_CODE();
+
+ BDD_ASSERT(pRecommendVidPnTopology == NULL);
+
+ return STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN;
+}
+
+NTSTATUS BASIC_DISPLAY_DRIVER::RecommendMonitorModes(_In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModes)
+{
+ PAGED_CODE();
+
+ // This is always called to recommend modes for the monitor. The sample driver doesn't provide EDID for a monitor, so
+ // the OS prefills the list with default monitor modes. Since the required mode might not be in the list, it should
+ // be provided as a recommended mode.
+ return AddSingleMonitorMode(pRecommendMonitorModes);
+}
+
+// Tell DMM about all the modes, etc. that are supported
+NTSTATUS BASIC_DISPLAY_DRIVER::EnumVidPnCofuncModality(_In_ CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModality)
+{
+ PAGED_CODE();
+
+ BDD_ASSERT(pEnumCofuncModality != NULL);
+
+ 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;
+ CONST D3DKMDT_VIDPN_PRESENT_PATH* pVidPnPresentPathTemp = NULL; // Used for AcquireNextPathInfo
+ 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))
+ {
+ BDD_LOG_ERROR2("DxgkCbQueryVidPnInterface failed with Status = 0x%I64x, hFunctionalVidPn = 0x%I64x", Status, pEnumCofuncModality->hConstrainingVidPn);
+ return Status;
+ }
+
+ // Get the VidPn Topology interface so we can enumerate all paths
+ Status = pVidPnInterface->pfnGetTopology(pEnumCofuncModality->hConstrainingVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
+ if (!NT_SUCCESS(Status))
+ {
+ BDD_LOG_ERROR2("pfnGetTopology failed with Status = 0x%I64x, hFunctionalVidPn = 0x%I64x", Status, pEnumCofuncModality->hConstrainingVidPn);
+ return Status;
+ }
+
+ // Get the first path before we start looping through them
+ Status = pVidPnTopologyInterface->pfnAcquireFirstPathInfo(hVidPnTopology, &pVidPnPresentPath);
+ if (!NT_SUCCESS(Status))
+ {
+ BDD_LOG_ERROR2("pfnAcquireFirstPathInfo failed with Status = 0x%I64x, hVidPnTopology = 0x%I64x", Status, hVidPnTopology);
+ 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))
+ {
+ BDD_LOG_ERROR3("pfnAcquireSourceModeSet failed with Status = 0x%I64x, hConstrainingVidPn = 0x%I64x, SourceId = 0x%I64x",
+ 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))
+ {
+ BDD_LOG_ERROR2("pfnAcquirePinnedModeInfo failed with Status = 0x%I64x, hVidPnSourceModeSet = 0x%I64x", Status, hVidPnSourceModeSet);
+ 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))
+ {
+ BDD_LOG_ERROR3("pfnReleaseSourceModeSet failed with Status = 0x%I64x, hConstrainingVidPn = 0x%I64x, hVidPnSourceModeSet = 0x%I64x",
+ 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))
+ {
+ BDD_LOG_ERROR3("pfnCreateNewSourceModeSet failed with Status = 0x%I64x, hConstrainingVidPn = 0x%I64x, SourceId = 0x%I64x",
+ 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))
+ {
+ break;
+ }
+
+ // Give DMM back the source modes just populated
+ Status = pVidPnInterface->pfnAssignSourceModeSet(pEnumCofuncModality->hConstrainingVidPn, pVidPnPresentPath->VidPnSourceId, hVidPnSourceModeSet);
+ if (!NT_SUCCESS(Status))
+ {
+ BDD_LOG_ERROR4("pfnAssignSourceModeSet failed with Status = 0x%I64x, hConstrainingVidPn = 0x%I64x, SourceId = 0x%I64x, hVidPnSourceModeSet = 0x%I64x",
+ 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))
+ {
+ BDD_LOG_ERROR3("pfnAcquireTargetModeSet failed with Status = 0x%I64x, hConstrainingVidPn = 0x%I64x, TargetId = 0x%I64x",
+ Status, pEnumCofuncModality->hConstrainingVidPn, pVidPnPresentPath->VidPnTargetId);
+ break;
+ }
+
+ Status = pVidPnTargetModeSetInterface->pfnAcquirePinnedModeInfo(hVidPnTargetModeSet, &pVidPnPinnedTargetModeInfo);
+ if (!NT_SUCCESS(Status))
+ {
+ BDD_LOG_ERROR2("pfnAcquirePinnedModeInfo failed with Status = 0x%I64x, hVidPnTargetModeSet = 0x%I64x", Status, hVidPnTargetModeSet);
+ 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))
+ {
+ BDD_LOG_ASSERTION3("pfnReleaseTargetModeSet failed with Status = 0x%I64x, hConstrainingVidPn = 0x%I64x, hVidPnTargetModeSet = 0x%I64x",
+ 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))
+ {
+ BDD_LOG_ERROR3("pfnCreateNewTargetModeSet failed with Status = 0x%I64x, hConstrainingVidPn = 0x%I64x, TargetId = 0x%I64x",
+ Status, pEnumCofuncModality->hConstrainingVidPn, pVidPnPresentPath->VidPnTargetId);
+ break;
+ }
+
+ Status = AddSingleTargetMode(pVidPnTargetModeSetInterface, hVidPnTargetModeSet, pVidPnPinnedSourceModeInfo, pVidPnPresentPath->VidPnSourceId);
+
+ if (!NT_SUCCESS(Status))
+ {
+ break;
+ }
+
+ // Give DMM back the source modes just populated
+ Status = pVidPnInterface->pfnAssignTargetModeSet(pEnumCofuncModality->hConstrainingVidPn, pVidPnPresentPath->VidPnTargetId, hVidPnTargetModeSet);
+ if (!NT_SUCCESS(Status))
+ {
+ BDD_LOG_ERROR4("pfnAssignTargetModeSet failed with Status = 0x%I64x, hConstrainingVidPn = 0x%I64x, TargetId = 0x%I64x, hVidPnTargetModeSet = 0x%I64x",
+ 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))
+ {
+ BDD_LOG_ASSERTION3("pfnReleaseModeInfo failed with Status = 0x%I64x, hVidPnTargetModeSet = 0x%I64x, pVidPnPinnedTargetModeInfo = 0x%I64x",
+ 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))
+ {
+ BDD_LOG_ASSERTION3("pfnReleaseTargetModeSet failed with Status = 0x%I64x, hConstrainingVidPn = 0x%I64x, hVidPnTargetModeSet = 0x%I64x",
+ 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))
+ {
+ BDD_LOG_ASSERTION3("pfnReleaseModeInfo failed with Status = 0x%I64x, hVidPnSourceModeSet = 0x%I64x, pVidPnPinnedSourceModeInfo = 0x%I64x",
+ 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))
+ {
+ BDD_LOG_ERROR3("pfnReleaseSourceModeSet failed with Status = 0x%I64x, hConstrainingVidPn = 0x%I64x, hVidPnSourceModeSet = 0x%I64x",
+ 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))
+ {
+ BDD_LOG_ERROR2("pfnUpdatePathSupportInfo failed with Status = 0x%I64x, hVidPnTopology = 0x%I64x", Status, hVidPnTopology);
+ 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))
+ {
+ BDD_LOG_ERROR3("pfnAcquireNextPathInfo failed with Status = 0x%I64x, hVidPnTopology = 0x%I64x, pVidPnPresentPathTemp = 0x%I64x", Status, hVidPnTopology, pVidPnPresentPathTemp);
+ break;
+ }
+
+ // ...and release the last path
+ NTSTATUS TempStatus = pVidPnTopologyInterface->pfnReleasePathInfo(hVidPnTopology, pVidPnPresentPathTemp);
+ if (!NT_SUCCESS(TempStatus))
+ {
+ BDD_LOG_ERROR3("pfnReleasePathInfo failed with Status = 0x%I64x, hVidPnTopology = 0x%I64x, pVidPnPresentPathTemp = 0x%I64x", TempStatus, hVidPnTopology, pVidPnPresentPathTemp);
+ 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);
+ BDD_ASSERT_CHK(NT_SUCCESS(TempStatus));
+ }
+
+ if ((pVidPnTargetModeSetInterface != NULL) &&
+ (pVidPnPinnedTargetModeInfo != NULL))
+ {
+ TempStatus = pVidPnTargetModeSetInterface->pfnReleaseModeInfo(hVidPnTargetModeSet, pVidPnPinnedTargetModeInfo);
+ BDD_ASSERT_CHK(NT_SUCCESS(TempStatus));
+ }
+
+ if (pVidPnPresentPath != NULL)
+ {
+ TempStatus = pVidPnTopologyInterface->pfnReleasePathInfo(hVidPnTopology, pVidPnPresentPath);
+ BDD_ASSERT_CHK(NT_SUCCESS(TempStatus));
+ }
+
+ if (pVidPnPresentPathTemp != NULL)
+ {
+ TempStatus = pVidPnTopologyInterface->pfnReleasePathInfo(hVidPnTopology, pVidPnPresentPathTemp);
+ BDD_ASSERT_CHK(NT_SUCCESS(TempStatus));
+ }
+
+ if (hVidPnSourceModeSet != 0)
+ {
+ TempStatus = pVidPnInterface->pfnReleaseSourceModeSet(pEnumCofuncModality->hConstrainingVidPn, hVidPnSourceModeSet);
+ BDD_ASSERT_CHK(NT_SUCCESS(TempStatus));
+ }
+
+ if (hVidPnTargetModeSet != 0)
+ {
+ TempStatus = pVidPnInterface->pfnReleaseTargetModeSet(pEnumCofuncModality->hConstrainingVidPn, hVidPnTargetModeSet);
+ BDD_ASSERT_CHK(NT_SUCCESS(TempStatus));
+ }
+
+ BDD_ASSERT_CHK(TempStatus == STATUS_NOT_FOUND || Status != STATUS_SUCCESS);
+
+ return Status;
+}
+
+NTSTATUS BASIC_DISPLAY_DRIVER::SetVidPnSourceVisibility(_In_ CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility)
+{
+ PAGED_CODE();
+
+ BDD_ASSERT(pSetVidPnSourceVisibility != NULL);
+ BDD_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
+ {
+ BlackOutScreen(SourceId);
+ }
+
+ // Store current visibility so it can be dealt with during Present call
+ m_CurrentModes[SourceId].Flags.SourceNotVisible = !(pSetVidPnSourceVisibility->Visible);
+ }
+
+ 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 BASIC_DISPLAY_DRIVER::CommitVidPn(_In_ CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPn)
+{
+ PAGED_CODE();
+
+ BDD_ASSERT(pCommitVidPn != NULL);
+ BDD_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))
+ {
+ BDD_LOG_ERROR2("DxgkCbQueryVidPnInterface failed with Status = 0x%I64x, hFunctionalVidPn = 0x%I64x", Status, pCommitVidPn->hFunctionalVidPn);
+ goto CommitVidPnExit;
+ }
+
+ // Get the VidPn Topology interface so can enumerate paths from source
+ Status = pVidPnInterface->pfnGetTopology(pCommitVidPn->hFunctionalVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
+ if (!NT_SUCCESS(Status))
+ {
+ BDD_LOG_ERROR2("pfnGetTopology failed with Status = 0x%I64x, hFunctionalVidPn = 0x%I64x", Status, pCommitVidPn->hFunctionalVidPn);
+ 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))
+ {
+ BDD_LOG_ERROR2("pfnGetNumPaths failed with Status = 0x%I64x, hVidPnTopology = 0x%I64x", Status, hVidPnTopology);
+ 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))
+ {
+ BDD_LOG_ERROR3("pfnAcquireSourceModeSet failed with Status = 0x%I64x, hFunctionalVidPn = 0x%I64x, SourceId = 0x%I64x", Status, pCommitVidPn->hFunctionalVidPn, pCommitVidPn->AffectedVidPnSourceId);
+ goto CommitVidPnExit;
+ }
+
+ // Get the mode that is being pinned
+ Status = pVidPnSourceModeSetInterface->pfnAcquirePinnedModeInfo(hVidPnSourceModeSet, &pPinnedVidPnSourceModeInfo);
+ if (!NT_SUCCESS(Status))
+ {
+ BDD_LOG_ERROR2("pfnAcquirePinnedModeInfo failed with Status = 0x%I64x, hFunctionalVidPn = 0x%I64x", Status, pCommitVidPn->hFunctionalVidPn);
+ 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)
+ {
+ Status = UnmapFrameBuffer(m_CurrentModes[pCommitVidPn->AffectedVidPnSourceId].FrameBuffer.Ptr,
+ m_CurrentModes[pCommitVidPn->AffectedVidPnSourceId].DispInfo.Pitch * m_CurrentModes[pCommitVidPn->AffectedVidPnSourceId].DispInfo.Height);
+ m_CurrentModes[pCommitVidPn->AffectedVidPnSourceId].FrameBuffer.Ptr = NULL;
+ m_CurrentModes[pCommitVidPn->AffectedVidPnSourceId].Flags.FrameBufferIsActive = FALSE;
+
+ 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))
+ {
+ BDD_LOG_ERROR2("pfnGetNumPathsFromSource failed with Status = 0x%I64x, hVidPnTopology = 0x%I64x", Status, hVidPnTopology);
+ 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))
+ {
+ BDD_LOG_ERROR4("pfnEnumPathTargetsFromSource failed with Status = 0x%I64x, hVidPnTopology = 0x%I64x, SourceId = 0x%I64x, PathIndex = 0x%I64x",
+ Status, hVidPnTopology, pCommitVidPn->AffectedVidPnSourceId, PathIndex);
+ goto CommitVidPnExit;
+ }
+
+ // Get the actual path info
+ Status = pVidPnTopologyInterface->pfnAcquirePathInfo(hVidPnTopology, pCommitVidPn->AffectedVidPnSourceId, TargetId, &pVidPnPresentPath);
+ if (!NT_SUCCESS(Status))
+ {
+ BDD_LOG_ERROR4("pfnAcquirePathInfo failed with Status = 0x%I64x, hVidPnTopology = 0x%I64x, SourceId = 0x%I64x, TargetId = 0x%I64x",
+ 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))
+ {
+ BDD_LOG_ERROR3("pfnReleasePathInfo failed with Status = 0x%I64x, hVidPnTopoogy = 0x%I64x, pVidPnPresentPath = 0x%I64x",
+ Status, hVidPnTopology, pVidPnPresentPath);
+ goto CommitVidPnExit;
+ }
+ pVidPnPresentPath = NULL; // Successfully released it
+ }
+
+CommitVidPnExit:
+
+ NTSTATUS TempStatus;
+ 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));
+ }
+
+ return Status;
+}
+
+NTSTATUS BASIC_DISPLAY_DRIVER::UpdateActiveVidPnPresentPath(_In_ CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPath)
+{
+ PAGED_CODE();
+
+ BDD_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;
+
+ return STATUS_SUCCESS;
+}
+
+//
+// Private BDD DMM functions
+//
+
+NTSTATUS BASIC_DISPLAY_DRIVER::SetSourceModeAndPath(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMode,
+ CONST D3DKMDT_VIDPN_PRESENT_PATH* pPath)
+{
+ PAGED_CODE();
+
+ CURRENT_BDD_MODE* pCurrentBddMode = &m_CurrentModes[pPath->VidPnSourceId];
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ pCurrentBddMode->Scaling = pPath->ContentTransformation.Scaling;
+ pCurrentBddMode->SrcModeWidth = pSourceMode->Format.Graphics.PrimSurfSize.cx;
+ pCurrentBddMode->SrcModeHeight = pSourceMode->Format.Graphics.PrimSurfSize.cy;
+ pCurrentBddMode->Rotation = pPath->ContentTransformation.Rotation;
+
+
+ if (!pCurrentBddMode->Flags.DoNotMapOrUnmap)
+ {
+ // Map the new frame buffer
+ BDD_ASSERT(pCurrentBddMode->FrameBuffer.Ptr == NULL);
+ Status = MapFrameBuffer(pCurrentBddMode->DispInfo.PhysicAddress,
+ pCurrentBddMode->DispInfo.Pitch * pCurrentBddMode->DispInfo.Height,
+ &(pCurrentBddMode->FrameBuffer.Ptr));
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+
+ pCurrentBddMode->Flags.FrameBufferIsActive = TRUE;
+ BlackOutScreen(pPath->VidPnSourceId);
+
+ // 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;
+ }
+
+ return Status;
+}
+
+
+NTSTATUS BASIC_DISPLAY_DRIVER::IsVidPnPathFieldsValid(CONST D3DKMDT_VIDPN_PRESENT_PATH* pPath) const
+{
+ PAGED_CODE();
+
+ if (pPath->VidPnSourceId >= MAX_VIEWS)
+ {
+ BDD_LOG_ERROR2("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)
+ {
+ BDD_LOG_ERROR2("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)
+ {
+ BDD_LOG_ERROR1("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))
+ {
+ BDD_LOG_ERROR1("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))
+ {
+ BDD_LOG_ERROR1("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))
+ {
+ BDD_LOG_ERROR1("pPath has a non-linear RGB color basis (0x%I64x)", pPath->VidPnTargetColorBasis);
+ return STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE;
+ }
+ else
+ {
+ return STATUS_SUCCESS;
+ }
+}
+
+NTSTATUS BASIC_DISPLAY_DRIVER::IsVidPnSourceModeFieldsValid(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMode) const
+{
+ PAGED_CODE();
+
+ if (pSourceMode->Type != D3DKMDT_RMT_GRAPHICS)
+ {
+ BDD_LOG_ERROR1("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))
+ {
+ BDD_LOG_ERROR1("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)
+ {
+ BDD_LOG_ERROR1("pSourceMode has a palettized access mode (0x%I64x)", pSourceMode->Format.Graphics.PixelValueAccessMode);
+ return STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE;
+ }
+ else
+ {
+ for (UINT PelFmtIdx = 0; PelFmtIdx < ARRAYSIZE(gBddPixelFormats); ++PelFmtIdx)
+ {
+ if (pSourceMode->Format.Graphics.PixelFormat == gBddPixelFormats[PelFmtIdx])
+ {
+ return STATUS_SUCCESS;
+ }
+ }
+
+ BDD_LOG_ERROR1("pSourceMode has an unknown pixel format (0x%I64x)", pSourceMode->Format.Graphics.PixelFormat);
+ return STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE;
+ }
+}
+
+
+
+// Add more mode from the table.
+struct SampleSourceMode
+{
+ UINT ModeWidth;
+ UINT ModeHeight;
+};
+
+// The driver will advertise all modes that fit within the actual required mode (see AddSingleSourceMode below)
+const static SampleSourceMode C_SampleSourceMode[] = {{800,600},{1024,768},{1152,864},{1280,800},{1280,1024},{1400,1050},{1600,1200},{1680,1050},{1920,1200}};
+const static UINT C_SampleSourceModeMax = sizeof(C_SampleSourceMode)/sizeof(C_SampleSourceMode[0]);
+
+NTSTATUS BASIC_DISPLAY_DRIVER::AddSingleSourceMode(_In_ CONST DXGK_VIDPNSOURCEMODESET_INTERFACE* pVidPnSourceModeSetInterface,
+ D3DKMDT_HVIDPNSOURCEMODESET hVidPnSourceModeSet,
+ D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId)
+{
+ PAGED_CODE();
+
+ // 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 (UINT PelFmtIdx = 0; PelFmtIdx < ARRAYSIZE(gBddPixelFormats); ++PelFmtIdx)
+ {
+ // Create new mode info that will be populated
+ D3DKMDT_VIDPN_SOURCE_MODE* pVidPnSourceModeInfo = NULL;
+ 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
+ BDD_LOG_ERROR2("pfnCreateNewModeInfo failed with Status = 0x%I64x, hVidPnSourceModeSet = 0x%I64x", Status, hVidPnSourceModeSet);
+ 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 = m_CurrentModes[SourceId].DispInfo.Width;
+ pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy = m_CurrentModes[SourceId].DispInfo.Height;
+ pVidPnSourceModeInfo->Format.Graphics.VisibleRegionSize = pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize;
+ pVidPnSourceModeInfo->Format.Graphics.Stride = m_CurrentModes[SourceId].DispInfo.Pitch;
+ pVidPnSourceModeInfo->Format.Graphics.PixelFormat = gBddPixelFormats[PelFmtIdx];
+ 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)
+ {
+ BDD_LOG_ERROR3("pfnAddMode failed with Status = 0x%I64x, hVidPnSourceModeSet = 0x%I64x, pVidPnSourceModeInfo = 0x%I64x", Status, hVidPnSourceModeSet, pVidPnSourceModeInfo);
+ return Status;
+ }
+ }
+ }
+
+ UINT WidthMax = m_CurrentModes[SourceId].DispInfo.Width;
+ UINT HeightMax = m_CurrentModes[SourceId].DispInfo.Height;
+
+ // Add all predefined modes that fit within the bounds of the required (POST) mode
+ for (UINT ModeIndex = 0; ModeIndex < C_SampleSourceModeMax; ++ModeIndex)
+ {
+ if (C_SampleSourceMode[ModeIndex].ModeWidth > WidthMax)
+ {
+ break;
+ }
+ else if (C_SampleSourceMode[ModeIndex].ModeWidth == WidthMax)
+ {
+ if(C_SampleSourceMode[ModeIndex].ModeHeight >= HeightMax)
+ {
+ break;
+ }
+ }
+ else
+ {
+ if(C_SampleSourceMode[ModeIndex].ModeHeight > HeightMax)
+ {
+ continue;
+ }
+ }
+
+ // 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 (UINT PelFmtIdx = 0; PelFmtIdx < ARRAYSIZE(gBddPixelFormats); ++PelFmtIdx)
+ {
+ // Create new mode info that will be populated
+ D3DKMDT_VIDPN_SOURCE_MODE* pVidPnSourceModeInfo = NULL;
+ NTSTATUS Status = pVidPnSourceModeSetInterface->pfnCreateNewModeInfo(hVidPnSourceModeSet, &pVidPnSourceModeInfo);
+ if (!NT_SUCCESS(Status))
+ {
+ // If failed to create a new mode info, continuing to the next mode and trying again isn't going to be at all helpful, so return
+ // Also, mode doesn't need to be released since it was never created
+ BDD_LOG_ERROR2("pfnCreateNewModeInfo failed with Status = 0x%I64x, hVidPnSourceModeSet = 0x%I64x", Status, hVidPnSourceModeSet);
+ return Status;
+ }
+
+ // Populate mode info with values from mode at ModeIndex and hard-coded values
+ // Always report 32 bpp format, this will be color converted during the present if the mode at ModeIndex was < 32bpp
+ pVidPnSourceModeInfo->Type = D3DKMDT_RMT_GRAPHICS;
+ pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cx = C_SampleSourceMode[ModeIndex].ModeWidth;
+ pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy = C_SampleSourceMode[ModeIndex].ModeHeight;
+ pVidPnSourceModeInfo->Format.Graphics.VisibleRegionSize = pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize;
+ pVidPnSourceModeInfo->Format.Graphics.Stride = 4*C_SampleSourceMode[ModeIndex].ModeWidth;
+ pVidPnSourceModeInfo->Format.Graphics.PixelFormat = gBddPixelFormats[PelFmtIdx];
+ 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 (Status != STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET)
+ {
+ BDD_LOG_ERROR3("pfnAddMode failed with Status = 0x%I64x, hVidPnSourceModeSet = 0x%I64x, pVidPnSourceModeInfo = 0x%I64x", Status, hVidPnSourceModeSet, pVidPnSourceModeInfo);
+ }
+
+ // 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, continue to next mode anyway
+ Status = pVidPnSourceModeSetInterface->pfnReleaseModeInfo(hVidPnSourceModeSet, pVidPnSourceModeInfo);
+ BDD_ASSERT_CHK(NT_SUCCESS(Status));
+ }
+ }
+ }
+
+
+ return STATUS_SUCCESS;
+}
+
+
+// Add the current mode information (acquired from the POST frame buffer) as the target mode.
+NTSTATUS BASIC_DISPLAY_DRIVER::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();
+
+ D3DKMDT_VIDPN_TARGET_MODE* pVidPnTargetModeInfo = NULL;
+ NTSTATUS 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
+ BDD_LOG_ERROR2("pfnCreateNewModeInfo failed with Status = 0x%I64x, hVidPnTargetModeSet = 0x%I64x", Status, hVidPnTargetModeSet);
+ return Status;
+ }
+
+ pVidPnTargetModeInfo->VideoSignalInfo.VideoStandard = D3DKMDT_VSS_OTHER;
+ UNREFERENCED_PARAMETER(pVidPnPinnedSourceModeInfo);
+ pVidPnTargetModeInfo->VideoSignalInfo.TotalSize.cx = m_CurrentModes[SourceId].DispInfo.Width;
+ pVidPnTargetModeInfo->VideoSignalInfo.TotalSize.cy = m_CurrentModes[SourceId].DispInfo.Height;
+ pVidPnTargetModeInfo->VideoSignalInfo.ActiveSize = pVidPnTargetModeInfo->VideoSignalInfo.TotalSize;
+ pVidPnTargetModeInfo->VideoSignalInfo.VSyncFreq.Numerator = D3DKMDT_FREQUENCY_NOTSPECIFIED;
+ pVidPnTargetModeInfo->VideoSignalInfo.VSyncFreq.Denominator = D3DKMDT_FREQUENCY_NOTSPECIFIED;
+ pVidPnTargetModeInfo->VideoSignalInfo.HSyncFreq.Numerator = D3DKMDT_FREQUENCY_NOTSPECIFIED;
+ pVidPnTargetModeInfo->VideoSignalInfo.HSyncFreq.Denominator = D3DKMDT_FREQUENCY_NOTSPECIFIED;
+ pVidPnTargetModeInfo->VideoSignalInfo.PixelRate = D3DKMDT_FREQUENCY_NOTSPECIFIED;
+ pVidPnTargetModeInfo->VideoSignalInfo.ScanLineOrdering = D3DDDI_VSSLO_PROGRESSIVE;
+ // We add this as PREFERRED since it is the only supported target
+ pVidPnTargetModeInfo->Preference = D3DKMDT_MP_PREFERRED;
+
+ Status = pVidPnTargetModeSetInterface->pfnAddMode(hVidPnTargetModeSet, pVidPnTargetModeInfo);
+ if (!NT_SUCCESS(Status))
+ {
+ if (Status != STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET)
+ {
+ BDD_LOG_ERROR3("pfnAddMode failed with Status = 0x%I64x, hVidPnTargetModeSet = 0x%I64x, pVidPnTargetModeInfo = 0x%I64x", Status, hVidPnTargetModeSet, pVidPnTargetModeInfo);
+ }
+ 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 = pVidPnTargetModeSetInterface->pfnReleaseModeInfo(hVidPnTargetModeSet, pVidPnTargetModeInfo);
+ UNREFERENCED_PARAMETER(TempStatus);
+ NT_ASSERT(NT_SUCCESS(TempStatus));
+ return Status;
+ }
+ else
+ {
+ // If AddMode succeeded with something other than STATUS_SUCCESS treat it as such anyway when propagating up
+ return STATUS_SUCCESS;
+ }
+}
+
+
+NTSTATUS BASIC_DISPLAY_DRIVER::AddSingleMonitorMode(_In_ CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModes)
+{
+ PAGED_CODE();
+
+ D3DKMDT_MONITOR_SOURCE_MODE* pMonitorSourceMode = NULL;
+ NTSTATUS 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
+ BDD_LOG_ERROR2("pfnCreateNewModeInfo failed with Status = 0x%I64x, hMonitorSourceModeSet = 0x%I64x", Status, pRecommendMonitorModes->hMonitorSourceModeSet);
+ return Status;
+ }
+
+ D3DDDI_VIDEO_PRESENT_SOURCE_ID CorrespondingSourceId = FindSourceForTarget(pRecommendMonitorModes->VideoPresentTargetId, TRUE);
+
+ // Since we don't know the real monitor timing information, just use the current display mode (from the POST device) with unknown frequencies
+ pMonitorSourceMode->VideoSignalInfo.VideoStandard = D3DKMDT_VSS_OTHER;
+ pMonitorSourceMode->VideoSignalInfo.TotalSize.cx = m_CurrentModes[CorrespondingSourceId].DispInfo.Width;
+ pMonitorSourceMode->VideoSignalInfo.TotalSize.cy = m_CurrentModes[CorrespondingSourceId].DispInfo.Height;
+ pMonitorSourceMode->VideoSignalInfo.ActiveSize = pMonitorSourceMode->VideoSignalInfo.TotalSize;
+ pMonitorSourceMode->VideoSignalInfo.VSyncFreq.Numerator = D3DKMDT_FREQUENCY_NOTSPECIFIED;
+ pMonitorSourceMode->VideoSignalInfo.VSyncFreq.Denominator = D3DKMDT_FREQUENCY_NOTSPECIFIED;
+ pMonitorSourceMode->VideoSignalInfo.HSyncFreq.Numerator = D3DKMDT_FREQUENCY_NOTSPECIFIED;
+ pMonitorSourceMode->VideoSignalInfo.HSyncFreq.Denominator = D3DKMDT_FREQUENCY_NOTSPECIFIED;
+ pMonitorSourceMode->VideoSignalInfo.PixelRate = D3DKMDT_FREQUENCY_NOTSPECIFIED;
+ pMonitorSourceMode->VideoSignalInfo.ScanLineOrdering = D3DDDI_VSSLO_PROGRESSIVE;
+
+ // 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)
+ {
+ BDD_LOG_ERROR3("pfnAddMode failed with Status = 0x%I64x, hMonitorSourceModeSet = 0x%I64x, pMonitorSourceMode = 0x%I64x",
+ 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;
+ }
+ else
+ {
+ // If AddMode succeeded with something other than STATUS_SUCCESS treat it as such anyway when propagating up
+ return STATUS_SUCCESS;
+ }
+}
+
diff --git a/C++/bdd_errorlog.hxx b/C++/bdd_errorlog.hxx
new file mode 100644
index 0000000..c3aa571
--- /dev/null
+++ b/C++/bdd_errorlog.hxx
@@ -0,0 +1,84 @@
+/******************************Module*Header*******************************\
+* Module Name: BDD_ErrorLog.hxx
+*
+* Basic Display Driver Logging Macros
+*
+*
+* Copyright (c) 2010 Microsoft Corporation
+*
+\**************************************************************************/
+#ifndef _BDD_ERRORLOG_HXX_
+#define _BDD_ERRORLOG_HXX_
+
+#define BDD_LOG_ERROR0(Msg)
+#define BDD_LOG_ERROR1(Msg,Param1)
+#define BDD_LOG_ERROR2(Msg,Param1,Param2)
+#define BDD_LOG_ERROR3(Msg,Param1,Param2,Param3)
+#define BDD_LOG_ERROR4(Msg,Param1,Param2,Param3,Param4)
+#define BDD_LOG_ERROR5(Msg,Param1,Param2,Param3,Param4,Param5)
+
+//
+// Warnings
+//
+
+#define BDD_LOG_WARNING0(Msg)
+#define BDD_LOG_WARNING1(Msg,Param1)
+#define BDD_LOG_WARNING2(Msg,Param1,Param2)
+#define BDD_LOG_WARNING3(Msg,Param1,Param2,Param3)
+#define BDD_LOG_WARNING4(Msg,Param1,Param2,Param3,Param4)
+#define BDD_LOG_WARNING5(Msg,Param1,Param2,Param3,Param4,Param5)
+
+//
+// Events (i.e. low-frequency tracing)
+//
+
+#define BDD_LOG_EVENT0(Msg)
+#define BDD_LOG_EVENT1(Msg,Param1)
+#define BDD_LOG_EVENT2(Msg,Param1,Param2)
+#define BDD_LOG_EVENT3(Msg,Param1,Param2,Param3)
+#define BDD_LOG_EVENT4(Msg,Param1,Param2,Param3,Param4)
+#define BDD_LOG_EVENT5(Msg,Param1,Param2,Param3,Param4,Param5)
+
+//
+// Information (i.e. high-frequency tracing)
+//
+
+#define BDD_LOG_INFORMATION0(Msg)
+#define BDD_LOG_INFORMATION1(Msg,Param1)
+#define BDD_LOG_INFORMATION2(Msg,Param1,Param2)
+#define BDD_LOG_INFORMATION3(Msg,Param1,Param2,Param3)
+#define BDD_LOG_INFORMATION4(Msg,Param1,Param2,Param3,Param4)
+#define BDD_LOG_INFORMATION5(Msg,Param1,Param2,Param3,Param4,Param5)
+
+//
+// Low resource logging macros.
+//
+
+#define BDD_LOG_LOW_RESOURCE0(Msg)
+#define BDD_LOG_LOW_RESOURCE1(Msg,Param1)
+#define BDD_LOG_LOW_RESOURCE2(Msg,Param1,Param2)
+#define BDD_LOG_LOW_RESOURCE3(Msg,Param1,Param2,Param3)
+#define BDD_LOG_LOW_RESOURCE4(Msg,Param1,Param2,Param3,Param4)
+#define BDD_LOG_LOW_RESOURCE5(Msg,Param1,Param2,Param3,Param4,Param5)
+
+//
+// Assertion logging macros.
+//
+
+#define BDD_LOG_ASSERTION0(Msg) NT_ASSERT(FALSE)
+#define BDD_LOG_ASSERTION1(Msg,Param1) NT_ASSERT(FALSE)
+#define BDD_LOG_ASSERTION2(Msg,Param1,Param2) NT_ASSERT(FALSE)
+#define BDD_LOG_ASSERTION3(Msg,Param1,Param2,Param3) NT_ASSERT(FALSE)
+#define BDD_LOG_ASSERTION4(Msg,Param1,Param2,Param3,Param4) NT_ASSERT(FALSE)
+#define BDD_LOG_ASSERTION5(Msg,Param1,Param2,Param3,Param4,Param5) NT_ASSERT(FALSE)
+#define BDD_ASSERT(exp) {if (!(exp)) {BDD_LOG_ASSERTION0(#exp);}}
+
+#if DBG
+#define BDD_ASSERT_CHK(exp) BDD_ASSERT(exp)
+#else
+#define BDD_ASSERT_CHK(exp) {}
+#endif
+
+
+#endif //_BDD_ERRORLOG_HXX_
+
diff --git a/C++/bdd_util.cxx b/C++/bdd_util.cxx
new file mode 100644
index 0000000..17b2db4
--- /dev/null
+++ b/C++/bdd_util.cxx
@@ -0,0 +1,115 @@
+/******************************Module*Header*******************************\
+* Module Name: bdd_util.cxx
+*
+* Basic Display Driver utility functions
+*
+* Created: 29-Mar-2011
+* Author: Amos Eshel [amosesh]
+*
+* Copyright (c) 2011 Microsoft Corporation
+\**************************************************************************/
+
+#include "BDD.hxx"
+
+
+#pragma code_seg("PAGE")
+
+//
+// EDID validation
+//
+
+BOOLEAN IsEdidHeaderValid(_In_reads_bytes_(EDID_V1_BLOCK_SIZE) const BYTE* pEdid)
+{
+ PAGED_CODE();
+
+ static const UCHAR EDID1Header[8] = {0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0};
+ return memcmp(pEdid, EDID1Header, sizeof(EDID1Header)) == 0;
+}
+
+BOOLEAN IsEdidChecksumValid(_In_reads_bytes_(EDID_V1_BLOCK_SIZE) const BYTE* pEdid)
+{
+ PAGED_CODE();
+
+ BYTE CheckSum = 0;
+ for (const BYTE* pEdidStart = pEdid; pEdidStart < (pEdid + EDID_V1_BLOCK_SIZE); ++pEdidStart)
+ {
+ CheckSum += *pEdidStart;
+ }
+
+ return CheckSum == 0;
+}
+
+//
+// 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))
+ {
+ BDD_LOG_ERROR3("One of PhysicalAddress.QuadPart (0x%I64x), Length (0x%I64x), VirtualAddress (0x%I64x) is NULL or 0",
+ PhysicalAddress.QuadPart, Length, VirtualAddress);
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ *VirtualAddress = MmMapIoSpace(PhysicalAddress,
+ Length,
+ MmWriteCombined);
+ if (*VirtualAddress == NULL)
+ {
+ // The underlying call to MmMapIoSpace failed. This may be because, MmWriteCombined
+ // isn't supported, so try again with MmNonCached
+
+ *VirtualAddress = MmMapIoSpace(PhysicalAddress,
+ Length,
+ MmNonCached);
+ if (*VirtualAddress == NULL)
+ {
+ BDD_LOG_LOW_RESOURCE1("MmMapIoSpace returned a NULL buffer when trying to allocate 0x%I64x bytes", Length);
+ 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))
+ {
+ BDD_LOG_ERROR2("Only one of Length (0x%I64x), VirtualAddress (0x%I64x) is NULL or 0",
+ Length, VirtualAddress);
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ MmUnmapIoSpace(VirtualAddress,
+ Length);
+
+ return STATUS_SUCCESS;
+}
+
diff --git a/C++/bltfuncs.cxx b/C++/bltfuncs.cxx
new file mode 100644
index 0000000..4b0ff99
--- /dev/null
+++ b/C++/bltfuncs.cxx
@@ -0,0 +1,346 @@
+/******************************Module*Header*******************************\
+ * Module Name: BltFuncs.cxx
+ *
+ * Basic Display Driver copying functionality
+ *
+ *
+ * Copyright (c) 2010 Microsoft Corporation
+\**************************************************************************/
+
+#include "BDD.hxx"
+
+// For the following macros, c must be a UCHAR.
+#define UPPER_6_BITS(c) (((c) & rMaskTable[6 - 1]) >> 2)
+#define UPPER_5_BITS(c) (((c) & rMaskTable[5 - 1]) >> 3)
+#define LOWER_6_BITS(c) (((BYTE)(c)) & lMaskTable[BITS_PER_BYTE - 6])
+#define LOWER_5_BITS(c) (((BYTE)(c)) & lMaskTable[BITS_PER_BYTE - 5])
+
+
+#define SHIFT_FOR_UPPER_5_IN_565 (6 + 5)
+#define SHIFT_FOR_MIDDLE_6_IN_565 (5)
+#define SHIFT_UPPER_5_IN_565_BACK ((BITS_PER_BYTE * 2) + (BITS_PER_BYTE - 5))
+#define SHIFT_MIDDLE_6_IN_565_BACK ((BITS_PER_BYTE * 1) + (BITS_PER_BYTE - 6))
+#define SHIFT_LOWER_5_IN_565_BACK ((BITS_PER_BYTE * 0) + (BITS_PER_BYTE - 5))
+
+// 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))
+
+#pragma code_seg(push)
+#pragma code_seg()
+// 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};
+
+/****************************Internal*Routine******************************\
+ * CopyBits32_32
+ *
+ *
+ * Copies rectangles from one surface to another. Both surfaces must have
+ * the same resolution.
+ *
+ * OffsetX, OffsetY - to add to the rectangle coordinates.
+ *
+ * Copied from %SDXROOT%\windows\Core\dxkernel\cdd\enable.cxx (CopySurfBits)
+ *
+\**************************************************************************/
+
+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));
+
+ 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;
+ }
+ }
+}
+
+
+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:
+ {
+ BDD_LOG_ASSERTION1("Invalid rotation (0x%I64x) specified", pBltInfo->Rotation);
+ *pPixelPitch = 0;
+ *pRowPitch = 0;
+ return;
+ }
+ }
+}
+
+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:
+ {
+ BDD_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
+ *
+\**************************************************************************/
+
+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;
+
+ 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;
+ }
+ }
+}
+
+/****************************Internal*Routine******************************\
+ * BltBits
+ *
+ *
+ * Logic to decide which of the above functions to call based on Rotation/BPP
+ *
+\**************************************************************************/
+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.
+ __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)
+ {
+ BDD_LOG_ERROR2("Either dst (0x%I64x) or src (0x%I64x) bits encountered exception during access.", pDst->pBits, pSrc->pBits);
+ }
+}
+
+// END: Non-Paged Code
+#pragma code_seg(pop)
+
diff --git a/C++/blthw.cxx b/C++/blthw.cxx
new file mode 100644
index 0000000..05fb047
--- /dev/null
+++ b/C++/blthw.cxx
@@ -0,0 +1,556 @@
+/******************************Module*Header*******************************\
+* Module Name: blthw.cxx
+*
+* Sample display driver functions for a HW blt simulation. This file is
+* only provided to simulate how a real hardware-accelerated display-only
+* driver functions, and should not be used in a real driver.
+*
+* Copyright (c) 2011 Microsoft Corporation
+\**************************************************************************/
+
+#include "BDD.hxx"
+
+typedef struct
+{
+ CONST DXGKRNL_INTERFACE* DxgkInterface;
+ DXGKARGCB_NOTIFY_INTERRUPT_DATA NotifyInterrupt;
+} SYNC_NOTIFY_INTERRUPT;
+
+KSYNCHRONIZE_ROUTINE SynchronizeVidSchNotifyInterrupt;
+
+BOOLEAN SynchronizeVidSchNotifyInterrupt(_In_opt_ PVOID params)
+{
+ // This routine is non-paged code called at the device interrupt level (DIRQL)
+ // to notify VidSch and schedule a DPC. It is meant as a demonstration of handling
+ // a real hardware interrupt, even though it is actually called from asynchronous
+ // present worker threads in this sample.
+ SYNC_NOTIFY_INTERRUPT* pParam = reinterpret_cast<SYNC_NOTIFY_INTERRUPT*>(params);
+
+ // The context is known to be non-NULL
+ __analysis_assume(pParam != NULL);
+
+ // Update driver information related to fences
+ switch(pParam->NotifyInterrupt.InterruptType)
+ {
+ case DXGK_INTERRUPT_DISPLAYONLY_VSYNC:
+ case DXGK_INTERRUPT_DISPLAYONLY_PRESENT_PROGRESS:
+ break;
+ default:
+ NT_ASSERT(FALSE);
+ return FALSE;
+ }
+
+ // Callback OS to report about the interrupt
+ pParam->DxgkInterface->DxgkCbNotifyInterrupt(pParam->DxgkInterface->DeviceHandle,&pParam->NotifyInterrupt);
+
+ // Now queue a DPC for this interrupt (to callback schedule at DCP level and let it do more work there)
+ // DxgkCbQueueDpc can return FALSE if there is already a DPC queued
+ // this is an acceptable condition
+ pParam->DxgkInterface->DxgkCbQueueDpc(pParam->DxgkInterface->DeviceHandle);
+
+ return TRUE;
+}
+
+#pragma code_seg("PAGE")
+
+KSTART_ROUTINE HwContextWorkerThread;
+
+struct DoPresentMemory
+{
+ PVOID DstAddr;
+ UINT DstStride;
+ ULONG DstBitPerPixel;
+ UINT SrcWidth;
+ UINT SrcHeight;
+ BYTE* SrcAddr;
+ LONG SrcPitch;
+ ULONG NumMoves; // in: Number of screen to screen moves
+ D3DKMT_MOVE_RECT* Moves; // in: Point to the list of moves
+ ULONG NumDirtyRects; // in: Number of direct rects
+ RECT* DirtyRect; // in: Point to the list of dirty rects
+ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation;
+ BOOLEAN SynchExecution;
+ D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceID;
+ HANDLE hAdapter;
+ PMDL Mdl;
+ BDD_HWBLT* DisplaySource;
+};
+
+void
+HwExecutePresentDisplayOnly(
+ HANDLE Context);
+
+NTSTATUS
+StartHwBltPresentWorkerThread(
+ _In_ PKSTART_ROUTINE StartRoutine,
+ _In_ _When_(return==0, __drv_aliasesMem) PVOID StartContext)
+/*++
+
+ Routine Description:
+
+ This routine creates the worker thread to execute a single present
+ command. Creating a new thread on every asynchronous present is not
+ efficient, but this file is only meant as a simulation, not an example
+ of implementation.
+
+ Arguments:
+
+ StartRoutine - start routine
+ StartContext - start context
+
+ Return Value:
+
+ Status
+
+--*/
+{
+ PAGED_CODE();
+
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
+ HANDLE hWorkerThread = NULL;
+
+ // copy data from the context which is need here, as it will be deleted in separate thread
+ DoPresentMemory* ctx = reinterpret_cast<DoPresentMemory*>(StartContext);
+ BDD_HWBLT* displaySource = ctx->DisplaySource;
+
+ NTSTATUS Status = PsCreateSystemThread(
+ &hWorkerThread,
+ THREAD_ALL_ACCESS,
+ &ObjectAttributes,
+ NULL,
+ NULL,
+ StartRoutine,
+ StartContext);
+
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+
+ // wait for thread to start - infinite wait -
+ // need to make sure the tread is running before OS stars submitting the work items to it
+ KeWaitForSingleObject(&displaySource->m_hThreadStartupEvent, Executive, KernelMode, FALSE, NULL);
+
+ // Handle is passed to the parent object which must close it
+ displaySource->SetPresentWorkerThreadInfo(hWorkerThread);
+
+ // Resume context thread, this is done by setting the event the thread is waiting on
+ KeSetEvent(&displaySource->m_hThreadSuspendEvent, 0, FALSE);
+
+ return STATUS_PENDING;
+}
+
+BDD_HWBLT::BDD_HWBLT():m_DevExt (NULL),
+ m_SynchExecution(TRUE),
+ m_hPresentWorkerThread(NULL),
+ m_pPresentWorkerThread(NULL)
+{
+ PAGED_CODE();
+
+ KeInitializeEvent(&m_hThreadStartupEvent, NotificationEvent, FALSE);
+ KeInitializeEvent(&m_hThreadSuspendEvent, SynchronizationEvent, FALSE);
+
+}
+
+
+BDD_HWBLT::~BDD_HWBLT()
+/*++
+
+ Routine Description:
+
+ This routine waits on present worker thread to exit before
+ destroying the object
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ None
+
+--*/
+{
+ PAGED_CODE();
+
+ // make sure the worker thread has exited
+ SetPresentWorkerThreadInfo(NULL);
+}
+
+#pragma warning(push)
+#pragma warning(disable:26135) // The function doesn't lock anything
+
+void
+BDD_HWBLT::SetPresentWorkerThreadInfo(
+ HANDLE hWorkerThread)
+/*++
+
+ Routine Description:
+
+ The method is updating present worker information
+ It is called in following cases:
+ - In ExecutePresent to update worker thread information
+ - In Dtor to wait on worker thread to exit
+
+ Arguments:
+
+ hWorkerThread - handle of the present worker thread
+
+ Return Value:
+
+ None
+
+--*/
+{
+
+ PAGED_CODE();
+
+ if (m_pPresentWorkerThread)
+ {
+ // Wait for thread to exit
+ KeWaitForSingleObject(m_pPresentWorkerThread, Executive, KernelMode,
+ FALSE, NULL);
+ // Dereference thread object
+ ObDereferenceObject(m_pPresentWorkerThread);
+ m_pPresentWorkerThread = NULL;
+
+ NT_ASSERT(m_hPresentWorkerThread);
+ ZwClose(m_hPresentWorkerThread);
+ m_hPresentWorkerThread = NULL;
+ }
+
+ if (hWorkerThread)
+ {
+ // Make sure that thread's handle would be valid even if the thread exited
+ ObReferenceObjectByHandle(hWorkerThread, THREAD_ALL_ACCESS, NULL,
+ KernelMode, &m_pPresentWorkerThread, NULL);
+ NT_ASSERT(m_pPresentWorkerThread);
+ m_hPresentWorkerThread = hWorkerThread;
+ }
+
+}
+#pragma warning(pop)
+
+NTSTATUS
+BDD_HWBLT::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)
+/*++
+
+ 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();
+
+ 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 (PagedPool) BYTE[size]);
+
+ if (!ctx)
+ {
+ return STATUS_NO_MEMORY;
+ }
+
+ RtlZeroMemory(ctx,size);
+
+ const CURRENT_BDD_MODE* pModeCur = m_DevExt->GetCurrentMode(m_SourceId);
+
+ 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->SourceID = m_SourceId;
+ ctx->hAdapter = m_DevExt;
+ ctx->Mdl = NULL;
+ ctx->DisplaySource = this;
+
+ // Alternate between synch and asynch execution, for demonstrating
+ // that a real hardware implementation can do either
+ m_SynchExecution = !m_SynchExecution;
+
+ ctx->SynchExecution = m_SynchExecution;
+
+ {
+ // Map Source into kernel space, as Blt will be executed by system worker thread
+ UINT sizeToMap = SrcBytesPerPixel*pModeCur->SrcModeWidth*pModeCur->SrcModeHeight;
+
+ 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*>
+ (MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority ));
+
+ 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);
+ }
+
+
+ if (m_SynchExecution)
+ {
+ HwExecutePresentDisplayOnly((PVOID)ctx);
+ return STATUS_SUCCESS;
+ }
+ else
+ {
+ // Create a worker thread to perform the present asynchronously
+ // Ctx will be deleted in worker thread (on exit)
+ return StartHwBltPresentWorkerThread(HwContextWorkerThread,(PVOID)ctx);
+ }
+}
+
+
+void
+ReportPresentProgress(
+ _In_ HANDLE Adapter,
+ _In_ D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId,
+ _In_ BOOLEAN CompletedOrFailed)
+/*++
+
+ Routine Description:
+
+ This routine runs a fake interrupt routine in order to tell the OS about the present progress.
+
+ Arguments:
+
+ Adapter - Handle to the adapter (Device Extension)
+ VidPnSourceId - Video present source id for the callback
+ CompletedOrFailed - Present progress status for the source
+
+ Return Value:
+
+ None
+
+--*/
+{
+ PAGED_CODE();
+
+ BASIC_DISPLAY_DRIVER* pDevExt =
+ reinterpret_cast<BASIC_DISPLAY_DRIVER*>(Adapter);
+
+ SYNC_NOTIFY_INTERRUPT SyncNotifyInterrupt = {};
+ SyncNotifyInterrupt.DxgkInterface = pDevExt->GetDxgkInterface();
+ SyncNotifyInterrupt.NotifyInterrupt.InterruptType = DXGK_INTERRUPT_DISPLAYONLY_PRESENT_PROGRESS;
+ SyncNotifyInterrupt.NotifyInterrupt.DisplayOnlyPresentProgress.VidPnSourceId = VidPnSourceId;
+
+ SyncNotifyInterrupt.NotifyInterrupt.DisplayOnlyPresentProgress.ProgressId =
+ (CompletedOrFailed)?DXGK_PRESENT_DISPLAYONLY_PROGRESS_ID_COMPLETE:
+ DXGK_PRESENT_DISPLAYONLY_PROGRESS_ID_FAILED;
+
+ // Execute the SynchronizeVidSchNotifyInterrupt function at the interrupt
+ // IRQL in order to fake a real present progress interrupt
+ BOOLEAN bRet = FALSE;
+ NT_VERIFY(NT_SUCCESS(pDevExt->GetDxgkInterface()->DxgkCbSynchronizeExecution(
+ pDevExt->GetDxgkInterface()->DeviceHandle,
+ (PKSYNCHRONIZE_ROUTINE)SynchronizeVidSchNotifyInterrupt,
+ (PVOID)&SyncNotifyInterrupt,0,&bRet)));
+ NT_ASSERT(bRet);
+}
+
+
+void
+HwContextWorkerThread(
+ HANDLE Context)
+{
+ PAGED_CODE();
+
+ DoPresentMemory* ctx = reinterpret_cast<DoPresentMemory*>(Context);
+ BDD_HWBLT* displaySource = ctx->DisplaySource;
+
+ // Signal event to indicate that the tread has started
+ KeSetEvent(&displaySource->m_hThreadStartupEvent, 0, FALSE);
+
+ // Suspend context thread, do this by waiting on the suspend event
+ KeWaitForSingleObject(&displaySource->m_hThreadSuspendEvent, Executive, KernelMode, FALSE, NULL);
+
+ HwExecutePresentDisplayOnly(Context);
+}
+
+
+void
+HwExecutePresentDisplayOnly(
+ HANDLE Context)
+/*++
+
+ Routine Description:
+
+ The routine executes present's commands and report progress to the OS
+
+ Arguments:
+
+ Context - Context with present's command
+
+ Return Value:
+
+ None
+
+--*/
+{
+ PAGED_CODE();
+
+ DoPresentMemory* ctx = reinterpret_cast<DoPresentMemory*>(Context);
+
+ // 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++)
+ {
+ BltBits(&DstBltInfo,
+ &SrcBltInfo,
+ 1, // NumRects
+ &ctx->Moves[i].DestRect);
+ }
+
+ // Copy all the dirty rects from source image to video frame buffer.
+ for (UINT i = 0; i < ctx->NumDirtyRects; i++)
+ {
+
+ BltBits(&DstBltInfo,
+ &SrcBltInfo,
+ 1, // NumRects
+ &ctx->DirtyRect[i]);
+ }
+
+ // Unmap unmap and unlock the pages.
+ if (ctx->Mdl)
+ {
+ MmUnlockPages(ctx->Mdl);
+ IoFreeMdl(ctx->Mdl);
+ }
+
+ if(ctx->SynchExecution)
+ {
+ // This code simulates Blt executed synchronously
+ // nothing should be done here, just exit
+ ;
+ }
+ else
+ {
+ // TRUE == completed
+ // This code is emulates interrupt which HW should generate
+ ReportPresentProgress(ctx->hAdapter,ctx->SourceID,TRUE);
+ }
+
+ delete [] reinterpret_cast<BYTE*>(ctx);
+}
diff --git a/C++/memory.cxx b/C++/memory.cxx
new file mode 100644
index 0000000..42de8bd
--- /dev/null
+++ b/C++/memory.cxx
@@ -0,0 +1,78 @@
+/******************************Module*Header*******************************\
+* Module Name: bdd.h
+*
+* Basic Display Driver memory allocation, deletion, and tracking
+*
+*
+* Copyright (c) 2010 Microsoft Corporation
+\**************************************************************************/
+
+#include "BDD.hxx"
+
+#pragma code_seg("PAGE")
+
+//
+// New and delete operators
+//
+_When_((PoolType & NonPagedPoolMustSucceed) != 0,
+ __drv_reportError("Must succeed pool allocations are forbidden. "
+ "Allocation failures cause a system crash"))
+void* __cdecl operator new(size_t Size, POOL_TYPE PoolType)
+{
+ PAGED_CODE();
+
+ Size = (Size != 0) ? Size : 1;
+
+ void* pObject = ExAllocatePoolWithTag(PoolType, Size, BDDTAG);
+
+#if DBG
+ if (pObject != NULL)
+ {
+ RtlFillMemory(pObject, Size, 0xCD);
+ }
+#endif // DBG
+
+ return pObject;
+}
+
+_When_((PoolType & NonPagedPoolMustSucceed) != 0,
+ __drv_reportError("Must succeed pool allocations are forbidden. "
+ "Allocation failures cause a system crash"))
+void* __cdecl operator new[](size_t Size, POOL_TYPE PoolType)
+{
+ PAGED_CODE();
+
+ Size = (Size != 0) ? Size : 1;
+
+ void* pObject = ExAllocatePoolWithTag(PoolType, Size, BDDTAG);
+
+#if DBG
+ if (pObject != NULL)
+ {
+ RtlFillMemory(pObject, Size, 0xCD);
+ }
+#endif // DBG
+
+ return pObject;
+}
+
+void __cdecl operator delete(void* pObject)
+{
+ PAGED_CODE();
+
+ if (pObject != NULL)
+ {
+ ExFreePool(pObject);
+ }
+}
+
+void __cdecl operator delete[](void* pObject)
+{
+ PAGED_CODE();
+
+ if (pObject != NULL)
+ {
+ ExFreePool(pObject);
+ }
+}
+
diff --git a/C++/readme.htm b/C++/readme.htm
new file mode 100644
index 0000000..772ab26
--- /dev/null
+++ b/C++/readme.htm
@@ -0,0 +1,46 @@
+<html>
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta http-equiv="Content-Language" content="en-us">
+ <title>Kernel-Mode Display-Only Miniport Driver</title>
+</head>
+
+<body>
+ <p>
+ This is a sample kernel-mode display-only miniport driver. It implements most of DDIs which display-only drivers should provide to the
+ Windows Display Driver Model (WDDM). The sample can be installed on top of a VESA-capable graphics adapter or on top of a graphics device
+ that supports access to the frame buffer through UEFI.
+ </p>
+ <p>
+ The code is provided mainly as a reference for people writing miniport drivers for display-only devices, although it can also be useful
+ for people working on full WDDM drivers to help in display-related DDI implementations.
+ </p>
+ <p>
+ The BltHw.* files are provided only to simulate how the blt operations would work on a real hardware device and should not be used as a
+ basis for actual implementation. The INF file is provided mainly to illustrate how to make the miniport driver visible to other WDDM
+ components.
+ </p>
+ <p>
+ Here are some useful links to MSDN documentation:
+ </p>
+ <ul>
+ <li>
+ <a href="http://msdn.microsoft.com/en-us/library/windows/hardware/ff569172.aspx">Display Devices (Adapters and Monitors)</a> -
+ The root of the MSDN docs tree for display adapter development
+ </li>
+ <li>
+ <a href="http://msdn.microsoft.com/en-us/library/windows/hardware/hh439923.aspx">New Reference Topics for Windows 8</a> -
+ Documents the new interfaces present in WDDM 1.2 (Windows 8)
+ </li>
+ <li>
+ <a href="http://msdn.microsoft.com/library/windows/hardware/br259098">WDDM Enhancements in Windows 8 Developer Preview</a> -
+ A summary of the new features in WDDM 1.2 (Windows 8)
+ <li>
+ <a href="http://msdn.microsoft.com/en-us/library/windows/hardware/ff568500.aspx">Multiple Monitors and Video Present Networks</a> -
+ Topics about making your driver support multiple targets/sources
+ </li>
+ </ul>
+</body>
+
+</html>
diff --git a/C++/sampledisplay.rc b/C++/sampledisplay.rc
new file mode 100644
index 0000000..2d4609b
--- /dev/null
+++ b/C++/sampledisplay.rc
@@ -0,0 +1,30 @@
+/*++
+
+Copyright (c) 2011 Microsoft Corporation
+
+Module Name:
+
+ SampleDisplay.rc
+
+Abstract:
+
+ This modules contains the version information for the Sample Display Driver
+
+Environment:
+
+ Kernel mode only
+
+--*/
+
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DRV
+#define VER_FILESUBTYPE VFT2_DRV_DISPLAY
+#define VER_FILEDESCRIPTION_STR "Microsoft Sample Display Driver"
+#define VER_INTERNALNAME_STR "SampleDisplay.sys"
+#define VER_ORIGINALFILENAME_STR "SampleDisplay.sys"
+
+#define VER_LANGNEUTRAL
+#include "common.ver"
diff --git a/description.html b/description.html
new file mode 100644
index 0000000..a2146af
--- /dev/null
+++ b/description.html
@@ -0,0 +1,245 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+ <head><link rel="stylesheet" type="text/css" href="description/Combined.css,0:SearchBox,0:ImageSprite;/Areas/Epx/Themes/Metro/Content:0&amp;amp;hashKey=117BAC28FA404ADE34B839F23DA6CC1E" xmlns="http://www.w3.org/1999/xhtml" />
+<link rel="stylesheet" type="text/css" href="description/d0a480a2-d1c4-4159-af59-5aa4abd59cb0Combined.css,0:ImageSprite;/Areas/Epx/Themes/Metro/Content:0&amp;amp;hashKey=9BB0483639637E71A098F1750E860CCF" xmlns="http://www.w3.org/1999/xhtml" />
+
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <title>Kernel mode display-only miniport driver (KMDOD) sample</title>
+ <link href="description/Galleries.css" type="text/css" rel="Stylesheet" /><link href="description/Layout.css" type="text/css" rel="Stylesheet" /><link href="description/Brand.css" type="text/css" rel="Stylesheet" /><link href="description/84ada392-ed9e-43d3-9c3e-f99f948be6cbBrand.css" type="text/css" rel="Stylesheet" />
+ <link href="description/iframedescription.css" rel="Stylesheet" type="text/css" />
+ <script src="description/offline.js" type="text/javascript"></script>
+ <style type="text/css">
+ #projectInfo {
+ overflow: auto;
+ }
+ #longDesc {
+ clear:both;
+ margin: 25px 0 10px 0;
+ }
+
+ #SampleIndexList{
+ margin-left: 15px;
+ }
+ </style>
+ </head>
+<body>
+ <div id="offlineDescription">
+ <h1>Kernel mode display-only miniport driver (KMDOD) sample</h1>
+ <br/>
+ <div id="projectInfo">
+ <div class="section">
+ <div class="itemBarLong tagsContainer">
+ <label for="Technologies">Technologies</label>
+ <div id="Technologies">
+ WDM, Windows Driver
+ </div>
+ </div>
+ <div class="itemBarLong tagsContainer">
+ <label for="Topics">Topics</label>
+ <div id="Topics">
+ display
+ </div>
+ </div>
+ <div class="itemBarLong">
+ <label for="Platforms">Platforms</label>
+ <div id="Platforms">
+ Desktop
+ </div>
+ </div>
+ <div class="itemBarLong">
+ <label for="Requirements">Requirements</label>
+ <div id="Requirements">
+
+ </div>
+ </div>
+ <div class="itemBar">
+ <label for="LastUpdated">Primary Language</label>
+ <div id="LastUpdated">en-US</div>
+ </div>
+ <div class="itemBar">
+ <label for="LastUpdated">Last Updated</label>
+ <div id="LastUpdated">10/26/2012</div>
+ </div>
+ <div class="itemBarLong">
+ <label for="License">License</label>
+ <div id="License">
+ <a href="license.rtf">MS-LPL</a></div>
+ </div>
+ <div class="itemBar">
+ <div class="viewonlinecont">
+ <a data-link="online" href="http://code.msdn.microsoft.com/windowshardware/Kernel-mode-display-only-49adea58">View this sample online</a>
+ </div>
+ </div>
+ </div>
+ </div>
+
+
+<script type="text/javascript">
+ function initializePage() {
+ var otherTabClass = 'otherTab';
+ var hiddenPreClass = 'hidden';
+
+ var htmlDecode = function(encodedData) {
+ var decodedData = "";
+ if (encodedData) {
+ var div = document.createElement('div');
+ div.innerHTML = encodedData;
+ decodedData = div.firstChild.nodeValue.replace( /\\r\\n/ig , '\r\n');
+ }
+ return decodedData;
+ };
+
+ Galleries.iterateElem(Galleries.findElem(null, 'div', 'scriptcode'), function (index, scriptBlock) {
+ var titleElem = Galleries.findElem(scriptBlock, 'div', 'title')[0];
+ var labelElems = Galleries.findElem(titleElem, 'span');
+ if (labelElems.length == 0) {
+ labelElems = titleElem;
+ }
+ var languageSpans = Galleries.findElem(scriptBlock, 'span', 'hidden');
+ var pres = Galleries.findElem(scriptBlock, 'pre');
+ if (languageSpans.length > 0 && pres.length > 1) {
+ Galleries.iterateElem(labelElems, function(index, elem) {
+ var codePre = pres[index];
+ var labelSpan = elem;
+ var languageSpan = languageSpans[index];
+
+ elem.code = codePre.innerHTML.replace( /(\r(\n)?)|((\r)?\n)/ig , '\\r\\n');
+
+ codePre.className = codePre.className.replace(hiddenPreClass, '');
+
+ languageSpan.parentNode.removeChild(languageSpan);
+ });
+
+ pres = Galleries.findElem(scriptBlock, 'pre');
+ Galleries.iterateElem(labelElems, function(index, elem) {
+ var codePre = pres[index];
+ var labelSpan = elem;
+ if (index == 0) {
+ scriptBlock.activeTab = 0;
+ }
+ else {
+ labelSpan.className += otherTabClass;
+ codePre.className += hiddenPreClass;
+ }
+ Galleries.attachEventHandler(labelSpan, 'click', function(e) {
+ var activeTab = scriptBlock.activeTab;
+ labelElems[activeTab].className += otherTabClass;
+ pres[activeTab].className += hiddenPreClass;
+
+ codePre.className = codePre.className.replace(hiddenPreClass, '');
+ labelSpan.className = labelSpan.className.replace(otherTabClass, '');
+ scriptBlock.activeTab = index;
+ });
+ });
+
+ var preview = Galleries.findElem(scriptBlock, 'div', 'preview');
+ if (preview.length == 0) {
+ preview.push(pres[pres.length - 1]);
+ }
+ Galleries.iterateElem(preview, function(index, elem) {
+ elem.parentNode.removeChild(elem);
+ });
+
+ if (window.clipboardData && clipboardData.setData) {
+ var copyLink = document.createElement('a');
+ copyLink.href = 'javascript:void(0);';
+ copyLink.className = 'copyCode';
+ copyLink.innerHTML = 'Copy Code';
+ Galleries.attachEventHandler(copyLink, 'click', function (e) {
+ clipboardData.setData("Text", htmlDecode(labelElems[scriptBlock.activeTab].code));
+ return false;
+ });
+ scriptBlock.insertBefore(copyLink, scriptBlock.childNodes[0]);
+ }
+ }
+ });
+ }
+
+ Galleries.onWindowLoad(function(){
+ initializePage();
+ });
+
+</script>
+<div id="longDesc">
+ <style> pre.syntax { font-size: 110 background: #dddddd; padding: 4px,8px; cursor: text; color: #000000; width: 97 } body{font-family:Verdana,Arial,Helvetica,sans-serif;color:#000;font-size:80%} H1{font-size:150%;font-weight:bold} H1.heading{font-size:110%;font-family:Verdana,Arial,Helvetica,sans-serif;font-weight:bold;line-height:120%}
+ H2{font-size:115%;font-weight:700} H2.subtitle{font-size:180%;font-weight:400;margin-bottom:.6em} H3{font-size:110%;font-weight:700} H4,H5,H6{font-size:100%;font-weight:700} h4.subHeading{font-size:100%} dl{margin:0 0 10px;padding:0 0 0 1px} dt{font-style:normal;margin:0}
+ li{margin-bottom:3px;margin-left:0} ol{line-height:140%;list-style-type:decimal;margin-bottom:15px;margin-left:24px} ol ol{line-height:140%;list-style-type:lower-alpha;margin-bottom:4px;margin-left:24px;margin-top:3px} ol ul,ul ol{line-height:140%;margin-bottom:15px;margin-top:15px}
+ p{margin:0 0 10px;padding:0} div.section p{margin-bottom:15px;margin-top:0} ul{line-height:140%;list-style-position:outside;list-style-type:disc;margin-bottom:15px} ul ul{line-height:140%;list-style-type:disc;margin-bottom:4px;margin-left:17px;margin-top:3px}
+ .heading{font-weight:700;margin-bottom:8px;margin-top:18px} .subHeading{font-size:100%;font-weight:700;margin:0} div#mainSection table{border:1px solid #ddd;font-size:100%;margin-bottom:5px;margin-left:5px;margin-top:5px;width:97%;clear:both} div#mainSection
+ table tr{vertical-align:top} div#mainSection table th{border-bottom:1px solid #c8cdde;color:#006;padding-left:5px;padding-right:5px;text-align:left} div#mainSection table td{border:1px solid #d5d5d3;margin:1px;padding-left:5px;padding-right:5px} div#mainSection
+ table td.imageCell{white-space:nowrap} /* These are the original lines from global-bn1945 div.ContentArea table th,div.ContentArea table td{background:#fff;border:0 solid #ccc;font-family:Verdana;padding:5px;text-align:left;vertical-align:top} div.ContentArea
+ table th{background:#ccc none repeat scroll 0% 50%;vertical-align:bottom} div.ContentArea table{border-collapse:collapse;width:auto} */ /* Removing ContentArea class requirement from commented out lines from global-bn1945 above */ table th,table td{background:#fff;border:0
+ solid #ccc;font-family:Verdana;padding:5px;text-align:left;vertical-align:top} table th{background:#ccc none repeat scroll 0% 50%;vertical-align:bottom} table{border-collapse:collapse;width:auto} div.clsNote{background-color:#eee;margin-bottom:4px;padding:2px}
+ div.code{width:98.9%} code{font-family:Monospace,Courier New,Courier;font-size:105%;color:#006} span.label{font-weight:bold} div.caption{font-weight:bold;font-size:100%;color:#039} .procedureSubHeading{font-size:110%;font-weight:bold} span.sub{vertical-align:sub}
+ span.sup{vertical-align:super} span.big{font-size:larger} span.small{font-size:smaller} span.tt{font-family:Courier,"Courier New",Consolas,monospace} .CCE_Message{color:Red;font-size:10pt} </style>
+<div id="mainSection">
+<p>The kernel mode display-only miniport driver (KMDOD) sample implements most of the device driver interfaces (DDIs) that a display-only miniport driver should provide to the Windows Display Driver Model (WDDM). The code is useful to understand how to write
+ a miniport driver for a display-only device, or how to develop a full WDDM driver.
+</p>
+<p>This code can also help you to understand the use and implementation of display-related DDIs. The INF file shows how to make a display miniport driver visible to other WDDM components.</p>
+<p>The sample can be installed on top of a VESA-capable graphics adapter, or on top of a graphics device that supports access to frame buffer memory through the Unified Extensible Firmware Interface (UEFI).</p>
+<p>The sample driver does not support the <i>sleep</i> power state. If it is placed in the sleep state, the driver will cause a system bugcheck to occur. There is no workaround available, by design.</p>
+<p>If the current display driver is not a WDDM 1.2 compliant driver, the sample driver might fail to install, with error code 43 displayed. The KMDOD driver is actually installed, but it cannot be started. The workaround for this issue is to switch to the Microsoft
+ Basic Display Adapter Driver before installing the KMDOD sample driver, or simply to reboot your system after installing the KMDOD sample.</p>
+<h3>Operating system requirements</h3>
+<table>
+<tbody>
+<tr>
+<th>Client</th>
+<td><dt>Windows&nbsp;8 </dt></td>
+</tr>
+<tr>
+<th>Server</th>
+<td><dt>Windows Server&nbsp;2012 </dt></td>
+</tr>
+</tbody>
+</table>
+<h3>Build the sample</h3>
+<p>For information on how to build a driver solution using Microsoft Visual Studio, see
+<a href="http://msdn.microsoft.com/en-us/library/windows/hardware/Ff554644">Building a Driver</a>.</p>
+<h3><a id="installation"></a><a id="INSTALLATION"></a>Installation</h3>
+<p>In Microsoft Visual Studio, press <b>F5</b> to build the sample and then deploy it to a target machine. For more information, see
+<a href="http://msdn.microsoft.com/en-us/library/windows/hardware/Hh454834">Deploying a Driver to a Test Computer</a>.</p>
+<p>In some cases you might need to install the driver manually, as follows.</p>
+<ol>
+<li>Add the following files to the directory given by …\[x64]\C&#43;&#43;\Package:
+<ul>
+<li>SampleDriver.cat </li><li>SampleDriver.inf </li><li>SampleDriver.sys </li><li>SampleDriver.cer </li></ul>
+</li><li>Unless you’ve provided a production certificate, you should manually install the SampleDriver.cer digital certificate with the following command:
+<p><code>Certutil.exe -addstore root SampleDriver.cer</code></p>
+</li><li>Then enable test signing by running the following BCDEdit command:
+<p><code>Bcdedit.exe -set TESTSIGNING ON</code></p>
+<p class="note"><b>Note</b>&nbsp;&nbsp;After you change the TESTSIGNING boot configuration option, restart the computer for the change to take effect.</p>
+<p>For more information, see <a href="http://msdn.microsoft.com/en-us/library/windows/hardware/Ff553484">
+The TESTSIGNING Boot Configuration Option</a>.</p>
+</li><li>Manually install the driver using Device Manager, which is available from Control Panel.
+</li></ol>
+<h4><a id="ACPI-based_GPUs"></a><a id="acpi-based_gpus"></a><a id="ACPI-BASED_GPUS"></a>ACPI-based GPUs</h4>
+<p>To install the KMDOD sample driver on a GPU that is an Advanced Configuration and Power Interface (ACPI) device, add these lines to the
+<code>[MS]</code>, <code>[MS.NTamd64]</code>, and <code>[MS.NTarm]</code> sections of the Sampledisplay.inf file:</p>
+<div class="code"><span>
+<table>
+<tbody>
+<tr>
+<th>text</th>
+</tr>
+<tr>
+<td>
+<pre>&quot; Kernel mode display only sample driver &quot; = KDODSamp_Inst, ACPI\CLS_0003&amp;SUBCLS_0000
+&quot; Kernel mode display only sample driver &quot; = KDODSamp_Inst, ACPI\CLS_0003&amp;SUBCLS_0001
+&quot; Kernel mode display only sample driver &quot; = KDODSamp_Inst, ACPI\CLS_0003&amp;SUBCLS_0003</pre>
+</td>
+</tr>
+</tbody>
+</table>
+</span></div>
+<p>This new code provides generic identifiers for ACPI hardware.</p>
+<p>You can optionally delete the original lines of code within these sections of the INF file.</p>
+</div>
+
+</div>
+
+
+ </div>
+</body>
+</html>
diff --git a/description/84ada392-ed9e-43d3-9c3e-f99f948be6cbBrand.css b/description/84ada392-ed9e-43d3-9c3e-f99f948be6cbBrand.css
new file mode 100644
index 0000000..982a368
--- /dev/null
+++ b/description/84ada392-ed9e-43d3-9c3e-f99f948be6cbBrand.css
@@ -0,0 +1,245 @@
+/*Global*/
+h1 {
+ font-size: 36px;
+ font-family: 'Segoe UI Light';
+ color: #707070;
+ font-weight: normal;
+ margin-bottom: 17px !important;
+}
+
+h2, h3, h4, h5, h6, #searchPage h3 {
+ font-family: 'Segoe UI', 'Lucida Grande', Verdana, Arial, Helvetica, sans-serif !important;
+ font-weight:normal;
+ color: #2A2A2A !important;
+}
+
+a, a:link, a:visited {
+ color: #0095c4;
+}
+
+body {
+ color:#707070;
+}
+
+.profile-usercard {
+ color:#707070 !important;
+}
+
+/*temporary setting to override msdn_windows.css
+can remove once conflicting settings are removed from that file*/
+
+
+.LocalNavigation, .LocalNavigation .TabOn, .LocalNavigation .TabOn:hover, .LocalNavigation .TabOff, .LocalNavigation .TabOff a:hover {
+ display: block;
+ background-color:transparent !important;
+ color: #0095c4;
+}
+
+.LocalNavigation .TabOff a {
+color:#707070 ;
+}
+
+/*End Global*/
+
+.EyebrowContainer
+{
+ margin-bottom: 0 !important;
+}
+
+#sideNav
+{
+ width: 215px !important;
+}
+
+#searchPage #mainContentContainer
+{
+ margin-right:0 !important;
+ margin-left:243px !important;
+}
+
+#searchPage .dirSubHeading h2
+{
+ font-size:1.1em !important;
+}
+
+#searchPage h2, #searchPage h3
+{
+ font-size: 1.25em !important;
+}
+
+#sideNav #contributeSection h3, .sidebar #contributeSection h3, #contributeSection h3
+{
+ font-size: 1.65em !important;
+}
+.subMenu > h2
+{
+ font-family: 'Segoe UI Light','Segoe UI', 'Lucida Grande', Verdana, Arial, Helvetica, sans-serif !important;
+ font-weight:normal;
+ font-size:30px;
+ margin: 15px 10px 5px 0;
+ padding-bottom:0px;
+}
+
+.itemRow {
+}
+ .itemRow .itemTitle {
+ font-weight: normal;
+ }
+ #MainContent a.officialMicrosoftLabel
+ {
+ color: #ACACAC;
+ }
+.
+.tabContents {
+ border-top-width:0px;
+}
+
+#UploadPage {
+ margin: 0px 0px 0px 10px;
+}
+ #UploadPage h1 {
+ padding: 0;
+ font-size: 22px;
+ }
+ #UploadPage h2 {
+ color:#F39700 !important;
+ }
+
+ #UploadPage #uploadPageInstruction {
+ margin-top:10px;
+ }
+
+ #UploadPage fieldset {
+ margin-left:0px;
+ }
+
+ #UploadPage fieldset h2 {
+ font-weight:normal;
+ }
+
+ #UploadPage fieldset#uploadsForm{
+ margin-top:25px;
+ }
+
+ #UploadPage fieldset#summary textarea {
+ margin-left:0px;
+ }
+
+
+#sideNav {
+}
+
+ #sideNav .section h3 {
+ background-color: transparent;
+
+ }
+
+ #sideNav .section UL LI {
+ border-bottom-width: 0px;
+ }
+
+ #sideNav .section form > div {
+ border-bottom: none;
+ color: #707070;
+ }
+ #sideNav .section ul li > div.itemCount
+ {
+ color: #707070;
+ }
+
+
+#searchPage {
+}
+
+ #searchPage h2, #searchPage h3 {
+ text-transform:none;
+ background-color:transparent;
+ font-weight:normal;
+ font-size:1.2em;
+ }
+
+ #searchPage .browseFilterBar {
+ background-color:transparent;
+ border-width:0px;
+ font-weight:normal;
+ }
+
+#requestsPage {
+ padding-top:15px;
+}
+
+ #requestsPage .tabHeaders {
+ overflow: visible;
+ }
+
+ #requestsPage #requestsList {
+ border: none;
+ }
+
+ #requestsPage h2, #requestsPage h3 {
+ text-transform:none;
+ background-color:transparent;
+ font-weight:normal;
+ font-size:1.2em;
+ }
+
+#extraActions {
+}
+ #extraActions .section
+ {
+ margin-bottom: 10px;
+ }
+ #extraActions .section a
+ {
+ font-weight:normal;
+ }
+
+ #extraActions #contributeSection div img {
+ width:0px;
+ }
+
+
+#projectPage {
+}
+
+ #projectPage .projectTitle {
+ color: #707070;
+ margin: 5px 0px 15px 0px;
+ }
+
+ #projectPage #publishBar a, #projectPage #publishBar a:visited {
+ color: #0095c4;
+ font-weight: normal;
+ }
+
+ #projectPage #Collections .bevelButton{
+ background-color: #F8F8F8;
+ color: #0095C4;
+ border: 1px solid #707070;
+ }
+
+ #projectPage #DiscussionsTabPane .threadHeader .title {
+ font-weight:bold !important;
+ color:Black !important;#F8F8F8;
+ font-family: 'Segoe UI', 'Lucida Grande', Verdana, Arial, Helvetica, sans-serif !important;
+ }
+
+ #projectPage .sidebar .section .titleBar h3 {
+ font-weight:normal;
+ font-size:1.2em;
+ }
+
+#LocalNav {
+}
+
+ #LocalNav.HeaderTabs {
+ margin-left:11px;
+ }
+
+#searchPage .dirSubHeading h1
+{
+ margin-bottom:17px !important;
+}
+
+
+
diff --git a/description/Brand.css b/description/Brand.css
new file mode 100644
index 0000000..9a1b7bb
--- /dev/null
+++ b/description/Brand.css
@@ -0,0 +1,3625 @@
+#BodyBackground
+{
+ min-width:0px;
+}
+
+#JelloExpander, .IE7 #JelloExpander, .IE8 #JelloExpander, .IE9 #JelloExpander
+{
+ padding-left:0px;
+ padding-right:0px;
+}
+
+#JelloSizer
+{
+ margin: 0 auto;
+ max-width: 0px;
+ padding: 0;
+ width: 100%;
+}
+
+/* Global Styles */
+body
+{
+ font-size:0.75em;
+}
+
+h1
+{
+ font-size: 3em;
+ font-family: 'Segoe UI Light','Segoe UI', 'Lucida Grande', Verdana, Arial, Helvetica, sans-serif;
+ color: #707070;
+ font-weight: normal;
+ padding-top:4px;
+ margin-bottom: 17px;
+ line-height: 1.3;
+ font-weight:100;
+}
+
+h2, h3, h4, h5, h6
+{
+ font-family: 'Segoe UI', 'Lucida Grande', Verdana, Arial, Helvetica, sans-serif;
+ color:#2a2a2a;
+ font-weight:normal;
+}
+
+a, a:link, a:visited {
+ color: #00749E;
+}
+a:hover {
+ color: #0095c4;
+ text-decoration:none;
+}
+
+/*---------- Masthead -----------*/
+
+.NetworkLogo a {
+ display: none;
+}
+
+/*-------- Start Advertisment --------*/
+
+.advertisment {
+ padding-top:5px;
+}
+
+/*-------- End Advertisment --------*/
+
+
+/*-------- Start LocalTabs Page --------*/
+#GalleriesNavigation {
+ float: right;
+}
+
+.LocalNavigation
+{
+ display:block;
+ overflow: auto;
+ width: auto;
+}
+ .LocalNavigation .HeaderTabs {
+ width: auto;
+ }
+ .LocalNavigation .TabOff a {
+ color:#333;
+ }
+
+ .LocalNavigation .TabOff a:hover {
+ background-color:#E0E7EC;
+ margin-top: 1px;
+ padding: 4px 6px;
+ }
+
+ .LocalNavigation #notificationLink span {
+ color:Red;
+ font-weight:bold;
+ }
+
+
+/*-------- End LocalTabs Page --------*/
+
+/*-------- Start SubMenu Page --------*/
+
+.subMenu
+{
+ margin: 0 0 10px 0;
+ color: #FFFFFF;
+ overflow: hidden;
+}
+
+.subMenu a, .subMenu span
+{
+ margin: 5px 5px 0 5px;
+}
+
+.subMenu > h2
+{
+ float: left;
+ margin: 7px 15px 0 0;
+ vertical-align: middle;
+ color: #666;
+ padding-bottom: 5px;
+}
+
+.subMenu .advancedSearchLink
+{
+ float: left;
+ margin: 9px 0 0 15px;
+}
+
+
+
+.subMenu .uploadLink
+{
+ float: right;
+ margin: 5px 5px 0 0;
+ padding: 0 0 0 30px;
+ height: 24px;
+ background: url('../Common/smalluploadicon.png') no-repeat 10px 0;
+ color: #0066E1;
+ cursor: pointer;
+}
+
+.subMenu #searchBoxContainer
+{
+ float: left;
+ width: 400px;
+ padding: 3px 50px;
+}
+
+/*-------- End SubMenu Page --------*/
+
+/*-------- Start SearchBox --------*/
+
+div.searchbox
+{
+ overflow:auto;
+ width:450px;
+ margin:26px 0 14px 0;
+}
+
+.srchbox
+{
+ width: 100%;
+ background: #FFFFFF;
+ padding: 0px 2px;
+ height: 25px;
+ border: 1px solid #ccc;
+ table-layout: auto;
+ margin-bottom:5px;
+}
+
+
+
+.srchbox #searchImageCell input
+{
+ background: transparent url('searchButton.png') no-repeat 0 0;
+ width: 20px;
+ height: 20px;
+ padding-left: 1px;
+ margin-top: 3px;
+}
+
+
+.srchbox #searchImageCell
+{
+ text-align: right;
+ padding: 0px;
+ vertical-align: middle;
+}
+
+.IE7 .srchbox #searchImageCell
+{
+ padding:2px 2px 0 0;
+}
+
+.srchbox #searchImageCell input
+{
+}
+
+
+table.srchbox
+{
+ table-layout: fixed;
+}
+
+.srchbox .stxtcell
+{
+ padding-right: 4px;
+ width:90%;
+}
+
+.srchbox .stxtcell > input
+{
+ margin-right: 4px;
+ height: 26px;
+ line-height:26px;
+ width: 100%;
+ padding: 0px;
+ padding-left: 4px;
+ padding-top: 2px;
+ border: none;
+ font-style: normal !important;
+ outline: none;
+}
+
+.IE7 .srchbox .stxtcell > input
+{
+ height: 20px;
+}
+
+.srchbox .stxtcell > input.stxtinptpassive
+{
+ color: #AAA;
+ font-style: normal !important;
+}
+
+/*-------- End SearchBox --------*/
+
+
+/*-------- Start Search Page --------*/
+
+
+#searchPage #mainContentContainer
+{
+ margin: 0 0 0 243px;
+}
+
+#searchPage .browseFilterBar, #dashboardPage .browseFilterBar
+{
+ padding: 5px 0 6px 0;
+
+}
+
+ #searchPage .browseFilterBar a, #dashboardPage .browseFilterBar a
+ {
+ font-weight:normal;
+ }
+
+ #searchPage .browseFilterBar .browseSort, #dashboardPage .browseFilterBar .browseSort
+ {
+ float:right;
+ }
+
+ #searchPage .browseBreadcrumb
+ {
+ padding-top:3px;
+ }
+
+ #searchPage .browseFilterBar .browseSort select, #dashboardPage .browseFilterBar .browseSort select
+ {
+ height:20px;
+ }
+
+ #searchPage .browseFilterBar .browseSort img, #dashboardPage .browseFilterBar .browseSort img
+ {
+ vertical-align:text-top;
+ }
+
+#searchPage h2, #searchPage h3
+{
+ font-size: 1.25em;
+ padding: 2px 0 3px 3px;
+}
+
+#searchPage h2
+{
+ display:inline;
+ clear:none;
+}
+
+ #dashboardsearchbox
+ {
+ width:420px;
+ margin:0;
+ float:left;
+ }
+
+/*-------- End Search Page --------*/
+
+/*-------- Begin Requests Page --------*/
+
+#requestsPage {
+ color:#666;
+}
+
+ #requestsPage h1 {
+ clear:none;
+ }
+ #requestsPage h2, #requestsPage h3
+ {
+ font-size: 1.25em;
+ }
+
+ #requestsPage h2
+ {
+ display:inline;
+ clear:none;
+ }
+
+ #requestsPage h3
+ {
+ padding: 2px 0 3px 3px;
+ }
+
+ #requestsPage #mainContentContainer
+ {
+ margin: 0 0 0 243px;
+ }
+
+ #requestsPage #mainContentWrapper {
+ float:left;
+ width:100%;
+ }
+ #requestsPage #mainContent {
+ position:relative;
+ }
+
+ #requestsPage #mainContent .subtitle{
+ margin-bottom:5px;
+ }
+
+ #requestsPage #requestsFilterBar {
+ margin-top: 10px;
+ overflow: auto;
+ }
+
+ #requestsPage #requestsFilterBar .requestsCrumb {
+ float: left;
+ margin:10px 0 10px 10px;
+ }
+ #requestsPage #requestsFilterBar .requestsSort {
+ float: right;
+ margin:10px 0 10px 0;
+ }
+
+ #requestsPage #Pager {
+ text-align: center;
+ padding-top: .75em;
+ padding-bottom: .75em;
+ }
+
+ #requestsPage #requestsRss {
+ float: right;
+ margin: 2px 0 0 3px;
+ cursor: pointer;
+ }
+
+ .IE7 #requestsPage #requestsList {
+ padding-top: 10px;
+ margin-top:5px;
+ }
+
+ #requestsPage #requestsList .noResults {
+ padding: 10px 0;
+ }
+
+
+/*-------- End Requests Page --------*/
+
+/*-------- Begin Request List Item --------*/
+.requestlistitem td
+{
+ padding: .9em 0 .9em .5em;
+}
+ .requestlistitem .votebox
+ {
+
+ text-align:center;
+ }
+
+ .requestlistitem .voteboxcontainer
+ {
+ vertical-align:top;
+ width: 75px;
+ }
+
+ .requestlistitem #votelabel
+ {
+ border-width:1px;
+ border-bottom-style:solid;
+ }
+
+ #myRequestsTab #votenumber,
+ #requestsPage #votenumber
+ {
+ background-color: #777;
+ padding: 6px 10px;
+ color: #fff;
+ margin-bottom: 5px;
+ font-size: 1.6em;
+ }
+
+ #myRequestsTab .votelink,
+ #requestsPage .votelink
+ {
+ font-weight:bold;
+ background-color: #eee;
+ padding: 5px 0;
+ width: 75px;
+ float: left;
+ }
+
+ #myRequestsTab .needvote,
+ #requestsPage .needvote
+ {
+ font-weight:bold;
+ }
+
+ #myRequestsTab .alreadyvoted, #myRequestsTab .resolved
+ #requestsPage .alreadyvoted, #requestsPage .resolved
+ {
+ font-weight:bold;
+ color: #666;
+ }
+
+ .requestlistitem .linkform
+ {
+ width:100%;
+ float:right;
+ margin-top:15px;
+ }
+
+ .requestlistitem .requesttitle
+ {
+ font-weight:600;
+ margin-bottom:3px;
+ }
+
+ .requestlistitem .requester
+ {
+ margin-bottom:3px;
+ }
+
+ .requestlistitem .hidden
+ {
+ display:none;
+ }
+
+ .requestlistitem .requestSummary div
+ {
+ margin-bottom:0.25em;
+ }
+
+ .requestlistitem .requestSummary
+ {
+ line-height: 1.45em;
+ width: 80%;
+ }
+ .requestlistitem .requestInfo
+ {
+ padding:1.2em 0 0 2.5em;
+ vertical-align:top;
+ width:15%;
+ line-height: 1.45em;
+ }
+
+ .requestlinks > td
+ {
+ padding-bottom: 16px;
+ }
+
+ .requestlinks div
+ {
+ float:right;
+ }
+
+ .requestlistitem .textbox
+ {
+ width:95%;
+ }
+
+
+
+/*-------- End Request List Item --------*/
+
+
+/*-------- Begin New Request Form --------*/
+#newrequest {
+ margin-top:5px;
+ background:#F8F8F8;
+ border-width:1px;
+ border-style:solid;
+ border-color:#E8E8E8;
+ padding:5px;
+}
+
+#newrequest > div:first-child {
+ font-weight:bold;
+}
+
+#newrequest .itemheading {
+ margin-top:5px;
+}
+
+#newrequest textarea {
+ width:95%;
+}
+
+#newrequest .field-validation-error {
+ display:block;
+ color:Red;
+ font-weight:bold;
+}
+#newrequest #submit {
+ margin-top:5px;
+}
+
+/*-------- End New Request Form --------*/
+
+/*-------- Request Description Page ------*/
+
+.reqDescPage #mainContent {
+ overflow: auto;
+}
+.reqDescPage #header {
+ float: left;
+ width: 100%;
+}
+
+.reqDescPage {
+ color: #000 !important;
+}
+
+.reqDescPage #sideNav {
+ background-color: #fff;
+}
+
+.reqDescPage #header #votenumber {
+ width: 50px;
+ padding: 6px 12px;
+ text-align: center;
+ float: left;
+}
+
+.reqDescPage #header .requestTitle {
+ margin: 0 0 5px 10px;
+ float: left;
+ width: 85%;
+}
+
+.reqDescPage #header .requestTitle h1 {
+ margin-bottom: 0px;
+ font-size: 2em;
+}
+
+.reqDescPage #headerLinks {
+ float: left;
+ margin-bottom: 15px;
+}
+
+.reqDescPage #headerLinks .votelink
+{
+ text-align: center;
+ float: left;
+}
+
+#requestsPage #headerLinks .assignlink
+{
+ font-weight:bold;
+ background-color: #eee;
+ padding: 5px 10px;
+ float: left;
+ margin-left: 10px;
+}
+
+.reqDescPage #projectInfo {
+ clear: both;
+}
+
+.reqDescPage #solutions {
+ clear: both;
+ padding-top: 30px;
+}
+
+.reqDescPage .solutionItems {
+ clear: both;
+}
+
+.reqDescPage .solutionHeader {
+ border-bottom: 1px solid #ccc;
+}
+
+.reqDescPage .solutionAddContainer {
+ padding-top: 15px;
+ float: left;
+}
+
+.reqDescPage #SubmittedProjectLinkUrl {
+ width: 400px;
+}
+
+.reqDescPage .solutionItem {
+ margin-top: 25px;
+ padding: 0 5px 5px 0;
+ float: left;
+}
+.reqDescPage .solutionItemDetails {
+ float: left;
+ width: 535px;
+}
+
+.reqDescPage .solutionItemLinks {
+ margin-top: 10px;
+ clear: both;
+ float: left;
+ width: 100%;
+}
+
+.reqDescPage .solutionItemLinks a {
+ float: left;
+ margin-right: 10px;
+ font-weight:bold;
+ background-color: #eee;
+ padding: 5px 10px;
+}
+
+.reqDescPage .solutionItem .itemTitle {
+ font-size: 1.2em;
+ padding-bottom: 5px;
+}
+
+.reqDescPage .tagsContainer label {
+ display: none;
+}
+
+.reqDescPage .solutionItem .summaryBox {
+ padding: .25em 0 .25em 0;
+ clear: both;
+ line-height: 1.45;
+}
+
+.reqDescPage .solutionsection {
+ float: left;
+ margin-left: 20px;
+}
+.reqDescPage .completedSolution {
+ font-size: 1.25em;
+ padding-top: 4px;
+}
+
+.reqDescPage .requestDescriptionCont, .reqDescPage .requestDicussions {
+ padding-top: 30px;
+ clear: both;
+ overflow: auto;
+}
+
+.reqDescPage .requestDescription {
+ padding-top: 10px;
+ line-height: 1.45;
+}
+
+.reqDescPage .requestDicussionsAsk {
+ padding: 10px 0;
+}
+
+.reqDescPage .watermark {
+ color:Gray;
+ }
+
+
+/*-------- Begin Extra Actions Section --------*/
+#extraActions
+{
+ float: right;
+ width: 300px;
+ vertical-align: top;
+}
+
+ #extraActions .section
+ {
+ padding: 0 0 10px 0;
+ overflow:auto;
+ }
+
+ #extraActions .section a
+ {
+ font-weight:bold;
+ }
+/*-------- End Extra Actions Section --------*/
+
+/*-------- Begin Contribute --------*/
+
+
+#contributeSection a
+{
+ font-size:1.1em;
+}
+
+#contributeSection, #sideNav #contributeSection h3, .sidebar #contributeSection h3, #contributeSection h3
+{
+ background-color:#fff;
+ margin: 0 0 9px 0;
+ padding-left: 0px;
+}
+
+#sideNav #contributeSection h3, .sidebar #contributeSection h3, #contributeSection h3
+{
+ font-size:1.65em;
+ margin-top:42px;
+}
+
+#sideNav #contributeSection, #contributeSection
+{
+ padding:0 0 41px 0;
+}
+
+#projectPage .sidebar #contributeSection
+{
+ margin: 10px 0 10px 0;
+ padding:0 0 5px 0;
+
+}
+
+#sideNav #contributeSection > div, .sidebar #contributeSection > div, #contributeSection > div
+{
+ padding: 0 0 2px 0;
+ overflow:auto;
+}
+
+#sideNav #contributeSection img, #contributeSection img
+{
+ float: left;
+ width: 25px;
+}
+
+#sideNav #contributeSection .contributeAction, .sidebar #contributeSection .contributeAction, #contributeSection .contributeAction
+{
+ padding:17px 0 0 0;
+}
+
+ #contributeSection .contributeAction img
+ {
+ background-color:#00749e;
+ margin-right:9px;
+ }
+
+ #contributeSection .contributeAction img:hover
+ {
+ background-color:#0095C4;
+ }
+
+ #contributeSection .contributeAction a
+ {
+ display:block;
+ line-height: 1.8;
+ }
+
+#uploadLink, #exclamationLink, #myContributionsLink
+{
+ display:block;
+ line-height: 1.8;
+}
+
+#myContributionsLink span
+{
+ color: red;
+}
+
+#feedbackLink
+{
+ background: url("FeedbackIcon.png") no-repeat;
+ width: 40px;
+ height: 40px;
+}
+
+.itemRow .affiliationLink, #editorPicksSection .affiliationLink
+{
+ background: url("../common/MicrosoftLogo.png") no-repeat;
+ width: 82px;
+ height: 18px;
+}
+
+
+#contributeSection a+div
+{
+
+}
+
+.IE7 #contributeSection a+div
+{
+ float:left;
+}
+/*-------- End Contribute --------*/
+
+
+/*-------- Begin Directory List Footer --------*/
+
+#directoryListFooter {
+ padding:5px;
+ margin-top:10px;
+ margin-bottom:10px;
+ border:1px solid #E6E6E6;
+ background-color:#F8F8F8;
+ width:438px;
+}
+
+#directoryListFooter h4
+{
+ font-size:1em;
+}
+
+/*-------- End Directory List Footer --------*/
+
+/*-------- Begin Editors Picks --------*/
+#editorPicksSection ul
+{
+ padding-left:0px;
+ line-height:135%;
+}
+
+ #editorPicksSection ul li
+ {
+ clear: left;
+ padding-top: 10px;
+ list-style:none;
+ }
+ #editorPicksSection ul li:first-child {
+ padding-top: 0;
+ }
+
+ #editorPicksSection a {
+ font-weight: normal !important;
+ }
+
+ #editorPicksSection ul li .thumbnail
+ {
+ float: left;
+ padding: 3px;
+ max-width: 60px;
+ }
+
+ #editorPicksSection ul li .thumbnail img {
+ max-width: 60px;
+ }
+/*-------- End Editors Picks --------*/
+
+/*-------- Begin Side Nav Section --------*/
+
+#sideNav
+{
+ width: 215px;
+ margin-left: 0;
+ vertical-align: top;
+ float: left;
+}
+
+ #sideNav #sideNavHeader
+ {
+ margin-bottom: 10px;
+ padding-left: 12px;
+ }
+
+ #sideNav #sideNavHeader a
+ {
+ margin-right:3px;
+ }
+
+ #sideNav .section
+ {
+ padding: 0 10px 18px 10px;
+ }
+ #sideNav .section h3
+ {
+
+ padding: 2px 0 3px 3px;
+ }
+
+ #sideNav .section ul
+ {
+ }
+
+ #sideNav .section ul li
+ {
+ padding: 4px 0 2px;
+ margin-left: 3px;
+ margin-right: 3px;
+ }
+
+
+ #sideNav .section form > div
+ {
+ padding: 4px 0 0 0;
+ border-bottom: none;
+ margin: 0 3px 0 3px;
+ color: #3A3E43;
+ }
+ .IE8 #sideNav .section ul li > div.itemText
+ {
+ word-wrap: break-word;
+ width: 225px;
+ }
+ #sideNav .section ul li > div.itemCount
+ {
+ color: #3A3E43;
+ }
+ #sideNav .section a
+ {
+ font-weight: normal;
+ }
+
+ #sideNav .section a:hover
+ {
+ text-decoration: underline;
+ }
+
+/*-------- End Side Nav Section --------*/
+
+
+
+/*-------- Start Dashboard Page --------*/
+
+#dashboardPage {
+ padding-top:5px;
+ clear:both;
+}
+#dashboardPage .contributions .tabContents {
+ padding: 5px 5px 10px 0;
+ clear:both;
+}
+ #dashboardPage .contributions .noContributions {
+ clear:both;
+ }
+#dashboardPage #mainContentWrapper {
+ float:left;
+ width:100%;
+}
+
+#dashboardPage #detailsSection {
+ float:left;
+ margin-left:-100%;
+ width:240px;
+ padding: 0 0 18px 10px;
+}
+
+.IE7 #dashboardPage #detailsSection {
+ width:auto;
+ min-width: 300px;
+ max-width: 300px;
+}
+.IE7 #dashboardPage #detailsSection .itemBar {
+ width: 270px;
+}
+
+#dashboardPage #detailsSection h3 {
+ word-wrap:break-word;
+}
+
+#dashboardPage #mainContent {
+ margin:0 0 0 250px;
+ position:relative;
+}
+
+#dashboardPage .dashboardEvenRow
+{
+ background-color: #ececec;
+}
+#dashboardPage .dashboardPadding
+{
+ padding-bottom: 4px;
+}
+#dashboardPage .dashboardCell
+{
+ width: 100%;
+ vertical-align: top;
+ padding: 1em 0.5em 0.5em 0.5em;
+}
+#dashboardPage .projectManagement
+{
+ width: 24em;
+ padding: 0em 1em 0em 1em;
+ vertical-align: top;
+ text-align: right;
+ float: right;
+}
+
+#dashboardPage #subscriptionsLink
+{
+ position:absolute;
+ right:5px;
+}
+
+#dashboardPage .itemDelete
+{
+ vertical-align:top;
+ padding-top:.8em;
+ width:30px;
+}
+
+#dashboardPage .itemDeleteText
+{
+ border-style:solid;
+ border-width:thin;
+ border-collapse:collapse;
+ padding-bottom:2px;
+ padding-left:4px;
+ padding-right:4px;
+ color:Gray
+}
+
+#dashboardPage #myRequestsTab .requestTabHeaders
+{
+ font-weight:normal;
+ border-bottom: solid 1px #CCC;
+ padding-bottom: 10px;
+ padding-top: 10px;
+ float: left;
+ width: 100%;
+}
+
+#dashboardPage #myRequestsTab .requestTabHeaders div:first-child
+{
+ border: 0;
+}
+
+#dashboardPage #myRequestsTab .requestTabHeaders div
+{
+ padding: 2px 9px 3px 9px;
+ font-size: 0.9em;
+ line-height: 125%;
+ color:#00749E;
+ border-left: solid 1px #555;
+ cursor: pointer;
+ float: left;
+ text-align: center;
+}
+
+#dashboardPage #myRequestsTab .requestTabHeaders div.currentRequest
+{
+ background-color:#fff;
+ cursor: default;
+ border-bottom:none;
+ margin-bottom:-2px;
+ color:#000;
+}
+
+#dashboardPage #myRequestsTab .requestTabHeaders div.currentRequest a {
+ color: #000;
+}
+
+
+#dashboardPage #myRequestsTab .requestTabHeaders div a
+{
+ text-decoration:none;
+}
+
+#dashboardPage #myRequestsTab .requestTabContents
+{
+ clear: both;
+}
+
+#dashboardPage #myRequestsTab .requestTabContents .noResults {
+ padding-top: 20px;
+}
+
+/*-------- End Dashboard Page --------*/
+
+/*-------- Start Upload Page --------*/
+
+#UploadPage
+{
+ margin-left:10px;
+ max-width:925px;
+}
+
+ #UploadPage .watermark {
+ color:Gray;
+ }
+
+ #UploadPage .projectTypeChoice {
+ }
+
+ #UploadPage .projectTypeChoice > div {
+ padding: 20px 10px 20px 10px;
+ border: 1px solid darkgrey;
+ cursor: pointer;
+ height: 200px;
+ float: left;
+ }
+
+ #UploadPage .projectTypeChoice > div + div
+ {
+ margin: 0 0 0 5px;
+ }
+
+ #UploadPage .projectTypeChoice div.current
+ {
+ background-color: #E9E9E9;
+ cursor: default;
+ }
+
+ #UploadPage .projectTypeChoice div.choice {
+ font-size: large;
+ font-weight: bold;
+ padding: 0 0 10px 0;
+ }
+
+ #UploadPage .projectTypeChoice div.description {
+ padding: 0 0 0 17px;
+ }
+
+ #UploadPage .projectTypeChoice #genericSampleUploadDescription {
+ padding-top: 5px;
+ }
+
+ #UploadPage .projectTypeChoice #genericSampleUploadDescription .logos {
+ overflow: auto;
+ }
+
+ #UploadPage .projectTypeChoice #genericSampleUploadDescription .vslogo {
+ background: url(../samples/vslogo.png) no-repeat;
+ width: 125px;
+ height: 18px;
+ }
+
+ #UploadPage .projectTypeChoice #genericSampleUploadDescription .javalogo {
+ background: url(../samples/javalogo.png) no-repeat;
+ width: 33px;
+ height: 60px;
+ float: left;
+ }
+
+ #UploadPage .projectTypeChoice #genericSampleUploadDescription .phplogo {
+ background: url(../samples/phplogo.png) no-repeat;
+ width: 65px;
+ height: 35px;
+ float: left;
+ margin: 15px 0 0 10px;
+ }
+
+ #UploadPage .projectTypeChoice #genericSampleUploadDescription .nodejslogo {
+ background: url(../samples/nodejslogo.png) no-repeat;
+ width: 90px;
+ height: 25px;
+ float: left;
+ margin: 18px 0 0 10px;
+ }
+
+ #UploadPage .projectTypeChoice #genericSampleUploadDescription > div+div {
+ margin-top: 10px;
+ }
+
+ #UploadPage .projectTypeContents {
+ clear: left;
+ padding: 10px 0 0 0;
+ }
+
+ #UploadPage .projectTypeContents .instruction > div+div {
+ padding-top: 5px;
+ }
+ #UploadPage #libraryContainer {
+ margin: 5px 0 0 0;
+ display: none;
+ }
+ #UploadPage fieldset
+ {
+ margin: 10px 0 30px 5px;
+ }
+
+ #UploadPage fieldset > *
+ {
+ margin-left:10px;
+ }
+
+ #UploadPage .fieldsetStyleContainer {
+ margin: 10px 0 0 5px;
+ }
+
+ #UploadPage fieldset h2,
+ #UploadPage .fieldsetStyleContainer h2
+ {
+ font-family: 'Segoe UI Semibold','Segoe UI','Lucida Grande',Verdana,Arial,Helvetica,sans-serif;
+ font-size: 17px;
+ font-weight: bold;
+ color: #3A3E43;
+ border-bottom: 2px solid #EFEFEF;
+ width: 100%;
+ padding-bottom: 3px;
+ margin-left:0px;
+ margin-bottom:8px;
+ }
+
+ .IE7 #UploadPage fieldset h2,
+ .IE7 #UploadPage .fieldsetStyleContainer h2
+ {
+ margin-left:-10px;
+ }
+
+ #UploadPage fieldset .field-validation-error
+ {
+ clear:left;
+ display:block;
+ margin-top:4px;
+ }
+
+ #UploadPage fieldset .required
+ {
+ margin-left: 3px;
+ }
+
+ #UploadPage fieldset .instruction,
+ #UploadPage .fieldsetStyleContainer .description,
+ #UploadPage .fieldsetStyleContainer .instruction
+ {
+ color: #3A3E43;
+ margin:0 0 10px 0;
+ }
+
+ #UploadPage fieldset .faqLink
+ {
+ margin: 0 0 10px 0;
+ }
+
+ #UploadPage fieldset label
+ {
+ display:block;
+ }
+
+ #UploadPage fieldset input[type=text]
+ {
+ width:60%;
+ }
+
+ #UploadPage fieldset input[type=checkbox]
+ {
+ float:left;
+ clear:left;
+ margin-right:5px;
+ }
+
+ #UploadPage fieldset input[type=radio]
+ {
+ float:left;
+ clear:left;
+ margin-right:5px;
+ }
+
+ #UploadPage fieldset#richDescription textarea
+ {
+ width:70%;
+ height:600px;
+ }
+
+ #UploadPage fieldset#summary textarea
+ {
+ width:60%;
+ height:100px;
+ margin-top: 10px;
+ margin-left: -30px;
+ }
+
+ .IE #UploadPage fieldset#summary textarea, .IE9 #UploadPage fieldset#summary textarea
+ {
+ margin-left: -30px;
+ overflow: auto;
+ }
+
+ .FF #UploadPage fieldset#summary textarea
+ {
+ margin-left: -30px;
+ }
+
+ #UploadPage fieldset#summary #SummaryReadOnly
+ {
+ width:60%;
+ margin-top: 10px;
+ padding-top: 5px;
+ color: #909082;
+ }
+
+ #UploadPage fieldset#summary #SummaryCharCount
+ {
+ width:60%;
+ text-align: right;
+ }
+
+ #UploadPage fieldset#options label
+ {
+ margin-bottom:10px;
+ }
+
+ #UploadPage fieldset#license label
+ {
+ margin-bottom:10px;
+ }
+
+ #UploadPage input[type="text"].tagInput, #UploadPage input[type="text"].listInput
+ {
+ width:40%;
+ float:left;
+ }
+
+ #UploadPage .addedTags, #UploadPage .addedProjects
+ {
+ margin-bottom:15px;
+ width: 500px;
+
+ }
+ #UploadPage .addedTags .tag, #UploadPage .addedProjects .projectTitle
+ {
+ position:relative;
+ overflow:hidden;
+ }
+
+ #UploadPage .addedTags .tag label, #UploadPage .addedProjects .projectTitle label
+ {
+ float:left;
+ width: 450px;
+ }
+
+ #UploadPage .addedTags .tag a, #UploadPage .addedProjects .projectTitle a
+ {
+ position:absolute;
+ text-align:right;
+ right:0px;
+ }
+
+ .fileManager .fileUploadProgressIndicator
+ {
+ width: 500px;
+ }
+
+ .fileManager .uploadProcessingWarning {
+ margin-top: 5px;
+ }
+
+ .fileManager .fileUploadProgressIndicator .throbber
+ {
+ font-weight: bold;
+ background: url('./progressIndicatorWhite.gif') no-repeat 10px 0;
+ padding: 7px 10px 5px 60px;
+ height: 25px;
+ margin-left: -10px;
+ }
+
+ .fileManager #uploadFrame, .fileManager .uploadFrame
+ {
+ width:100%;
+ }
+
+ .fileManager .addLabel + a
+ {
+ margin-left:25px;
+ }
+
+ .fileManager fieldset label {
+ display: block;
+ }
+
+ .fileManager .unlocalizedFiles {
+ color:#808080;
+ }
+
+ .fileManager .filesContainer
+ {
+ margin-bottom:15px;
+ width: 500px;
+
+ }
+
+ .fileManager .filesContainer .file
+ {
+ position:relative;
+ overflow:hidden;
+ }
+
+ .fileManager .filesContainer .file .title {
+ border-bottom: 1px solid #000000;
+ padding-bottom: 3px;
+ margin-top: 10px;
+ margin-bottom: 10px;
+ }
+
+ .fileManager .filesContainer .file .title .manageLinks
+ {
+ float: right;
+ }
+
+ .fileManager .filesContainer .file .version {
+ padding: 0 0 20px 10px;
+ }
+
+ .fileManager .filesContainer .file .version label {
+ float: left;
+ font-weight: bold;
+ }
+
+ .fileManager .filesContainer .file .version span {
+ float: left;
+ margin-left: 5px;
+ }
+
+ .fileManager .filesContainer .file .language {
+ clear: left;
+ padding: 0 0 5px 10px;
+ }
+
+ .fileManager .filesContainer .file .language label {
+ font-weight: bold;
+ }
+
+ .fileManager .filesContainer .file .language label + label {
+ font-weight: normal;
+ padding-left: 10px;
+ }
+
+ .fileManager .filesContainer .file .language div {
+ padding-left: 20px;
+ }
+
+ .file .requirements {
+ clear: left;
+ padding: 0 0 0 10px;
+ }
+
+ .file .requirements label {
+ font-weight: bold;
+ }
+
+ .file .requirements > div {
+ padding-left: 20px;
+ }
+
+ .file .requirements .requirementsContent {
+ padding-top: 5px;
+ padding-bottom: 10px;
+ }
+
+ .file .requirements .requirementsContent label {
+ font-style: italic;
+ font-weight: normal;
+ }
+
+ .file .requirements .requirementsContent > div
+ {
+ margin-bottom:4px;
+ position:relative;
+ }
+
+ .requirementsContent .requirementsRemove {
+ float:right;
+ position:absolute;
+ right:0px;
+ }
+
+ .requirements .requirementsAddError {
+ color:#ff0000;
+ }
+
+ .requirements .reqBrowseButton {
+ margin-left : 10px;
+ }
+
+ #UploadPage fieldset .requirements input[type="text"] {
+ margin-right: 10px;
+ width: 70%;
+ }
+
+ .reqBrowsefade
+ {
+ position: absolute;
+ background-color: #aaaaaa;
+ }
+ .reqBrowse
+ {
+ background-color: #f4f4f4;
+ border:1px solid #000000;
+ -border-radius: 5px;
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+ padding:15px;
+ position: absolute;
+ display: block;
+ }
+
+ .reqBrowsebuttons
+ {
+ text-align:right;
+ position:absolute;
+ right:10px;
+ bottom:5px;
+ }
+ .reqBrowsebuttons > button
+ {
+ color: Blue;
+ border: none;
+ background: none;
+ font-weight: bold;
+ cursor:pointer;
+ }
+
+ .reqBrowseclose
+ {
+ display:none;
+ }
+
+ .reqBrowseDialog
+ {
+ width: 700px;
+ clear:both;
+ overflow:hidden;
+ padding-bottom: 20px;
+ }
+
+ .reqBrowseDialog > h2
+ {
+ border-bottom: 1px solid #000000;
+ padding-bottom: 5px;
+ }
+ .reqBrowseDialog > p
+ {
+ margin: 15px 0 15px 0;
+ }
+
+ .reqBrowseSearchCont
+ {
+ width: 100%;
+ background: white;
+ padding: 0px 2px;
+ -moz-border-radius: 2px;
+ border-radius: 2px;
+ border: 1px solid #888;
+ margin-bottom: 5px;
+ height: 29px;
+ }
+ .reqBrowseSearchCont .rbboxcont
+ {
+ width:90%;
+ float:left;
+ margin-top: 2px;
+ }
+
+ .reqBrowseSearchCont input
+ {
+ border:none;
+ outline:none;
+ border-color: transparent;
+ }
+ .reqBrowseSearchBox
+ {
+ margin-right: 4px;
+ height: 20px;
+ line-height: 20px;
+ width: 100%;
+ padding-left: 4px;
+ padding-top: 2px;
+ }
+
+ .reqBrowseSearchBoxDefault
+ {
+ color: #AAA;
+ }
+ .reqBrowseSearchCont .rbbtncont
+ {
+ float: right;
+ margin-top: 4px;
+ }
+ .reqBrowseSearchBtn
+ {
+ background: transparent url('searchButton.png') no-repeat 0 0;
+ width: 22px;
+ height: 22px;
+ float:left;
+ cursor:pointer;
+ }
+
+ .reqBrowseTabs
+ {
+ border-bottom: 5px solid #E8E8E8;
+ margin:3px 0;
+ overflow:auto;
+ }
+
+ .reqBrowseTabs .reqBrowseTabsR
+ {
+ color:#fff !important;
+ }
+
+ .reqBrowseTabs .reqBrowseTabsHighlight
+ {
+ color:#000 !important;
+ background-color:#E8E8E8;
+ }
+
+ .reqBrowseTabs a
+ {
+ padding:5px 12px;
+ color:#fff;
+ background-color:#888;
+ font-weight:bold;
+ float:left;
+ margin: 0 4px 0px 0;
+ }
+
+ .reqBrowsePager td
+ {
+ text-align:center;
+ }
+ .reqBrowseDialog #Pager
+ {
+ margin: 5px 0 15px 0;
+ }
+
+ .reqBrowseContent
+ {
+ height:310px;
+ overflow:auto;
+ clear:both;
+ position:relative;
+ }
+
+ .reqBrowsePager
+ {
+ width:700px;
+ margin:0 auto;
+ }
+
+ .reqBrowseContentError
+ {
+ color:#ff0000;
+ margin:5px;
+ }
+ .reqBrowseContent .requirementItem
+ {
+ border-bottom: 2px solid #E8E8E8;
+ padding: 4px 0 6px 0;
+ overflow:auto;
+ }
+ .reqBrowseContent .section1
+ {
+ float:left;
+ width:75%;
+ padding-left:25px;
+ position:relative;
+ }
+
+ .reqBrowseContent .section1 input
+ {
+ position:absolute;
+ left:0px;
+ }
+
+ .reqBrowseContent .title
+ {
+ font-weight:bold;
+ }
+ .reqBrowseContent .section2
+ {
+ float:right;
+ }
+
+
+ .progressIndicatorfade
+ {
+ position: absolute;
+ background-color: #FFFFFF;
+ }
+ .progressIndicator
+ {
+ background-color: #f4f4f4;
+ border: 1px solid #000000;
+ -border-radius: 5px;
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+ padding: 15px;
+ position: absolute;
+ display: block;
+ max-width: 70%;
+ max-height: 70%;
+ }
+ #progressIndicator .progressIndicatorclose
+ {
+ display: none;
+ }
+
+ #progressIndicatorContent
+ {
+ font-weight: bold;
+ padding: 7px 10px 0 10px;
+ height: 25px;
+ }
+
+
+/*-------- End Upload Page --------*/
+
+/* ---
+ --- Homepage ---
+ --- */
+p
+{
+ margin: 0 0 1px 0;
+}
+#homePageHeader
+{
+ float: left;
+ margin-bottom: 1em;
+ width: 100%;
+}
+
+.tagline {
+ font-size: x-small;
+ position: relative;
+ top: -11px;
+}
+
+.logo
+{
+ float: left;
+ width: 455px;
+ height: 70px;
+ font-weight: bold;
+ font-size: 22px;
+ margin: 0 10px 0 0;
+ color: #3A3E43;
+}
+.logo > img
+{
+ float: right;
+}
+.logo > div
+{
+ color: #3A3E43;
+ font-weight: bold;
+ font-size: 22px;
+}
+
+.welcomeInfo
+{
+ float: left;
+ width: 700px;
+}
+.welcomeInfo h2
+{
+ font-size: 16px;
+}
+.welcomeInfo p
+{
+ margin: 5px 0 0 0;
+}
+
+#siteActions > div
+{
+ border: 1px solid #BBBBBB;
+ padding: 15px 5px 0 65px;
+ height: 55px;
+ background-repeat: no-repeat;
+ background-position: 10px 10px;
+}
+#siteActions a, #siteActions p
+{
+ margin-top: 5px;
+}
+
+#siteActions .label a
+{
+ font-size: 1.25em;
+ font-weight: bold;
+ margin-bottom: 3px;
+}
+
+#myGalleryBox
+{
+ background-image: url("MyGalleryIcon.png");
+}
+
+#findActions
+{
+ float: right;
+ padding: 10px;
+ width: 225px;
+ height: 50px;
+ border: 1px solid #BBBBBB;
+ margin: 0 10px 0 0;
+}
+
+#findBox div:first-child
+{
+ margin: 0 0 5px 0;
+ font-weight: bold;
+}
+
+#legalDisclaimer
+{
+ margin: 0 0 10px;
+ color: #798072;
+ font-size: 0.8em;
+}
+
+#siteActions
+{
+ float: right;
+ width: 200px;
+}
+#siteActions > div
+{
+ margin-bottom: 10px;
+}
+.homePageProjects
+{
+ width: 100%;
+ float: left;
+}
+.homePageProjects > div
+{
+ padding-left: 1.5em;
+}
+.homePageProjects > div:first-child
+{
+ padding-left: 0;
+}
+
+.homePageProjects .projectList ul
+{
+ padding: 0;
+ margin: 0;
+}
+.homePageProjects li
+{
+ margin-top: .5em;
+ padding-bottom: 0.5em;
+ list-style-type: none;
+}
+.homePageProjects .itemRow a, .homePageProjects .itemRow a:hover
+{
+ color: #0054A6;
+}
+
+.projectList > a:first-child
+{
+ margin-left: 1px;
+ float: right;
+}
+.projectList > a, .projectList > a:hover
+{
+ color: #5BAEDB;
+}
+.projectListTitle
+{
+ height: 27px;
+ font-size: 16px;
+ font-weight: bold;
+ line-height: 125%;
+ background: #E8E8E8;
+ padding: 5px 5px 5px 25px;
+}
+.homePageListPager
+{
+ text-align: right;
+ margin-bottom: -.5em;
+}
+
+.recentlyAddedProjects
+{
+ float: left;
+ width: 32%;
+}
+.mostPopularProjects
+{
+ float: right;
+ width: 32%;
+}
+.highestRankedProjects
+{
+ overflow: hidden;
+}
+* html .highestRankedProjects
+{
+ float: left;
+}
+* html .highestRankedProjects > div
+{
+ width: 100%;
+}
+
+#Pager
+{
+ text-align:left;
+}
+
+/* Impromptu warning style */
+.ipWarningfade
+{
+ position: absolute;
+ background-color: #aaaaaa;
+}
+div.ipWarning
+{
+ width: 400px;
+ position: absolute;
+ border-radius: 10px;
+ -moz-border-radius: 10px;
+ -webkit-border-radius: 10px;
+ padding: 20px 0 20px 20px;
+ background-color: #FCE5E6;
+ border: solid 2px #EE1F25;
+}
+.ipWarningcontainer
+{
+ font-weight: bold;
+}
+.ipWarningclose
+{
+ display: none;
+}
+.ipWarningmessage div
+{
+ position: relative;
+}
+.ipWarningmessage div div + div
+{
+ text-align: center;
+ padding-right: 20px;
+}
+.ipWarningmessage div div:first-child div
+{
+ margin-left: 50px;
+}
+.ipWarningmessage div div:first-child img
+{
+ position: absolute;
+ margin: -20px 0 0 0;
+ top: 35%;
+}
+.ipWarningbuttons
+{
+ text-align: center;
+ margin: 20px 0 0 0;
+}
+.ipWarning button
+{
+ padding: 4px 8px 4px 8px;
+ margin: 2px;
+ font-weight: bold;
+ border: solid 1px #A6A3A6;
+ color: #FFFFFF;
+ background: #B8BABC;
+ filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#B8BABC',EndColorStr='#949699');
+}
+
+#eyebrow
+{
+ width: 100%;
+}
+#siteMessage .unsupportedLocale {
+ margin: 10px 0 0 243px;
+ border: solid 1px #CCC;
+ background: #FCFEC5;
+ padding: 5px;
+}
+
+#Footer
+{
+ width: 100%;
+ height: auto;
+}
+
+.clear
+{
+ clear: both;
+}
+
+#buildVersion
+{
+ clear: both;
+ margin-left: auto;
+ margin-right: auto;
+ padding-right: 26px;
+ padding-top: 8px;
+ text-align: right;
+}
+
+#page
+{
+ clear: both;
+ padding-top: 10px;
+}
+
+#page h1
+{
+ padding: 10px 0px;
+}
+
+#ownerBar
+{
+ background: #EFEFEF;
+ border: 2px solid #7FCBF5;
+ text-align: left;
+ color: Black;
+ margin: 10px 0 20px 0;
+ padding: 5px;
+ word-spacing: 0px;
+ font-size: medium;
+}
+
+#ownerBar a
+{
+ color: Blue;
+ padding: 0 5px 0 5px;
+}
+
+
+
+
+/*-------- Start Tab Control --------*/
+
+.tabHeaders
+{
+ font-weight:normal;
+ text-transform: uppercase;
+ border-bottom: solid 1px #CCC;
+ float: left;
+ width: 100%;
+}
+
+.tabHeaders div
+{
+ padding: 7px 19px 8px 19px;
+ font-size: 0.9em;
+ line-height: 125%;
+ color:#00749E;
+ cursor: pointer;
+ float: left;
+ text-align: center;
+}
+
+.tabHeaders div.current
+{
+ background-color:#fff;
+ cursor: default;
+ border: 1px solid #CCC;
+ border-bottom:none;
+ margin-bottom:-2px;
+ color:#000;
+}
+
+.tabHeaders div a
+{
+ text-decoration:none;
+}
+
+.tabContents
+{
+ clear: both;
+}
+
+#MainContent .tabHeaders div.current a
+{
+ color:#000;
+}
+
+.tabContents div.current
+{
+ display: block;
+}
+/*-------- End Tab Control --------*/
+
+.itemContainer
+{
+ width: 100%;
+}
+.itemRow .itemTitle
+{
+ padding-bottom: 5px;
+ font-size:1.1em;
+}
+
+.itemRow .itemBody, .itemRow .itemInfo
+{
+ padding:15px 17px 16px 0;
+}
+.itemRow .itemDescription
+{
+ overflow: hidden;
+ max-height: 80px;
+}
+.itemRow .itemBody
+{
+ vertical-align: top;
+ line-height: 1.4;
+}
+.itemRow .itemBody a.officialMicrosoftLabel
+{
+ color: #ACACAC;
+}
+.itemRow .itemInfo
+{
+ vertical-align: top;
+ padding-left: .5em;
+ line-height: 1.4;
+ width: 10em;
+ text-align:right;
+}
+
+.IE7 .itemRow .itemInfo
+{
+ width:11em;
+}
+
+.itemRow .itemInfo .ratingStars
+{
+ float: left;
+}
+.itemRow .itemInfo .ratingCount
+{
+ padding: 0 0 0 5px;
+ float: left;
+}
+.itemRow .ratingInfo
+{
+ text-align: center;
+}
+
+.itemRow .affiliationLink, #editorPicksSection .affiliationLink
+{
+ position: relative;
+ top: 3px;
+}
+
+#editorPicksSection a.officialMicrosoftLabel
+{
+ color: #ACACAC;
+}
+
+.itemRow .tagsContainer label {
+ display:none;
+}
+
+.editorPickedItem
+{
+ background-color:#F8F8F8;
+}
+
+.editorPickedText
+{
+ font-size:1.25em;
+ padding-bottom:2px;
+}
+.editorPickedItem > td
+{
+ border-top:6px solid #fff;
+}
+
+.dirSubHeading
+{
+ margin-bottom:15px;
+}
+
+#searchPage .dirSubHeading h2
+{
+ line-height:1.4;
+ font-size:1.1em;
+}
+
+#searchPage .dirSubHeading h2 span
+{
+ padding-top:5px;
+ display:block;
+}
+
+#searchPage .dirSubHeading h1, #searchPage .dirSubHeading h2
+{
+ clear:none;
+ padding-left:0px;
+}
+
+.dirSubHeading .dirSubLinks
+{
+ font-size:1.2em;
+ padding-top:5px;
+}
+
+
+.summaryBox
+{
+ padding: .25em 0 .25em 0;
+ clear: both;
+ line-height:1.45;
+}
+
+/*-------- Start Rating Stars --------*/
+
+.RatingStar
+{
+ width: 11px;
+ height: 11px;
+ padding: 0 8px 0 0;
+ background-position: center;
+ float: left;
+}
+
+.FilledRatingStar, .HalfRatingStar, .EmptyRatingStar, .FilledRatingStarHover
+{
+ width: 11px;
+ height: 11px;
+ padding: 0px 1px 0px 0px;
+ margin-top: 2px;
+}
+
+.FilledRatingStar
+{
+ background: url(../samples/fullStar.png) no-repeat;
+}
+
+.ownerRating .FilledRatingStar
+{
+ background: url(../samples/fullStar.png) no-repeat;
+}
+
+.FilledRatingStarHover
+{
+ background: url(../samples/fullStarHover.png) no-repeat;
+
+}
+
+.HalfRatingStar
+{
+ background: url(../samples/halfStar.png) no-repeat;
+
+}
+
+.EmptyRatingStar
+{
+ background: url(../samples/emptyStar.png) no-repeat;
+
+}
+
+.EditStarMode .RatingStar
+{
+ cursor: pointer;
+}
+
+
+
+/*-------- End Rating Stars --------*/
+
+.discussionFormTable
+{
+ width: 100%;
+ table-layout: fixed;
+}
+
+
+#ReviewsTabPane .seeAllLink, #DiscussionsTabPane .seeAllLink
+{
+ margin-top: 10px;
+ text-align: center;
+}
+
+/*-------- Start DiscussionsTab --------*/
+
+.threadActions
+{
+ text-align: right;
+ margin-top: 10px;
+ float: right;
+}
+
+#DiscussionsTabPane .reply, #DiscussionsTabPane .toggleDiscussion
+{
+ cursor: pointer;
+}
+
+
+#defaultDicussionText, #newDiscussion
+{
+ padding-top: 10px;
+}
+#DiscussionsTabPane .posts
+{
+ display: block;
+}
+#DiscussionsTabPane .threadHeader .left
+{
+ float: left;
+}
+#DiscussionsTabPane .threadHeader .right
+{
+ float: right;
+}
+#DiscussionsTabPane .normal
+{
+ font-weight: normal;
+}
+
+#DiscussionsTabPane .threadHeader
+{
+ position: relative;
+ background-color: #ECECEC;
+ padding: 4px 10px 4px 10px;
+}
+
+#DiscussionsTabPane .threadHeader .title
+{
+ color: #000000;
+ font-weight: bold;
+ margin-bottom: .7em;
+}
+#DiscussionsTabPane .threadHeader .label
+{
+ color: #000000;
+}
+#DiscussionsTabPane .postMeta
+{
+ color: #666666;
+}
+#DiscussionsTabPane .threadHeader .value
+{
+ font-weight: bold;
+ color: #000000;
+}
+
+#DiscussionsTabPane .reply
+{
+ font-weight: normal;
+ cursor: hand;
+}
+
+#DiscussionsTabPane ul li
+{
+ list-style-type: none;
+ list-style-image: none;
+ padding-bottom: 10px;
+}
+
+#DiscussionsTabPane ul
+{
+ padding-left: 0px;
+ margin-left: 0px;
+ padding-right: 2px;
+}
+
+.IE #reviewList .right
+{
+ margin-right: -1em;
+}
+
+#newDiscussion
+{
+ margin: 0 0 15px 0;
+}
+#newDiscussion #Title
+{
+ width: 50%;
+}
+#newDiscussion textarea
+{
+ width: 99%;
+ height: 10em;
+}
+
+#DiscussionsTabPane
+{
+ margin-left: 0px;
+ padding: 0 1em 1em 1em;
+}
+
+
+.postMeta
+{
+ float: right;
+}
+
+.postReply
+{
+ cursor: hand;
+ float: right;
+ font-weight: bold;
+}
+
+.postSaveReply
+{
+ display: none;
+}
+
+.postSaveReply textarea
+{
+ width: 99%;
+ margin-bottom: 4px;
+ height: 8em;
+}
+
+.toggleDiscussion
+{
+ cursor: hand;
+}
+
+.saveReplyErrorMessage
+{
+ display: none;
+ margin: 0 0 4px 0;
+ color: Red;
+ font-weight: bold;
+}
+
+#discussionListItem .avatar
+{
+ float: left;
+ padding: 5px;
+ vertical-align: middle;
+}
+
+#discussionListItem .discussion
+{
+ margin-left: 55px;
+ padding: 0 5px 5px 5px;
+ vertical-align: top;
+}
+
+.IE7 #discussionListItem .avatar
+{
+ margin-top: 15px;
+}
+
+
+/*-------- End DiscussionsTab --------*/
+
+
+.flotChart
+{
+ height: 300px;
+}
+
+#projectMenuBarTop
+{
+ padding: 10px 0 20px 0;
+ font-weight: bold;
+ font-size: 25px;
+}
+.dayHeader
+{
+ font-weight: bold;
+}
+
+/*-------- Start StatsPage --------*/
+#statsPage
+{
+ border: none;
+ background-color: Transparent;
+ margin-top: 1em;
+}
+
+#statsPage .rangeBox
+{
+ padding: 5px;
+ background-color: #ECECEC;
+ border: solid 1px #C2C2C2;
+ float: left;
+}
+#statsPage .statBox
+{
+ margin-top: 1em;
+ margin-bottom: 10px;
+ overflow: hidden;
+ display: none;
+}
+#statsPage .statBox h3
+{
+ font-size: 1.1em;
+ display: inline;
+}
+
+#statsPage #statMessage
+{
+ margin-top: 1em;
+ display: none;
+}
+
+#statsPage #statDownloadBox img {
+ float: left;
+}
+
+#statsPage .statDownloadLink {
+ padding-left: 5px;
+ vertical-align: middle;
+}
+
+#pointTooltip
+{
+ border: solid #000000 1px;
+ height: 35px;
+ background-color: #EEEEEE;
+ position: absolute;
+ display: none;
+ text-align: center;
+ padding: 9px;
+ border-radius: 4px;
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+ z-index: 1000;
+ white-space: nowrap;
+}
+
+.flotChart
+{
+ height: 300px;
+}
+
+/*-------- End StatsPage --------*/
+
+
+/***************************************************************/
+/* TagAutoComplete Styles */
+/***************************************************************/
+.AutoCompletePanel
+{
+ font-size: 95%;
+ border: solid .1em #999;
+ background-color: #f0f0f0;
+ padding: .15em;
+}
+
+.AutoCompletePanel div.Row
+{
+ color: #000;
+ cursor: pointer;
+ background-color: transparent;
+ padding: .15em .25em;
+ text-align: left;
+}
+
+.AutoCompletePanel div.Selected
+{
+ color: #fff;
+ background-color: #6D6D6D;
+}
+
+
+/*-------- Start Subscription Form --------*/
+
+#subscribeForm
+{
+ background-color: #D3D3D1;
+ border: 1px solid #000000;
+ -border-radius: 5px;
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+ padding: 15px;
+ position: absolute;
+ display: block;
+}
+
+#subscribeForm .subscribeFormbuttons
+{
+ text-align: right;
+ margin-top: 10px;
+}
+#subscribeForm .subscribeFormbuttons > button
+{
+ color: Blue;
+ border: none;
+ background: none;
+ font-weight: bold;
+ cursor: pointer;
+}
+
+#subscribeForm .subscribeFormclose
+{
+ display: none;
+}
+
+#subscribeForm table
+{
+ margin-bottom: 15px;
+}
+
+#subscribeForm table th
+{
+ text-align: left;
+ font-weight: bold;
+ border-bottom: 1px solid #000000;
+}
+
+#subscribeForm table td
+{
+ padding: 5px 10px 5px 20px;
+}
+
+#subscribeForm .rowHeading td
+{
+ font-weight: bold;
+ border-bottom: 1px solid #FFFFFF;
+}
+
+#subscribeForm table tr td:first-child
+{
+ padding: 5px 40px 5px 0;
+}
+
+
+/*-------- End Subscription Form --------*/
+
+/*-------- Start Tag Browser --------*/
+
+.tagBrowserfade
+{
+ position: absolute;
+ background-color: #aaaaaa;
+}
+#tagBrowser
+{
+ background-color: #f4f4f4;
+ border:1px solid #000000;
+ -border-radius: 5px;
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+ padding:15px;
+ position: absolute;
+ display: block;
+}
+
+#tagBrowser .tagBrowserbuttons
+{
+ text-align:right;
+ margin-top: 10px;
+}
+#tagBrowser .tagBrowserbuttons > button
+{
+ color: Blue;
+ border: none;
+ background: none;
+ font-weight: bold;
+ cursor:pointer;
+}
+
+#tagBrowser .tagBrowserclose
+{
+ display:none;
+}
+
+.tagBrowserContainer {
+ width: 450px;
+}
+
+.tagBrowserContainer h2 {
+ border-bottom: 1px solid #000000;
+ padding-bottom: 5px;
+}
+.tagBrowserContainer > p {
+ margin: 15px 0 15px 0;
+}
+
+.tagBrowserContainer .tags {
+ margin: 5px;
+ height: 225px;
+ overflow-y: scroll;
+}
+
+
+/*-------- End Tag Browser --------*/
+
+/*-------- Start List Filter Box --------*/
+
+div#filterInputBox
+{
+ overflow:auto;
+ min-width:225px;
+}
+
+.filterBox
+{
+ width: 100%;
+ background: #FFFFFF;
+ padding: 0px 2px;
+ height: 25px;
+ -moz-border-radius: 2px;
+ border-radius: 2px;
+ border: 1px solid #888888;
+ table-layout: auto;
+ margin-bottom:5px;
+}
+
+ .filterBox #filterImageCell
+ {
+ text-align: right;
+ padding: 0px;
+ vertical-align: middle;
+ }
+
+ .IE7 .filterBox #filterImageCell
+ {
+ padding:2px 2px 0 0;
+ }
+
+ .filterBox #filterImg
+ {
+ background: transparent url('searchButton.png') no-repeat 0 0;
+ width: 22px;
+ height: 22px;
+ }
+
+table.filterBox
+{
+ table-layout: fixed;
+}
+
+ .filterBox .stxtcell
+ {
+ padding-right: 4px;
+ width:90%;
+ }
+
+ .filterBox .stxtcell > input
+ {
+ margin-right: 4px;
+ height: 26px;
+ line-height:26px;
+ width: 100%;
+ padding: 0px;
+ padding-left: 4px;
+ padding-top: 2px;
+ border: none;
+ }
+
+ .IE7 .filterBox .stxtcell > input
+ {
+ height: 20px;
+ }
+
+ .filterBox .stxtcell > input.stxtinptpassive
+ {
+ color: #ACACAC;
+ }
+
+/*-------- End List Filter Box --------*/
+
+/*-------- Start Notifications --------*/
+
+#notificationsSummaryBox
+{
+ font-weight: bold;
+ padding: .5em;
+}
+
+
+.notificationsByDay, .notifications
+{
+ /*list-style: none;*/
+}
+
+.dayHeader
+{
+ border-bottom: 1px solid silver;
+ margin-top: 1em;
+ padding-bottom: .5em;
+}
+
+.notifications
+{
+ margin-top: .5em;
+}
+
+ul.notifications li
+{
+ line-height: 1.5em;
+}
+
+ul.notifications li.unread
+{
+ font-weight: bold;
+}
+
+ul.notifications li ol, ul.notifications li ul
+{
+ margin-left: 1.5em;
+}
+
+/*-------- End Notifications --------*/
+
+/*-------- Start ProjectDetailsPage --------*/
+
+#projectPage #projectInfo
+{
+ position: relative;
+ margin-top: 5px;
+ height: 100%;
+}
+#projectInfo .section
+{
+ float: left;
+ margin-bottom: 0px;
+ height: 100%;
+}
+
+ #projectInfo .section .itemBar, #projectInfo .section .itemBarLong
+ {
+ clear: both;
+ padding: 7px 0 7px 0;
+ overflow:auto;
+ }
+
+ #projectInfo .section .itemBarLong:first-child
+ {
+ padding-top:3px;
+ }
+
+ .IE7 #projectInfo .section .itemBar, .IE7 #projectInfo .section .itemBarLong
+ {
+ padding-top: 5px;
+ }
+
+ #projectInfo .section .itemBar > label, #projectInfo .section .itemBarLong > label
+ {
+ width: 130px;
+ float: left;
+ text-transform: capitalize;
+ }
+
+ #projectInfo .section .itemBar div#yourRating {
+ float:left;
+ }
+
+ #projectInfo .section .itemBar div.RatingStar {
+ margin:2px 1px 0 0;
+ }
+
+ #projectInfo .section .itemBar div#RatingCount {
+ padding: 0 0 0 3px;
+ }
+
+ #projectInfo .section .itemBar .ratingsWithCountContainer img {
+ vertical-align:top;
+ float:left;
+ padding-right: 4px;
+ }
+
+ #projectInfo .section .itemBar > span, #projectInfo .section .itemBarLong > span, #projectPage .section .itemBar > div
+ {
+ float: left;
+ }
+
+ #projectInfo .section .itemBar, #projectInfo .section .itemBarLong {
+ width: 100%;
+ }
+
+ #projectInfo .section .itemBar > span {
+ float: none;
+ }
+
+ #projectInfo .section .itemBar > span .shareThisItem {
+ white-space: nowrap;
+ }
+
+ #projectInfo .section .itemBarLong div
+ {
+ margin-left: 130px;
+ padding: 0;
+ }
+
+ #projectInfo .section .viewonlinecont
+ {
+ background-color:#d3d3d3;
+ padding:5px 10px;
+ margin-top:10px;
+ float:left;
+ font-weight:bold;
+ }
+
+#projectInfo #sectionLeft
+{
+ width: 50%;
+}
+#projectInfo #sectionRight
+{
+ width: 50%;
+}
+.IE7 #projectInfo #sectionRight
+{
+ width: auto;
+}
+
+#projectPage h2.projectSummary
+{
+ font-weight:normal;
+ font-size: 1.1em;
+ margin-bottom: 11px;
+ line-height:1.4;
+}
+
+.IE7 #projectPage h2.projectSummary
+{
+ font-family: 'Segoe UI' , 'Lucida Grande' ,Verdana,Arial,Helvetica,sans-serif;
+}
+
+.IE #projectPage .projectTitle, .IE9 #projectPage .projectTitle
+{
+ width: 100%;
+}
+
+#projectPage #reportAbuse
+{
+ float: left;
+ font-size: x-small;
+}
+
+#projectPage .hiddenSidebar {
+ display: none;
+}
+
+#projectPage .fullProjectBody {
+ margin-left:-275px;
+}
+
+.IE8 #projectPage #userCard {
+ float: left;
+ height: auto;
+}
+
+#projectPage #userCard .avatar img {
+ max-width: 100px;
+ max-height: 100px;
+}
+
+#projectDetails
+{
+ overflow:hidden;
+}
+
+#projectBody
+{
+ width: 100%;
+ overflow:hidden;
+}
+
+ #projectDetails > div:first-child
+ {
+ margin: 5px 0 0 260px;
+ }
+
+ #projectBody > div:first-child
+ {
+ margin: 20px 0 0 260px;
+ }
+
+ .IE7 #projectContent .tabHeaders
+ {
+ overflow:hidden;
+ margin-bottom:-20px;
+ }
+
+#projectPage .sidebar
+{
+ float: left;
+ width: 215px;
+ margin-right: -250px;
+}
+
+ #projectPage .sidebar .section
+ {
+ margin: 20px 0 10px 0;
+ }
+
+ #projectPage .sidebar .section .titleBar h3
+ {
+ padding: 0 0 2px 0;
+ }
+
+ #projectPage .sidebar .section .itemBarRight
+ {
+ min-height: 21px;
+ position: relative;
+ padding-top: 5px;
+ }
+
+ #projectPage .sidebar .section .titleBar
+ {
+ margin-bottom: 5px;
+ }
+
+ #projectPage .sidebar .section .authorItem
+ {
+ padding: 0 0 5px 10px;
+ }
+
+ #projectPage .sidebar .section .authorItem a
+ {
+ display:block;
+ float:left;
+ max-width:170px;
+ }
+
+ #projectPage .sidebar .section .authorItem > div
+ {
+ float:right;
+ }
+
+ #projectPage .sidebar #advertisement
+ {
+ margin-top: 20px;
+ }
+
+ #projectPage .sidebar #advertisement .label
+ {
+ text-align: center;
+ }
+
+ #projectPage .sidebar #moreFromAuthor
+ {
+ width:225px;
+ margin: 20px 0 10px 0;
+ float:left;
+ }
+
+ #projectPage .sidebar #moreFromAuthor .bottomBar {
+ padding: 5px 0px 5px 25px;
+ text-align: right;
+ }
+
+#projectPage #Collections {
+ min-height:22px;
+ min-width:169px;
+}
+
+#projectPage #Collections .bevelButton {
+ background-color: #8CC63F;
+}
+
+#projectPage .bevelButton
+{
+ font-weight: bold;
+ border-radius: 3px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ color: white;
+ padding: 2px 10px 3px;
+ text-align: center;
+}
+
+#projectPage #DiscussionsTabPane .bevelButton
+{
+ font-weight: normal;
+ color: black;
+ padding: 1px 10px 1px;
+}
+
+#projectPage #Downloads {
+ padding: 0 0 8px 0;
+ float: left;
+}
+ #projectPage #Downloads > div:first-child {
+ float: left;
+ margin: 15px 0 0 0;
+ height:35px;
+ line-height:1.6;
+ width: 130px;
+ }
+ #projectPage #Downloads label
+ {
+ font-size:1.25em;
+ }
+ #projectPage #Downloads input
+ {
+ min-width: 100px;
+ padding: 3px 10px 3px 10px;
+ margin: 3px 10px 0 10px;
+ font-weight: bold;
+ float: left;
+ }
+
+ #projectPage #Downloads .button
+ {
+ background-color:#007494;
+ color:#fff;
+ padding:5px 15px;
+ margin: 15px 15px 0 0;
+ float:left;
+ }
+
+ #projectPage #Downloads .button:hover
+ {
+ background-color:#0095c4;
+ text-decoration:none;
+ }
+
+#projectPage #projectBody .attachments {
+ margin: 0 0 15px 0;
+}
+
+ #projectPage #projectBody .attachments label {
+ float: left;
+ }
+
+ #projectPage #projectBody .attachments .files a, #projectPage #projectBody .attachments .files span {
+ float: left;
+ padding: 0 5px 0 5px;
+ }
+
+#publishBar
+{
+ border: 1px solid #707070;
+ background-color: #F8F8F8;
+ margin-top: 10px;
+}
+
+#sourceItem {
+ height: 610px;
+}
+ #sourceItem > div:first-child {
+ padding: 20px 5px 0 15px;
+ font-weight: bold;
+ }
+ #sourceItem > div+div {
+ height: 560px;
+ padding: 10px;
+ overflow: auto;
+ }
+ #sourceItem .copyCode {
+ font-weight: normal;
+ margin: 0 15px 0 0;
+ float: right;
+ }
+
+.sourceList {
+ height: 600px;
+ padding: 5px;
+ border-top: 1px solid #CCC;
+ margin-top: -1px;
+}
+
+ .sourceList .sourceListTabHeader
+ {
+ margin:20px 10px;
+ }
+ .sourceList .sourceListTabs
+ {
+ margin-bottom:20px;
+ border-bottom: 1px solid #CCC;
+ float:left;
+ width:100%;
+ }
+ .sourceList .sourceListTabs .languageTab {
+ padding:5px 10px 5px 10px;
+ font-weight: bold;
+ float: left;
+ margin: 0 3px 0px 0;
+ color:#00749E;
+ }
+ .sourceList .sourceListTabs .languageTab:hover
+ {
+ color: #0095C4;
+ }
+
+ .sourceList .sourceListTabs .selectedLanguage {
+ background-color: #fff;
+ color: #000;
+ border: 1px solid #ccc;
+ border-bottom:none;
+ margin-bottom:-2px;
+ }
+
+ .sourceList .sourceListTabs .unselectedLanguage {
+ cursor: pointer;
+ }
+
+ .sourceList .endTabs {
+ clear: both;
+ }
+
+ .sourceList .sourceListContent {
+ padding-top: 5px;
+ }
+
+
+.sbfc,
+.sbfe
+{
+ white-space: nowrap;
+ text-indent: 20px;
+ cursor: pointer;
+ padding: .2em 0em .2em 0em;
+ background-repeat: no-repeat;
+ background-position: left center;
+ font-weight: bold;
+ text-decoration: none !important;
+}
+
+.sbfc
+{
+ background-image: url(../samples/node_closed.gif);
+}
+
+.sbfe
+{
+ white-space: nowrap;
+ background-image: url(../samples/node_opened.gif);
+}
+
+.ndbf
+{
+ white-space: nowrap;
+ text-indent:20px;
+}
+
+.sbf
+{
+ white-space: nowrap;
+ background: url(../samples/bullet.gif) no-repeat 4px -1px;
+ cursor: pointer;
+ text-indent: 20px;
+ white-space: nowrap;
+ padding: .1em 0em .1em 0em;
+}
+
+.sbsf,
+.sbf:hover
+{
+ color: #000;
+ text-decoration: none !important;
+
+}
+
+.sbsf
+{
+ color: #000 !important;
+ background-color: rgb(232, 232, 232);
+}
+
+.sbf:hover
+{
+ color: #ce8b10;
+}
+
+/*-------- Translate --------*/
+.translatePage {
+ width: 900px;
+}
+.translatePage .fileManager {
+ margin-bottom:20px;
+}
+.translatePage .fileManager h4 {
+ margin-top:10px;
+}
+.translatePage #formContainer {
+ width: 100%;
+}
+.translatePage .formLabel {
+ width: 300px;
+ padding: 5px;
+}
+ .translatePage .textInput {
+ width: 425px;
+}
+.translatePage TEXTAREA.richText {
+ height: 600px;
+ width: 620px;
+}
+.translatePage TEXTAREA.unadornedEditor {
+ height: 600px;
+}
+.translatePage .formWideLabel, .translatePage .richText {
+ padding: 5px;
+}
+.translatePage .formWideLabel, .translatePage .unadornedEditor {
+ width: 750px;
+ padding: 5px;
+}
+.translatePage #languageSelection {
+ margin: 15px;
+ display: inline-block;
+}
+
+.translateTab, .translateTabSelected {
+ font-weight: bold;
+ float: left;
+ text-align: center;
+ margin: 10px;
+ padding: 7px;
+ background: #E8E8E8;
+ white-space: nowrap;
+ cursor: pointer;
+}
+
+.translateTabSelected
+{
+ color: White;
+ background: Gray;
+}
+
+.translateTabSelected .translateLabel, .translateTab .translateLabel
+{
+ white-space: nowrap;
+ float: left;
+ padding: 0 5px 0 5px;
+}
+
+.translateTab #deleteLanguage, .translateTab #moreLanguages
+{
+ padding-left: 10px;
+}
+
+.translateLabel #deleteLanguage {
+ color: #FFFFFF;
+}
+/*-------- End Translate --------*/
+/*-------- Begin Eula --------*/
+
+
+#eulaPagefade
+{
+ position: absolute;
+ background-color: #FFFFFF;
+}
+
+#eulaPage
+{
+ background-color: #f4f4f4;
+ border: 1px solid #000000;
+ -border-radius: 5px;
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+ padding: 15px;
+ display: block;
+ max-width: 70%;
+}
+
+#eulaPage .eulaPageclose
+{
+ text-align: right;
+}
+
+#eulaPage .eulaPagemessage
+{
+ overflow: auto;
+ max-height: 350px;
+}
+
+ #eulaPage .eulaPagemessage h1
+ {
+ margin: 0 0 5px 0;
+ }
+
+#eulaPage .eulaPagebuttons
+{
+ text-align: right;
+ margin-top: 10px;
+}
+#eulaPage .eulaPagebuttons > button
+{
+ color: Blue;
+ border: none;
+ background: none;
+ font-weight: bold;
+ cursor: pointer;
+}
+
+
+ #eulaPage #eula #documentText
+ {
+ line-height: normal;
+ }
+
+/*-------- End DocumentView --------*/
+/*-------- Begin FAQ --------*/
+
+#FAQPage #TableOfContents h2
+{
+ padding: 5px;
+ border-bottom: 2px solid #EFEFEF;
+ margin: 0 0 10px 0;
+ max-width: 70%;
+}
+
+#FAQPage .FAQSection
+{
+ padding: 10px 0px;
+ width: 70%;
+}
+
+ #FAQPage .FAQSection h2
+ {
+ padding: 5px;
+ border-bottom: 2px solid #EFEFEF;
+ }
+
+ #FAQPage .FAQSection h3
+ {
+ padding: 5px;
+ }
+
+ #FAQPage .FAQSection ul, #FAQPage .FAQSection ol
+ {
+ margin: 0;
+ }
+
+ #FAQPage .FAQSection #description > div
+ {
+ overflow: auto;
+ padding-left: 10px;
+ }
+
+ #FAQPage .FAQSection #description img
+ {
+ float: left;
+ }
+
+ #FAQPage .FAQSection #description div > div
+ {
+ padding-top: 10px;
+ float: left;
+ }
+
+ #FAQPage .FAQSection > div > div
+ {
+ padding: 0 15px;
+ }
+
+ #FAQPage #Reputation th, #FAQPage #Reputation td
+ {
+ padding-left: 20px;
+ }
+
+/*-------- End FAQ --------*/
+/*-------- Begin DocumentView --------*/
+
+#documentView #documentText
+{
+ line-height: normal;
+}
+
+/*-------- End DocumentView --------*/
+
+.Opera wbr:after
+{
+ content: "\00200B";
+}
+
+
+.IE9 wbr:after
+{
+ content: "\00200B";
+}
+
+.IE8 wbr {
+ width: 0px;
+ display: inline-block;
+ overflow: hidden;
+}
+
+/*-------- Begin FileManager --------*/
+
+.uploadControlNoError
+ {
+ height:30px
+ }
+.uploadControlWithError
+ {
+ height:80px;
+ }
+/*-------- End FileManager --------*/
+
+/*-------- Begin User Card --------*/
+#userCard .titleBar {
+ border-bottom: solid 5px #E8E8E8;
+ margin: 10px 0 5px 0;
+}
+ #userCard .titleBar h3
+ {
+ font-size: 1.0em;
+ font-weight: bold;
+ line-height: 125%;
+ padding: 0 0 2px 0;
+ }
+
+#userCard .userFeed {
+ float: right;
+}
+
+#userCard .bio {
+ max-width:300px;
+ white-space: normal;
+}
+
+#userCard .avatar
+{
+ padding: 5px 5px 10px 5px;
+ margin: 0 0 3px 0;
+ text-align: center;
+}
+
+#userCard .itemBar {
+ padding: 5px;
+}
+
+ #userCard .itemBar label
+ {
+ float: left;
+ text-transform: capitalize;
+ }
+
+ #userCard .itemBar label+span {
+ display: block;
+ margin-left: 100px;
+ }
+
+#userCard .collapsableSidebar {
+ clear:both;
+ width:100%;
+ margin-top: 5px;
+}
+
+/* Profile Overrides */
+#userCard
+{
+ padding: 0 0 10px 0
+}
+
+#userCard .profile-usercard
+{
+ width:225px;
+}
+
+#userCard .profile-usercard, #userCard .profile-inline, #userCard .profile-inline-header
+{
+ border:0px;
+ background-color:#fff;
+}
+
+#userCard .profile-userimage-large
+{
+ margin-bottom:10px;
+ border:none;
+ width:auto;
+ height:auto;
+}
+
+#userCard .profile-inline .profile-inline-header-details
+{
+ width:100%;
+ display:block;
+ clear:both;
+ margin-left:0px;
+}
+
+
+
+/*-------- End User Card --------*/
+/*-------- Begin Description Progress Meter --------*/
+
+#descriptionProgressMeter {
+ float: right;
+ border-top: 1px solid #DADADA;
+ border-left: 1px solid #DADADA;
+ width: 210px;
+ padding-left: 7px;
+}
+
+ #descriptionProgressMeter h4 {
+ font-weight: bold;
+ }
+
+ #descriptionProgressMeter #progressGraphic {
+ border: 1px solid #888888;
+ width: 205px;
+ margin: 10px 0;
+ background-color: #E9E9E9;
+ padding: 1px 0 0 1px;
+ }
+
+ #descriptionProgressMeter #progressGraphic div {
+ background-image: url("../common/progress_meter.png");
+ padding-left: 5px;
+ }
+
+ #descriptionProgressMeter #progressText {
+ font-weight: bold;
+ margin: 5px 0;
+
+ }
+
+ #descriptionProgressMeter #goodDescriptionText p+p {
+ padding: 5px 0;
+ }
+
+ #descriptionProgressMeter #goodDescriptionText > div {
+ margin-top: 5px;
+ width: 150px;
+ border-radius: 5px;
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+ overflow: auto;
+ }
+
+ #descriptionProgressMeter #goodDescriptionText div img {
+ float: left;
+ }
+
+ #descriptionProgressMeter #goodDescriptionText div div {
+ margin: 7px 0 5px 10px;
+ }
+
+/*-------- End Description Progress Indicator --------*/
+
+/*-------- Start Sample Pack Tab View --------*/
+.SamplePackTab #headerBar
+{
+ padding: 15px 5px 20px 5px;
+ font-weight: bold
+}
+ .SamplePackTab #headerBar .reportCount
+ {
+ padding-top: 2px;
+ }
+ .SamplePackTab #headerBar .samplePackSort
+ {
+ float: right;
+ color: #666;
+ }
+/*-------- End Sample Pack Tab View --------*/ \ No newline at end of file
diff --git a/description/Combined.css b/description/Combined.css
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/description/Combined.css
diff --git a/description/Galleries.css b/description/Galleries.css
new file mode 100644
index 0000000..f31f820
--- /dev/null
+++ b/description/Galleries.css
@@ -0,0 +1,418 @@
+/* ***************************************************
+Galleries.css - Common Structure
+
+This is where we define common layout for structures that are truly close to common across the different
+Galleries sites. To make sure this works we need to follow certain conventions.
+
+1. Define each logical structure in its own section with its own comment block that gives the section
+a Name, Description and defines the root element if one exists (i.e #someElement). Also, mark the closing block.
+
+2. Indent styles in a section to represent if it is a child of a previous element.
+i.e. #someDiv{
+ }
+ #someDiv ul {
+ }
+
+3. Do not include brand specific information here like colors and fonts unless they are *really* common.
+
+4. If there is an element that you know will be overridden in each brand stylesheet still include it here with an empty definition.
+This will aid in knowing what section to override and what selectors to use.
+
+i.e. #someSction a {
+ }
+
+5. When you add a new section also update the Table of Contents below so that we have a quick overview of the sections
+
+ *****************************************************/
+
+/****************************************************
+Table of Contents
+
+ Global - global classes
+
+ FileAttachmentDisplay - The list of attached files under the editor
+ Eyebrow - The breadcrumb control at the top of the master page
+ Pager - The common paging control, used for browsing pages of search results
+ Profile User Card - Elements in the profile usercard control
+ SideNav - The navigation side bar that contains the search filters
+
+
+*****************************************************/
+
+/********************************
+Name: Global
+Root: none
+Description: truly global classes
+********************************/
+body {
+ text-align: left;
+ direction: ltr;
+}
+
+img.rss {
+ background: url(../../../GlobalResources/Images/Rss.png) no-repeat;
+ background-position: 0px 0px;
+ height: 17px;
+ width: 17px;
+}
+/* End Global Section */
+
+/********************************
+Name: FileAttachmentDisplay
+Root: #fileAttachmentDisplay
+Description: The list of attached files under the editor
+********************************/
+#fileAttachmentDisplay {
+}
+ #fileAttachmentDisplay .attachment {
+ margin-right: 10px;
+ float: left;
+ }
+
+ #fileAttachmentDisplay .attachment .displayAttachment {
+ padding: 0px 0 13px 0;
+ float: left;
+ }
+
+ #fileAttachmentDisplay .attachment .removeAttachment {
+ background-image: url('/Content/Common/delete.png');
+ display: block;
+ width: 16px;
+ height: 16px;
+ float: left;
+ }
+/* End FileAttachmentDisplay Section */
+
+
+/********************************
+Name: Eyebrow
+Root: .EyebrowContainer
+Description: The breadcrumb control at the top of the master page
+********************************/
+.EyebrowContainer {
+}
+ .EyebrowContainer div.EyebrowElement{
+ display:inline;
+ }
+
+ .EyebrowContainer .EyebrowElement{
+ font-weight:normal
+ }
+ .EyebrowContainer .EyebrowLeafLink{
+ color:#000;
+ }
+/* End Eyebrow Section */
+
+/********************************
+Name: Pager
+Root: #Pager
+Description: The common paging control, used for browsing pages of search results
+********************************/
+#Pager {
+}
+ #Pager div{
+ display:inline;
+ }
+/* End Pager Section */
+
+/********************************
+
+Name: Profile User Card
+Root: #dashboardPage #userCard
+Description: Elements in the profile usercard control
+
+********************************/
+ #dashboardPage #userCard .profile-usercard-inline {
+ margin: 5px 0 10px 0;
+ }
+
+ /* #dashboardPage #userCard .profile-usercard {
+ width: 288px;
+ }
+/* End Profile User Card Section */
+
+/********************************
+
+Name: Discussion
+Root: #DiscussionsTabPane
+Description: Defines the layout of the dicussion
+
+
+********************************/
+#DiscussionsTabPane {
+}
+
+ #DiscussionsTabPane .itemHidden
+ {
+ background: lightgrey;
+ }
+
+ #discussionListItem {
+ }
+
+ .discussion .postActions
+ {
+ float: right;
+ }
+
+ #discussionListItem .postItem
+ {
+ white-space: pre-wrap;
+ word-wrap: break-word;
+ font-size:1em;
+ }
+
+/* End Discussion Section */
+
+
+/********************************
+
+Name: SearchDefaultLocale
+Root: .searchDefaultLocale
+Description: Defines the layout of the include english result checkbox on the Browse Page
+
+
+********************************/
+.searchDefaultLocale
+{
+ float: right;
+ margin: 20px 0 0 5px;
+}
+ .searchDefaultLocale input
+ {
+ vertical-align:top;
+ }
+ .searchDefaultLocale span
+ {
+ margin-left: -3px;
+ }
+/*-------- End SearchDefaultLocale --------*/
+
+
+/********************************
+
+Name: SideNav
+Root: #sideNav
+Description: Defines the layout of the naviation elements on the side of the Browse Page
+ These represent the different filters like Code Language, Category and Tag
+
+
+********************************/
+
+#sideNav {
+ width: 250px;
+ vertical-align:top;
+ background-color:#eee;
+}
+ #sideNav h3 {
+ }
+
+ #sideNav .section {
+ padding: 0 0 10px 0;
+ position: relative;
+ }
+
+ #sideNav .section a {
+ }
+
+ #sideNav .section a:hover {
+ }
+
+ #sideNav .section > div {
+ padding:5px 5px 5px 0;
+ line-height:150%;
+ }
+
+ #sideNav .section ul {
+ list-style-type:none;
+ padding:0px;
+ margin:0px;
+ }
+
+ #sideNav .section ul li {
+ position: relative;
+ padding: 5px 5px 5px 0;
+ }
+
+ #sideNav .section ul li .selectedFilter {
+ float: left;
+ padding-right: 5px;
+ }
+
+ #sideNav .section div.itemCount {
+ float: right;
+ }
+
+ #sideNav .section form input[ type = "checkbox"] {
+ margin: 0px 4px 0px 0px;
+ vertical-align: middle;
+ }
+/* End SideNav Section */
+
+/*----------- Contribution Logos *******/
+.contributionLogo {
+ float: left;
+ position: relative;
+ margin-right: 6px;
+}
+
+.logo_visualstudio {
+ background: transparent url('../common/logos/visualstudio.png') no-repeat;
+ width: 23px;
+ height: 12px;
+ margin-top: 3px;
+}
+.logo_allinonecode {
+ background: transparent url('../common/logos/1code.png') no-repeat;
+ width: 14px;
+ height: 16px;
+}
+.logo_exchange {
+ background: transparent url('../common/logos/exchange.png') no-repeat;
+ width: 14px;
+ height: 16px;
+}
+.logo_ie {
+ background: transparent url('../common/logos/ie.png') no-repeat;
+ width: 16px;
+ height: 16px;
+}
+.logo_office {
+ background: transparent url('../common/logos/office.png') no-repeat;
+ width: 17px;
+ height: 16px;
+}
+.logo_windows {
+ background: transparent url('../common/logos/windows.png') no-repeat;
+ width: 17px;
+ height: 16px;
+ }
+.logo_azure {
+ background: transparent url('../common/logos/windowsazure.png') no-repeat;
+ width: 18px;
+ height: 16px;
+}
+
+.logo_windowsphone {
+ background: transparent url('../common/logos/windowsphone.png') no-repeat;
+ width: 16px;
+ height: 16px;
+ }
+
+ .contributionLogoTip {
+ position: absolute;
+ display: none;
+ border: solid 1px #CCC;
+ color: #333;
+ background-color: #F0F0F0;
+ font-size: 11px;
+ font-family: "Segoe UI",Sans-Serif;
+ box-shadow: 3px 3px 5px #888;
+ -moz-box-shadow: 3px 3px 5px #888;
+ z-index: 1003;
+ padding: 5px;
+ min-width: 250px;
+ }
+
+/*----------- End Contribution Logos *******/
+
+.clear
+{
+ clear: both;
+}
+
+.customcontributionLogoTip {
+ position: absolute;
+ display: none;
+ border: solid 1px #CCC;
+ background-color: white;
+ color: #333;
+ font-size: 11px;
+ font-family: "Segoe UI",Sans-Serif;
+ box-shadow: 3px 3px 5px #888;
+ -moz-box-shadow: 3px 3px 5px #888;
+ z-index: 1004;
+ padding: 5px;
+ min-width: 250px;
+}
+
+.customcontributionTittle {
+ font-size: 14px;
+ margin-left: 90px;
+}
+
+.customcontributionDiscription {
+ font-size: 13px;
+ margin: 10px 5px;
+ text-align: justify;
+}
+
+.customcontribution {
+ float: left;
+ position: relative;
+ margin-right: 6px;
+}
+
+.customcontributionLink {
+ margin-left: 5px;
+}
+
+.customcontributionlogo {
+ float: left;
+ padding: 0 10px;
+ margin: 0;
+ width: 70px;
+ height: 70px;
+ background-repeat: no-repeat;
+}
+
+
+.logo_azure_large {
+ background-image: url('../common/logos/windowsazure_large.png');
+}
+.logo_visualstudio_large {
+ background-image: url('../common/logos/visualstudio_large.png');
+}
+.logo_exchange_large {
+ background-image: url('../common/logos/exchange_large.png');
+}
+.logo_ie_large {
+ background-image: url('../common/logos/ie_large.png');
+}
+.logo_office_large {
+ background-image: url('../common/logos/office_large.png');
+}
+.logo_windows_large {
+ background-image: url('../common/logos/windows_large.png');
+}
+.logo_windowsphone_large {
+ background-image: url('../common/logos/windowsphone_large.png');
+}
+
+/* Custome Header */
+.dirSubHeading .windowssdk .container
+{
+ background: #FF3300 url('wpappsbackground.png') no-repeat;
+ color: white;
+ padding: 8px 10px 18px 170px;
+}
+
+.dirSubHeading .windowssdk .container h1, .dirSubHeading .windowssdk .container h2 {
+ color: white !important;
+}
+
+.dirSubHeading .windowssdk .container p {
+ margin: 20px 0 0 0 !important;
+}
+
+.dirSubHeading .windowssdk .container a {
+ background-color:#ffd800;
+ color: #2a2a2a !important;
+ cursor:pointer;
+ font-size:13px;
+ font-family:'Segoe UI Semibold','Segoe UI','Lucida Grande',Verdana,Arial,Helvetica,sans-serif;
+ padding:4px 12px 6px;
+}
+
+
+
diff --git a/description/Layout.css b/description/Layout.css
new file mode 100644
index 0000000..d00769f
--- /dev/null
+++ b/description/Layout.css
@@ -0,0 +1,147 @@
+#container {
+ min-height: 768px;
+}
+
+#leftSubHeaderContainer
+{
+ margin-top:20px;
+}
+
+#title h1
+{
+ font-size:25px;
+}
+
+#subtitle h2
+{
+ font-size:15px;
+}
+
+#subtitle
+{
+ margin-left:10px;
+}
+
+
+#formContainer
+{
+ margin-left:10px;
+ margin-top:30px;
+}
+
+.formLabel
+{
+ float:left;
+ width: 250px;
+}
+
+.formRow
+{
+ clear:both;
+ padding: 10px 0 10px 10px;
+}
+
+
+.formRecaptchaRow
+{
+ clear:both;
+ float:left;
+ margin-top:20px;
+ margin-left:10px;
+ margin-bottom:20px;
+}
+
+.formSubmitRow
+{
+ clear:both;
+ margin-top:20px;
+ margin-left:300px;
+ margin-bottom:20px;
+}
+
+.formControl {
+ width:300px;
+ float:left;
+}
+.formControl .textInput
+{
+ width:300px;
+}
+
+.formControl textarea
+{
+ width:425px;
+ height:100px;
+}
+
+.formControl .tag
+{
+ width:425px;
+}
+
+.formControl .richText
+{
+ margin-top:10px;
+ width:500px;
+ height:440px;
+}
+
+.formWideLabel
+{
+ width:500px;
+}
+
+.formBigLabel
+{
+ margin-top:20px;
+ font-size:20px;
+}
+
+.formControlBelow
+{
+ clear:both;
+ margin-top:10px;
+ width:500px;
+}
+
+.required
+{
+ color: Red;
+}
+.helpText
+{
+ color: #9D9D9D;
+ font-style: italic;
+}
+
+#agreementSummary
+{
+ clear:both;
+ margin-top:10px;
+ width:800px;
+}
+
+.field-validation-error, .validation-summary-errors
+{
+ color: #FF0000;
+ font-weight: bold;
+}
+
+.tinyMCETemplate {
+ position: relative;
+ left: 400px;
+ width: 300px;
+ max-height: 300px;
+ overflow: auto;
+}
+
+.IE6 .tinyMCETemplate {
+ left: 25px;
+}
+
+.ownerBar {
+ padding: 5px;
+}
+.ownerBar .ownerBarOptions {
+ float: right;
+}
diff --git a/description/d0a480a2-d1c4-4159-af59-5aa4abd59cb0Combined.css b/description/d0a480a2-d1c4-4159-af59-5aa4abd59cb0Combined.css
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/description/d0a480a2-d1c4-4159-af59-5aa4abd59cb0Combined.css
diff --git a/description/iframedescription.css b/description/iframedescription.css
new file mode 100644
index 0000000..6a9277b
--- /dev/null
+++ b/description/iframedescription.css
@@ -0,0 +1,179 @@
+body {
+ color: #000000;
+ font-family: 'Segoe UI',Verdana,Arial;
+ font-size: 0.813em;
+ font-style: normal;
+ word-wrap: break-word;
+}
+
+/*BEGIN HEADERS*/
+.h1, h1 {
+ color: #3A3E43;
+ font-family: 'Segoe UI',Verdana,Arial;
+ font-size: 1.4em;
+ font-weight: bold;
+ margin: 0;
+}
+
+.h2, h2 {
+ color: #3A3E43;
+ font-family: 'Segoe UI',Verdana,Arial;
+ font-size: 1.2em;
+ font-weight: bold;
+}
+.h3, h3 {
+ color: #3A3E43;
+ font-family: 'Segoe UI',Verdana,Arial;
+ font-size: 1.077em;
+ font-weight: bold;
+}
+.h4, h4 {
+ color: #3A3E43;
+ font-family: 'Segoe UI',Verdana,Arial;
+ font-size: 1em;
+ font-weight: bold;
+}
+h4.subHeading {
+ margin-bottom: 7px;
+ margin-top: 13px;
+}
+/*END HEADERS*/
+
+/*BEGIN LINKS*/
+a:link {
+ color: #00749E;
+ text-decoration: none;
+}
+a:hover {
+ text-decoration: underline;
+}
+a:visited {
+ color: #960BB4;
+ text-decoration: none;
+}
+a:focus {
+ outline: 1px dotted #000000;
+}
+
+a.libraryLink:link {
+ text-decoration:none;
+ border-bottom:1px dotted;
+}
+
+/*END LINKS*/
+
+/*BEGIN IMAGES*/
+img {
+ border: 0 none;
+}
+/*END IMAGES*/
+
+/*BEGIN TABLE*/
+.title table {
+ color: #000000;
+ font-family: 'Segoe UI',Verdana,Arial;
+ font-size: 1.077em;
+ font-style: normal;
+}
+table {
+ border-collapse: collapse;
+}
+
+table, table th, table td {
+ border:1px solid #BBBBBB;
+}
+/*END TABLE*/
+
+/*BEGIN LIST*/
+ul {
+ list-style-type: disc;
+ margin-left:40px;
+ padding-left: 0;
+}
+ul li {
+ padding-bottom: 10px;
+}
+ol {
+ margin-left:40px;
+ padding-left: 0;
+}
+ol li {
+ padding-bottom: 10px;
+}
+/*END LIST*/
+
+.scriptcode {
+ position: relative;
+ padding: 8px 8px 8px 8px;
+ background: #FFFFFF;
+ font-size: 12px;
+ line-height: 125%;
+ font-weight:normal;
+}
+.scriptcode pre
+{
+ white-space: pre-wrap !important; /* css-3 */
+ word-wrap: break-word !important; /* Internet Explorer 5.5+ */
+ margin:0 0 10px 0 !important;
+ padding: 10px;
+ border-top: solid 2px #D0D2D2;
+ border-bottom: solid 2px #D0D2D2;
+ border-left: solid 1px #D0D2D2;
+ border-right: solid 1px #D0D2D2;
+}
+
+.scriptcode .title {
+ color:#E66A38;
+ font-size: 12px;
+ font-weight:bold;
+ margin: 0;
+ min-height: 23px;
+}
+.scriptcode .title > span:first-child {
+ border-left: solid 1px #D0D2D2;
+}
+.scriptcode .title > span {
+ padding: 4px 8px 4px 8px;
+ display: inline-block;
+ border-top: 1px solid #D0D2D2;
+ border-right: 1px solid #D0D2D2;
+ border-collapse: collapse;
+ text-align: center;
+ background: white;
+}
+.scriptcode .title > span.otherTab {
+ color: #1364C4;
+ background: #EFF5FF;
+ cursor: pointer;
+}
+
+.scriptcode .hidden {
+ display: none !important;
+ visibility: hidden !important;
+}
+
+.scriptcode .copyCode {
+ padding: 8px 2px 0 2px !important;
+ margin-right: 15px;
+ position: absolute !important;
+ right: 0 !important;
+ top: 17px;
+ display:block !important;
+ background: #FFFFFF;
+}
+.scriptcode .pluginLinkHolder {
+ display: none;
+}
+.scriptcode .pluginEditHolderLink {
+ display: none;
+}
+
+.Opera wbr
+{
+ display: inline-block;
+}
+
+.IE9 wbr:after
+{
+content: "\00200B";
+}
diff --git a/description/offline.js b/description/offline.js
new file mode 100644
index 0000000..a3941e1
--- /dev/null
+++ b/description/offline.js
@@ -0,0 +1,52 @@
+var Galleries = Galleries || { };
+
+(function() {
+
+ function findElem(parent, tagName, className) {
+ var elemToSearch = (parent) ? parent : document.body;
+ var tagMatch = elemToSearch.getElementsByTagName(tagName);
+ var evaluator = function(elem) {
+ return (className) ? (elem.className.indexOf(className) > -1) : true;
+ };
+
+ return findArrayElem(tagMatch, evaluator);
+ }
+
+ function findArrayElem(array, evaluator) {
+ var newArray = new Array();
+ for (var count = 0; count < array.length; count++) {
+ if (evaluator(array[count])) {
+ newArray.push(array[count]);
+ }
+ }
+ return newArray;
+ }
+
+ function iterateElem(elems, delegate) {
+ for(var count = 0; count < elems.length; count++) {
+ delegate(count, elems[count]);
+ }
+ }
+
+ function isHidden(elem) {
+ return (elem.offsetHeight === 0 && elem.offsetWidth === 0) || elem.style && elem.style.display === "none";
+ }
+
+ function onWindowLoad(callback) {
+ attachEventHandler(null, 'load', callback);
+ }
+
+ function attachEventHandler(elem, event, callback) {
+ var elemToAttach = (elem) ? elem : window;
+ if (document.addEventListener) {
+ elemToAttach.addEventListener(event, callback, false);
+ } else if ( document.attachEvent ) {
+ elemToAttach.attachEvent('on' + event, callback);
+ }
+ }
+
+ Galleries.findElem = findElem;
+ Galleries.iterateElem = iterateElem;
+ Galleries.attachEventHandler = attachEventHandler;
+ Galleries.onWindowLoad = onWindowLoad;
+})(); \ No newline at end of file
diff --git a/license.rtf b/license.rtf
new file mode 100644
index 0000000..93a8878
--- /dev/null
+++ b/license.rtf
@@ -0,0 +1,25 @@
+{\rtf1\ansi\ansicpg1252\uc1\htmautsp\deff2{\fonttbl{\f0\fcharset0 Times New Roman;}{\f2\fcharset0 MS Shell Dlg;}}{\colortbl\red0\green0\blue0;\red255\green255\blue255;}\loch\hich\dbch\pard\plain\ltrpar\itap0{\lang1033\fs16\f2\cf0 \cf0\ql{\f2 \line \li0\ri0\sa0\sb0\fi0\ql\par}
+{\fs40\f2 {\ltrch MICROSOFT LIMITED PUBLIC LICENSE version 1.1}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 \line {\ltrch ----------------------}\line \li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch This license governs use of code marked as \ldblquote sample\rdblquote or \ldblquote example\rdblquote available on this web site without a license agreement, as provided under the section above titled \ldblquote NOTICE SPECIFIC TO SOFTWARE AVAILABLE ON THIS WEB SITE.\rdblquote If you use such code (the \ldblquote software\rdblquote ), you accept this license. If you do not accept the license, do not use the software.}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 \line \li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch 1. Definitions}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch The terms \ldblquote reproduce,\rdblquote \ldblquote reproduction,\rdblquote \ldblquote derivative works,\rdblquote and \ldblquote distribution\rdblquote have the same meaning here as under U.S. copyright law. }\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch A \ldblquote contribution\rdblquote is the original software, or any additions or changes to the software.}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch A \ldblquote contributor\rdblquote is any person that distributes its contribution under this license.}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch \ldblquote Licensed patents\rdblquote are a contributor\rquote s patent claims that read directly on its contribution.}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 \line \li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch 2. Grant of Rights}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch (A) Copyright Grant - Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch (B) Patent Grant - Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 \line \li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch 3. Conditions and Limitations}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch (A) No Trademark License- This license does not grant you rights to use any contributors\rquote name, logo, or trademarks.}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch (E) The software is licensed \ldblquote as-is.\rdblquote You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch (F) Platform Limitation - The licenses granted in sections 2(A) and 2(B) extend only to the software or derivative works that you create that run directly on a Microsoft Windows operating system product, Microsoft run-time technology (such as the .NET Framework or Silverlight), or Microsoft application platform (such as Microsoft Office or Microsoft Dynamics).}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 \line \li0\ri0\sa0\sb0\fi0\ql\par}
+}
+} \ No newline at end of file