* 前情提要之本文另一篇: Windows Driver 開發學習筆記
* Graphic driver要了解一下
* Umd kmd 基本概念要懂
* 會寫程式 XD
關於 WDF 、WDK、WDM、DDK 介紹
(轉自: DDK與WDK的區別與聯繫)
最近嘗試去了解WINDOWS下的驅動開發,現在總結一下最近看到的資料。
1. 專門的開發包
首先,先從基礎的東西說起,開發WINDOWS下的驅動程序,需要一個專門的開發包
如:
- 開發 JAVA 程序,我們可能需要一個JDK
- 開發 WINDOWS 應用程式(Applications),我們需要WINDOWS的SDK
- 開發 WINDOWS 下的驅動程序(Drivers),我們需要一個DDK/WDK。
2. DDK(Driver Developer Kit)和 WDK(Windows Driver Kit)的區別:
這個要說說驅動相關的一些歷史:
- (1). 95/98/ME下,驅動模型為:Vxd, 相關資料可以看《編程高手箴言》的前幾個章節,裡面有很詳細的介紹,雖然這個東西已經過時,但大概看看還是會增長見識的。
- (2). 2000/XP/2003下,Windows採用WDM驅動模型(Windows Driver Model),開發2000/XP/2003的驅動開發包為:DDK。
- (3). Vista及以後版本,採用了WDF驅動模型(Windows Driver Foudation),對應的開發包:WDK。
其實WDK可以看做是DDK的升級版本,現在一般的WDK是包含以前DDK相關的功能,現在XP下也可以用WDK開發驅動,WDK能編譯出2000-2008的各種驅動。
3. 副檔名的區別
- Vxd驅動文件擴展名為:.vxd。
- WDM和WDF驅動文件擴展名為:.sys。
4. 相關的名詞解釋
- DDK——Driver Developer Kit,設備驅動程序開發包。
- WDK——Windows Driver Kit,Windows驅動程序開發包,就是DDK升級改名了。
- VxD——Virtual Device Driver,虛擬設備驅動程序,9X中的一種驅動程序。
- WDM——Windows Driver Model,Windows驅動程序模型,98以上版本的一種驅動程序。
- WDF——Windows Driver Frameworks, 驅動程序包括兩個類型,一個是內核級的,稱為KMDF(Kernel-Mode Driver Framework),為SYS文件;另一個是用戶級的,稱為UMDF(User-Mode Driver Framework),為DLL文件。
- 驅動程序的文件格式都是PE格式。
windows驅動開發: 比較 WDM 與 WDF
(轉載自 yinaiyun52)
如所周知,自Windows 2000開始,開發驅動程序必以WDM為基礎的,但其開發難度之大,根本不能奢望像用戶模式應用程序開發那樣容易。為改善這種局面,微軟推出了新的驅動程序開發環境 – WDF驅動模型。
WDF驅動框架對WDM進行了一次封裝
WDF框架就好像C++中的基類一樣,且這個基類中的model, IO model ,pnp和電源管理模型;且提供了一些與操作系統相關的處理函數,這些函數好像C++中的虛函數一樣,WDF驅動中能夠對這些函數進行override;特別是Pnp管理和電源管理!基本上都由WDF框架做了,而WDF的功能驅動幾乎不要對它進行特殊的處理;
要預先指出的是,WDF這不是另起爐灶改弦更張,而是以WDM為基礎進行了建模和封裝,顯著特點是降低了開發難度。
因為:
1、 將原來普通程序設計中基於對象的技術應用到了驅動開發中。 WDM中雖也有對像模型,但與真正的基於對象技術根本就不是一回事。為了實現基於對象的技術,微軟精心設計了對像模型並進行了封裝。屬性、方法、事件等等“一個都不能少”。
2、 無論內核模式的驅動程序或者用戶模式的驅動程序,都採用同一套對像模型構建,採用同一個基礎承載。這個基礎就是WDF。 WDF雖然已經是經過封裝和定義的對像模型,但對內核模式和用戶模式對象來說,WDF又是兩者的父對象。換言之兩者都是繼承了WDF才得到的,或者都是從WDF派生而來的。相對於內核模式,派生出的對象稱為“KMD框架”即KMDF;相對於用戶模式,派生出的模型稱為“UMD框架”即UMDF。無論何種模式的框架,其內部封裝的方法、執行的行為其實還是用WDM完成的。
3、 更重要的,也是微軟反复炫耀的是封裝了驅動程序中的某些共同行為:例如即插即用和電源管理就屬於這種共同行為。因為大多數驅動程序中都需要處理即插即用和電源管理問題,據說這大概要上千行的代碼,況且,沒有相當水平還不一定能處理好。為了一勞永逸,WDF乾脆將即插即用和電源管理封裝了進了對象之內,一舉成了對象的缺省(默認)行為。
4、 改變了操作系統內核與驅動程序之間的關係,WDM驅動程序中,一方面要處理硬件,另一方面要處理驅動程序與操作系統內核的交互。現在WDF則將驅動程序與操作系統內核之間進行了分離,驅動程序與操作系統交互工作交給框架內封裝的方法(函數)完成,這樣驅動開發者只需專注處理硬件的行為即可。這不僅避免了顧此失彼兩面不周的弊端,也由於雙方的分離,對操作系統內的某些改動,硬件製造商配套驅動程序的開發都有莫大的好處。
5、 兩種模式的驅動程序(KMDF、UMDF)都使用同一環境進行構建,這一環境稱為WDK。
即KMDF,UMDF的開發環境為WDK。
Windows Device Kit (WDK): 把測試套件(test suites)集成進來,DDK 就成了WDK。 WDK是針對微軟操作系統系列的驅動器集成開發系統。它組合了Windows DDK和Hardware Compatibility Test (HCT) kits(硬件兼容性測試工具),同時提供了微軟內部用來測試Windows操作系統穩定性和可靠性的測試套件。
6、 雖然經過封裝並引入基於對象的技術,所開發的驅動程序在執行效率上並不比原來遜色。
WDF和WDM的關係有點類似於MFC和Windows SDK的關係。 WDF只是在WDM上面加了一層,來簡化driver的開發,特別是PNP,power和IO cancellation 等幾個方面有很大改進。
現在學習WDF最好的資料還是DDK帶的sample code。 WHDC有一些資料:
http://www.microsoft.com/whdc/driver/wdf/default.mspx
再繼續說新舊時代
關鍵的visual studio 2012, 新時代忽然就來了, VS2012是Win8發布之後才出來的,有很多針對Win8的特性,但也能在Win7/Vista系統上運行。
舊時代
近期的win8與win10的系統出現以前, 也就是含win7之前的系統, 如果要開發kernel/driver的驅動程式, 環境的準備比較繁瑣, 首先需要手動下載WDK並安裝, 因為開發環境是在安裝好的WDK當中。WDK是Windows Driver Kit縮寫,即Windows驅動開發包。它提供的開發環境非常簡陋,不是一個便於開發的IDE環境,而僅僅是一些散裝的編譯工具包。
新時代
基本上必須要安裝三個軟體:
1. 我這裡使用 visual studio 2015版本 (或2012之後的版本)
2. WDK 10 (或Win8之後的版本)
3. Win10 SDK
請您先下載安裝 VS2015, 再安裝 Win10 的 WDK, 然後WDK的編譯環境就會自動整合進去 VS2015裡面, 所以重新開啟VS2015的時候, 在new project 新項目嚮導裡面, 就能夠找到driver(內核驅動)項目了。
開啟 Visual Studio 2015,選擇 New Project 建立新專案:
選擇 Visual C++ > Windows Driver > WDF
跳出的分別是有自動生成代碼的KMDF和沒有自動代碼的KMDF(empty),以及UMDF
我們選擇 Kernel Mode Driver (KMDF),直接按 OK 用預設值建立一個簡單的 driver 專案
測試安裝好的 Visual Studio 2015 + Windows SDK 10 + Windows Driver Kit 10
正常的話, 可以編譯通過successfully!
微軟釋出的 Driver samples for Windows 10 – 擷取video 部分
網址: https://github.com/microsoft/Windows-driver-samples/tree/master/video/KMDOD
目前我使用的為visual studio 2015 + (WinSDK)Windows Software Development kit 10.0.14393.33 + (WDK)Windows Driver kit 10.0.14393.0
資源指令碼檔案 .rc
包含目前專案中的資源所適用之指令碼的資源指令碼檔。 .aps 檔會在您每次存檔時覆寫此檔案。
原始檔控制中包含此檔案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
/*++ 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" |
驅動程式檔案 .inf
.INF是 Device Information File 的縮寫,是微軟為供硬體製造商散佈其設備驅動程式而發展, .INF 檔是一種具有特定格式的純文字檔,我們可說它是種安裝腳本檔(Setup Script)。為甚麼當我們在檔案總管對 .INF 檔按右鍵後,快顯功能表會出現「安裝」指令呢? 這是因為微軟已在其作業系統 Windows 中提供了 Setup API(註一),程式設計師只需用任何文書編輯軟體撰寫 .INF 檔,便可完成大部份的安裝工作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
;++ ; ; Copyright (c) 2011 Microsoft Corporation ; ; Module Name: ; ; SampleDisplay.inf ; ; Abstract: ; ; Inf file for Kernel mode display only sample driver ; ;-- [Version] Signature = "$Windows NT$" Class=Display ClassGUID={4d36e968-e325-11ce-bfc1-08002be10318} Provider=%ProviderString% DriverVer= 03/15/2011, 0.03.15.0011 CatalogFile=SampleDisplay.cat [DestinationDirs] KDODSamp.Files = 12 [SourceDisksNames] 0=%SampleDisk% [SourceDisksFiles] SampleDisplay.sys=0 [Manufacturer] %ManufacturerName%=Standard,NTx86,NTamd64,NTarm,NTarm64 ; ; Allow the driver to be loaded on VGA and XGA exposed by PCI bus and ACPI ; [Standard.NTx86] %SampleDeviceName% = KDODSamp_Inst, PCI\CC_0300 %SampleDeviceName% = KDODSamp_Inst, PCI\CC_0301 %SampleDeviceName% = KDODSamp_Inst, ACPI\CLS_0003&SUBCLS_0000 %SampleDeviceName% = KDODSamp_Inst, ACPI\CLS_0003&SUBCLS_0001 [Standard.NTamd64] %SampleDeviceName% = KDODSamp_Inst, PCI\CC_0300 %SampleDeviceName% = KDODSamp_Inst, PCI\CC_0301 %SampleDeviceName% = KDODSamp_Inst, ACPI\CLS_0003&SUBCLS_0000 %SampleDeviceName% = KDODSamp_Inst, ACPI\CLS_0003&SUBCLS_0001 [Standard.NTarm] %SampleDeviceName% = KDODSamp_Inst, PCI\CC_0300 %SampleDeviceName% = KDODSamp_Inst, PCI\CC_0301 %SampleDeviceName% = KDODSamp_Inst, ACPI\CLS_0003&SUBCLS_0000 %SampleDeviceName% = KDODSamp_Inst, ACPI\CLS_0003&SUBCLS_0001 [Standard.NTarm64] %SampleDeviceName% = KDODSamp_Inst, PCI\CC_0300 %SampleDeviceName% = KDODSamp_Inst, PCI\CC_0301 %SampleDeviceName% = KDODSamp_Inst, ACPI\CLS_0003&SUBCLS_0000 %SampleDeviceName% = KDODSamp_Inst, ACPI\CLS_0003&SUBCLS_0001 [KDODSamp_Inst] FeatureScore=F9 CopyFiles = KDODSamp.Files ; ; Install driver service ; [KDODSamp_Inst.Services] AddService = KDODSamp,0x00000002,KDODSamp_Service_Inst,KDODSamp_EventLog_Inst [KDODSamp_Service_Inst] ServiceType = %SERVICE_KERNEL_DRIVER% StartType = %SERVICE_DEMAND_START% ErrorControl = %SERVICE_ERROR_IGNORE% ServiceBinary = %12%\SampleDisplay.sys ; ; Display Adapter Specific Settings ; [KDODSamp.Files] SampleDisplay.sys [KDODSamp_EventLog_Inst] AddReg = KDODSamp_EventLog_Inst.AddReg [KDODSamp_EventLog_Inst.AddReg] HKR,,EventMessageFile,%REG_EXPAND_SZ%,"%%SystemRoot%%\System32\IoLogMsg.dll" HKR,,TypesSupported,%REG_DWORD%,7 [Strings] ; *******Localizable Strings******* ProviderString="TODO-Set-Provider" ManufacturerName="TODO-Set-Manufacturer" SampleDisk = "Sample Disk" SampleDeviceName = "Kernel mode display only sample driver" ; *******Non Localizable Strings******* SERVICE_BOOT_START = 0x0 SERVICE_SYSTEM_START = 0x1 SERVICE_AUTO_START = 0x2 SERVICE_DEMAND_START = 0x3 SERVICE_DISABLED = 0x4 SERVICE_KERNEL_DRIVER = 0x1 SERVICE_ERROR_IGNORE = 0x0 SERVICE_ERROR_NORMAL = 0x1 SERVICE_ERROR_SEVERE = 0x2 SERVICE_ERROR_CRITICAL = 0x3 REG_MULTI_SZ = 0x00010000 REG_EXPAND_SZ = 0x00020000 REG_DWORD = 0x00010001 |
C++程式標頭檔案 bdd.hxx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 |
/******************************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> }; #define EDID_V1_BLOCK_SIZE 128 #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 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, size_t s); 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_ |
C++程式檔案 bdd.cxx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 |
/******************************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 = 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; } case DXGKQAITYPE_DISPLAY_DRIVERCAPS_EXTENSION: { DXGK_DISPLAY_DRIVERCAPS_EXTENSION* pDriverDisplayCaps; if (pQueryAdapterInfo->OutputDataSize < sizeof(*pDriverDisplayCaps)) { BDD_LOG_ERROR2("pQueryAdapterInfo->OutputDataSize (0x%I64x) is smaller than sizeof(DXGK_DISPLAY_DRIVERCAPS_EXTENSION) (0x%I64x)", pQueryAdapterInfo->OutputDataSize, sizeof(DXGK_DISPLAY_DRIVERCAPS_EXTENSION)); return STATUS_INVALID_PARAMETER; } pDriverDisplayCaps = (DXGK_DISPLAY_DRIVERCAPS_EXTENSION*)pQueryAdapterInfo->pOutputData; // Reset all caps values RtlZeroMemory(pDriverDisplayCaps, pQueryAdapterInfo->OutputDataSize); // We claim to support virtual display mode. pDriverDisplayCaps->VirtualModeSupport = 1; 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 |
C++程式檔案 bdd_ddi.cxx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 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; 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; } 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) |
C++程式檔案 bdd_dmm.cxx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 |
/******************************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; // Since clone is not supported, should not support path-independent rotations LocalVidPnPresentPath.ContentTransformation.RotationSupport.Offset0 = 1; 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; 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; } } |
C++程式檔案 bdd_util.cxx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
/******************************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 = MmMapIoSpaceEx(PhysicalAddress, Length, PAGE_READWRITE | PAGE_WRITECOMBINE); if (*VirtualAddress == NULL) { // The underlying call to MmMapIoSpace failed. This may be because, MmWriteCombined // isn't supported, so try again with MmNonCached *VirtualAddress = MmMapIoSpaceEx(PhysicalAddress, Length, PAGE_READWRITE | PAGE_NOCACHE); 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; } |
最後找出diagnostic tool關於 video & graphic card部分的測試
參考文章:
微軟 Getting started with Windows drivers
Steward
小z说:内核驱动的编译环境
VS2012开发驱动小Tip之:更改KMDF版本以支持XP系统