Changeset 34430 in vbox for trunk/src/VBox/Additions/common/VBoxVideo
- Timestamp:
- Nov 27, 2010 2:07:28 AM (14 years ago)
- Location:
- trunk/src/VBox/Additions/common/VBoxVideo
- Files:
-
- 1 added
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxVideo/HGSMIBase.cpp
r34390 r34430 1 1 /* $Id$ */ 2 2 /** @file 3 * VirtualBox Video miniport driver for NT/2k/XP - HGSMI related functions. 3 * VirtualBox Video driver, common code - HGSMI initialisation and helper 4 * functions. 4 5 */ 5 6 6 7 /* 7 * Copyright (C) 2006-20 09Oracle Corporation8 * Copyright (C) 2006-2010 Oracle Corporation 8 9 * 9 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 16 17 */ 17 18 18 #include <string.h> 19 20 #include "VBoxVideo.h" 21 #include "Helper.h" 19 #include <VBox/VBoxVideoGuest.h> 20 #include <VBox/VBoxVideo.h> 21 #include <VBox/VBoxGuest.h> 22 #include <VBox/Hardware/VBoxVideoVBE.h> 23 #include <VBox/VMMDev.h> 22 24 23 25 #include <iprt/asm.h> 24 26 #include <iprt/log.h> 25 #include <iprt/thread.h> 26 #include <VBox/VMMDev.h> 27 #include <VBox/VBoxGuest.h> 28 #include <VBox/VBoxVideo.h> 29 30 // #include <VBoxDisplay.h> 31 32 // #include "vboxioctl.h" 27 28 #include <string.h> 33 29 34 30 /** Send completion notification to the host for the command located at offset 35 31 * @a offt into the host command buffer. */ 36 void HGSMINotifyHostCmdComplete(PHGSMIHOSTCOMMANDCONTEXT pCtx, HGSMIOFFSET offt)32 static void HGSMINotifyHostCmdComplete(PHGSMIHOSTCOMMANDCONTEXT pCtx, HGSMIOFFSET offt) 37 33 { 38 34 VBoxVideoCmnPortWriteUlong(pCtx->port, offt); 39 35 } 40 36 41 /** Acknowlege an IRQ. */ 42 void HGSMIClearIrq(PHGSMIHOSTCOMMANDCONTEXT pCtx) 43 { 44 VBoxVideoCmnPortWriteUlong(pCtx->port, HGSMIOFFSET_VOID); 45 } 46 47 /** Inform the host that a command has been handled. */ 48 static void HGSMIHostCmdComplete(PHGSMIHOSTCOMMANDCONTEXT pCtx, void * pvMem) 37 38 /** 39 * Inform the host that a command has been handled. 40 * 41 * @param pCtx the context containing the heap to be used 42 * @param pvMem pointer into the heap as mapped in @a pCtx to the command to 43 * be completed 44 */ 45 RTDECL(void) VBoxHGSMIHostCmdComplete(PHGSMIHOSTCOMMANDCONTEXT pCtx, 46 void *pvMem) 49 47 { 50 48 HGSMIBUFFERHEADER *pHdr = HGSMIBufferHeaderFromData(pvMem); … … 57 55 } 58 56 57 59 58 /** Submit an incoming host command to the appropriate handler. */ 60 59 static void hgsmiHostCmdProcess(PHGSMIHOSTCOMMANDCONTEXT pCtx, … … 78 77 } 79 78 79 80 80 /** Get and handle the next command from the host. */ 81 81 static void hgsmiHostCommandQueryProcess(PHGSMIHOSTCOMMANDCONTEXT pCtx) … … 86 86 } 87 87 88 88 89 /** Drain the host command queue. */ 89 void hgsmiProcessHostCommandQueue(PHGSMIHOSTCOMMANDCONTEXT pCtx)90 RTDECL(void) VBoxHGSMIProcessHostQueue(PHGSMIHOSTCOMMANDCONTEXT pCtx) 90 91 { 91 92 while (pCtx->pfHostFlags->u32HostFlags & HGSMIHOSTFLAGS_COMMANDS_PENDING) … … 98 99 } 99 100 101 100 102 /** Detect whether HGSMI is supported by the host. */ 101 bool VBoxHGSMIIsSupported(void)103 RTDECL(bool) VBoxHGSMIIsSupported(void) 102 104 { 103 105 uint16_t DispiId; … … 112 114 113 115 114 void* vboxHGSMIBufferAlloc(PHGSMIGUESTCOMMANDCONTEXT pCtx, 115 HGSMISIZE cbData, 116 uint8_t u8Ch, 117 uint16_t u16Op) 116 /** 117 * Allocate and initialise a command descriptor in the guest heap for a 118 * guest-to-host command. 119 * 120 * @returns pointer to the descriptor's command data buffer 121 * @param pCtx the context containing the heap to be used 122 * @param cbData the size of the command data to go into the descriptor 123 * @param u8Ch the HGSMI channel to be used, set to the descriptor 124 * @param u16Op the HGSMI command to be sent, set to the descriptor 125 */ 126 RTDECL(void *) VBoxHGSMIBufferAlloc(PHGSMIGUESTCOMMANDCONTEXT pCtx, 127 HGSMISIZE cbData, 128 uint8_t u8Ch, 129 uint16_t u16Op) 118 130 { 119 131 #ifdef VBOX_WITH_WDDM … … 123 135 } 124 136 125 void vboxHGSMIBufferFree(PHGSMIGUESTCOMMANDCONTEXT pCtx, void *pvBuffer) 137 138 /** 139 * Free a descriptor allocated by @a VBoxHGSMIBufferAlloc. 140 * 141 * @param pCtx the context containing the heap used 142 * @param pvBuffer the pointer returned by @a VBoxHGSMIBufferAlloc 143 */ 144 RTDECL(void) VBoxHGSMIBufferFree(PHGSMIGUESTCOMMANDCONTEXT pCtx, 145 void *pvBuffer) 126 146 { 127 147 #ifdef VBOX_WITH_WDDM … … 131 151 } 132 152 133 int vboxHGSMIBufferSubmit(PHGSMIGUESTCOMMANDCONTEXT pCtx, void *pvBuffer) 153 154 /** 155 * Submit a command descriptor allocated by @a VBoxHGSMIBufferAlloc. 156 * 157 * @param pCtx the context containing the heap used 158 * @param pvBuffer the pointer returned by @a VBoxHGSMIBufferAlloc 159 */ 160 RTDECL(int) VBoxHGSMIBufferSubmit(PHGSMIGUESTCOMMANDCONTEXT pCtx, 161 void *pvBuffer) 134 162 { 135 163 /* Initialize the buffer and get the offset for port IO. */ … … 148 176 149 177 178 /** Query the host for an HGSMI configuration parameter via an HGSMI command. 179 */ 150 180 static int vboxQueryConfHGSMI(PHGSMIGUESTCOMMANDCONTEXT pCtx, uint32_t u32Index, 151 181 uint32_t *pulValue) … … 164 194 p->u32Index = u32Index; 165 195 p->u32Value = 0; 166 rc = vboxHGSMIBufferSubmit(pCtx, p);196 rc = VBoxHGSMIBufferSubmit(pCtx, p); 167 197 if (RT_SUCCESS(rc)) 168 198 { … … 180 210 181 211 182 static int vboxHGSMIBufferLocation(PHGSMIGUESTCOMMANDCONTEXT pCtx, 183 HGSMIOFFSET offLocation) 212 /** Inform the host of the location of the host flags in VRAM via an HGSMI 213 * command. */ 214 static int vboxHGSMIReportFlagsLocation(PHGSMIGUESTCOMMANDCONTEXT pCtx, 215 HGSMIOFFSET offLocation) 184 216 { 185 217 HGSMIBUFFERLOCATION *p; … … 196 228 p->offLocation = offLocation; 197 229 p->cbLocation = sizeof(HGSMIHOSTFLAGS); 198 rc = vboxHGSMIBufferSubmit(pCtx, p);230 rc = VBoxHGSMIBufferSubmit(pCtx, p); 199 231 /* Free the IO buffer. */ 200 232 HGSMIHeapFree (&pCtx->heapCtx, p); … … 206 238 207 239 240 /** Notify the host of HGSMI-related guest capabilities via an HGSMI command. 241 */ 208 242 static int vboxHGSMISendCapsInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx, 209 243 uint32_t fCaps) … … 222 256 pCaps->rc = VERR_NOT_IMPLEMENTED; 223 257 pCaps->fCaps = fCaps; 224 rc = vboxHGSMIBufferSubmit(pCtx, pCaps);258 rc = VBoxHGSMIBufferSubmit(pCtx, pCaps); 225 259 if (RT_SUCCESS(rc)) 226 260 { … … 237 271 238 272 239 static int vboxVBVAInitInfoHeap(PHGSMIGUESTCOMMANDCONTEXT pCtx, 240 uint32_t u32HeapOffset, uint32_t u32HeapSize) 273 /** Tell the host about the location of the area of VRAM set aside for the host 274 * heap. */ 275 static int vboxHGSMIReportHostArea(PHGSMIGUESTCOMMANDCONTEXT pCtx, 276 uint32_t u32AreaOffset, uint32_t u32AreaSize) 241 277 { 242 278 VBVAINFOHEAP *p; … … 250 286 { 251 287 /* Prepare data to be sent to the host. */ 252 p->u32HeapOffset = u32 HeapOffset;253 p->u32HeapSize = u32 HeapSize;254 rc = vboxHGSMIBufferSubmit(pCtx, p);288 p->u32HeapOffset = u32AreaOffset; 289 p->u32HeapSize = u32AreaSize; 290 rc = VBoxHGSMIBufferSubmit(pCtx, p); 255 291 /* Free the IO buffer. */ 256 292 HGSMIHeapFree(&pCtx->heapCtx, p); … … 262 298 263 299 264 int VBoxHGSMISendViewInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx, uint32_t u32Count, 265 PFNHGSMIFILLVIEWINFO pfnFill, void *pvData) 300 /** 301 * Tell the host about how VRAM is divided up between each screen via an HGSMI 302 * command. It is acceptable to specifiy identical data for each screen if 303 * they share a single framebuffer. 304 * @todo confirm that that really is acceptable 305 * 306 * @returns iprt status code, either VERR_NO_MEMORY or the status returned by 307 * @a pfnFill 308 * @param pCtx the context containing the heap to use 309 * @param u32Count the number of screens we are activating 310 * @param pfnFill a callback which initialises the VBVAINFOVIEW structures 311 * for all screens 312 * @param pvData context data for @a pfnFill 313 */ 314 RTDECL(int) VBoxHGSMISendViewInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx, 315 uint32_t u32Count, 316 PFNHGSMIFILLVIEWINFO pfnFill, 317 void *pvData) 266 318 { 267 319 int rc; 268 320 /* Issue the screen info command. */ 269 void *p = vboxHGSMIBufferAlloc(pCtx, sizeof(VBVAINFOVIEW) * u32Count,321 void *p = VBoxHGSMIBufferAlloc(pCtx, sizeof(VBVAINFOVIEW) * u32Count, 270 322 HGSMI_CH_VBVA, VBVA_INFO_VIEW); 271 323 if (p) … … 274 326 rc = pfnFill(pvData, pInfo); 275 327 if (RT_SUCCESS(rc)) 276 vboxHGSMIBufferSubmit (pCtx, p);277 vboxHGSMIBufferFree(pCtx, p);328 VBoxHGSMIBufferSubmit (pCtx, p); 329 VBoxHGSMIBufferFree(pCtx, p); 278 330 } 279 331 else … … 298 350 * of the host flags 299 351 */ 300 void vboxHGSMIGetBaseMappingInfo(uint32_t cbVRAM,301 uint32_t *poffVRAMBaseMapping,302 uint32_t *pcbMapping,303 uint32_t *poffGuestHeapMemory,304 uint32_t *pcbGuestHeapMemory,305 uint32_t *poffHostFlags)352 RTDECL(void) VBoxHGSMIGetBaseMappingInfo(uint32_t cbVRAM, 353 uint32_t *poffVRAMBaseMapping, 354 uint32_t *pcbMapping, 355 uint32_t *poffGuestHeapMemory, 356 uint32_t *pcbGuestHeapMemory, 357 uint32_t *poffHostFlags) 306 358 { 307 359 AssertPtrReturnVoid(poffVRAMBaseMapping); … … 328 380 * @a pvGuestHeapMemory within the video RAM 329 381 */ 330 int vboxHGSMISetupGuestContext(PHGSMIGUESTCOMMANDCONTEXT pCtx,331 void *pvGuestHeapMemory,332 uint32_t cbGuestHeapMemory,333 uint32_t offVRAMGuestHeapMemory)382 RTDECL(int) VBoxHGSMISetupGuestContext(PHGSMIGUESTCOMMANDCONTEXT pCtx, 383 void *pvGuestHeapMemory, 384 uint32_t cbGuestHeapMemory, 385 uint32_t offVRAMGuestHeapMemory) 334 386 { 335 387 /** @todo should we be using a fixed ISA port value here? */ … … 345 397 * requests. 346 398 * 347 * @param pCtx the guest context used to query the host399 * @param pCtx the context containing the heap to use 348 400 * @param cbVRAM how much video RAM is allocated to the device 349 401 * @param offVRAMBaseMapping the offset of the basic communication structures 350 402 * into the guest's VRAM 351 * @param poffVRAMHostArea where to store the offset of the host area into 352 * the guest's VRAM 353 * @param pcbHostArea where to store the size of the host area 354 */ 355 void vboxHGSMIGetHostAreaMapping(PHGSMIGUESTCOMMANDCONTEXT pCtx, 356 uint32_t cbVRAM, uint32_t offVRAMBaseMapping, 357 uint32_t *poffVRAMHostArea, 358 uint32_t *pcbHostArea) 403 * @param poffVRAMHostArea where to store the offset into VRAM of the host 404 * heap area 405 * @param pcbHostArea where to store the size of the host heap area 406 */ 407 RTDECL(void) VBoxHGSMIGetHostAreaMapping(PHGSMIGUESTCOMMANDCONTEXT pCtx, 408 uint32_t cbVRAM, 409 uint32_t offVRAMBaseMapping, 410 uint32_t *poffVRAMHostArea, 411 uint32_t *pcbHostArea) 359 412 { 360 413 uint32_t offVRAMHostArea = offVRAMBaseMapping, cbHostArea = 0; … … 387 440 388 441 389 /** Initialise the host context structure. */ 390 void vboxHGSMISetupHostContext(PHGSMIHOSTCOMMANDCONTEXT pCtx, 391 void *pvBaseMapping, uint32_t offHostFlags, 392 void *pvHostAreaMapping, 393 uint32_t offVRAMHostArea, uint32_t cbHostArea) 442 /** 443 * Initialise the host context structure. 444 * 445 * @param pCtx the context structure to initialise 446 * @param pvBaseMapping where the basic HGSMI structures are mapped at 447 * @param offHostFlags the offset of the host flags into the basic HGSMI 448 * structures 449 * @param pvHostAreaMapping where the area for the host heap is mapped at 450 * @param offVRAMHostArea offset of the host heap area into VRAM 451 * @param cbHostArea size in bytes of the host heap area 452 */ 453 RTDECL(void) VBoxHGSMISetupHostContext(PHGSMIHOSTCOMMANDCONTEXT pCtx, 454 void *pvBaseMapping, 455 uint32_t offHostFlags, 456 void *pvHostAreaMapping, 457 uint32_t offVRAMHostArea, 458 uint32_t cbHostArea) 394 459 { 395 460 uint8_t *pu8HostFlags = ((uint8_t *)pvBaseMapping) + offHostFlags; … … 403 468 404 469 /** 405 * Mirror the information in the host context structure to the host. 406 */ 407 static int vboxHGSMISendHostCtxInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx, 408 HGSMIOFFSET offBufferLocation, 409 uint32_t fCaps, uint32_t u32HeapOffset, 410 uint32_t u32HeapSize) 470 * Tell the host about the ways it can use to communicate back to us via an 471 * HGSMI command 472 * 473 * @returns iprt status value 474 * @param pCtx the context containing the heap to use 475 * @param offVRAMFlagsLocation where we wish the host to place its flags 476 * relative to the start of the VRAM 477 * @param fCaps additions HGSMI capabilities the guest 478 * supports 479 * @param offVRAMHostArea offset into VRAM of the host heap area 480 * @param cbHostArea size in bytes of the host heap area 481 */ 482 RTDECL(int) VBoxHGSMISendHostCtxInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx, 483 HGSMIOFFSET offVRAMFlagsLocation, 484 uint32_t fCaps, 485 uint32_t offVRAMHostArea, 486 uint32_t cbHostArea) 411 487 { 412 488 Log(("VBoxVideo::vboxSetupAdapterInfo\n")); … … 414 490 /* setup the flags first to ensure they are initialized by the time the 415 491 * host heap is ready */ 416 int rc = vboxHGSMI BufferLocation(pCtx, offBufferLocation);492 int rc = vboxHGSMIReportFlagsLocation(pCtx, offVRAMFlagsLocation); 417 493 AssertRC(rc); 418 494 if (RT_SUCCESS(rc) && fCaps) … … 425 501 { 426 502 /* Report the host heap location. */ 427 rc = vbox VBVAInitInfoHeap(pCtx, u32HeapOffset, u32HeapSize);503 rc = vboxHGSMIReportHostArea(pCtx, offVRAMHostArea, cbHostArea); 428 504 AssertRC(rc); 429 505 } … … 434 510 435 511 /** 436 * Returns the count of virtual monitors attached to the guest. Returns 437 * 1 on failure. 438 */ 439 unsigned vboxHGSMIGetMonitorCount(PHGSMIGUESTCOMMANDCONTEXT pCtx) 512 * Gets the count of virtual monitors attached to the guest via an HGSMI 513 * command 514 * 515 * @returns the right count on success or 1 on failure. 516 * @param pCtx the context containing the heap to use 517 */ 518 RTDECL(uint32_t) VBoxHGSMIGetMonitorCount(PHGSMIGUESTCOMMANDCONTEXT pCtx) 440 519 { 441 520 /* Query the configured number of displays. */ … … 451 530 452 531 /** 453 * Helper function to register secondary displays (DualView). Note that this will not 454 * be available on pre-XP versions, and some editions on XP will fail because they are 455 * intentionally crippled. 456 * 457 * HGSMI variant is a bit different because it uses only HGSMI interface (VBVA channel) 458 * to talk to the host. 459 */ 460 void VBoxSetupDisplaysHGSMI(PVBOXVIDEO_COMMON pCommon, 461 uint32_t AdapterMemorySize, uint32_t fCaps) 462 { 463 /** @todo I simply converted this from Windows error codes. That is wrong, 464 * but we currently freely mix and match those (failure == rc > 0) and iprt 465 * ones (failure == rc < 0) anyway. This needs to be fully reviewed and 466 * fixed. */ 467 int rc = VINF_SUCCESS; 468 uint32_t offVRAMBaseMapping, cbMapping, offGuestHeapMemory, cbGuestHeapMemory, 469 offHostFlags, offVRAMHostArea, cbHostArea; 470 Log(("VBoxVideo::VBoxSetupDisplays: pCommon = %p\n", pCommon)); 471 472 memset(pCommon, 0, sizeof(*pCommon)); 473 pCommon->cbVRAM = AdapterMemorySize; 474 pCommon->cDisplays = 1; 475 pCommon->bHGSMI = VBoxHGSMIIsSupported (); 476 /* Why does this use VBoxVideoCmnMemZero? The MSDN docs say that it should 477 * only be used on mapped display adapter memory. Done with memset above. */ 478 // VBoxVideoCmnMemZero(&pCommon->areaHostHeap, sizeof(HGSMIAREA)); 479 if (pCommon->bHGSMI) 480 { 481 vboxHGSMIGetBaseMappingInfo(pCommon->cbVRAM, &offVRAMBaseMapping, 482 &cbMapping, &offGuestHeapMemory, 483 &cbGuestHeapMemory, &offHostFlags); 484 485 /* Map the adapter information. It will be needed for HGSMI IO. */ 486 /** @todo all callers of VBoxMapAdapterMemory expect it to use iprt 487 * error codes, but it doesn't. */ 488 rc = VBoxMapAdapterMemory (pCommon, &pCommon->pvAdapterInformation, 489 offVRAMBaseMapping, cbMapping); 490 if (RT_FAILURE(rc)) 491 { 492 Log(("VBoxVideo::VBoxSetupDisplays: VBoxMapAdapterMemory pvAdapterInfoirrmation failed rc = %d\n", 493 rc)); 494 495 pCommon->bHGSMI = false; 496 } 497 else 498 { 499 /* Setup an HGSMI heap within the adapter information area. */ 500 rc = vboxHGSMISetupGuestContext(&pCommon->guestCtx, 501 pCommon->pvAdapterInformation, 502 cbGuestHeapMemory, 503 offVRAMBaseMapping 504 + offGuestHeapMemory); 505 506 if (RT_FAILURE(rc)) 507 { 508 Log(("VBoxVideo::VBoxSetupDisplays: HGSMIHeapSetup failed rc = %d\n", 509 rc)); 510 511 pCommon->bHGSMI = false; 512 } 513 } 514 } 515 516 /* Setup the host heap and the adapter memory. */ 517 if (pCommon->bHGSMI) 518 { 519 vboxHGSMIGetHostAreaMapping(&pCommon->guestCtx, pCommon->cbVRAM, 520 offVRAMBaseMapping, &offVRAMHostArea, 521 &cbHostArea); 522 if (cbHostArea) 523 { 524 525 /* Map the heap region. 526 * 527 * Note: the heap will be used for the host buffers submitted to the guest. 528 * The miniport driver is responsible for reading FIFO and notifying 529 * display drivers. 530 */ 531 pCommon->cbMiniportHeap = cbHostArea; 532 rc = VBoxMapAdapterMemory (pCommon, &pCommon->pvMiniportHeap, 533 offVRAMHostArea, cbHostArea); 534 if (RT_FAILURE(rc)) 535 { 536 pCommon->pvMiniportHeap = NULL; 537 pCommon->cbMiniportHeap = 0; 538 pCommon->bHGSMI = false; 539 } 540 else 541 vboxHGSMISetupHostContext(&pCommon->hostCtx, 542 pCommon->pvAdapterInformation, 543 offHostFlags, 544 pCommon->pvMiniportHeap, 545 offVRAMHostArea, cbHostArea); 546 } 547 else 548 { 549 /* Host has not requested a heap. */ 550 pCommon->pvMiniportHeap = NULL; 551 pCommon->cbMiniportHeap = 0; 552 } 553 } 554 555 if (pCommon->bHGSMI) 556 { 557 /* Setup the information for the host. */ 558 rc = vboxHGSMISendHostCtxInfo(&pCommon->guestCtx, 559 offVRAMBaseMapping + offHostFlags, 560 fCaps, offVRAMHostArea, 561 pCommon->cbMiniportHeap); 562 563 if (RT_FAILURE(rc)) 564 { 565 pCommon->bHGSMI = false; 566 } 567 } 568 569 /* Check whether the guest supports multimonitors. */ 570 if (pCommon->bHGSMI) 571 /* Query the configured number of displays. */ 572 pCommon->cDisplays = vboxHGSMIGetMonitorCount(&pCommon->guestCtx); 573 574 if (!pCommon->bHGSMI) 575 VBoxFreeDisplaysHGSMI(pCommon); 576 577 Log(("VBoxVideo::VBoxSetupDisplays: finished\n")); 578 } 579 580 static bool VBoxUnmapAdpInfoCallback(void *pvCommon) 581 { 582 PVBOXVIDEO_COMMON pCommon = (PVBOXVIDEO_COMMON)pvCommon; 583 584 pCommon->hostCtx.pfHostFlags = NULL; 585 return true; 586 } 587 588 void VBoxFreeDisplaysHGSMI(PVBOXVIDEO_COMMON pCommon) 589 { 590 VBoxUnmapAdapterMemory(pCommon, &pCommon->pvMiniportHeap); 591 HGSMIHeapDestroy(&pCommon->guestCtx.heapCtx); 592 593 /* Unmap the adapter information needed for HGSMI IO. */ 594 VBoxSyncToVideoIRQ(pCommon, VBoxUnmapAdpInfoCallback, pCommon); 595 VBoxUnmapAdapterMemory(pCommon, &pCommon->pvAdapterInformation); 596 } 597 598 599 bool vboxUpdatePointerShape(PHGSMIGUESTCOMMANDCONTEXT pCtx, 600 uint32_t fFlags, 601 uint32_t cHotX, 602 uint32_t cHotY, 603 uint32_t cWidth, 604 uint32_t cHeight, 605 uint8_t *pPixels, 606 uint32_t cbLength) 532 * Pass the host a new mouse pointer shape via an HGSMI command. 533 * 534 * @returns success or failure 535 * @todo why not return an iprt status code? 536 * @param fFlags cursor flags, @see VMMDevReqMousePointer::fFlags 537 * @param cHotX horizontal position of the hot spot 538 * @param cHotY vertical position of the hot spot 539 * @param cWidth width in pixels of the cursor 540 * @param cHeight height in pixels of the cursor 541 * @param pPixels pixel data, @see VMMDevReqMousePointer for the format 542 * @param cbLength size in bytes of the pixel data 543 */ 544 RTDECL(bool) VBoxHGSMIUpdatePointerShape(PHGSMIGUESTCOMMANDCONTEXT pCtx, 545 uint32_t fFlags, 546 uint32_t cHotX, 547 uint32_t cHotY, 548 uint32_t cWidth, 549 uint32_t cHeight, 550 uint8_t *pPixels, 551 uint32_t cbLength) 607 552 { 608 553 VBVAMOUSEPOINTERSHAPE *p; … … 649 594 /* Copy the actual pointer data. */ 650 595 memcpy (p->au8Data, pPixels, cbData); 651 rc = vboxHGSMIBufferSubmit(pCtx, p);596 rc = VBoxHGSMIBufferSubmit(pCtx, p); 652 597 if (RT_SUCCESS(rc)) 653 598 rc = p->i32Result; … … 663 608 } 664 609 665 #ifndef VBOX_WITH_WDDM666 typedef struct _VBVAMINIPORT_CHANNELCONTEXT667 {668 PFNHGSMICHANNELHANDLER pfnChannelHandler;669 void *pvChannelHandler;670 }VBVAMINIPORT_CHANNELCONTEXT;671 672 typedef struct _VBVADISP_CHANNELCONTEXT673 {674 /** The generic command handler builds up a list of commands - in reverse675 * order! - here */676 VBVAHOSTCMD *pCmd;677 bool bValid;678 }VBVADISP_CHANNELCONTEXT;679 680 typedef struct _VBVA_CHANNELCONTEXTS681 {682 PVBOXVIDEO_COMMON pCommon;683 uint32_t cUsed;684 uint32_t cContexts;685 VBVAMINIPORT_CHANNELCONTEXT mpContext;686 VBVADISP_CHANNELCONTEXT aContexts[1];687 }VBVA_CHANNELCONTEXTS;688 689 static int vboxVBVADeleteChannelContexts(PVBOXVIDEO_COMMON pCommon,690 VBVA_CHANNELCONTEXTS * pContext)691 {692 VBoxVideoCmnMemFreeDriver(pCommon, pContext);693 return VINF_SUCCESS;694 }695 696 static int vboxVBVACreateChannelContexts(PVBOXVIDEO_COMMON pCommon, VBVA_CHANNELCONTEXTS ** ppContext)697 {698 uint32_t cDisplays = (uint32_t)pCommon->cDisplays;699 const size_t size = RT_OFFSETOF(VBVA_CHANNELCONTEXTS, aContexts[cDisplays]);700 VBVA_CHANNELCONTEXTS * pContext = (VBVA_CHANNELCONTEXTS*)VBoxVideoCmnMemAllocDriver(pCommon, size);701 if(pContext)702 {703 memset(pContext, 0, size);704 pContext->cContexts = cDisplays;705 pContext->pCommon = pCommon;706 *ppContext = pContext;707 return VINF_SUCCESS;708 }709 return VERR_GENERAL_FAILURE;710 }711 712 static VBVADISP_CHANNELCONTEXT* vboxVBVAFindHandlerInfo(VBVA_CHANNELCONTEXTS *pCallbacks, int iId)713 {714 if(iId < 0)715 {716 return NULL;717 }718 else if(pCallbacks->cContexts > (uint32_t)iId)719 {720 return &pCallbacks->aContexts[iId];721 }722 return NULL;723 }724 725 DECLCALLBACK(void) hgsmiHostCmdComplete (HVBOXVIDEOHGSMI hHGSMI, struct _VBVAHOSTCMD * pCmd)726 {727 PHGSMIHOSTCOMMANDCONTEXT pCtx = &((PVBOXVIDEO_COMMON)hHGSMI)->hostCtx;728 HGSMIHostCmdComplete(pCtx, pCmd);729 }730 731 /** Reverses a NULL-terminated linked list of VBVAHOSTCMD structures. */732 static VBVAHOSTCMD *vboxVBVAReverseList(VBVAHOSTCMD *pList)733 {734 VBVAHOSTCMD *pFirst = NULL;735 while (pList)736 {737 VBVAHOSTCMD *pNext = pList;738 pList = pList->u.pNext;739 pNext->u.pNext = pFirst;740 pFirst = pNext;741 }742 return pFirst;743 }744 745 DECLCALLBACK(int) hgsmiHostCmdRequest (HVBOXVIDEOHGSMI hHGSMI, uint8_t u8Channel, uint32_t iDevice, struct _VBVAHOSTCMD ** ppCmd)746 {747 // if(display < 0)748 // return VERR_INVALID_PARAMETER;749 if(!ppCmd)750 return VERR_INVALID_PARAMETER;751 752 PHGSMIHOSTCOMMANDCONTEXT pCtx = &((PVBOXVIDEO_COMMON)hHGSMI)->hostCtx;753 754 /* pick up the host commands */755 hgsmiProcessHostCommandQueue(pCtx);756 757 HGSMICHANNEL *pChannel = HGSMIChannelFindById (&pCtx->channels, u8Channel);758 if(pChannel)759 {760 VBVA_CHANNELCONTEXTS * pContexts = (VBVA_CHANNELCONTEXTS *)pChannel->handler.pvHandler;761 VBVADISP_CHANNELCONTEXT *pDispContext = vboxVBVAFindHandlerInfo(pContexts, iDevice);762 Assert(pDispContext);763 if(pDispContext)764 {765 VBVAHOSTCMD *pCmd;766 do767 pCmd = ASMAtomicReadPtrT(&pDispContext->pCmd, VBVAHOSTCMD *);768 while (!ASMAtomicCmpXchgPtr(&pDispContext->pCmd, NULL, pCmd));769 *ppCmd = vboxVBVAReverseList(pCmd);770 771 return VINF_SUCCESS;772 }773 }774 775 return VERR_INVALID_PARAMETER;776 }777 778 779 static DECLCALLBACK(int) vboxVBVAChannelGenericHandler(void *pvHandler, uint16_t u16ChannelInfo, void *pvBuffer, HGSMISIZE cbBuffer)780 {781 VBVA_CHANNELCONTEXTS *pCallbacks = (VBVA_CHANNELCONTEXTS*)pvHandler;782 // Assert(0);783 Assert(cbBuffer > VBVAHOSTCMD_HDRSIZE);784 if(cbBuffer > VBVAHOSTCMD_HDRSIZE)785 {786 VBVAHOSTCMD *pHdr = (VBVAHOSTCMD*)pvBuffer;787 Assert(pHdr->iDstID >= 0);788 if(pHdr->iDstID >= 0)789 {790 VBVADISP_CHANNELCONTEXT* pHandler = vboxVBVAFindHandlerInfo(pCallbacks, pHdr->iDstID);791 Assert(pHandler && pHandler->bValid);792 if(pHandler && pHandler->bValid)793 {794 VBVAHOSTCMD *pFirst = NULL, *pLast = NULL;795 for(VBVAHOSTCMD *pCur = pHdr; pCur; )796 {797 Assert(!pCur->u.Data);798 Assert(!pFirst);799 Assert(!pLast);800 801 switch(u16ChannelInfo)802 {803 case VBVAHG_DISPLAY_CUSTOM:804 {805 #if 0 /* Never taken */806 if(pLast)807 {808 pLast->u.pNext = pCur;809 pLast = pCur;810 }811 else812 #endif813 {814 pFirst = pCur;815 pLast = pCur;816 }817 Assert(!pCur->u.Data);818 #if 0 /* Who is supposed to set pNext? */819 //TODO: use offset here820 pCur = pCur->u.pNext;821 Assert(!pCur);822 #else823 Assert(!pCur->u.pNext);824 pCur = NULL;825 #endif826 Assert(pFirst);827 Assert(pFirst == pLast);828 break;829 }830 case VBVAHG_EVENT:831 {832 VBVAHOSTCMDEVENT *pEventCmd = VBVAHOSTCMD_BODY(pCur, VBVAHOSTCMDEVENT);833 VBoxVideoCmnSignalEvent(pCallbacks->pCommon, pEventCmd->pEvent);834 }835 default:836 {837 Assert(u16ChannelInfo==VBVAHG_EVENT);838 Assert(!pCur->u.Data);839 #if 0 /* pLast has been asserted to be NULL, and who should set pNext? */840 //TODO: use offset here841 if(pLast)842 pLast->u.pNext = pCur->u.pNext;843 VBVAHOSTCMD * pNext = pCur->u.pNext;844 pCur->u.pNext = NULL;845 #else846 Assert(!pCur->u.pNext);847 #endif848 HGSMIHostCmdComplete(&pCallbacks->pCommon->hostCtx, pCur);849 #if 0 /* pNext is NULL, and the other things have already been asserted */850 pCur = pNext;851 Assert(!pCur);852 Assert(!pFirst);853 Assert(pFirst == pLast);854 #else855 pCur = NULL;856 #endif857 break;858 }859 }860 }861 862 /* we do not support lists currently */863 Assert(pFirst == pLast);864 if(pLast)865 {866 Assert(pLast->u.pNext == NULL);867 }868 869 if(pFirst)870 {871 Assert(pLast);872 VBVAHOSTCMD *pCmd;873 do874 {875 pCmd = ASMAtomicReadPtrT(&pHandler->pCmd, VBVAHOSTCMD *);876 pFirst->u.pNext = pCmd;877 }878 while (!ASMAtomicCmpXchgPtr(&pHandler->pCmd, pFirst, pCmd));879 }880 else881 {882 Assert(!pLast);883 }884 return VINF_SUCCESS;885 }886 }887 else888 {889 //TODO: impl890 // HGSMIMINIPORT_CHANNELCONTEXT *pHandler = vboxVideoHGSMIFindHandler;891 // if(pHandler && pHandler->pfnChannelHandler)892 // {893 // pHandler->pfnChannelHandler(pHandler->pvChannelHandler, u16ChannelInfo, pHdr, cbBuffer);894 //895 // return VINF_SUCCESS;896 // }897 }898 }899 /* no handlers were found, need to complete the command here */900 HGSMIHostCmdComplete(&pCallbacks->pCommon->hostCtx, pvBuffer);901 return VINF_SUCCESS;902 }903 904 static HGSMICHANNELHANDLER g_OldHandler;905 906 int vboxVBVAChannelDisplayEnable(PVBOXVIDEO_COMMON pCommon,907 int iDisplay, /* negative would mean this is a miniport handler */908 uint8_t u8Channel)909 {910 VBVA_CHANNELCONTEXTS * pContexts;911 HGSMICHANNEL * pChannel = HGSMIChannelFindById (&pCommon->hostCtx.channels, u8Channel);912 if(!pChannel)913 {914 int rc = vboxVBVACreateChannelContexts(pCommon, &pContexts);915 if(RT_FAILURE(rc))916 {917 return rc;918 }919 }920 else921 {922 pContexts = (VBVA_CHANNELCONTEXTS *)pChannel->handler.pvHandler;923 }924 925 VBVADISP_CHANNELCONTEXT *pDispContext = vboxVBVAFindHandlerInfo(pContexts, iDisplay);926 Assert(pDispContext);927 if(pDispContext)928 {929 #ifdef DEBUGVHWASTRICT930 Assert(!pDispContext->bValid);931 #endif932 Assert(!pDispContext->pCmd);933 if(!pDispContext->bValid)934 {935 pDispContext->bValid = true;936 pDispContext->pCmd = NULL;937 938 int rc = VINF_SUCCESS;939 if(!pChannel)940 {941 rc = HGSMIChannelRegister (&pCommon->hostCtx.channels,942 u8Channel,943 "VGA Miniport HGSMI channel",944 vboxVBVAChannelGenericHandler,945 pContexts,946 &g_OldHandler);947 }948 949 if(RT_SUCCESS(rc))950 {951 pContexts->cUsed++;952 return VINF_SUCCESS;953 }954 }955 }956 957 if(!pChannel)958 {959 vboxVBVADeleteChannelContexts(pCommon, pContexts);960 }961 962 return VERR_GENERAL_FAILURE;963 }964 #endif /* !VBOX_WITH_WDDM */965 610 966 611 /** @todo Mouse pointer position to be read from VMMDev memory, address of the memory region … … 981 626 * 982 627 */ 983
Note:
See TracChangeset
for help on using the changeset viewer.