Changeset 50754 in vbox for trunk/src/VBox
- Timestamp:
- Mar 12, 2014 5:43:09 PM (11 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVbva.cpp
r49591 r50754 114 114 } 115 115 116 static bool vboxVBVAExInformHost(PVBVAEXBUFFERCONTEXT pCtx, 117 PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx, bool bEnable) 118 { 119 bool bRc = false; 120 121 #if 0 /* All callers check this */ 122 if (ppdev->bHGSMISupported) 123 #endif 124 { 125 void *p = VBoxHGSMIBufferAlloc(pHGSMICtx, 126 sizeof (VBVAENABLE_EX), 127 HGSMI_CH_VBVA, 128 pCtx->u16EnableOp); 129 if (!p) 130 { 131 LogFunc(("HGSMIHeapAlloc failed\n")); 116 static int vboxCmdVbvaSubmitHgsmi(PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx, HGSMIOFFSET offDr) 117 { 118 VBoxVideoCmnPortWriteUlong(pHGSMICtx->port, offDr); 119 return VINF_SUCCESS; 120 } 121 #define vboxCmdVbvaSubmit vboxCmdVbvaSubmitHgsmi 122 123 static VBOXCMDVBVA_CTL * vboxCmdVbvaCtlCreate(PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx, uint32_t cbCtl) 124 { 125 Assert(cbCtl >= sizeof (VBOXCMDVBVA_CTL)); 126 return (VBOXCMDVBVA_CTL*)VBoxSHGSMICommandAlloc(&pHGSMICtx->heapCtx, cbCtl, HGSMI_CH_VBVA, VBVA_CMDVBVA_CTL); 127 } 128 129 static void vboxCmdVbvaCtlFree(PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx, VBOXCMDVBVA_CTL * pCtl) 130 { 131 VBoxSHGSMICommandFree(&pHGSMICtx->heapCtx, pCtl); 132 } 133 134 static int vboxCmdVbvaCtlSubmitSync(PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx, VBOXCMDVBVA_CTL * pCtl) 135 { 136 const VBOXSHGSMIHEADER* pHdr = VBoxSHGSMICommandPrepSynch(&pHGSMICtx->heapCtx, pCtl); 137 if (!pHdr) 138 { 139 WARN(("VBoxSHGSMICommandPrepSynch returnd NULL")); 140 return VERR_INVALID_PARAMETER; 141 } 142 143 HGSMIOFFSET offCmd = VBoxSHGSMICommandOffset(&pHGSMICtx->heapCtx, pHdr); 144 if (offCmd == HGSMIOFFSET_VOID) 145 { 146 WARN(("VBoxSHGSMICommandOffset returnd NULL")); 147 VBoxSHGSMICommandCancelSynch(&pHGSMICtx->heapCtx, pHdr); 148 return VERR_INVALID_PARAMETER; 149 } 150 151 int rc = vboxCmdVbvaSubmit(pHGSMICtx, offCmd); 152 if (RT_SUCCESS(rc)) 153 { 154 rc = VBoxSHGSMICommandDoneSynch(&pHGSMICtx->heapCtx, pHdr); 155 if (RT_SUCCESS(rc)) 156 { 157 rc = pCtl->i32Result; 158 if (!RT_SUCCESS(rc)) 159 WARN(("pCtl->i32Result %d", pCtl->i32Result)); 160 161 return rc; 132 162 } 133 163 else 134 { 135 VBVAENABLE_EX *pEnable = (VBVAENABLE_EX *)p; 136 137 pEnable->Base.u32Flags = bEnable? VBVA_F_ENABLE: VBVA_F_DISABLE; 138 pEnable->Base.u32Offset = pCtx->offVRAMBuffer; 139 pEnable->Base.i32Result = VERR_NOT_SUPPORTED; 140 pEnable->Base.u32Flags |= VBVA_F_ABSOFFSET; 141 142 VBoxHGSMIBufferSubmit(pHGSMICtx, p); 143 144 if (bEnable) 145 { 146 bRc = RT_SUCCESS(pEnable->Base.i32Result); 147 } 148 else 149 { 150 bRc = true; 151 } 152 153 VBoxHGSMIBufferFree(pHGSMICtx, p); 154 } 155 } 156 157 return bRc; 164 WARN(("VBoxSHGSMICommandDoneSynch returnd %d", rc)); 165 } 166 else 167 WARN(("vboxCmdVbvaSubmit returnd %d", rc)); 168 169 VBoxSHGSMICommandCancelSynch(&pHGSMICtx->heapCtx, pHdr); 170 171 return rc; 172 } 173 174 static int vboxCmdVbvaCtlSubmitAsync(PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx, VBOXCMDVBVA_CTL * pCtl, PFNVBOXSHGSMICMDCOMPLETION_IRQ pfnCompletionIrq, void *pvCompletionIrq) 175 { 176 const VBOXSHGSMIHEADER* pHdr = VBoxSHGSMICommandPrepAsynchIrq(&pHGSMICtx->heapCtx, pCtl, pfnCompletionIrq, pvCompletionIrq, VBOXSHGSMI_FLAG_GH_ASYNCH_FORCE); 177 if (!pHdr) 178 { 179 WARN(("VBoxSHGSMICommandPrepAsynchIrq returnd NULL")); 180 return VERR_INVALID_PARAMETER; 181 } 182 183 HGSMIOFFSET offCmd = VBoxSHGSMICommandOffset(&pHGSMICtx->heapCtx, pHdr); 184 if (offCmd == HGSMIOFFSET_VOID) 185 { 186 WARN(("VBoxSHGSMICommandOffset returnd NULL")); 187 VBoxSHGSMICommandCancelAsynch(&pHGSMICtx->heapCtx, pHdr); 188 return VERR_INVALID_PARAMETER; 189 } 190 191 int rc = vboxCmdVbvaSubmit(pHGSMICtx, offCmd); 192 if (RT_SUCCESS(rc)) 193 { 194 VBoxSHGSMICommandDoneAsynch(&pHGSMICtx->heapCtx, pHdr); 195 return rc; 196 } 197 else 198 WARN(("vboxCmdVbvaSubmit returnd %d", rc)); 199 200 VBoxSHGSMICommandCancelAsynch(&pHGSMICtx->heapCtx, pHdr); 201 202 return rc; 203 } 204 205 static int vboxVBVAExCtlSubmitEnableDisable(PVBVAEXBUFFERCONTEXT pCtx, PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx, bool fEnable) 206 { 207 VBOXCMDVBVA_CTL_ENABLE *pCtl = (VBOXCMDVBVA_CTL_ENABLE*)vboxCmdVbvaCtlCreate(pHGSMICtx, sizeof (*pCtl)); 208 if (!pCtl) 209 { 210 WARN(("vboxCmdVbvaCtlCreate failed")); 211 return VERR_NO_MEMORY; 212 } 213 214 pCtl->Hdr.u32Type = VBOXCMDVBVACTL_TYPE_ENABLE; 215 pCtl->Hdr.i32Result = VERR_NOT_IMPLEMENTED; 216 memset(&pCtl->Enable, 0, sizeof (pCtl->Enable)); 217 pCtl->Enable.u32Flags = fEnable? VBVA_F_ENABLE: VBVA_F_DISABLE; 218 pCtl->Enable.u32Offset = pCtx->offVRAMBuffer; 219 pCtl->Enable.i32Result = VERR_NOT_SUPPORTED; 220 pCtl->Enable.u32Flags |= VBVA_F_ABSOFFSET; 221 222 int rc = vboxCmdVbvaCtlSubmitSync(pHGSMICtx, &pCtl->Hdr); 223 if (RT_SUCCESS(rc)) 224 { 225 rc = pCtl->Hdr.i32Result; 226 if (!RT_SUCCESS(rc)) 227 WARN(("vboxCmdVbvaCtlSubmitSync Disable failed %d", rc)); 228 } 229 else 230 WARN(("vboxCmdVbvaCtlSubmitSync returnd %d", rc)); 231 232 vboxCmdVbvaCtlFree(pHGSMICtx, &pCtl->Hdr); 233 234 return rc; 158 235 } 159 236 … … 189 266 pCtx->pVBVA = pVBVA; 190 267 191 bRc = vboxVBVAEx InformHost(pCtx, pHGSMICtx, true);268 bRc = vboxVBVAExCtlSubmitEnableDisable(pCtx, pHGSMICtx, true); 192 269 } 193 270 … … 209 286 pCtx->pVBVA = NULL; 210 287 211 vboxVBVAEx InformHost(pCtx, pHGSMICtx, false);288 vboxVBVAExCtlSubmitEnableDisable(pCtx, pHGSMICtx, false); 212 289 213 290 return; … … 539 616 uint32_t cbBuffer, 540 617 PFNVBVAEXBUFFERFLUSH pfnFlush, 541 void *pvFlush, 542 uint16_t u16EnableOp) 618 void *pvFlush) 543 619 { 544 620 memset(pCtx, 0, RT_OFFSETOF(VBVAEXBUFFERCONTEXT, pVBVA)); 545 621 pCtx->offVRAMBuffer = offVRAMBuffer; 546 622 pCtx->cbBuffer = cbBuffer; 547 pCtx->u16EnableOp = u16EnableOp;548 623 pCtx->pfnFlush = pfnFlush; 549 624 pCtx->pvFlush = pvFlush; … … 824 899 { 825 900 Assert(pVbva->Vbva.pVBVA); 826 VBoxVBVAExSetupBufferContext(&pVbva->Vbva, offBuffer, cbBuffer, voxCmdVbvaFlushCb, pDevExt , VBVA_CMDVBVA_ENABLE);901 VBoxVBVAExSetupBufferContext(&pVbva->Vbva, offBuffer, cbBuffer, voxCmdVbvaFlushCb, pDevExt); 827 902 } 828 903 else -
trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVbva.h
r49591 r50754 77 77 * read it. */ 78 78 bool fHwBufferOverflow; 79 /* VBVA operation used to enable/disable VBVA */80 uint16_t u16EnableOp;81 79 /* the window between indexRecordFirstUncompleted and pVBVA->::indexRecordFirst represents 82 80 * command records processed by the host, but not completed by the guest yet */ … … 150 148 uint32_t cbBuffer, 151 149 PFNVBVAEXBUFFERFLUSH pfnFlush, 152 void *pvFlush, 153 uint16_t u16EnableOp); 150 void *pvFlush); 154 151 155 152 DECLINLINE(uint32_t) VBoxVBVAExGetSize(PVBVAEXBUFFERCONTEXT pCtx) -
trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPWddm.cpp
r50678 r50754 1353 1353 switch (chInfo) 1354 1354 { 1355 case VBVA_ VBVACMD_CTL:1355 case VBVA_CMDVBVA_CTL: 1356 1356 { 1357 1357 int rc = VBoxSHGSMICommandProcessCompletion (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, (VBOXSHGSMIHEADER*)pvCmd, TRUE /*bool bIrq*/ , &CtlList); -
trunk/src/VBox/Devices/Graphics/DevVGA.cpp
r50552 r50754 5499 5499 LogFlow(("vgaReset\n")); 5500 5500 5501 if (pThis->pVdma) 5502 vboxVDMAReset(pThis->pVdma); 5503 5501 5504 #ifdef VBOX_WITH_HGSMI 5502 5505 VBVAReset(pThis); … … 5949 5952 # endif 5950 5953 #endif 5954 pThis->IVBVACallbacks.pfnCrCtlSubmit = vboxCmdVBVACmdHostCtl; 5951 5955 5952 5956 /* -
trunk/src/VBox/Devices/Graphics/DevVGA.h
r50259 r50754 625 625 int vboxVDMACrHgsmiControlCompleteAsync(PPDMIDISPLAYVBVACALLBACKS pInterface, PVBOXVDMACMD_CHROMIUM_CTL pCmd, int rc); 626 626 # endif 627 int vboxCmdVBVACmdHostCtl(PPDMIDISPLAYVBVACALLBACKS pInterface, 628 struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, 629 PFNCRCTLCOMPLETION pfnCompletion, 630 void *pvCompletion); 627 631 628 632 int vboxVBVASaveStateExec (PPDMDEVINS pDevIns, PSSMHANDLE pSSM); … … 634 638 int vboxVDMAConstruct(PVGASTATE pVGAState, uint32_t cPipeElements); 635 639 int vboxVDMADestruct(PVBOXVDMAHOST pVdma); 640 int vboxVDMAReset(PVBOXVDMAHOST pVdma); 636 641 void vboxVDMAControl(PVBOXVDMAHOST pVdma, PVBOXVDMA_CTL pCmd, uint32_t cbCmd); 637 642 void vboxVDMACommand(PVBOXVDMAHOST pVdma, PVBOXVDMACBUF_DR pCmd, uint32_t cbCmd); … … 640 645 # endif /* VBOX_WITH_VDMA */ 641 646 642 int vboxCmdVBVAEnable(PVGASTATE pVGAState, VBVABUFFER *pVBVA);643 int vboxCmdVBVADisable(PVGASTATE pVGAState);644 647 int vboxCmdVBVACmdSubmit(PVGASTATE pVGAState); 645 648 int vboxCmdVBVACmdFlush(PVGASTATE pVGAState); 646 649 void vboxCmdVBVACmdTimer(PVGASTATE pVGAState); 650 int vboxCmdVBVACmdCtl(PVGASTATE pVGAState, VBOXCMDVBVA_CTL *pCtl, uint32_t cbCtl); 647 651 648 652 #endif /* VBOX_WITH_HGSMI */ -
trunk/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp
r50259 r50754 1940 1940 switch (u16ChannelInfo) 1941 1941 { 1942 case VBVA_CMDVBVA_SUBMIT: 1943 { 1944 rc = vboxCmdVBVACmdSubmit(pVGAState); 1945 break; 1946 } 1947 case VBVA_CMDVBVA_FLUSH: 1948 { 1949 rc =vboxCmdVBVACmdFlush(pVGAState); 1950 break; 1951 } 1952 case VBVA_CMDVBVA_CTL: 1953 { 1954 if (cbBuffer < VBoxSHGSMIBufferHeaderSize() + sizeof (VBOXCMDVBVA_CTL)) 1955 { 1956 Log(("buffer too small\n")); 1957 #ifdef DEBUG_misha 1958 AssertMsgFailed(("buffer too small\n")); 1959 #endif 1960 rc = VERR_INVALID_PARAMETER; 1961 break; 1962 } 1963 1964 VBOXCMDVBVA_CTL *pCtl = (VBOXCMDVBVA_CTL*)VBoxSHGSMIBufferData((PVBOXSHGSMIHEADER)pvBuffer); 1965 rc = vboxCmdVBVACmdCtl(pVGAState, pCtl, cbBuffer - VBoxSHGSMIBufferHeaderSize()); 1966 break; 1967 } 1942 1968 #ifdef VBOX_WITH_VDMA 1943 1969 case VBVA_VDMA_CMD: … … 2253 2279 } break; 2254 2280 #endif 2255 2256 case VBVA_CMDVBVA_ENABLE:2257 {2258 if (cbBuffer < sizeof (VBVAENABLE))2259 {2260 rc = VERR_INVALID_PARAMETER;2261 break;2262 }2263 2264 VBVAENABLE *pEnable = (VBVAENABLE *)pvBuffer;2265 2266 if ((pEnable->u32Flags & (VBVA_F_ENABLE | VBVA_F_DISABLE)) == VBVA_F_ENABLE)2267 {2268 uint32_t u32Offset = pEnable->u32Offset;2269 VBVABUFFER *pVBVA = (VBVABUFFER *)HGSMIOffsetToPointerHost (pIns, u32Offset);2270 2271 if (pVBVA)2272 rc = vboxCmdVBVAEnable(pVGAState, pVBVA);2273 else2274 {2275 LogRel(("Invalid VBVABUFFER offset 0x%x!!!\n",2276 pEnable->u32Offset));2277 rc = VERR_INVALID_PARAMETER;2278 }2279 }2280 else if ((pEnable->u32Flags & (VBVA_F_ENABLE | VBVA_F_DISABLE)) == VBVA_F_DISABLE)2281 {2282 rc = vboxCmdVBVADisable(pVGAState);2283 }2284 else2285 {2286 LogRel(("Invalid VBVA_ENABLE flags 0x%x!!!\n", pEnable->u32Flags));2287 rc = VERR_INVALID_PARAMETER;2288 }2289 2290 pEnable->i32Result = rc;2291 break;2292 }2293 case VBVA_CMDVBVA_SUBMIT:2294 {2295 rc = vboxCmdVBVACmdSubmit(pVGAState);2296 break;2297 }2298 case VBVA_CMDVBVA_FLUSH:2299 {2300 rc =vboxCmdVBVACmdFlush(pVGAState);2301 break;2302 }2303 2281 case VBVA_SCANLINE_CFG: 2304 2282 { -
trunk/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp
r50550 r50754 21 21 #include <iprt/mem.h> 22 22 #include <iprt/asm.h> 23 #include <iprt/list.h> 23 24 24 25 #include "DevVGA.h" … … 26 27 27 28 #include <VBox/VBoxVideo3D.h> 29 #include <VBox/VBoxVideoHost3D.h> 30 31 #ifdef DEBUG_misha 32 # define VBOXVDBG_MEMCACHE_DISABLE 33 #endif 34 35 #ifndef VBOXVDBG_MEMCACHE_DISABLE 36 # include <iprt/memcache.h> 37 #endif 28 38 29 39 #ifdef DEBUG_misha … … 37 47 } while (0) 38 48 39 #ifdef VBOX_VDMA_WITH_WORKERTHREAD 40 typedef enum 41 { 42 VBOXVDMAPIPE_STATE_CLOSED = 0, 43 VBOXVDMAPIPE_STATE_CREATED = 1, 44 VBOXVDMAPIPE_STATE_OPENNED = 2, 45 VBOXVDMAPIPE_STATE_CLOSING = 3 46 } VBOXVDMAPIPE_STATE; 47 48 typedef struct VBOXVDMAPIPE 49 { 49 #define VBOXVDMATHREAD_STATE_TERMINATED 0 50 #define VBOXVDMATHREAD_STATE_CREATED 1 51 #define VBOXVDMATHREAD_STATE_TERMINATING 2 52 53 typedef struct VBOXVDMATHREAD 54 { 55 RTTHREAD hWorkerThread; 50 56 RTSEMEVENT hEvent; 51 /* critical section for accessing pipe properties */ 52 RTCRITSECT hCritSect; 53 VBOXVDMAPIPE_STATE enmState; 54 /* true iff the other end needs Event notification */ 55 bool bNeedNotify; 56 } VBOXVDMAPIPE, *PVBOXVDMAPIPE; 57 58 typedef enum 59 { 60 VBOXVDMAPIPE_CMD_TYPE_UNDEFINED = 0, 61 VBOXVDMAPIPE_CMD_TYPE_DMACMD = 1, 62 VBOXVDMAPIPE_CMD_TYPE_DMACTL = 2 63 } VBOXVDMAPIPE_CMD_TYPE; 64 65 typedef struct VBOXVDMAPIPE_CMD_BODY 66 { 67 VBOXVDMAPIPE_CMD_TYPE enmType; 68 union 69 { 70 PVBOXVDMACBUF_DR pDr; 71 PVBOXVDMA_CTL pCtl; 72 void *pvCmd; 73 } u; 74 }VBOXVDMAPIPE_CMD_BODY, *PVBOXVDMAPIPE_CMD_BODY; 75 76 typedef struct VBOXVDMAPIPE_CMD 77 { 78 HGSMILISTENTRY Entry; 79 VBOXVDMAPIPE_CMD_BODY Cmd; 80 } VBOXVDMAPIPE_CMD, *PVBOXVDMAPIPE_CMD; 81 82 #define VBOXVDMAPIPE_CMD_FROM_ENTRY(_pE) ( (PVBOXVDMAPIPE_CMD)((uint8_t *)(_pE) - RT_OFFSETOF(VBOXVDMAPIPE_CMD, Entry)) ) 83 84 typedef struct VBOXVDMAPIPE_CMD_POOL 85 { 86 HGSMILIST List; 87 uint32_t cCmds; 88 VBOXVDMAPIPE_CMD aCmds[1]; 89 } VBOXVDMAPIPE_CMD_POOL, *PVBOXVDMAPIPE_CMD_POOL; 90 #endif 57 RTSEMEVENT hClientEvent; 58 volatile uint32_t u32State; 59 } VBOXVDMATHREAD, *PVBOXVDMATHREAD; 91 60 92 61 … … 94 63 * 95 64 * submitter | processor 96 * STOPPED 97 * | 98 * | 99 * > 65 * 100 66 * LISTENING ---> PROCESSING 101 * ^ _/102 * | _/103 * | _/104 * | _/105 * | _/106 * | _/107 * | /108 * < >109 * PAUSED110 67 * 111 68 * */ 112 #define VBVAEXHOSTCONTEXT_STATE_STOPPED 0 113 #define VBVAEXHOSTCONTEXT_STATE_LISTENING 1 114 #define VBVAEXHOSTCONTEXT_STATE_PROCESSING 2 115 #define VBVAEXHOSTCONTEXT_STATE_PAUSED 3 69 #define VBVAEXHOSTCONTEXT_STATE_LISTENING 0 70 #define VBVAEXHOSTCONTEXT_STATE_PROCESSING 1 71 72 #define VBVAEXHOSTCONTEXT_ESTATE_DISABLED -1 73 #define VBVAEXHOSTCONTEXT_ESTATE_PAUSED 0 74 #define VBVAEXHOSTCONTEXT_ESTATE_ENABLED 1 116 75 117 76 typedef struct VBVAEXHOSTCONTEXT 118 77 { 119 78 VBVABUFFER *pVBVA; 120 uint32_t cbCurData; 121 volatile uint32_t u32State; 122 volatile uint32_t u32Pause; 123 volatile uint32_t u32cOtherCommands; 79 volatile int32_t i32State; 80 volatile int32_t i32EnableState; 81 volatile uint32_t u32cCtls; 82 /* critical section for accessing ctl lists */ 83 RTCRITSECT CltCritSect; 84 RTLISTNODE GuestCtlList; 85 RTLISTNODE HostCtlList; 86 #ifndef VBOXVDBG_MEMCACHE_DISABLE 87 RTMEMCACHE CtlCache; 88 #endif 124 89 } VBVAEXHOSTCONTEXT; 90 91 typedef enum 92 { 93 VBVAEXHOSTCTL_TYPE_UNDEFINED = 0, 94 VBVAEXHOSTCTL_TYPE_HH_INTERNAL_PAUSE, 95 VBVAEXHOSTCTL_TYPE_HH_INTERNAL_RESUME, 96 VBVAEXHOSTCTL_TYPE_HH_ENABLE, 97 VBVAEXHOSTCTL_TYPE_HH_TERM, 98 VBVAEXHOSTCTL_TYPE_HH_RESET, 99 VBVAEXHOSTCTL_TYPE_HH_SAVESTATE, 100 VBVAEXHOSTCTL_TYPE_HH_LOADSTATE, 101 VBVAEXHOSTCTL_TYPE_HH_BE_OPAQUE, 102 VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE, 103 VBVAEXHOSTCTL_TYPE_GH_ENABLE_DISABLE 104 } VBVAEXHOSTCTL_TYPE; 105 106 struct VBVAEXHOSTCTL; 107 108 typedef DECLCALLBACKPTR(void, PFNVBVAEXHOSTCTL_COMPLETE)(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvComplete); 109 110 typedef struct VBVAEXHOSTCTL 111 { 112 RTLISTNODE Node; 113 VBVAEXHOSTCTL_TYPE enmType; 114 union 115 { 116 struct 117 { 118 uint8_t * pu8Cmd; 119 uint32_t cbCmd; 120 } cmd; 121 122 struct 123 { 124 PSSMHANDLE pSSM; 125 uint32_t u32Version; 126 } state; 127 } u; 128 PFNVBVAEXHOSTCTL_COMPLETE pfnComplete; 129 void *pvComplete; 130 } VBVAEXHOSTCTL; 125 131 126 132 /* VBoxVBVAExHP**, i.e. processor functions, can NOT be called concurrently with each other, … … 128 134 * Can only be called be the processor, i.e. the entity that acquired the processor state by direct or indirect call to the VBoxVBVAExHSCheckCommands 129 135 * see mor edetailed comments in headers for function definitions */ 130 static bool VBoxVBVAExHPCmdCheckRelease(struct VBVAEXHOSTCONTEXT *pCmdVbva); 131 static int VBoxVBVAExHPCmdGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd); 136 typedef enum 137 { 138 VBVAEXHOST_DATA_TYPE_NO_DATA = 0, 139 VBVAEXHOST_DATA_TYPE_CMD, 140 VBVAEXHOST_DATA_TYPE_HOSTCTL, 141 VBVAEXHOST_DATA_TYPE_GUESTCTL, 142 } VBVAEXHOST_DATA_TYPE; 143 static VBVAEXHOST_DATA_TYPE VBoxVBVAExHPDataGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd); 144 145 static void VBoxVBVAExHPDataCompleteCmd(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint32_t cbCmd); 146 static void VBoxVBVAExHPDataCompleteCtl(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL *pCtl, int rc); 132 147 133 148 /* VBoxVBVAExHP**, i.e. processor functions, can NOT be called concurrently with each other, … … 135 150 static int VBoxVBVAExHSCheckCommands(struct VBVAEXHOSTCONTEXT *pCmdVbva); 136 151 137 static voidVBoxVBVAExHSInit(struct VBVAEXHOSTCONTEXT *pCmdVbva);152 static int VBoxVBVAExHSInit(struct VBVAEXHOSTCONTEXT *pCmdVbva); 138 153 static int VBoxVBVAExHSEnable(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVABUFFER *pVBVA); 139 154 static int VBoxVBVAExHSDisable(struct VBVAEXHOSTCONTEXT *pCmdVbva); … … 142 157 static int VBoxVBVAExHSLoadState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM, uint32_t u32Version); 143 158 159 static VBVAEXHOSTCTL* VBoxVBVAExHCtlAlloc(VBVAEXHOSTCONTEXT *pCmdVbva) 160 { 161 #ifndef VBOXVDBG_MEMCACHE_DISABLE 162 return (VBVAEXHOSTCONTEXT*)RTMemCacheAlloc(pCmdVbva->CtlCache); 163 #else 164 return (VBVAEXHOSTCTL*)RTMemAlloc(sizeof (VBVAEXHOSTCTL)); 165 #endif 166 } 167 168 static void VBoxVBVAExHCtlFree(VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL *pCtl) 169 { 170 #ifndef VBOXVDBG_MEMCACHE_DISABLE 171 RTMemCacheFree(pCmdVbva->CtlCache, pCtl); 172 #else 173 RTMemFree(pCtl); 174 #endif 175 } 176 177 static VBVAEXHOSTCTL* VBoxVBVAExHCtlCreate(VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL_TYPE enmType) 178 { 179 VBVAEXHOSTCTL* pCtl = VBoxVBVAExHCtlAlloc(pCmdVbva); 180 if (!pCtl) 181 { 182 WARN(("VBoxVBVAExHCtlAlloc failed\n")); 183 return NULL; 184 } 185 186 pCtl->enmType = enmType; 187 return pCtl; 188 } 189 190 static int vboxVBVAExHSProcessorAcquire(struct VBVAEXHOSTCONTEXT *pCmdVbva) 191 { 192 Assert(pCmdVbva->i32State >= VBVAEXHOSTCONTEXT_STATE_LISTENING); 193 194 if (ASMAtomicCmpXchgS32(&pCmdVbva->i32State, VBVAEXHOSTCONTEXT_STATE_PROCESSING, VBVAEXHOSTCONTEXT_STATE_LISTENING)) 195 return VINF_SUCCESS; 196 return VERR_SEM_BUSY; 197 } 198 199 static VBVAEXHOSTCTL* vboxVBVAExHPCheckCtl(struct VBVAEXHOSTCONTEXT *pCmdVbva, bool *pfHostCtl, bool fHostOnlyMode) 200 { 201 Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING); 202 203 if(!fHostOnlyMode && !ASMAtomicUoReadU32(&pCmdVbva->u32cCtls)) 204 return NULL; 205 206 int rc = RTCritSectEnter(&pCmdVbva->CltCritSect); 207 if (RT_SUCCESS(rc)) 208 { 209 VBVAEXHOSTCTL* pCtl = RTListGetFirst(&pCmdVbva->HostCtlList, VBVAEXHOSTCTL, Node); 210 if (pCtl) 211 *pfHostCtl = true; 212 else if (!fHostOnlyMode) 213 { 214 if (ASMAtomicUoReadS32(&pCmdVbva->i32EnableState) > VBVAEXHOSTCONTEXT_ESTATE_PAUSED) 215 { 216 pCtl = RTListGetFirst(&pCmdVbva->GuestCtlList, VBVAEXHOSTCTL, Node); 217 /* pCtl can not be null here since pCmdVbva->u32cCtls is not null, 218 * and there are no HostCtl commands*/ 219 Assert(pCtl); 220 *pfHostCtl = false; 221 } 222 } 223 224 if (pCtl) 225 { 226 RTListNodeRemove(&pCtl->Node); 227 ASMAtomicDecU32(&pCmdVbva->u32cCtls); 228 } 229 230 RTCritSectLeave(&pCmdVbva->CltCritSect); 231 232 return pCtl; 233 } 234 else 235 WARN(("RTCritSectEnter failed %d\n", rc)); 236 237 return NULL; 238 } 239 240 static VBVAEXHOSTCTL* VBoxVBVAExHPCheckHostCtlOnDisable(struct VBVAEXHOSTCONTEXT *pCmdVbva) 241 { 242 bool fHostCtl; 243 return vboxVBVAExHPCheckCtl(pCmdVbva, &fHostCtl, true); 244 } 245 246 247 static bool vboxVBVAExHPCheckProcessCtlInternal(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL* pCtl) 248 { 249 switch (pCtl->enmType) 250 { 251 case VBVAEXHOSTCTL_TYPE_HH_INTERNAL_PAUSE: 252 if (pCmdVbva->i32EnableState > VBVAEXHOSTCONTEXT_ESTATE_PAUSED) 253 ASMAtomicWriteS32(&pCmdVbva->i32EnableState, VBVAEXHOSTCONTEXT_ESTATE_PAUSED); 254 return true; 255 case VBVAEXHOSTCTL_TYPE_HH_INTERNAL_RESUME: 256 if (pCmdVbva->i32EnableState == VBVAEXHOSTCONTEXT_ESTATE_PAUSED) 257 ASMAtomicWriteS32(&pCmdVbva->i32EnableState, VBVAEXHOSTCONTEXT_ESTATE_ENABLED); 258 return true; 259 default: 260 return false; 261 } 262 } 263 264 static void vboxVBVAExHPProcessorRelease(struct VBVAEXHOSTCONTEXT *pCmdVbva) 265 { 266 Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING); 267 268 ASMAtomicWriteS32(&pCmdVbva->i32State, VBVAEXHOSTCONTEXT_STATE_LISTENING); 269 } 270 271 static void vboxVBVAExHPHgEventSet(struct VBVAEXHOSTCONTEXT *pCmdVbva) 272 { 273 Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING); 274 if (pCmdVbva->pVBVA) 275 ASMAtomicOrU32(&pCmdVbva->pVBVA->hostFlags.u32HostEvents, VBVA_F_STATE_PROCESSING); 276 } 277 278 static void vboxVBVAExHPHgEventClear(struct VBVAEXHOSTCONTEXT *pCmdVbva) 279 { 280 Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING); 281 if (pCmdVbva->pVBVA) 282 ASMAtomicAndU32(&pCmdVbva->pVBVA->hostFlags.u32HostEvents, ~VBVA_F_STATE_PROCESSING); 283 } 284 285 static int vboxVBVAExHPCmdGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd) 286 { 287 Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING); 288 Assert(pCmdVbva->i32EnableState > VBVAEXHOSTCONTEXT_ESTATE_PAUSED); 289 290 VBVABUFFER *pVBVA = pCmdVbva->pVBVA; 291 292 uint32_t indexRecordFirst = pVBVA->indexRecordFirst; 293 uint32_t indexRecordFree = pVBVA->indexRecordFree; 294 295 Log(("first = %d, free = %d\n", 296 indexRecordFirst, indexRecordFree)); 297 298 if (indexRecordFirst == indexRecordFree) 299 { 300 /* No records to process. Return without assigning output variables. */ 301 return VINF_EOF; 302 } 303 304 uint32_t cbRecordCurrent = ASMAtomicReadU32(&pVBVA->aRecords[indexRecordFirst].cbRecord); 305 306 /* A new record need to be processed. */ 307 if (cbRecordCurrent & VBVA_F_RECORD_PARTIAL) 308 { 309 /* the record is being recorded, try again */ 310 return VINF_TRY_AGAIN; 311 } 312 313 uint32_t cbRecord = cbRecordCurrent & ~VBVA_F_RECORD_PARTIAL; 314 315 if (!cbRecord) 316 { 317 /* the record is being recorded, try again */ 318 return VINF_TRY_AGAIN; 319 } 320 321 /* we should not get partial commands here actually */ 322 Assert(cbRecord); 323 324 /* The size of largest contiguous chunk in the ring biffer. */ 325 uint32_t u32BytesTillBoundary = pVBVA->cbData - pVBVA->off32Data; 326 327 /* The pointer to data in the ring buffer. */ 328 uint8_t *pSrc = &pVBVA->au8Data[pVBVA->off32Data]; 329 330 /* Fetch or point the data. */ 331 if (u32BytesTillBoundary >= cbRecord) 332 { 333 /* The command does not cross buffer boundary. Return address in the buffer. */ 334 *ppCmd = pSrc; 335 *pcbCmd = cbRecord; 336 return VINF_SUCCESS; 337 } 338 339 LogRel(("CmdVbva: cross-bound writes unsupported\n")); 340 return VERR_INVALID_STATE; 341 } 342 343 static void VBoxVBVAExHPDataCompleteCmd(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint32_t cbCmd) 344 { 345 VBVABUFFER *pVBVA = pCmdVbva->pVBVA; 346 pVBVA->off32Data = (pVBVA->off32Data + cbCmd) % pVBVA->cbData; 347 348 pVBVA->indexRecordFirst = (pVBVA->indexRecordFirst + 1) % RT_ELEMENTS(pVBVA->aRecords); 349 } 350 351 static void VBoxVBVAExHPDataCompleteCtl(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL *pCtl, int rc) 352 { 353 if (pCtl->pfnComplete) 354 pCtl->pfnComplete(pCmdVbva, pCtl, rc, pCtl->pvComplete); 355 else 356 VBoxVBVAExHCtlFree(pCmdVbva, pCtl); 357 } 358 359 static VBVAEXHOST_DATA_TYPE vboxVBVAExHPDataGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd) 360 { 361 Assert(pCmdVbva->i32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING); 362 VBVAEXHOSTCTL*pCtl; 363 bool fHostClt; 364 365 for(;;) 366 { 367 pCtl = vboxVBVAExHPCheckCtl(pCmdVbva, &fHostClt, false); 368 if (pCtl) 369 { 370 if (fHostClt) 371 { 372 if (!vboxVBVAExHPCheckProcessCtlInternal(pCmdVbva, pCtl)) 373 { 374 *ppCmd = (uint8_t*)pCtl; 375 *pcbCmd = sizeof (*pCtl); 376 return VBVAEXHOST_DATA_TYPE_HOSTCTL; 377 } 378 } 379 else 380 { 381 *ppCmd = (uint8_t*)pCtl; 382 *pcbCmd = sizeof (*pCtl); 383 return VBVAEXHOST_DATA_TYPE_GUESTCTL; 384 } 385 } 386 387 if (ASMAtomicUoReadS32(&pCmdVbva->i32EnableState) <= VBVAEXHOSTCONTEXT_ESTATE_PAUSED) 388 return VBVAEXHOST_DATA_TYPE_NO_DATA; 389 390 int rc = vboxVBVAExHPCmdGet(pCmdVbva, ppCmd, pcbCmd); 391 switch (rc) 392 { 393 case VINF_SUCCESS: 394 return VBVAEXHOST_DATA_TYPE_CMD; 395 case VINF_EOF: 396 return VBVAEXHOST_DATA_TYPE_NO_DATA; 397 case VINF_TRY_AGAIN: 398 RTThreadSleep(1); 399 continue; 400 default: 401 /* this is something really unexpected, i.e. most likely guest has written something incorrect to the VBVA buffer */ 402 WARN(("Warning: vboxVBVAExHCmdGet returned unexpected status %d\n", rc)); 403 return VBVAEXHOST_DATA_TYPE_NO_DATA; 404 } 405 } 406 407 WARN(("Warning: VBoxVBVAExHCmdGet unexpected state\n")); 408 return VBVAEXHOST_DATA_TYPE_NO_DATA; 409 } 410 411 static VBVAEXHOST_DATA_TYPE VBoxVBVAExHPDataGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd) 412 { 413 VBVAEXHOST_DATA_TYPE enmType = vboxVBVAExHPDataGet(pCmdVbva, ppCmd, pcbCmd); 414 if (enmType == VBVAEXHOST_DATA_TYPE_NO_DATA) 415 { 416 vboxVBVAExHPHgEventClear(pCmdVbva); 417 vboxVBVAExHPProcessorRelease(pCmdVbva); 418 /* we need to prevent racing between us clearing the flag and command check/submission thread, i.e. 419 * 1. we check the queue -> and it is empty 420 * 2. submitter adds command to the queue 421 * 3. submitter checks the "processing" -> and it is true , thus it does not submit a notification 422 * 4. we clear the "processing" state 423 * 5. ->here we need to re-check the queue state to ensure we do not leak the notification of the above command 424 * 6. if the queue appears to be not-empty set the "processing" state back to "true" 425 **/ 426 int rc = vboxVBVAExHSProcessorAcquire(pCmdVbva); 427 if (RT_SUCCESS(rc)) 428 { 429 /* we are the processor now */ 430 enmType = vboxVBVAExHPDataGet(pCmdVbva, ppCmd, pcbCmd); 431 if (enmType == VBVAEXHOST_DATA_TYPE_NO_DATA) 432 { 433 vboxVBVAExHPProcessorRelease(pCmdVbva); 434 return VBVAEXHOST_DATA_TYPE_NO_DATA; 435 } 436 437 vboxVBVAExHPHgEventSet(pCmdVbva); 438 } 439 } 440 441 return enmType; 442 } 443 444 DECLINLINE(bool) vboxVBVAExHSHasCommands(struct VBVAEXHOSTCONTEXT *pCmdVbva) 445 { 446 VBVABUFFER *pVBVA = pCmdVbva->pVBVA; 447 448 if (pVBVA) 449 { 450 uint32_t indexRecordFirst = pVBVA->indexRecordFirst; 451 uint32_t indexRecordFree = pVBVA->indexRecordFree; 452 453 if (indexRecordFirst != indexRecordFree) 454 return true; 455 } 456 457 return !!ASMAtomicReadU32(&pCmdVbva->u32cCtls); 458 } 459 460 /* Checks whether the new commands are ready for processing 461 * @returns 462 * VINF_SUCCESS - there are commands are in a queue, and the given thread is now the processor (i.e. typically it would delegate processing to a worker thread) 463 * VINF_EOF - no commands in a queue 464 * VINF_ALREADY_INITIALIZED - another thread already processing the commands 465 * VERR_INVALID_STATE - the VBVA is paused or pausing */ 466 static int VBoxVBVAExHSCheckCommands(struct VBVAEXHOSTCONTEXT *pCmdVbva) 467 { 468 int rc = vboxVBVAExHSProcessorAcquire(pCmdVbva); 469 if (RT_SUCCESS(rc)) 470 { 471 /* we are the processor now */ 472 if (vboxVBVAExHSHasCommands(pCmdVbva)) 473 { 474 vboxVBVAExHPHgEventSet(pCmdVbva); 475 return VINF_SUCCESS; 476 } 477 478 vboxVBVAExHPProcessorRelease(pCmdVbva); 479 return VINF_EOF; 480 } 481 if (rc == VERR_SEM_BUSY) 482 return VINF_ALREADY_INITIALIZED; 483 return VERR_INVALID_STATE; 484 } 485 486 static int VBoxVBVAExHSInit(struct VBVAEXHOSTCONTEXT *pCmdVbva) 487 { 488 memset(pCmdVbva, 0, sizeof (*pCmdVbva)); 489 int rc = RTCritSectInit(&pCmdVbva->CltCritSect); 490 if (RT_SUCCESS(rc)) 491 { 492 #ifndef VBOXVDBG_MEMCACHE_DISABLE 493 rc = RTMemCacheCreate(&pCmdVbva->CtlCache, sizeof (VBVAEXHOSTCTL), 494 0, /* size_t cbAlignment */ 495 UINT32_MAX, /* uint32_t cMaxObjects */ 496 NULL, /* PFNMEMCACHECTOR pfnCtor*/ 497 NULL, /* PFNMEMCACHEDTOR pfnDtor*/ 498 NULL, /* void *pvUser*/ 499 0 /* uint32_t fFlags*/ 500 ); 501 if (RT_SUCCESS(rc)) 502 #endif 503 { 504 RTListInit(&pCmdVbva->GuestCtlList); 505 RTListInit(&pCmdVbva->HostCtlList); 506 pCmdVbva->i32State = VBVAEXHOSTCONTEXT_STATE_PROCESSING; 507 pCmdVbva->i32EnableState = VBVAEXHOSTCONTEXT_ESTATE_DISABLED; 508 return VINF_SUCCESS; 509 } 510 #ifndef VBOXVDBG_MEMCACHE_DISABLE 511 else 512 WARN(("RTMemCacheCreate failed %d\n", rc)); 513 #endif 514 } 515 else 516 WARN(("RTCritSectInit failed %d\n", rc)); 517 518 return rc; 519 } 520 521 DECLINLINE(bool) VBoxVBVAExHSIsEnabled(struct VBVAEXHOSTCONTEXT *pCmdVbva) 522 { 523 return (ASMAtomicUoReadS32(&pCmdVbva->i32EnableState) >= VBVAEXHOSTCONTEXT_ESTATE_PAUSED); 524 } 525 526 static int VBoxVBVAExHSEnable(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVABUFFER *pVBVA) 527 { 528 if (VBoxVBVAExHSIsEnabled(pCmdVbva)) 529 return VINF_ALREADY_INITIALIZED; 530 531 pCmdVbva->pVBVA = pVBVA; 532 pCmdVbva->pVBVA->hostFlags.u32HostEvents = 0; 533 ASMAtomicWriteS32(&pCmdVbva->i32EnableState, VBVAEXHOSTCONTEXT_ESTATE_ENABLED); 534 return VINF_SUCCESS; 535 } 536 537 static int VBoxVBVAExHSDisable(struct VBVAEXHOSTCONTEXT *pCmdVbva) 538 { 539 if (!VBoxVBVAExHSIsEnabled(pCmdVbva)) 540 return VINF_SUCCESS; 541 542 ASMAtomicWriteS32(&pCmdVbva->i32EnableState, VBVAEXHOSTCONTEXT_ESTATE_DISABLED); 543 return VINF_SUCCESS; 544 } 545 546 static void VBoxVBVAExHSTerm(struct VBVAEXHOSTCONTEXT *pCmdVbva) 547 { 548 /* ensure the processor is stopped */ 549 Assert(pCmdVbva->i32State >= VBVAEXHOSTCONTEXT_STATE_LISTENING); 550 551 /* ensure no one tries to submit the command */ 552 if (pCmdVbva->pVBVA) 553 pCmdVbva->pVBVA->hostFlags.u32HostEvents = 0; 554 555 Assert(RTListIsEmpty(&pCmdVbva->GuestCtlList)); 556 Assert(RTListIsEmpty(&pCmdVbva->HostCtlList)); 557 558 RTCritSectDelete(&pCmdVbva->CltCritSect); 559 560 #ifndef VBOXVDBG_MEMCACHE_DISABLE 561 RTMemCacheDestroy(pCmdVbva->CtlCache); 562 #endif 563 564 memset(pCmdVbva, 0, sizeof (*pCmdVbva)); 565 } 566 567 /* Saves state 568 * @returns - same as VBoxVBVAExHSCheckCommands, or failure on load state fail 569 */ 570 static int VBoxVBVAExHSSaveState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM) 571 { 572 int rc; 573 574 int32_t i32EnableState = ASMAtomicUoReadS32(&pCmdVbva->i32EnableState); 575 if (i32EnableState >= VBVAEXHOSTCONTEXT_ESTATE_PAUSED) 576 { 577 if (i32EnableState != VBVAEXHOSTCONTEXT_ESTATE_PAUSED) 578 { 579 WARN(("vbva not paused\n")); 580 return VERR_INVALID_STATE; 581 } 582 583 rc = SSMR3PutU32(pSSM, (uint32_t)(((uint8_t*)pCmdVbva->pVBVA) - pu8VramBase)); 584 AssertRCReturn(rc, rc); 585 return VINF_SUCCESS; 586 } 587 588 rc = SSMR3PutU32(pSSM, 0xffffffff); 589 AssertRCReturn(rc, rc); 590 591 return VINF_SUCCESS; 592 } 593 594 typedef enum 595 { 596 VBVAEXHOSTCTL_SOURCE_GUEST = 0, 597 VBVAEXHOSTCTL_SOURCE_HOST_ANY, 598 VBVAEXHOSTCTL_SOURCE_HOST_ENABLED 599 } VBVAEXHOSTCTL_SOURCE; 600 601 602 static int VBoxVBVAExHCtlSubmit(VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete) 603 { 604 if ((enmSource == VBVAEXHOSTCTL_SOURCE_HOST_ENABLED) && !VBoxVBVAExHSIsEnabled(pCmdVbva)) 605 { 606 WARN(("cmd vbva not enabled\n")); 607 return VERR_INVALID_STATE; 608 } 609 610 pCtl->pfnComplete = pfnComplete; 611 pCtl->pvComplete = pvComplete; 612 613 int rc = RTCritSectEnter(&pCmdVbva->CltCritSect); 614 if (RT_SUCCESS(rc)) 615 { 616 if (enmSource > VBVAEXHOSTCTL_SOURCE_GUEST) 617 { 618 if ((enmSource == VBVAEXHOSTCTL_SOURCE_HOST_ENABLED) && !VBoxVBVAExHSIsEnabled(pCmdVbva)) 619 { 620 WARN(("cmd vbva not enabled\n")); 621 RTCritSectLeave(&pCmdVbva->CltCritSect); 622 return VERR_INVALID_STATE; 623 } 624 RTListAppend(&pCmdVbva->HostCtlList, &pCtl->Node); 625 } 626 else 627 RTListAppend(&pCmdVbva->GuestCtlList, &pCtl->Node); 628 629 ASMAtomicIncU32(&pCmdVbva->u32cCtls); 630 631 RTCritSectLeave(&pCmdVbva->CltCritSect); 632 633 rc = VBoxVBVAExHSCheckCommands(pCmdVbva); 634 } 635 else 636 WARN(("RTCritSectEnter failed %d\n", rc)); 637 638 return rc; 639 } 640 641 642 /* Loads state 643 * @returns - same as VBoxVBVAExHSCheckCommands, or failure on load state fail 644 */ 645 static int VBoxVBVAExHSLoadState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM, uint32_t u32Version) 646 { 647 AssertMsgFailed(("implement!\n")); 648 uint32_t u32; 649 int rc = SSMR3GetU32(pSSM, &u32); 650 AssertRCReturn(rc, rc); 651 if (u32 != 0xffffffff) 652 { 653 VBVABUFFER *pVBVA = (VBVABUFFER*)pu8VramBase + u32; 654 rc = VBoxVBVAExHSEnable(pCmdVbva, pVBVA); 655 AssertRCReturn(rc, rc); 656 return VBoxVBVAExHSCheckCommands(pCmdVbva); 657 } 658 659 return VINF_SUCCESS; 660 } 661 144 662 typedef struct VBOXVDMAHOST 145 663 { … … 147 665 PVGASTATE pVGAState; 148 666 VBVAEXHOSTCONTEXT CmdVbva; 667 VBOXVDMATHREAD Thread; 668 VBOXCRCMD_SVRINFO CrSrvInfo; 669 VBVAEXHOSTCTL* pCurRemainingHostCtl; 149 670 #ifdef VBOX_VDMA_WITH_WATCHDOG 150 671 PTMTIMERR3 WatchDogTimer; 151 672 #endif 152 #ifdef VBOX_VDMA_WITH_WORKERTHREAD153 VBOXVDMAPIPE Pipe;154 HGSMILIST PendingList;155 RTTHREAD hWorkerThread;156 VBOXVDMAPIPE_CMD_POOL CmdPool;157 #endif158 673 } VBOXVDMAHOST, *PVBOXVDMAHOST; 159 674 675 int VBoxVDMAThreadNotifyConstructSucceeded(PVBOXVDMATHREAD pThread) 676 { 677 Assert(pThread->u32State == VBOXVDMATHREAD_STATE_TERMINATED); 678 int rc = RTSemEventSignal(pThread->hClientEvent); 679 AssertRC(rc); 680 if (RT_SUCCESS(rc)) 681 { 682 pThread->u32State = VBOXVDMATHREAD_STATE_CREATED; 683 return VINF_SUCCESS; 684 } 685 return rc; 686 } 687 688 int VBoxVDMAThreadNotifyConstructFailed(PVBOXVDMATHREAD pThread) 689 { 690 Assert(pThread->u32State == VBOXVDMATHREAD_STATE_TERMINATED); 691 int rc = RTSemEventSignal(pThread->hClientEvent); 692 AssertRC(rc); 693 if (RT_SUCCESS(rc)) 694 return VINF_SUCCESS; 695 return rc; 696 } 697 698 DECLINLINE(bool) VBoxVDMAThreadIsTerminating(PVBOXVDMATHREAD pThread) 699 { 700 return ASMAtomicUoReadU32(&pThread->u32State) == VBOXVDMATHREAD_STATE_TERMINATING; 701 } 702 703 int VBoxVDMAThreadCreate(PVBOXVDMATHREAD pThread, PFNRTTHREAD pfnThread, void *pvThread) 704 { 705 int rc = RTSemEventCreate(&pThread->hEvent); 706 if (RT_SUCCESS(rc)) 707 { 708 rc = RTSemEventCreate(&pThread->hClientEvent); 709 if (RT_SUCCESS(rc)) 710 { 711 pThread->u32State = VBOXVDMATHREAD_STATE_TERMINATED; 712 rc = RTThreadCreate(&pThread->hWorkerThread, pfnThread, pvThread, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "VDMA"); 713 if (RT_SUCCESS(rc)) 714 { 715 rc = RTSemEventWait(pThread->hClientEvent, RT_INDEFINITE_WAIT); 716 if (RT_SUCCESS(rc)) 717 { 718 if (pThread->u32State == VBOXVDMATHREAD_STATE_CREATED) 719 return VINF_SUCCESS; 720 WARN(("thread routine failed the initialization\n")); 721 rc = VERR_INVALID_STATE; 722 } 723 else 724 WARN(("RTSemEventWait failed %d\n", rc)); 725 726 RTThreadWait(pThread->hWorkerThread, RT_INDEFINITE_WAIT, NULL); 727 } 728 else 729 WARN(("RTThreadCreate failed %d\n", rc)); 730 731 RTSemEventDestroy(pThread->hClientEvent); 732 } 733 else 734 WARN(("RTSemEventCreate failed %d\n", rc)); 735 736 RTSemEventDestroy(pThread->hEvent); 737 } 738 else 739 WARN(("RTSemEventCreate failed %d\n", rc)); 740 741 return rc; 742 } 743 744 DECLINLINE(int) VBoxVDMAThreadEventNotify(PVBOXVDMATHREAD pThread) 745 { 746 int rc = RTSemEventSignal(pThread->hEvent); 747 AssertRC(rc); 748 return rc; 749 } 750 751 DECLINLINE(int) VBoxVDMAThreadEventWait(PVBOXVDMATHREAD pThread, RTMSINTERVAL cMillies) 752 { 753 int rc = RTSemEventWait(pThread->hEvent, cMillies); 754 AssertRC(rc); 755 return rc; 756 } 757 758 void VBoxVDMAThreadMarkTerminating(PVBOXVDMATHREAD pThread) 759 { 760 Assert(pThread->u32State == VBOXVDMATHREAD_STATE_CREATED); 761 ASMAtomicWriteU32(&pThread->u32State, VBOXVDMATHREAD_STATE_TERMINATING); 762 } 763 764 void VBoxVDMAThreadTerm(PVBOXVDMATHREAD pThread) 765 { 766 int rc; 767 if (ASMAtomicReadU32(&pThread->u32State) != VBOXVDMATHREAD_STATE_TERMINATING) 768 { 769 VBoxVDMAThreadMarkTerminating(pThread); 770 rc = VBoxVDMAThreadEventNotify(pThread); 771 AssertRC(rc); 772 } 773 rc = RTThreadWait(pThread->hWorkerThread, RT_INDEFINITE_WAIT, NULL); 774 AssertRC(rc); 775 RTSemEventDestroy(pThread->hClientEvent); 776 RTSemEventDestroy(pThread->hEvent); 777 } 778 779 static int vdmaVBVACtlSubmitSync(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource); 160 780 161 781 #ifdef VBOX_WITH_CRHGSMI … … 248 868 if(RT_SUCCESS(rc)) 249 869 { 250 rc = vboxVDMACrCtlPostAsync 870 rc = vboxVDMACrCtlPostAsync(pVGAState, pCmd, cbCmd, vboxVDMACrCtlCbSetEvent, (void*)hComplEvent); 251 871 #ifdef DEBUG_misha 252 872 AssertRC(rc); … … 270 890 } 271 891 272 static void vboxVDMACrCmdNotifyPerform(struct VBOXVDMAHOST *pVdma) 273 { 892 typedef struct VDMA_VBVA_CTL_CYNC_COMPLETION 893 { 894 int rc; 895 RTSEMEVENT hEvent; 896 } VDMA_VBVA_CTL_CYNC_COMPLETION; 897 898 static DECLCALLBACK(void) vboxVDMACrHgcmSubmitSyncCompletion(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, int rc, void *pvCompletion) 899 { 900 VDMA_VBVA_CTL_CYNC_COMPLETION *pData = (VDMA_VBVA_CTL_CYNC_COMPLETION*)pvCompletion; 901 pData->rc = rc; 902 rc = RTSemEventSignal(pData->hEvent); 903 if (!RT_SUCCESS(rc)) 904 WARN(("RTSemEventSignal failed %d\n", rc)); 905 } 906 907 static int vboxVDMACrHgcmSubmitSync(struct VBOXVDMAHOST *pVdma, VBOXCRCMDCTL* pCtl, uint32_t cbCtl) 908 { 909 VDMA_VBVA_CTL_CYNC_COMPLETION Data; 910 Data.rc = VERR_NOT_IMPLEMENTED; 911 int rc = RTSemEventCreate(&Data.hEvent); 912 if (!RT_SUCCESS(rc)) 913 { 914 WARN(("RTSemEventCreate failed %d\n", rc)); 915 return rc; 916 } 917 274 918 PVGASTATE pVGAState = pVdma->pVGAState; 275 pVGAState->pDrv->pfnCrCmdNotifyCmds(pVGAState->pDrv); 276 } 919 rc = pVGAState->pDrv->pfnCrHgcmCtlSubmit(pVGAState->pDrv, pCtl, cbCtl, vboxVDMACrHgcmSubmitSyncCompletion, &Data); 920 if (RT_SUCCESS(rc)) 921 { 922 rc = RTSemEventWait(Data.hEvent, RT_INDEFINITE_WAIT); 923 if (RT_SUCCESS(rc)) 924 { 925 rc = Data.rc; 926 if (!RT_SUCCESS(rc)) 927 { 928 WARN(("pfnCrHgcmCtlSubmit command failed %d\n", rc)); 929 } 930 931 } 932 else 933 WARN(("RTSemEventWait failed %d\n", rc)); 934 } 935 else 936 WARN(("pfnCrHgcmCtlSubmit failed %d\n", rc)); 937 938 939 RTSemEventDestroy(Data.hEvent); 940 941 return rc; 942 } 943 944 static DECLCALLBACK(VBOXCRCMDCTL*) vboxVDMACrHgcmHandleEnableRemainingHostCommand(HVBOXCRCMDCTL_REMAINING_HOST_COMMAND hClient, uint32_t *pcbCtl, int prevCmdRc) 945 { 946 struct VBOXVDMAHOST *pVdma = hClient; 947 if (!pVdma->pCurRemainingHostCtl) 948 { 949 /* disable VBVA, all subsequent host commands will go HGCM way */ 950 VBoxVBVAExHSDisable(&pVdma->CmdVbva); 951 } 952 else 953 { 954 VBoxVBVAExHPDataCompleteCtl(&pVdma->CmdVbva, pVdma->pCurRemainingHostCtl, prevCmdRc); 955 } 956 957 pVdma->pCurRemainingHostCtl = VBoxVBVAExHPCheckHostCtlOnDisable(&pVdma->CmdVbva); 958 if (pVdma->pCurRemainingHostCtl) 959 { 960 *pcbCtl = pVdma->pCurRemainingHostCtl->u.cmd.cbCmd; 961 return (VBOXCRCMDCTL*)pVdma->pCurRemainingHostCtl->u.cmd.pu8Cmd; 962 } 963 964 *pcbCtl = 0; 965 return NULL; 966 } 967 968 static int vboxVDMACrHgcmHandleEnable(struct VBOXVDMAHOST *pVdma) 969 { 970 VBOXCRCMDCTL_ENABLE Enable; 971 Enable.Hdr.enmType = VBOXCRCMDCTL_TYPE_ENABLE; 972 Enable.hRHCmd = pVdma; 973 Enable.pfnRHCmd = vboxVDMACrHgcmHandleEnableRemainingHostCommand; 974 975 int rc = vboxVDMACrHgcmSubmitSync(pVdma, &Enable.Hdr, sizeof (Enable)); 976 Assert(!pVdma->pCurRemainingHostCtl); 977 if (RT_SUCCESS(rc)) 978 { 979 Assert(!VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva)); 980 return VINF_SUCCESS; 981 } 982 983 Assert(VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva)); 984 WARN(("vboxVDMACrHgcmSubmitSync failed %d\n", rc)); 985 986 return rc; 987 } 988 989 static int vdmaVBVAEnableProcess(struct VBOXVDMAHOST *pVdma, uint32_t u32Offset) 990 { 991 if (VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva)) 992 { 993 WARN(("vdma VBVA is already enabled\n")); 994 return VERR_INVALID_STATE; 995 } 996 997 VBVABUFFER *pVBVA = (VBVABUFFER *)HGSMIOffsetToPointerHost(pVdma->pHgsmi, u32Offset); 998 if (!pVBVA) 999 { 1000 WARN(("invalid offset %d\n", u32Offset)); 1001 return VERR_INVALID_PARAMETER; 1002 } 1003 1004 if (!pVdma->CrSrvInfo.pfnEnable) 1005 { 1006 #ifdef DEBUG_misha 1007 WARN(("pfnEnable is NULL\n")); 1008 return VERR_NOT_SUPPORTED; 1009 #endif 1010 } 1011 1012 int rc = VBoxVBVAExHSEnable(&pVdma->CmdVbva, pVBVA); 1013 if (RT_SUCCESS(rc)) 1014 { 1015 VBOXCRCMDCTL Ctl; 1016 Ctl.enmType = VBOXCRCMDCTL_TYPE_DISABLE; 1017 rc = vboxVDMACrHgcmSubmitSync(pVdma, &Ctl, sizeof (Ctl)); 1018 if (RT_SUCCESS(rc)) 1019 { 1020 PVGASTATE pVGAState = pVdma->pVGAState; 1021 VBOXCRCMD_SVRENABLE_INFO Info; 1022 Info.hCltScr = pVGAState->pDrv; 1023 Info.pfnCltScrUpdateBegin = pVGAState->pDrv->pfnVBVAUpdateBegin; 1024 Info.pfnCltScrUpdateProcess = pVGAState->pDrv->pfnVBVAUpdateProcess; 1025 Info.pfnCltScrUpdateEnd = pVGAState->pDrv->pfnVBVAUpdateEnd; 1026 rc = pVdma->CrSrvInfo.pfnEnable(pVdma->CrSrvInfo.hSvr, &Info); 1027 if (RT_SUCCESS(rc)) 1028 return VINF_SUCCESS; 1029 else 1030 WARN(("pfnEnable failed %d\n", rc)); 1031 1032 vboxVDMACrHgcmHandleEnable(pVdma); 1033 } 1034 else 1035 WARN(("vboxVDMACrHgcmSubmitSync failed %d\n", rc)); 1036 1037 VBoxVBVAExHSDisable(&pVdma->CmdVbva); 1038 } 1039 else 1040 WARN(("VBoxVBVAExHSEnable failed %d\n", rc)); 1041 1042 return rc; 1043 } 1044 1045 static int vdmaVBVADisableProcess(struct VBOXVDMAHOST *pVdma) 1046 { 1047 if (!VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva)) 1048 { 1049 Log(("vdma VBVA is already disabled\n")); 1050 return VINF_SUCCESS; 1051 } 1052 1053 int rc = pVdma->CrSrvInfo.pfnDisable(pVdma->CrSrvInfo.hSvr); 1054 if (RT_SUCCESS(rc)) 1055 { 1056 /* disable is a bit tricky 1057 * we need to ensure the host ctl commands do not come out of order 1058 * and do not come over HGCM channel until after it is enabled */ 1059 rc = vboxVDMACrHgcmHandleEnable(pVdma); 1060 if (RT_SUCCESS(rc)) 1061 return rc; 1062 1063 PVGASTATE pVGAState = pVdma->pVGAState; 1064 VBOXCRCMD_SVRENABLE_INFO Info; 1065 Info.hCltScr = pVGAState->pDrv; 1066 Info.pfnCltScrUpdateBegin = pVGAState->pDrv->pfnVBVAUpdateBegin; 1067 Info.pfnCltScrUpdateProcess = pVGAState->pDrv->pfnVBVAUpdateProcess; 1068 Info.pfnCltScrUpdateEnd = pVGAState->pDrv->pfnVBVAUpdateEnd; 1069 pVdma->CrSrvInfo.pfnEnable(pVdma->CrSrvInfo.hSvr, &Info); 1070 } 1071 else 1072 WARN(("pfnDisable failed %d\n", rc)); 1073 1074 return rc; 1075 } 1076 1077 static int vboxVDMACrHostCtlProcess(struct VBOXVDMAHOST *pVdma, VBVAEXHOSTCTL *pCmd) 1078 { 1079 switch (pCmd->enmType) 1080 { 1081 case VBVAEXHOSTCTL_TYPE_HH_SAVESTATE: 1082 if (!VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva)) 1083 { 1084 WARN(("VBVAEXHOSTCTL_TYPE_HH_SAVESTATE for disabled vdma VBVA\n")); 1085 return VERR_INVALID_STATE; 1086 } 1087 return pVdma->CrSrvInfo.pfnSaveState(pVdma->CrSrvInfo.hSvr, pCmd->u.state.pSSM); 1088 case VBVAEXHOSTCTL_TYPE_HH_LOADSTATE: 1089 if (!VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva)) 1090 { 1091 WARN(("VBVAEXHOSTCTL_TYPE_HH_LOADSTATE for disabled vdma VBVA\n")); 1092 return VERR_INVALID_STATE; 1093 } 1094 return pVdma->CrSrvInfo.pfnLoadState(pVdma->CrSrvInfo.hSvr, pCmd->u.state.pSSM, pCmd->u.state.u32Version); 1095 case VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE: 1096 if (!VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva)) 1097 { 1098 WARN(("VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE for disabled vdma VBVA\n")); 1099 return VERR_INVALID_STATE; 1100 } 1101 return pVdma->CrSrvInfo.pfnHostCtl(pVdma->CrSrvInfo.hSvr, pCmd->u.cmd.pu8Cmd, pCmd->u.cmd.cbCmd); 1102 case VBVAEXHOSTCTL_TYPE_HH_TERM: 1103 { 1104 int rc = vdmaVBVADisableProcess(pVdma); 1105 if (!RT_SUCCESS(rc)) 1106 { 1107 WARN(("vdmaVBVADisableProcess failed %d\n", rc)); 1108 return rc; 1109 } 1110 1111 VBoxVDMAThreadMarkTerminating(&pVdma->Thread); 1112 return VINF_SUCCESS; 1113 } 1114 case VBVAEXHOSTCTL_TYPE_HH_RESET: 1115 { 1116 int rc = vdmaVBVADisableProcess(pVdma); 1117 if (!RT_SUCCESS(rc)) 1118 { 1119 WARN(("vdmaVBVADisableProcess failed %d\n", rc)); 1120 return rc; 1121 } 1122 return VINF_SUCCESS; 1123 } 1124 default: 1125 WARN(("unexpected host ctl type %d\n", pCmd->enmType)); 1126 return VERR_INVALID_PARAMETER; 1127 } 1128 } 1129 1130 static int vboxVDMACrGuestCtlProcess(struct VBOXVDMAHOST *pVdma, VBVAEXHOSTCTL *pCmd) 1131 { 1132 switch (pCmd->enmType) 1133 { 1134 case VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE: 1135 if (!VBoxVBVAExHSIsEnabled(&pVdma->CmdVbva)) 1136 { 1137 WARN(("VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE for disabled vdma VBVA\n")); 1138 return VERR_INVALID_STATE; 1139 } 1140 return pVdma->CrSrvInfo.pfnGuestCtl(pVdma->CrSrvInfo.hSvr, pCmd->u.cmd.pu8Cmd, pCmd->u.cmd.cbCmd); 1141 case VBVAEXHOSTCTL_TYPE_GH_ENABLE_DISABLE: 1142 { 1143 VBVAENABLE *pEnable = (VBVAENABLE *)pCmd->u.cmd.pu8Cmd; 1144 Assert(pCmd->u.cmd.cbCmd == sizeof (VBVAENABLE)); 1145 if ((pEnable->u32Flags & (VBVA_F_ENABLE | VBVA_F_DISABLE)) == VBVA_F_ENABLE) 1146 { 1147 uint32_t u32Offset = pEnable->u32Offset; 1148 return vdmaVBVAEnableProcess(pVdma, u32Offset); 1149 } 1150 1151 return vdmaVBVADisableProcess(pVdma); 1152 } 1153 default: 1154 WARN(("unexpected ctl type %d\n", pCmd->enmType)); 1155 return VERR_INVALID_PARAMETER; 1156 } 1157 } 1158 277 1159 278 1160 /* … … 280 1162 * 281 1163 */ 282 static int vboxVDMACrCmdPr eprocess(struct VBOXVDMAHOST *pVdma, uint8_t* pu8Cmd, uint32_t cbCmd)1164 static int vboxVDMACrCmdProcess(struct VBOXVDMAHOST *pVdma, uint8_t* pu8Cmd, uint32_t cbCmd) 283 1165 { 284 1166 if (*pu8Cmd == VBOXCMDVBVA_OPTYPE_NOP) … … 305 1187 } 306 1188 307 static DECLCALLBACK(int) vboxVDMACrCmdCltCmdGet(HVBOXCRCMDCLT hClt, PVBOXCMDVBVA_HDR *ppNextCmd, uint32_t *pcbNextCmd) 308 { 309 struct VBOXVDMAHOST *pVdma = hClt; 310 311 VBoxVBVAExHPCmdCheckRelease(&pVdma->CmdVbva); 312 313 uint32_t cbCmd; 314 uint8_t *pu8Cmd; 315 316 for(;;) 317 { 318 int rc = VBoxVBVAExHPCmdGet(&pVdma->CmdVbva, &pu8Cmd, &cbCmd); 319 switch (rc) 320 { 321 case VINF_SUCCESS: 322 { 323 rc = vboxVDMACrCmdPreprocess(pVdma, pu8Cmd, cbCmd); 324 switch (rc) 325 { 326 case VINF_SUCCESS: 327 *ppNextCmd = (PVBOXCMDVBVA_HDR)pu8Cmd; 328 *pcbNextCmd = cbCmd; 329 return VINF_SUCCESS; 330 case VINF_EOF: 331 continue; 332 default: 333 Assert(!RT_FAILURE(rc)); 334 return RT_FAILURE(rc) ? rc : VERR_INTERNAL_ERROR; 335 } 336 break; 337 } 338 case VINF_EOF: 339 return VINF_EOF; 340 case VINF_PERMISSION_DENIED: 341 /* processing was paused, processing state was released, only VBoxVBVAExHS*** calls are now allowed */ 342 return VINF_EOF; 343 case VINF_INTERRUPTED: 344 /* command processing was interrupted, processor state remains set. client can process any commands */ 345 vboxVDMACrCmdNotifyPerform(pVdma); 346 return VINF_EOF; 347 default: 348 Assert(!RT_FAILURE(rc)); 349 return RT_FAILURE(rc) ? rc : VERR_INTERNAL_ERROR; 350 } 351 } 352 353 WARN(("Warning: vboxVDMACrCmdCltCmdGet unexpected state\n")); 354 return VERR_INTERNAL_ERROR; 355 } 356 357 static DECLCALLBACK(int) vboxVDMACrCmdCltDmGet(HVBOXCRCMDCLT hClt, uint32_t idScreen, struct VBVAINFOSCREEN *pScreen, void **ppvVram) 358 { 359 struct VBOXVDMAHOST *pVdma = hClt; 360 PVGASTATE pVGAState = pVdma->pVGAState; 361 362 return VBVAGetScreenInfo(pVGAState, idScreen, pScreen, ppvVram); 1189 static DECLCALLBACK(int) vboxVDMACrCmdEnable(HVBOXCRCMDSVR hSvr, VBOXCRCMD_SVRENABLE_INFO *pInfo) 1190 { 1191 return VINF_SUCCESS; 1192 } 1193 1194 static DECLCALLBACK(void) vboxVDMACrCmdDisable(HVBOXCRCMDSVR hSvr) 1195 { 1196 } 1197 1198 static DECLCALLBACK(int) vboxVDMACrCmdCtl(HVBOXCRCMDSVR hSvr, uint8_t* pCmd, uint32_t cbCmd) 1199 { 1200 return VERR_NOT_SUPPORTED; 1201 } 1202 1203 static DECLCALLBACK(int) vboxVDMACrCmdCmd(HVBOXCRCMDSVR hSvr, PVBOXCMDVBVA_HDR pCmd, uint32_t cbCmd) 1204 { 1205 switch (pCmd->u8OpCode) 1206 { 1207 #if 0 1208 case VBOXCMDVBVA_OPTYPE_BLT_OFFPRIMSZFMT_OR_ID: 1209 { 1210 crVBoxServerCrCmdBltProcess(pCmd, cbCmd); 1211 break; 1212 } 1213 #endif 1214 default: 1215 WARN(("unsupported command\n")); 1216 pCmd->i8Result = -1; 1217 } 1218 return VINF_SUCCESS; 363 1219 } 364 1220 365 1221 static int vboxVDMACrCtlHgsmiSetup(struct VBOXVDMAHOST *pVdma) 366 1222 { 367 PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP pCmd ;368 pCmd = (PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP) vboxVDMACrCtlCreate (VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP,369 sizeof (*pCmd));1223 PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP pCmd = (PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP) 1224 vboxVDMACrCtlCreate (VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP, sizeof (*pCmd)); 1225 int rc = VERR_NO_MEMORY; 370 1226 if (pCmd) 371 1227 { 372 VBOXCRCMD_CLTINFO CltInfo;373 CltInfo.hClient = pVdma;374 CltInfo.pfnCmdGet = vboxVDMACrCmdCltCmdGet;375 CltInfo.pfnDmGet = vboxVDMACrCmdCltDmGet;376 1228 PVGASTATE pVGAState = pVdma->pVGAState; 377 1229 pCmd->pvVRamBase = pVGAState->vram_ptrR3; 378 1230 pCmd->cbVRam = pVGAState->vram_size; 379 pCmd->pCrCmdClientInfo = &CltInfo; 380 int rc = vboxVDMACrCtlPost(pVGAState, &pCmd->Hdr, sizeof (*pCmd)); 381 Assert(RT_SUCCESS(rc) || rc == VERR_NOT_SUPPORTED); 1231 rc = vboxVDMACrCtlPost(pVGAState, &pCmd->Hdr, sizeof (*pCmd)); 382 1232 if (RT_SUCCESS(rc)) 383 1233 { 384 1234 rc = vboxVDMACrCtlGetRc(&pCmd->Hdr); 385 } 1235 if (RT_SUCCESS(rc)) 1236 pVdma->CrSrvInfo = pCmd->CrCmdServerInfo; 1237 else if (rc != VERR_NOT_SUPPORTED) 1238 WARN(("vboxVDMACrCtlGetRc returned %d\n", rc)); 1239 } 1240 else 1241 WARN(("vboxVDMACrCtlPost failed %d\n", rc)); 1242 386 1243 vboxVDMACrCtlRelease(&pCmd->Hdr); 387 return rc; 388 } 389 return VERR_NO_MEMORY; 1244 } 1245 1246 if (!RT_SUCCESS(rc)) 1247 memset(&pVdma->CrSrvInfo, 0, sizeof (pVdma->CrSrvInfo)); 1248 1249 return rc; 390 1250 } 391 1251 … … 883 1743 } 884 1744 885 #ifdef VBOX_VDMA_WITH_WORKERTHREAD 886 887 int vboxVDMAPipeConstruct(PVBOXVDMAPIPE pPipe) 888 { 889 int rc = RTSemEventCreate(&pPipe->hEvent); 890 AssertRC(rc); 891 if (RT_SUCCESS(rc)) 892 { 893 rc = RTCritSectInit(&pPipe->hCritSect); 894 AssertRC(rc); 895 if (RT_SUCCESS(rc)) 896 { 897 pPipe->enmState = VBOXVDMAPIPE_STATE_CREATED; 898 pPipe->bNeedNotify = true; 899 return VINF_SUCCESS; 900 // RTCritSectDelete(pPipe->hCritSect); 901 } 902 RTSemEventDestroy(pPipe->hEvent); 903 } 904 return rc; 905 } 906 907 int vboxVDMAPipeOpenServer(PVBOXVDMAPIPE pPipe) 908 { 909 int rc = RTCritSectEnter(&pPipe->hCritSect); 910 AssertRC(rc); 911 if (RT_SUCCESS(rc)) 912 { 913 Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CREATED); 914 switch (pPipe->enmState) 915 { 916 case VBOXVDMAPIPE_STATE_CREATED: 917 pPipe->enmState = VBOXVDMAPIPE_STATE_OPENNED; 918 pPipe->bNeedNotify = false; 919 rc = VINF_SUCCESS; 1745 static DECLCALLBACK(int) vboxVDMAWorkerThread(RTTHREAD ThreadSelf, void *pvUser) 1746 { 1747 PVBOXVDMAHOST pVdma = (PVBOXVDMAHOST)pvUser; 1748 PVGASTATE pVGAState = pVdma->pVGAState; 1749 VBVAEXHOSTCONTEXT *pCmdVbva = &pVdma->CmdVbva; 1750 PHGSMIINSTANCE pHgsmi = pVdma->pHgsmi; 1751 uint8_t *pCmd; 1752 uint32_t cbCmd; 1753 1754 int rc = VBoxVDMAThreadNotifyConstructSucceeded(&pVdma->Thread); 1755 if (!RT_SUCCESS(rc)) 1756 { 1757 WARN(("VBoxVDMAThreadNotifyConstructSucceeded failed %d\n", rc)); 1758 return rc; 1759 } 1760 1761 while (!VBoxVDMAThreadIsTerminating(&pVdma->Thread)) 1762 { 1763 VBVAEXHOST_DATA_TYPE enmType = VBoxVBVAExHPDataGet(pCmdVbva, &pCmd, &cbCmd); 1764 switch (enmType) 1765 { 1766 case VBVAEXHOST_DATA_TYPE_CMD: 1767 vboxVDMACrCmdProcess(pVdma, pCmd, cbCmd); 1768 VBoxVBVAExHPDataCompleteCmd(pCmdVbva, cbCmd); 1769 VBVARaiseIrqNoWait(pVGAState, 0); 920 1770 break; 921 case VBOXVDMAPIPE_STATE_OPENNED: 922 pPipe->bNeedNotify = false; 923 rc = VINF_ALREADY_INITIALIZED; 1771 case VBVAEXHOST_DATA_TYPE_HOSTCTL: 1772 rc = vboxVDMACrHostCtlProcess(pVdma, (VBVAEXHOSTCTL*)pCmd); 1773 VBoxVBVAExHPDataCompleteCtl(pCmdVbva, (VBVAEXHOSTCTL*)pCmd, rc); 1774 break; 1775 case VBVAEXHOST_DATA_TYPE_GUESTCTL: 1776 rc = vboxVDMACrGuestCtlProcess(pVdma, (VBVAEXHOSTCTL*)pCmd); 1777 VBoxVBVAExHPDataCompleteCtl(pCmdVbva, (VBVAEXHOSTCTL*)pCmd, rc); 1778 break; 1779 case VBVAEXHOST_DATA_TYPE_NO_DATA: 1780 rc = VBoxVDMAThreadEventWait(&pVdma->Thread, RT_INDEFINITE_WAIT); 1781 AssertRC(rc); 924 1782 break; 925 1783 default: 926 AssertBreakpoint(); 927 rc = VERR_INVALID_STATE; 1784 WARN(("unexpected type %d\n", enmType)); 928 1785 break; 929 1786 } 930 931 RTCritSectLeave(&pPipe->hCritSect); 932 } 933 return rc; 934 } 935 936 int vboxVDMAPipeCloseServer(PVBOXVDMAPIPE pPipe) 937 { 938 int rc = RTCritSectEnter(&pPipe->hCritSect); 939 AssertRC(rc); 940 if (RT_SUCCESS(rc)) 941 { 942 Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED 943 || pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSING); 944 switch (pPipe->enmState) 945 { 946 case VBOXVDMAPIPE_STATE_CLOSING: 947 pPipe->enmState = VBOXVDMAPIPE_STATE_CLOSED; 948 rc = VINF_SUCCESS; 949 break; 950 case VBOXVDMAPIPE_STATE_CLOSED: 951 rc = VINF_ALREADY_INITIALIZED; 952 break; 953 default: 954 AssertBreakpoint(); 955 rc = VERR_INVALID_STATE; 956 break; 957 } 958 959 RTCritSectLeave(&pPipe->hCritSect); 960 } 961 return rc; 962 } 963 964 int vboxVDMAPipeCloseClient(PVBOXVDMAPIPE pPipe) 965 { 966 int rc = RTCritSectEnter(&pPipe->hCritSect); 967 AssertRC(rc); 968 if (RT_SUCCESS(rc)) 969 { 970 bool bNeedNotify = false; 971 Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED 972 || pPipe->enmState == VBOXVDMAPIPE_STATE_CREATED 973 || pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED); 974 switch (pPipe->enmState) 975 { 976 case VBOXVDMAPIPE_STATE_OPENNED: 977 pPipe->enmState = VBOXVDMAPIPE_STATE_CLOSING; 978 bNeedNotify = pPipe->bNeedNotify; 979 pPipe->bNeedNotify = false; 980 break; 981 case VBOXVDMAPIPE_STATE_CREATED: 982 pPipe->enmState = VBOXVDMAPIPE_STATE_CLOSED; 983 pPipe->bNeedNotify = false; 984 break; 985 case VBOXVDMAPIPE_STATE_CLOSED: 986 rc = VINF_ALREADY_INITIALIZED; 987 break; 988 default: 989 AssertBreakpoint(); 990 rc = VERR_INVALID_STATE; 991 break; 992 } 993 994 RTCritSectLeave(&pPipe->hCritSect); 995 996 if (bNeedNotify) 997 { 998 rc = RTSemEventSignal(pPipe->hEvent); 999 AssertRC(rc); 1000 } 1001 } 1002 return rc; 1003 } 1004 1005 1006 typedef DECLCALLBACK(bool) FNHVBOXVDMARWCB(PVBOXVDMAPIPE pPipe, void *pvCallback); 1007 typedef FNHVBOXVDMARWCB *PFNHVBOXVDMARWCB; 1008 1009 int vboxVDMAPipeModifyServer(PVBOXVDMAPIPE pPipe, PFNHVBOXVDMARWCB pfnCallback, void * pvCallback) 1010 { 1011 int rc = RTCritSectEnter(&pPipe->hCritSect); 1012 AssertRC(rc); 1013 if (RT_SUCCESS(rc)) 1014 { 1015 do 1016 { 1017 Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED 1018 || pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSING); 1019 1020 if (pPipe->enmState >= VBOXVDMAPIPE_STATE_OPENNED) 1021 { 1022 bool bProcessing = pfnCallback(pPipe, pvCallback); 1023 pPipe->bNeedNotify = !bProcessing; 1024 if (bProcessing) 1025 { 1026 RTCritSectLeave(&pPipe->hCritSect); 1027 rc = VINF_SUCCESS; 1028 break; 1029 } 1030 else if (pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSING) 1031 { 1032 pPipe->enmState = VBOXVDMAPIPE_STATE_CLOSED; 1033 RTCritSectLeave(&pPipe->hCritSect); 1034 rc = VINF_EOF; 1035 break; 1036 } 1037 } 1038 else 1039 { 1040 AssertBreakpoint(); 1041 rc = VERR_INVALID_STATE; 1042 RTCritSectLeave(&pPipe->hCritSect); 1043 break; 1044 } 1045 1046 RTCritSectLeave(&pPipe->hCritSect); 1047 1048 rc = RTSemEventWait(pPipe->hEvent, RT_INDEFINITE_WAIT); 1049 AssertRC(rc); 1050 if (!RT_SUCCESS(rc)) 1051 break; 1052 1053 rc = RTCritSectEnter(&pPipe->hCritSect); 1054 AssertRC(rc); 1055 if (!RT_SUCCESS(rc)) 1056 break; 1057 } while (1); 1058 } 1059 1060 return rc; 1061 } 1062 1063 int vboxVDMAPipeModifyClient(PVBOXVDMAPIPE pPipe, PFNHVBOXVDMARWCB pfnCallback, void * pvCallback) 1064 { 1065 int rc = RTCritSectEnter(&pPipe->hCritSect); 1066 AssertRC(rc); 1067 if (RT_SUCCESS(rc)) 1068 { 1069 bool bNeedNotify = false; 1070 Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED); 1071 if (pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED) 1072 { 1073 bool bModified = pfnCallback(pPipe, pvCallback); 1074 if (bModified) 1075 { 1076 bNeedNotify = pPipe->bNeedNotify; 1077 pPipe->bNeedNotify = false; 1078 } 1079 } 1080 else 1081 rc = VERR_INVALID_STATE; 1082 1083 RTCritSectLeave(&pPipe->hCritSect); 1084 1085 if (bNeedNotify) 1086 { 1087 rc = RTSemEventSignal(pPipe->hEvent); 1088 AssertRC(rc); 1089 } 1090 } 1091 return rc; 1092 } 1093 1094 int vboxVDMAPipeDestruct(PVBOXVDMAPIPE pPipe) 1095 { 1096 Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED 1097 || pPipe->enmState == VBOXVDMAPIPE_STATE_CREATED); 1098 /* ensure the pipe is closed */ 1099 vboxVDMAPipeCloseClient(pPipe); 1100 1101 Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED); 1102 1103 if (pPipe->enmState != VBOXVDMAPIPE_STATE_CLOSED) 1104 return VERR_INVALID_STATE; 1105 1106 int rc = RTCritSectDelete(&pPipe->hCritSect); 1107 AssertRC(rc); 1108 1109 rc = RTSemEventDestroy(pPipe->hEvent); 1110 AssertRC(rc); 1787 } 1111 1788 1112 1789 return VINF_SUCCESS; 1113 1790 } 1114 #endif1115 1791 1116 1792 static void vboxVDMACommandProcess(PVBOXVDMAHOST pVdma, PVBOXVDMACBUF_DR pCmd, uint32_t cbCmd) … … 1180 1856 AssertRC(rc); 1181 1857 } 1182 1183 #ifdef VBOX_VDMA_WITH_WORKERTHREAD1184 typedef struct1185 {1186 struct VBOXVDMAHOST *pVdma;1187 VBOXVDMAPIPE_CMD_BODY Cmd;1188 bool bHasCmd;1189 } VBOXVDMACMD_PROCESS_CONTEXT, *PVBOXVDMACMD_PROCESS_CONTEXT;1190 1191 static DECLCALLBACK(bool) vboxVDMACommandProcessCb(PVBOXVDMAPIPE pPipe, void *pvCallback)1192 {1193 PVBOXVDMACMD_PROCESS_CONTEXT pContext = (PVBOXVDMACMD_PROCESS_CONTEXT)pvCallback;1194 struct VBOXVDMAHOST *pVdma = pContext->pVdma;1195 HGSMILISTENTRY *pEntry = hgsmiListRemoveHead(&pVdma->PendingList);1196 if (pEntry)1197 {1198 PVBOXVDMAPIPE_CMD pPipeCmd = VBOXVDMAPIPE_CMD_FROM_ENTRY(pEntry);1199 Assert(pPipeCmd);1200 pContext->Cmd = pPipeCmd->Cmd;1201 hgsmiListPrepend(&pVdma->CmdPool.List, pEntry);1202 pContext->bHasCmd = true;1203 return true;1204 }1205 1206 pContext->bHasCmd = false;1207 return false;1208 }1209 1210 static DECLCALLBACK(int) vboxVDMAWorkerThread(RTTHREAD ThreadSelf, void *pvUser)1211 {1212 PVBOXVDMAHOST pVdma = (PVBOXVDMAHOST)pvUser;1213 PHGSMIINSTANCE pHgsmi = pVdma->pHgsmi;1214 VBOXVDMACMD_PROCESS_CONTEXT Context;1215 Context.pVdma = pVdma;1216 1217 int rc = vboxVDMAPipeOpenServer(&pVdma->Pipe);1218 AssertRC(rc);1219 if (RT_SUCCESS(rc))1220 {1221 do1222 {1223 rc = vboxVDMAPipeModifyServer(&pVdma->Pipe, vboxVDMACommandProcessCb, &Context);1224 AssertRC(rc);1225 if (RT_SUCCESS(rc))1226 {1227 switch (Context.Cmd.enmType)1228 {1229 case VBOXVDMAPIPE_CMD_TYPE_DMACMD:1230 {1231 PVBOXVDMACBUF_DR pDr = Context.Cmd.u.pDr;1232 vboxVDMACommandProcess(pVdma, pDr);1233 break;1234 }1235 case VBOXVDMAPIPE_CMD_TYPE_DMACTL:1236 {1237 PVBOXVDMA_CTL pCtl = Context.Cmd.u.pCtl;1238 vboxVDMAControlProcess(pVdma, pCtl);1239 break;1240 }1241 default:1242 AssertBreakpoint();1243 break;1244 }1245 1246 if (rc == VINF_EOF)1247 {1248 rc = VINF_SUCCESS;1249 break;1250 }1251 }1252 else1253 break;1254 } while (1);1255 }1256 1257 /* always try to close the pipe to make sure the client side is notified */1258 int tmpRc = vboxVDMAPipeCloseServer(&pVdma->Pipe);1259 AssertRC(tmpRc);1260 return rc;1261 }1262 #endif1263 1858 1264 1859 #ifdef VBOX_VDMA_WITH_WATCHDOG … … 1301 1896 AssertRC(rc); 1302 1897 #endif 1303 #ifdef VBOX_VDMA_WITH_WORKERTHREAD 1304 hgsmiListInit(&pVdma->PendingList); 1305 rc = vboxVDMAPipeConstruct(&pVdma->Pipe); 1306 AssertRC(rc); 1898 rc = VBoxVBVAExHSInit(&pVdma->CmdVbva); 1307 1899 if (RT_SUCCESS(rc)) 1308 1900 { 1309 rc = RTThreadCreate(&pVdma->hWorkerThread, vboxVDMAWorkerThread, pVdma, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "VDMA"); 1310 AssertRC(rc); 1901 rc = VBoxVDMAThreadCreate(&pVdma->Thread, vboxVDMAWorkerThread, pVdma); 1311 1902 if (RT_SUCCESS(rc)) 1312 1903 { 1313 hgsmiListInit(&pVdma->CmdPool.List);1314 pVdma->CmdPool.cCmds = cPipeElements;1315 for (uint32_t i = 0; i < cPipeElements; ++i)1316 {1317 hgsmiListAppend(&pVdma->CmdPool.List, &pVdma->CmdPool.aCmds[i].Entry);1318 }1319 # if 0 //def VBOX_WITH_CRHGSMI1320 int tmpRc = vboxVDMACrCtlHgsmiSetup(pVdma);1321 # endif1322 #endif1323 1904 pVGAState->pVdma = pVdma; 1324 VBoxVBVAExHSInit(&pVdma->CmdVbva);1325 1905 #ifdef VBOX_WITH_CRHGSMI 1326 1906 int rcIgnored = vboxVDMACrCtlHgsmiSetup(pVdma); NOREF(rcIgnored); /** @todo is this ignoring intentional? */ 1327 1907 #endif 1328 1908 return VINF_SUCCESS; 1329 #ifdef VBOX_VDMA_WITH_WORKERTHREAD 1330 } 1331 1332 int tmpRc = vboxVDMAPipeDestruct(&pVdma->Pipe); 1333 AssertRC(tmpRc); 1334 } 1909 } 1910 else 1911 WARN(("VBoxVDMAThreadCreate faile %d\n", rc)); 1912 1913 VBoxVBVAExHSTerm(&pVdma->CmdVbva); 1914 } 1915 else 1916 WARN(("VBoxVBVAExHSInit faile %d\n", rc)); 1335 1917 1336 1918 RTMemFree(pVdma); 1337 #endif1338 1919 } 1339 1920 else … … 1343 1924 } 1344 1925 1926 int vboxVDMAReset(struct VBOXVDMAHOST *pVdma) 1927 { 1928 VBVAEXHOSTCTL Ctl; 1929 Ctl.enmType = VBVAEXHOSTCTL_TYPE_HH_RESET; 1930 int rc = vdmaVBVACtlSubmitSync(pVdma, &Ctl, VBVAEXHOSTCTL_SOURCE_HOST_ANY); 1931 if (!RT_SUCCESS(rc)) 1932 { 1933 WARN(("vdmaVBVACtlSubmitSync failed %d\n", rc)); 1934 return rc; 1935 } 1936 return VINF_SUCCESS; 1937 } 1938 1345 1939 int vboxVDMADestruct(struct VBOXVDMAHOST *pVdma) 1346 1940 { 1347 #ifdef VBOX_VDMA_WITH_WORKERTHREAD 1348 /* @todo: implement*/ 1349 AssertBreakpoint(); 1350 #endif 1941 VBVAEXHOSTCTL Ctl; 1942 Ctl.enmType = VBVAEXHOSTCTL_TYPE_HH_TERM; 1943 int rc = vdmaVBVACtlSubmitSync(pVdma, &Ctl, VBVAEXHOSTCTL_SOURCE_HOST_ANY); 1944 if (!RT_SUCCESS(rc)) 1945 { 1946 WARN(("vdmaVBVACtlSubmitSync failed %d\n", rc)); 1947 return rc; 1948 } 1949 VBoxVDMAThreadTerm(&pVdma->Thread); 1351 1950 VBoxVBVAExHSTerm(&pVdma->CmdVbva); 1352 1951 RTMemFree(pVdma); 1353 1952 return VINF_SUCCESS; 1354 1953 } 1355 1356 #ifdef VBOX_VDMA_WITH_WORKERTHREAD1357 typedef struct1358 {1359 struct VBOXVDMAHOST *pVdma;1360 VBOXVDMAPIPE_CMD_BODY Cmd;1361 bool bQueued;1362 } VBOXVDMACMD_SUBMIT_CONTEXT, *PVBOXVDMACMD_SUBMIT_CONTEXT;1363 1364 DECLCALLBACK(bool) vboxVDMACommandSubmitCb(PVBOXVDMAPIPE pPipe, void *pvCallback)1365 {1366 PVBOXVDMACMD_SUBMIT_CONTEXT pContext = (PVBOXVDMACMD_SUBMIT_CONTEXT)pvCallback;1367 struct VBOXVDMAHOST *pVdma = pContext->pVdma;1368 HGSMILISTENTRY *pEntry = hgsmiListRemoveHead(&pVdma->CmdPool.List);1369 Assert(pEntry);1370 if (pEntry)1371 {1372 PVBOXVDMAPIPE_CMD pPipeCmd = VBOXVDMAPIPE_CMD_FROM_ENTRY(pEntry);1373 pPipeCmd->Cmd = pContext->Cmd;1374 VBoxSHGSMICommandMarkAsynchCompletion(pContext->Cmd.u.pvCmd);1375 pContext->bQueued = true;1376 hgsmiListAppend(&pVdma->PendingList, pEntry);1377 return true;1378 }1379 1380 /* @todo: should we try to flush some commands here? */1381 pContext->bQueued = false;1382 return false;1383 }1384 #endif1385 1954 1386 1955 int vboxVDMASaveStateExecPrep(struct VBOXVDMAHOST *pVdma, PSSMHANDLE pSSM) … … 1545 2114 1546 2115 /**/ 1547 static int vboxVBVAExHSProcessorAcquire(struct VBVAEXHOSTCONTEXT *pCmdVbva) 1548 { 1549 Assert(pCmdVbva->u32State != VBVAEXHOSTCONTEXT_STATE_STOPPED); 1550 1551 uint32_t oldState; 1552 if (!ASMAtomicReadU32(&pCmdVbva->u32Pause)) 1553 { 1554 if (ASMAtomicCmpXchgExU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_PROCESSING, VBVAEXHOSTCONTEXT_STATE_LISTENING, &oldState)) 1555 return VINF_SUCCESS; 1556 return oldState == VBVAEXHOSTCONTEXT_STATE_PROCESSING ? VERR_SEM_BUSY : VERR_INVALID_STATE; 1557 } 1558 return VERR_INVALID_STATE; 1559 } 1560 1561 static bool vboxVBVAExHPCheckPause(struct VBVAEXHOSTCONTEXT *pCmdVbva) 1562 { 1563 Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING); 1564 1565 if (!ASMAtomicReadU32(&pCmdVbva->u32Pause)) 1566 return false; 1567 1568 ASMAtomicWriteU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_PAUSED); 1569 return true; 1570 } 1571 1572 static bool vboxVBVAExHPCheckOtherCommands(struct VBVAEXHOSTCONTEXT *pCmdVbva) 1573 { 1574 Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING); 1575 1576 return !!ASMAtomicUoReadU32(&pCmdVbva->u32cOtherCommands); 1577 } 1578 1579 static void vboxVBVAExHPProcessorRelease(struct VBVAEXHOSTCONTEXT *pCmdVbva) 1580 { 1581 Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING); 1582 1583 if (!vboxVBVAExHPCheckPause(pCmdVbva)) 1584 ASMAtomicWriteU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_LISTENING); 2116 2117 static int vdmaVBVACtlSubmit(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete) 2118 { 2119 int rc = VBoxVBVAExHCtlSubmit(&pVdma->CmdVbva, pCtl, enmSource, pfnComplete, pvComplete); 2120 if (RT_SUCCESS(rc)) 2121 { 2122 if (rc == VINF_SUCCESS) 2123 return VBoxVDMAThreadEventNotify(&pVdma->Thread); 2124 else 2125 Assert(rc == VINF_ALREADY_INITIALIZED); 2126 } 1585 2127 else 1586 ASMAtomicWriteU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_PAUSED); 1587 } 1588 1589 static void vboxVBVAExHPHgEventSet(struct VBVAEXHOSTCONTEXT *pCmdVbva) 1590 { 1591 Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING); 1592 1593 ASMAtomicOrU32(&pCmdVbva->pVBVA->hostFlags.u32HostEvents, VBVA_F_STATE_PROCESSING); 1594 } 1595 1596 static void vboxVBVAExHPHgEventClear(struct VBVAEXHOSTCONTEXT *pCmdVbva) 1597 { 1598 Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING); 1599 1600 ASMAtomicAndU32(&pCmdVbva->pVBVA->hostFlags.u32HostEvents, ~VBVA_F_STATE_PROCESSING); 1601 } 1602 1603 static bool vboxVBVAExHPCmdCheckRelease(struct VBVAEXHOSTCONTEXT *pCmdVbva) 1604 { 1605 if (!pCmdVbva->cbCurData) 1606 return false; 1607 1608 VBVABUFFER *pVBVA = pCmdVbva->pVBVA; 1609 pVBVA->off32Data = (pVBVA->off32Data + pCmdVbva->cbCurData) % pVBVA->cbData; 1610 1611 pVBVA->indexRecordFirst = (pVBVA->indexRecordFirst + 1) % RT_ELEMENTS(pVBVA->aRecords); 1612 1613 pCmdVbva->cbCurData = 0; 1614 1615 return true; 1616 } 1617 1618 static int vboxVBVAExHPCmdGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd) 1619 { 1620 Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING); 1621 1622 VBVABUFFER *pVBVA = pCmdVbva->pVBVA; 1623 1624 uint32_t indexRecordFirst = pVBVA->indexRecordFirst; 1625 uint32_t indexRecordFree = pVBVA->indexRecordFree; 1626 1627 Log(("first = %d, free = %d\n", 1628 indexRecordFirst, indexRecordFree)); 1629 1630 if (indexRecordFirst == indexRecordFree) 1631 { 1632 /* No records to process. Return without assigning output variables. */ 1633 return VINF_EOF; 1634 } 1635 1636 uint32_t cbRecordCurrent = ASMAtomicReadU32(&pVBVA->aRecords[indexRecordFirst].cbRecord); 1637 1638 /* A new record need to be processed. */ 1639 if (cbRecordCurrent & VBVA_F_RECORD_PARTIAL) 1640 { 1641 /* the record is being recorded, try again */ 1642 return VINF_TRY_AGAIN; 1643 } 1644 1645 uint32_t cbRecord = cbRecordCurrent & ~VBVA_F_RECORD_PARTIAL; 1646 1647 if (!cbRecord) 1648 { 1649 /* the record is being recorded, try again */ 1650 return VINF_TRY_AGAIN; 1651 } 1652 1653 /* we should not get partial commands here actually */ 1654 Assert(cbRecord); 1655 1656 /* The size of largest contiguous chunk in the ring biffer. */ 1657 uint32_t u32BytesTillBoundary = pVBVA->cbData - pVBVA->off32Data; 1658 1659 /* The pointer to data in the ring buffer. */ 1660 uint8_t *pSrc = &pVBVA->au8Data[pVBVA->off32Data]; 1661 1662 /* Fetch or point the data. */ 1663 if (u32BytesTillBoundary >= cbRecord) 1664 { 1665 /* The command does not cross buffer boundary. Return address in the buffer. */ 1666 *ppCmd = pSrc; 1667 *pcbCmd = cbRecord; 1668 pCmdVbva->cbCurData = cbRecord; 2128 WARN(("VBoxVBVAExHCtlSubmit failed %d\n", rc)); 2129 2130 return rc; 2131 } 2132 2133 static DECLCALLBACK(void) vboxCmdVBVACmdCtlGuestCompletion(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvContext) 2134 { 2135 PVBOXVDMAHOST pVdma = (PVBOXVDMAHOST)pvContext; 2136 VBOXCMDVBVA_CTL *pGCtl = (VBOXCMDVBVA_CTL*)(pCtl->u.cmd.pu8Cmd - sizeof (VBOXCMDVBVA_CTL)); 2137 AssertRC(rc); 2138 pGCtl->i32Result = rc; 2139 2140 Assert(pVdma->pVGAState->fGuestCaps & VBVACAPS_COMPLETEGCMD_BY_IOREAD); 2141 rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pGCtl); 2142 AssertRC(rc); 2143 2144 VBoxVBVAExHCtlFree(pVbva, pCtl); 2145 } 2146 2147 static int vdmaVBVACtlOpaqueSubmit(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL_SOURCE enmSource, uint8_t* pu8Cmd, uint32_t cbCmd, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete) 2148 { 2149 VBVAEXHOSTCTL* pHCtl = VBoxVBVAExHCtlCreate(&pVdma->CmdVbva, VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE); 2150 if (!pHCtl) 2151 { 2152 WARN(("VBoxVBVAExHCtlCreate failed\n")); 2153 return VERR_NO_MEMORY; 2154 } 2155 2156 pHCtl->u.cmd.pu8Cmd = pu8Cmd; 2157 pHCtl->u.cmd.cbCmd = cbCmd; 2158 int rc = vdmaVBVACtlSubmit(pVdma, pHCtl, enmSource, pfnComplete, pvComplete); 2159 if (!RT_SUCCESS(rc)) 2160 { 2161 WARN(("vdmaVBVACtlSubmit failed rc %d\n", rc)); 2162 return rc;; 2163 } 2164 return VINF_SUCCESS; 2165 } 2166 2167 static int vdmaVBVACtlOpaqueGuestSubmit(PVBOXVDMAHOST pVdma, VBOXCMDVBVA_CTL *pCtl, uint32_t cbCtl) 2168 { 2169 Assert(cbCtl >= sizeof (VBOXCMDVBVA_CTL)); 2170 VBoxSHGSMICommandMarkAsynchCompletion(pCtl); 2171 int rc = vdmaVBVACtlOpaqueSubmit(pVdma, VBVAEXHOSTCTL_SOURCE_GUEST, (uint8_t*)(pCtl+1), cbCtl - sizeof (VBOXCMDVBVA_CTL), vboxCmdVBVACmdCtlGuestCompletion, pVdma); 2172 if (RT_SUCCESS(rc)) 1669 2173 return VINF_SUCCESS; 1670 } 1671 1672 LogRel(("CmdVbva: cross-bound writes unsupported\n")); 1673 return VERR_INVALID_STATE; 1674 } 1675 1676 /* Resumes command processing 1677 * @returns - same as VBoxVBVAExHSCheckCommands 1678 */ 1679 static int vboxVBVAExHSResume(struct VBVAEXHOSTCONTEXT *pCmdVbva) 1680 { 1681 Assert(pCmdVbva->u32State != VBVAEXHOSTCONTEXT_STATE_STOPPED); 1682 1683 ASMAtomicWriteU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_LISTENING); 1684 1685 return VBoxVBVAExHSCheckCommands(pCmdVbva); 1686 } 1687 1688 /* pause the command processing. this will make the processor stop the command processing and release the processing state 1689 * to resume the command processing the vboxVBVAExHSResume must be called */ 1690 static void vboxVBVAExHSPause(struct VBVAEXHOSTCONTEXT *pCmdVbva) 1691 { 1692 Assert(pCmdVbva->u32State != VBVAEXHOSTCONTEXT_STATE_STOPPED); 1693 1694 Assert(!pCmdVbva->u32Pause); 1695 1696 ASMAtomicWriteU32(&pCmdVbva->u32Pause, 1); 1697 1698 for(;;) 1699 { 1700 if (ASMAtomicCmpXchgU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_PAUSED, VBVAEXHOSTCONTEXT_STATE_LISTENING)) 1701 break; 1702 1703 if (ASMAtomicReadU32(&pCmdVbva->u32State) == VBVAEXHOSTCONTEXT_STATE_PAUSED) 1704 break; 1705 1706 RTThreadSleep(2); 1707 } 1708 1709 pCmdVbva->u32Pause = 0; 1710 } 1711 1712 /* releases (completed) the command previously acquired by VBoxVBVAExHCmdGet 1713 * for convenience can be called if no command is currently acquired 1714 * in that case it will do nothing and return false. 1715 * if the completion notification is needed returns true. */ 1716 static bool VBoxVBVAExHPCmdCheckRelease(struct VBVAEXHOSTCONTEXT *pCmdVbva) 1717 { 1718 Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING); 1719 1720 return vboxVBVAExHPCmdCheckRelease(pCmdVbva); 1721 } 1722 1723 /* 1724 * @returns 1725 * VINF_SUCCESS - new command is obtained 1726 * VINF_EOF - processor has completed all commands and release the processing state, only VBoxVBVAExHS*** calls are now allowed 1727 * VINF_PERMISSION_DENIED - processing was paused, processing state was released, only VBoxVBVAExHS*** calls are now allowed 1728 * VINF_INTERRUPTED - command processing was interrupted, processor state remains set. client can process any commands, 1729 * and call VBoxVBVAExHPCmdGet again for further processing 1730 * VERR_** - error happened, most likely guest corrupted VBVA data 1731 * 1732 */ 1733 static int VBoxVBVAExHPCmdGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd) 1734 { 1735 Assert(pCmdVbva->u32State == VBVAEXHOSTCONTEXT_STATE_PROCESSING); 1736 1737 for(;;) 1738 { 1739 if (vboxVBVAExHPCheckPause(pCmdVbva)) 1740 return VINF_PERMISSION_DENIED; 1741 if (vboxVBVAExHPCheckOtherCommands(pCmdVbva)) 1742 return VINF_INTERRUPTED; 1743 1744 int rc = vboxVBVAExHPCmdGet(pCmdVbva, ppCmd, pcbCmd); 1745 switch (rc) 1746 { 1747 case VINF_SUCCESS: 1748 return VINF_SUCCESS; 1749 case VINF_EOF: 1750 vboxVBVAExHPHgEventClear(pCmdVbva); 1751 vboxVBVAExHPProcessorRelease(pCmdVbva); 1752 /* we need to prevent racing between us clearing the flag and command check/submission thread, i.e. 1753 * 1. we check the queue -> and it is empty 1754 * 2. submitter adds command to the queue 1755 * 3. submitter checks the "processing" -> and it is true , thus it does not submit a notification 1756 * 4. we clear the "processing" state 1757 * 5. ->here we need to re-check the queue state to ensure we do not leak the notification of the above command 1758 * 6. if the queue appears to be not-empty set the "processing" state back to "true" 1759 **/ 1760 if (VBoxVBVAExHSCheckCommands(pCmdVbva) == VINF_SUCCESS) 1761 continue; 1762 return VINF_EOF; 1763 case VINF_TRY_AGAIN: 1764 RTThreadSleep(1); 1765 continue; 1766 default: 1767 /* this is something really unexpected, i.e. most likely guest has written something incorrect to the VBVA buffer */ 1768 if (RT_FAILURE(rc)) 1769 return rc; 1770 1771 WARN(("Warning: vboxVBVAExHCmdGet returned unexpected success status %d\n", rc)); 1772 return VERR_INTERNAL_ERROR; 1773 } 1774 } 1775 1776 WARN(("Warning: VBoxVBVAExHCmdGet unexpected state\n")); 1777 return VERR_INTERNAL_ERROR; 1778 } 1779 1780 /* Checks whether the new commands are ready for processing 1781 * @returns 1782 * VINF_SUCCESS - there are commands are in a queue, and the given thread is now the processor (i.e. typically it would delegate processing to a worker thread) 1783 * VINF_EOF - no commands in a queue 1784 * VINF_ALREADY_INITIALIZED - another thread already processing the commands 1785 * VERR_INVALID_STATE - the VBVA is paused or pausing */ 1786 static int VBoxVBVAExHSCheckCommands(struct VBVAEXHOSTCONTEXT *pCmdVbva) 1787 { 1788 if (ASMAtomicUoReadU32(&pCmdVbva->u32State) == VBVAEXHOSTCONTEXT_STATE_STOPPED) 1789 return VINF_EOF; 1790 1791 int rc = vboxVBVAExHSProcessorAcquire(pCmdVbva); 2174 2175 WARN(("vdmaVBVACtlOpaqueSubmit failed %d\n", rc)); 2176 pCtl->i32Result = rc; 2177 rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pCtl); 2178 AssertRC(rc); 2179 return VINF_SUCCESS; 2180 } 2181 2182 static DECLCALLBACK(void) vboxCmdVBVACmdCtlHostCompletion(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvCompletion) 2183 { 2184 VBOXCRCMDCTL* pVboxCtl = (VBOXCRCMDCTL*)pCtl->u.cmd.pu8Cmd; 2185 if (pVboxCtl->pfnInternal) 2186 ((PFNCRCTLCOMPLETION)pVboxCtl->pfnInternal)(pVboxCtl, pCtl->u.cmd.cbCmd, rc, pvCompletion); 2187 VBoxVBVAExHCtlFree(pVbva, pCtl); 2188 } 2189 2190 static int vdmaVBVACtlOpaqueHostSubmit(PVBOXVDMAHOST pVdma, struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, 2191 PFNCRCTLCOMPLETION pfnCompletion, 2192 void *pvCompletion) 2193 { 2194 pCmd->pfnInternal = (void(*)())pfnCompletion; 2195 int rc = vdmaVBVACtlOpaqueSubmit(pVdma, VBVAEXHOSTCTL_SOURCE_HOST_ENABLED, (uint8_t*)pCmd, cbCmd, vboxCmdVBVACmdCtlHostCompletion, pvCompletion); 2196 if (!RT_SUCCESS(rc)) 2197 { 2198 if (rc == VERR_INVALID_STATE) 2199 { 2200 pCmd->pfnInternal = NULL; 2201 PVGASTATE pVGAState = pVdma->pVGAState; 2202 rc = pVGAState->pDrv->pfnCrHgcmCtlSubmit(pVGAState->pDrv, pCmd, cbCmd, pfnCompletion, pvCompletion); 2203 if (!RT_SUCCESS(rc)) 2204 WARN(("pfnCrHgsmiControlProcess failed %d\n", rc)); 2205 2206 return rc; 2207 } 2208 WARN(("vdmaVBVACtlOpaqueSubmit failed %d\n", rc)); 2209 return rc; 2210 } 2211 2212 return VINF_SUCCESS; 2213 } 2214 2215 static int vdmaVBVACtlEnableDisableSubmitInternal(PVBOXVDMAHOST pVdma, VBOXCMDVBVA_CTL_ENABLE *pEnable, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete) 2216 { 2217 VBVAEXHOSTCTL* pHCtl = VBoxVBVAExHCtlCreate(&pVdma->CmdVbva, VBVAEXHOSTCTL_TYPE_GH_ENABLE_DISABLE); 2218 if (!pHCtl) 2219 { 2220 WARN(("VBoxVBVAExHCtlCreate failed\n")); 2221 return VERR_NO_MEMORY; 2222 } 2223 2224 pHCtl->u.cmd.pu8Cmd = (uint8_t*)&pEnable->Enable; 2225 pHCtl->u.cmd.cbCmd = sizeof (pEnable->Enable); 2226 int rc = vdmaVBVACtlSubmit(pVdma, pHCtl, VBVAEXHOSTCTL_SOURCE_GUEST, pfnComplete, pvComplete); 2227 if (!RT_SUCCESS(rc)) 2228 { 2229 WARN(("vdmaVBVACtlSubmit failed rc %d\n", rc)); 2230 return rc;; 2231 } 2232 return VINF_SUCCESS; 2233 } 2234 2235 static int vdmaVBVACtlEnableDisableSubmit(PVBOXVDMAHOST pVdma, VBOXCMDVBVA_CTL_ENABLE *pEnable) 2236 { 2237 VBoxSHGSMICommandMarkAsynchCompletion(&pEnable->Hdr); 2238 int rc = vdmaVBVACtlEnableDisableSubmitInternal(pVdma, pEnable, vboxCmdVBVACmdCtlGuestCompletion, pVdma); 1792 2239 if (RT_SUCCESS(rc)) 1793 { 1794 /* we are the processor now */ 1795 VBVABUFFER *pVBVA = pCmdVbva->pVBVA; 1796 1797 uint32_t indexRecordFirst = pVBVA->indexRecordFirst; 1798 uint32_t indexRecordFree = pVBVA->indexRecordFree; 1799 1800 if (indexRecordFirst != indexRecordFree) 1801 { 1802 vboxVBVAExHPHgEventSet(pCmdVbva); 1803 return VINF_SUCCESS; 1804 } 1805 1806 vboxVBVAExHPProcessorRelease(pCmdVbva); 1807 return VINF_EOF; 1808 } 1809 if (rc == VERR_SEM_BUSY) 1810 return VINF_ALREADY_INITIALIZED; 1811 Assert(rc == VERR_INVALID_STATE); 1812 return VERR_INVALID_STATE; 1813 } 1814 1815 static void VBoxVBVAExHSInit(struct VBVAEXHOSTCONTEXT *pCmdVbva) 1816 { 1817 memset(pCmdVbva, 0, sizeof (*pCmdVbva)); 1818 } 1819 1820 static int VBoxVBVAExHSEnable(struct VBVAEXHOSTCONTEXT *pCmdVbva, VBVABUFFER *pVBVA) 1821 { 1822 if (ASMAtomicUoReadU32(&pCmdVbva->u32State) != VBVAEXHOSTCONTEXT_STATE_STOPPED) 1823 return VINF_ALREADY_INITIALIZED; 1824 1825 pCmdVbva->pVBVA = pVBVA; 1826 pCmdVbva->pVBVA->hostFlags.u32HostEvents = 0; 1827 ASMAtomicWriteU32(&pCmdVbva->u32State, VBVAEXHOSTCONTEXT_STATE_LISTENING); 2240 return VINF_SUCCESS; 2241 2242 WARN(("vdmaVBVACtlEnableDisableSubmitInternal failed %d\n", rc)); 2243 pEnable->Hdr.i32Result = rc; 2244 rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, &pEnable->Hdr); 2245 AssertRC(rc); 1828 2246 return VINF_SUCCESS; 1829 2247 } 1830 2248 1831 static int VBoxVBVAExHSDisable(struct VBVAEXHOSTCONTEXT *pCmdVbva) 1832 { 1833 if (ASMAtomicUoReadU32(&pCmdVbva->u32State) == VBVAEXHOSTCONTEXT_STATE_STOPPED) 1834 return VINF_SUCCESS; 1835 1836 /* ensure no commands pending and one tries to submit them */ 1837 int rc = vboxVBVAExHSProcessorAcquire(pCmdVbva); 2249 static DECLCALLBACK(void) vdmaVBVACtlSubmitSyncCompletion(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvContext) 2250 { 2251 VDMA_VBVA_CTL_CYNC_COMPLETION *pData = (VDMA_VBVA_CTL_CYNC_COMPLETION*)pvContext; 2252 pData->rc = rc; 2253 rc = RTSemEventSignal(pData->hEvent); 2254 if (!RT_SUCCESS(rc)) 2255 WARN(("RTSemEventSignal failed %d\n", rc)); 2256 } 2257 2258 static int vdmaVBVACtlSubmitSync(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource) 2259 { 2260 VDMA_VBVA_CTL_CYNC_COMPLETION Data; 2261 Data.rc = VERR_NOT_IMPLEMENTED; 2262 int rc = RTSemEventCreate(&Data.hEvent); 2263 if (!RT_SUCCESS(rc)) 2264 { 2265 WARN(("RTSemEventCreate failed %d\n", rc)); 2266 return rc; 2267 } 2268 2269 rc = vdmaVBVACtlSubmit(pVdma, pCtl, enmSource, vdmaVBVACtlSubmitSyncCompletion, &Data); 1838 2270 if (RT_SUCCESS(rc)) 1839 2271 { 1840 pCmdVbva->pVBVA->hostFlags.u32HostEvents = 0; 1841 memset(pCmdVbva, 0, sizeof (*pCmdVbva)); 1842 return VINF_SUCCESS; 1843 } 1844 return VERR_INVALID_STATE; 1845 } 1846 1847 static void VBoxVBVAExHSTerm(struct VBVAEXHOSTCONTEXT *pCmdVbva) 1848 { 1849 /* ensure the processor is stopped */ 1850 if (ASMAtomicUoReadU32(&pCmdVbva->u32State) == VBVAEXHOSTCONTEXT_STATE_STOPPED) 1851 return; 1852 1853 /* ensure no one tries to submit the command */ 1854 vboxVBVAExHSPause(pCmdVbva); 1855 pCmdVbva->pVBVA->hostFlags.u32HostEvents = 0; 1856 memset(pCmdVbva, 0, sizeof (*pCmdVbva)); 1857 } 1858 1859 /* Saves state 1860 * @returns - same as VBoxVBVAExHSCheckCommands, or failure on load state fail 1861 */ 1862 static int VBoxVBVAExHSSaveState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM) 1863 { 1864 int rc; 1865 if (ASMAtomicUoReadU32(&pCmdVbva->u32State) != VBVAEXHOSTCONTEXT_STATE_STOPPED) 1866 { 1867 vboxVBVAExHSPause(pCmdVbva); 1868 rc = SSMR3PutU32(pSSM, (uint32_t)(((uint8_t*)pCmdVbva->pVBVA) - pu8VramBase)); 1869 AssertRCReturn(rc, rc); 1870 return vboxVBVAExHSResume(pCmdVbva); 1871 } 1872 1873 rc = SSMR3PutU32(pSSM, 0xffffffff); 1874 AssertRCReturn(rc, rc); 1875 1876 return VINF_EOF; 1877 } 1878 1879 /* Loads state 1880 * @returns - same as VBoxVBVAExHSCheckCommands, or failure on load state fail 1881 */ 1882 static int VBoxVBVAExHSLoadState(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t* pu8VramBase, PSSMHANDLE pSSM, uint32_t u32Version) 1883 { 1884 uint32_t u32; 1885 int rc = SSMR3GetU32(pSSM, &u32); 1886 AssertRCReturn(rc, rc); 1887 if (u32 != 0xffffffff) 1888 { 1889 VBVABUFFER *pVBVA = (VBVABUFFER*)pu8VramBase + u32; 1890 rc = VBoxVBVAExHSEnable(pCmdVbva, pVBVA); 1891 AssertRCReturn(rc, rc); 1892 return VBoxVBVAExHSCheckCommands(pCmdVbva); 1893 } 1894 1895 return VINF_EOF; 1896 } 1897 1898 int vboxCmdVBVAEnable(PVGASTATE pVGAState, VBVABUFFER *pVBVA) 1899 { 1900 struct VBOXVDMAHOST *pVdma = pVGAState->pVdma; 1901 return VBoxVBVAExHSEnable(&pVdma->CmdVbva, pVBVA); 1902 } 1903 1904 int vboxCmdVBVADisable(PVGASTATE pVGAState) 1905 { 1906 struct VBOXVDMAHOST *pVdma = pVGAState->pVdma; 1907 return VBoxVBVAExHSDisable(&pVdma->CmdVbva); 1908 } 1909 1910 static int vboxCmdVBVACmdSubmitPerform(PVGASTATE pVGAState) 1911 { 1912 struct VBOXVDMAHOST *pVdma = pVGAState->pVdma; 2272 rc = RTSemEventWait(Data.hEvent, RT_INDEFINITE_WAIT); 2273 if (RT_SUCCESS(rc)) 2274 { 2275 rc = Data.rc; 2276 if (!RT_SUCCESS(rc)) 2277 WARN(("vdmaVBVACtlSubmitSyncCompletion returned %d\n", rc)); 2278 } 2279 else 2280 WARN(("RTSemEventWait failed %d\n", rc)); 2281 } 2282 else 2283 WARN(("vdmaVBVACtlSubmit failed %d\n", rc)); 2284 2285 RTSemEventDestroy(Data.hEvent); 2286 2287 return rc; 2288 } 2289 2290 static int vdmaVBVAPause(PVBOXVDMAHOST pVdma) 2291 { 2292 VBVAEXHOSTCTL Ctl; 2293 Ctl.enmType = VBVAEXHOSTCTL_TYPE_HH_INTERNAL_PAUSE; 2294 return vdmaVBVACtlSubmitSync(pVdma, &Ctl, VBVAEXHOSTCTL_SOURCE_HOST_ANY); 2295 } 2296 2297 static int vdmaVBVAResume(PVBOXVDMAHOST pVdma) 2298 { 2299 VBVAEXHOSTCTL Ctl; 2300 Ctl.enmType = VBVAEXHOSTCTL_TYPE_HH_INTERNAL_RESUME; 2301 return vdmaVBVACtlSubmitSync(pVdma, &Ctl, VBVAEXHOSTCTL_SOURCE_HOST_ANY); 2302 } 2303 2304 static int vboxVDMACmdSubmitPerform(struct VBOXVDMAHOST *pVdma) 2305 { 1913 2306 int rc = VBoxVBVAExHSCheckCommands(&pVdma->CmdVbva); 1914 2307 switch (rc) 1915 2308 { 1916 2309 case VINF_SUCCESS: 1917 return pVGAState->pDrv->pfnCrCmdNotifyCmds(pVGAState->pDrv);2310 return VBoxVDMAThreadEventNotify(&pVdma->Thread); 1918 2311 case VINF_ALREADY_INITIALIZED: 1919 2312 case VINF_EOF: … … 1926 2319 } 1927 2320 2321 2322 int vboxCmdVBVACmdHostCtl(PPDMIDISPLAYVBVACALLBACKS pInterface, 2323 struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, 2324 PFNCRCTLCOMPLETION pfnCompletion, 2325 void *pvCompletion) 2326 { 2327 PVGASTATE pVGAState = PPDMIDISPLAYVBVACALLBACKS_2_PVGASTATE(pInterface); 2328 struct VBOXVDMAHOST *pVdma = pVGAState->pVdma; 2329 return vdmaVBVACtlOpaqueHostSubmit(pVdma, pCmd, cbCmd, pfnCompletion, pvCompletion); 2330 } 2331 2332 int vboxCmdVBVACmdCtl(PVGASTATE pVGAState, VBOXCMDVBVA_CTL *pCtl, uint32_t cbCtl) 2333 { 2334 struct VBOXVDMAHOST *pVdma = pVGAState->pVdma; 2335 int rc = VINF_SUCCESS; 2336 switch (pCtl->u32Type) 2337 { 2338 case VBOXCMDVBVACTL_TYPE_3DCTL: 2339 return vdmaVBVACtlOpaqueGuestSubmit(pVdma, pCtl, cbCtl); 2340 case VBOXCMDVBVACTL_TYPE_ENABLE: 2341 if (cbCtl != sizeof (VBOXCMDVBVA_CTL_ENABLE)) 2342 { 2343 WARN(("incorrect enable size\n")); 2344 rc = VERR_INVALID_PARAMETER; 2345 break; 2346 } 2347 return vdmaVBVACtlEnableDisableSubmit(pVdma, (VBOXCMDVBVA_CTL_ENABLE*)pCtl); 2348 default: 2349 WARN(("unsupported type\n")); 2350 rc = VERR_INVALID_PARAMETER; 2351 break; 2352 } 2353 2354 pCtl->i32Result = rc; 2355 rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pCtl); 2356 AssertRC(rc); 2357 return VINF_SUCCESS; 2358 } 2359 1928 2360 int vboxCmdVBVACmdSubmit(PVGASTATE pVGAState) 1929 2361 { 1930 return vboxCmdVBVACmdSubmitPerform(pVGAState); 2362 if (!VBoxVBVAExHSIsEnabled(&pVGAState->pVdma->CmdVbva)) 2363 { 2364 WARN(("vdma VBVA is disabled\n")); 2365 return VERR_INVALID_STATE; 2366 } 2367 2368 return vboxVDMACmdSubmitPerform(pVGAState->pVdma); 1931 2369 } 1932 2370 1933 2371 int vboxCmdVBVACmdFlush(PVGASTATE pVGAState) 1934 2372 { 1935 return vboxCmdVBVACmdSubmitPerform(pVGAState); 2373 WARN(("flush\n")); 2374 if (!VBoxVBVAExHSIsEnabled(&pVGAState->pVdma->CmdVbva)) 2375 { 2376 WARN(("vdma VBVA is disabled\n")); 2377 return VERR_INVALID_STATE; 2378 } 2379 return vboxVDMACmdSubmitPerform(pVGAState->pVdma); 1936 2380 } 1937 2381 1938 2382 void vboxCmdVBVACmdTimer(PVGASTATE pVGAState) 1939 2383 { 1940 vboxCmdVBVACmdSubmitPerform(pVGAState); 1941 } 2384 if (!VBoxVBVAExHSIsEnabled(&pVGAState->pVdma->CmdVbva)) 2385 return; 2386 vboxVDMACmdSubmitPerform(pVGAState->pVdma); 2387 } -
trunk/src/VBox/GuestHost/OpenGL/include/cr_server.h
r50394 r50754 34 34 #include <VBox/Hardware/VBoxVideoVBE.h> 35 35 #include <VBox/VBoxVideo3D.h> 36 #include <VBox/VBoxVideoHost3D.h> 36 37 37 38 #ifdef __cplusplus … … 406 407 uint32_t fBlitterMode; 407 408 CR_BLITTER Blitter; 408 409 VBOXCRCMD_CLTINFO CltInfo;410 409 411 410 CR_SERVER_RPW RpwWorker; … … 486 485 SPUDispatchTable TmpCtxDispatch; 487 486 487 VBOXCRCMD_SVRENABLE_INFO CrCmdClientInfo; 488 488 489 #ifdef VBOX_WITH_CRSERVER_DUMPER 489 490 CR_RECORDER Recorder; … … 566 567 extern DECLEXPORT(int32_t) crVBoxServerCrHgsmiCtl(struct VBOXVDMACMD_CHROMIUM_CTL *pCtl, uint32_t cbCtl); 567 568 568 extern DECLEXPORT(int32_t) crVBoxServerCrCmdNotifyCmds();569 569 #endif 570 570 -
trunk/src/VBox/GuestHost/OpenGL/include/cr_vreg.h
r50412 r50754 64 64 VBoxRectScale(pResult, xScale, yScale); 65 65 } 66 67 DECLINLINE(void) VBoxRectUnscale(PRTRECT pRect, float xScale, float yScale) 68 { 69 pRect->xLeft = CR_FLOAT_RCAST(int32_t, pRect->xLeft / xScale); 70 pRect->yTop = CR_FLOAT_RCAST(int32_t, pRect->yTop / yScale); 71 pRect->xRight = CR_FLOAT_RCAST(int32_t, pRect->xRight / xScale); 72 pRect->yBottom = CR_FLOAT_RCAST(int32_t, pRect->yBottom / yScale); 73 } 74 75 DECLINLINE(void) VBoxRectUnscaled(const RTRECT *pRect, float xScale, float yScale, PRTRECT pResult) 76 { 77 *pResult = *pRect; 78 VBoxRectUnscale(pResult, xScale, yScale); 79 } 66 80 #endif 67 81 -
trunk/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp
r50394 r50754 962 962 * We differentiate between a function handler for the guest and one for the host. 963 963 */ 964 static DECLCALLBACK(int) svcHostCall(void *, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])964 static int svcHostCallPerform(void *, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 965 965 { 966 966 int rc = VINF_SUCCESS; … … 980 980 switch (u32Function) 981 981 { 982 case SHCRGL_HOST_FN_CRCMD_NOTIFY_CMDS:983 {984 rc = crVBoxServerCrCmdNotifyCmds();985 } break;986 982 #ifdef VBOX_WITH_CRHGSMI 987 983 case SHCRGL_HOST_FN_CRHGSMI_CMD: … … 1477 1473 } 1478 1474 1475 static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 1476 { 1477 switch (u32Function) 1478 { 1479 case SHCRGL_HOST_FN_CTL: 1480 { 1481 if (cParms != 1) 1482 { 1483 WARN(("cParams != 1")); 1484 return VERR_INVALID_PARAMETER; 1485 } 1486 1487 if (paParms->type != VBOX_HGCM_SVC_PARM_PTR) 1488 { 1489 WARN(("invalid param type")); 1490 return VERR_INVALID_PARAMETER; 1491 } 1492 1493 if (paParms->u.pointer.size < sizeof (VBOXCRCMDCTL)) 1494 { 1495 WARN(("invalid param size")); 1496 return VERR_INVALID_PARAMETER; 1497 } 1498 1499 if ((paParms->u.pointer.size - sizeof (VBOXCRCMDCTL)) % sizeof(VBOXHGCMSVCPARM)) 1500 { 1501 WARN(("invalid param size")); 1502 return VERR_INVALID_PARAMETER; 1503 } 1504 1505 VBOXCRCMDCTL *pCtl = (VBOXCRCMDCTL*)paParms->u.pointer.addr; 1506 uint32_t cParams = (paParms->u.pointer.size - sizeof (VBOXCRCMDCTL)) / sizeof (VBOXHGCMSVCPARM); 1507 return svcHostCallPerform(NULL, pCtl->u32Function, cParms, (VBOXHGCMSVCPARM*)(pCtl + 1)); 1508 } 1509 case VBOXCRCMDCTL_TYPE_DISABLE: 1510 AssertMsgFailed(("VBOXCRCMDCTL_TYPE_DISABLE\n")); 1511 return VERR_NOT_IMPLEMENTED; 1512 case VBOXCRCMDCTL_TYPE_ENABLE: 1513 AssertMsgFailed(("VBOXCRCMDCTL_TYPE_ENABLE\n")); 1514 return VERR_NOT_IMPLEMENTED; 1515 default: 1516 return svcHostCallPerform(NULL, u32Function, cParms, paParms); 1517 } 1518 1519 } 1520 1479 1521 extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable) 1480 1522 { -
trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server.h
r50625 r50754 428 428 void CrFbVisitCreatedEntries(HCR_FRAMEBUFFER hFb, PFNCR_FRAMEBUFFER_ENTRIES_VISITOR_CB pfnVisitorCb, void *pvContext); 429 429 int CrFbResize(HCR_FRAMEBUFFER hFb, const struct VBVAINFOSCREEN * pScreen, void *pvVRAM); 430 int CrFbBltGetContents(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, uint32_t cRects, const RTRECT *pPrects, CR_BLITTER_IMG *pImg);430 int CrFbBltGetContents(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pPrects, CR_BLITTER_IMG *pImg); 431 431 bool CrFbIsEnabled(HCR_FRAMEBUFFER hFb); 432 432 int CrFbEntryCreateForTexId(HCR_FRAMEBUFFER hFb, GLuint idTex, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry); -
trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c
r50625 r50754 3186 3186 } 3187 3187 3188 static int32_t crVBoxServerCrCmdProcess(PVBOXCMDVBVA_HDR pCmd, uint32_t cbCmd) 3189 { 3188 static DECLCALLBACK(int) crVBoxCrCmdEnable(HVBOXCRCMDSVR hSvr, VBOXCRCMD_SVRENABLE_INFO *pInfo) 3189 { 3190 cr_server.CrCmdClientInfo = *pInfo; 3191 AssertFailed(); 3192 return VERR_NOT_IMPLEMENTED; 3193 } 3194 3195 static DECLCALLBACK(int) crVBoxCrCmdDisable(HVBOXCRCMDSVR hSvr) 3196 { 3197 AssertFailed(); 3198 memset(&cr_server.CrCmdClientInfo, 0, sizeof (cr_server.CrCmdClientInfo)); 3199 return VERR_NOT_IMPLEMENTED; 3200 } 3201 3202 static DECLCALLBACK(int) crVBoxCrCmdHostCtl(HVBOXCRCMDSVR hSvr, uint8_t* pCmd, uint32_t cbCmd) 3203 { 3204 AssertFailed(); 3205 return VERR_NOT_IMPLEMENTED; 3206 } 3207 3208 static DECLCALLBACK(int) crVBoxCrCmdGuestCtl(HVBOXCRCMDSVR hSvr, uint8_t* pCmd, uint32_t cbCmd) 3209 { 3210 AssertFailed(); 3211 return VERR_NOT_IMPLEMENTED; 3212 } 3213 3214 static DECLCALLBACK(int) crVBoxCrCmdSaveState(HVBOXCRCMDSVR hSvr, PSSMHANDLE pSSM) 3215 { 3216 AssertFailed(); 3217 return VERR_NOT_IMPLEMENTED; 3218 } 3219 3220 static DECLCALLBACK(int) crVBoxCrCmdLoadState(HVBOXCRCMDSVR hSvr, PSSMHANDLE pSSM, uint32_t u32Version) 3221 { 3222 AssertFailed(); 3223 return VERR_NOT_IMPLEMENTED; 3224 } 3225 3226 3227 static DECLCALLBACK(int) crVBoxCrCmdCmd(HVBOXCRCMDSVR hSvr, PVBOXCMDVBVA_HDR pCmd, uint32_t cbCmd) 3228 { 3229 AssertFailed(); 3190 3230 switch (pCmd->u8OpCode) 3191 3231 { … … 3219 3259 } 3220 3260 3221 int32_t crVBoxServerCrCmdNotifyCmds()3222 {3223 PVBOXCMDVBVA_HDR pCmd = NULL;3224 uint32_t cbCmd;3225 3226 for (;;)3227 {3228 int rc = cr_server.CltInfo.pfnCmdGet(cr_server.CltInfo.hClient, &pCmd, &cbCmd);3229 if (rc == VINF_EOF)3230 return VINF_SUCCESS;3231 if (!RT_SUCCESS(rc))3232 return rc;3233 3234 rc = crVBoxServerCrCmdProcess(pCmd, cbCmd);3235 if (!RT_SUCCESS(rc))3236 return rc;3237 }3238 3239 /* should not be here! */3240 AssertFailed();3241 return VERR_INTERNAL_ERROR;3242 }3243 3244 3261 /* We moved all CrHgsmi command processing to crserverlib to keep the logic of dealing with CrHgsmi commands in one place. 3245 3262 * … … 3594 3611 g_pvVRamBase = (uint8_t*)pSetup->pvVRamBase; 3595 3612 g_cbVRam = pSetup->cbVRam; 3596 cr_server.CltInfo = *pSetup->pCrCmdClientInfo; 3613 pSetup->CrCmdServerInfo.hSvr = NULL; 3614 pSetup->CrCmdServerInfo.pfnEnable = crVBoxCrCmdEnable; 3615 pSetup->CrCmdServerInfo.pfnDisable = crVBoxCrCmdDisable; 3616 pSetup->CrCmdServerInfo.pfnCmd = crVBoxCrCmdCmd; 3617 pSetup->CrCmdServerInfo.pfnHostCtl = crVBoxCrCmdHostCtl; 3618 pSetup->CrCmdServerInfo.pfnGuestCtl = crVBoxCrCmdGuestCtl; 3619 pSetup->CrCmdServerInfo.pfnSaveState = crVBoxCrCmdSaveState; 3620 pSetup->CrCmdServerInfo.pfnLoadState = crVBoxCrCmdLoadState; 3597 3621 rc = VINF_SUCCESS; 3598 3622 break; -
trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.cpp
r50625 r50754 687 687 || pScreen->u16BitsPerPixel != 32) 688 688 { 689 RTRECT Rect; 689 RTRECT SrcRect; 690 RTRECT DstRect; 690 691 691 692 pScreenshot->Img.cbData = pScreen->u32LineSize * pScreen->u32Height; … … 711 712 pScreenshot->Img.bpp = 32; 712 713 pScreenshot->Img.pitch = pitch; 713 Rect.xLeft = 0; 714 Rect.yTop = 0; 715 Rect.xRight = pScreen->u32Width; 716 Rect.yBottom = pScreen->u32Height; 717 int rc = CrFbBltGetContents(hFb, &Rect, 1, &Rect, &pScreenshot->Img); 714 SrcRect.xLeft = 0; 715 SrcRect.yTop = 0; 716 SrcRect.xRight = pScreen->u32Width; 717 SrcRect.yBottom = pScreen->u32Height; 718 DstRect.xLeft = 0; 719 DstRect.yTop = 0; 720 DstRect.xRight = width; 721 DstRect.yBottom = height; 722 int rc = CrFbBltGetContents(hFb, &SrcRect, &DstRect, 1, &DstRect, &pScreenshot->Img); 718 723 if (!RT_SUCCESS(rc)) 719 724 { -
trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_presenter.cpp
r50430 r50754 320 320 } 321 321 322 static void crFbBltImgScaledRects(const CR_BLITTER_IMG *pSrc, const RTPOINT *pSrcDataPoint, bool fSrcInvert, const RTRECT *pCopyRect, const RTPOINT *pDstDataPoint, float strX, float strY, CR_BLITTER_IMG *pDst) 323 { 324 int32_t srcX = pCopyRect->xLeft - pSrcDataPoint->x; 325 int32_t srcY = pCopyRect->yTop - pSrcDataPoint->y; 326 Assert(srcX >= 0); 327 Assert(srcY >= 0); 328 329 RTRECT UnscaledCopyRect; 330 VBoxRectUnscaled(pCopyRect, strX, strY, &UnscaledCopyRect); 331 332 srcX = CR_FLOAT_RCAST(int32_t, srcX / strX); 333 srcY = CR_FLOAT_RCAST(int32_t, srcY / strY); 334 335 int32_t UnscaledSrcWidth = UnscaledCopyRect.xRight - UnscaledCopyRect.xLeft; 336 int32_t delta = (int32_t)pSrc->width - srcX - UnscaledSrcWidth; 337 if (delta < 0) 338 UnscaledSrcWidth += delta; 339 340 if (UnscaledSrcWidth <= 0) 341 { 342 LOG(("UnscaledSrcWidth <= 0")); 343 if (UnscaledSrcWidth < 0) 344 WARN(("src width (%d) < 0", UnscaledSrcWidth)); 345 return; 346 } 347 348 int32_t UnscaledSrcHeight = UnscaledCopyRect.yBottom - UnscaledCopyRect.yTop; 349 delta = (int32_t)pSrc->height - srcY - UnscaledSrcHeight; 350 if (delta < 0) 351 UnscaledSrcHeight += delta; 352 353 if (UnscaledSrcHeight <= 0) 354 { 355 LOG(("UnscaledSrcHeight <= 0")); 356 if (UnscaledSrcHeight < 0) 357 WARN(("src height (%d) < 0", UnscaledSrcHeight)); 358 return; 359 } 360 361 int32_t dstX = pCopyRect->xLeft - pDstDataPoint->x; 362 int32_t dstY = pCopyRect->yTop - pDstDataPoint->y; 363 Assert(dstX >= 0); 364 Assert(dstY >= 0); 365 366 367 uint8_t *pu8Src = ((uint8_t*)pSrc->pvData) + pSrc->pitch * (!fSrcInvert ? srcY : pSrc->height - srcY - 1) + srcX * 4; 368 uint8_t *pu8Dst = ((uint8_t*)pDst->pvData) + pDst->pitch * dstY + dstX * 4; 369 370 CrBmpScale32(pu8Dst, pDst->pitch, 371 pCopyRect->xRight - pCopyRect->xLeft, 372 pCopyRect->yBottom - pCopyRect->yTop, 373 pu8Src, 374 fSrcInvert ? -pSrc->pitch : pSrc->pitch, 375 UnscaledSrcWidth, 376 UnscaledSrcHeight 377 ); 378 } 379 322 380 static void crFbImgFromScreenVram(const VBVAINFOSCREEN *pScreen, void *pvVram, CR_BLITTER_IMG *pImg) 323 381 { … … 338 396 } 339 397 340 static int crFbBltGetContentsDirect(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)398 static int crFbBltGetContentsDirect(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg) 341 399 { 342 400 VBOXVR_LIST List; … … 348 406 349 407 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter; 350 RTPOINT SrcPoint = {pSrcRect->xLeft, pSrcRect->yTop}; 351 float strX = ((float)pImg->width) / (pSrcRect->xRight - pSrcRect->xLeft); 352 float strY = ((float)pImg->height) / (pSrcRect->yBottom - pSrcRect->yTop); 353 354 RTPOINT ScaledSrcPoint; 355 ScaledSrcPoint.x = CR_FLOAT_RCAST(int32_t, strX * SrcPoint.x); 356 ScaledSrcPoint.y = CR_FLOAT_RCAST(int32_t, strY * SrcPoint.y); 357 358 RTPOINT ZeroPoint = {0, 0}; 408 int32_t srcWidth = pSrcRect->xRight - pSrcRect->xLeft; 409 int32_t srcHeight = pSrcRect->yBottom - pSrcRect->yTop; 410 int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft; 411 int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop; 412 413 RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop}; 414 float strX = ((float)dstWidth) / srcWidth; 415 float strY = ((float)dstHeight) / srcHeight; 416 bool fScale = (dstWidth != srcWidth || dstHeight != srcHeight); 417 418 const RTPOINT ZeroPoint = {0, 0}; 359 419 360 420 VBoxVrListInit(&List); … … 388 448 } 389 449 390 for (uint32_t i = 0; i < cRects; ++i) 391 { 392 const RTRECT * pRect = &pRects[i]; 393 for (uint32_t j = 0; j < cRegions; ++j) 450 for (uint32_t j = 0; j < cRegions; ++j) 451 { 452 /* rects are in dst coordinates, 453 * while the pReg is in source coords 454 * convert */ 455 const RTRECT * pReg = &pRegions[j]; 456 RTRECT ScaledReg; 457 /* scale */ 458 VBoxRectScaled(pReg, strX, strY, &ScaledReg); 459 /* translate */ 460 VBoxRectTranslate(&ScaledReg, pDstRect->xLeft, pDstRect->yTop); 461 462 for (uint32_t i = 0; i < cRects; ++i) 394 463 { 395 const RTRECT * pReg = &pRegions[j]; 464 const RTRECT * pRect = &pRects[i]; 465 396 466 RTRECT Intersection; 397 VBoxRectIntersected(pRect, pReg, &Intersection); 398 if (VBoxRectIsZero(&Intersection)) 399 continue; 400 401 VBoxRectScale(&Intersection, strX, strY); 467 VBoxRectIntersected(pRect, &ScaledReg, &Intersection); 402 468 if (VBoxRectIsZero(&Intersection)) 403 469 continue; … … 455 521 width = CR_FLOAT_RCAST(uint32_t, strX * pVrTex->width); 456 522 height = CR_FLOAT_RCAST(uint32_t, strY * pVrTex->height); 457 ScaledEntryPoint.x = CR_FLOAT_RCAST(int32_t, strX * CrVrScrCompositorEntryRectGet(pEntry)->xLeft) ;458 ScaledEntryPoint.y = CR_FLOAT_RCAST(int32_t, strY * CrVrScrCompositorEntryRectGet(pEntry)->yTop) ;523 ScaledEntryPoint.x = CR_FLOAT_RCAST(int32_t, strX * CrVrScrCompositorEntryRectGet(pEntry)->xLeft) + pDstRect->xLeft; 524 ScaledEntryPoint.y = CR_FLOAT_RCAST(int32_t, strY * CrVrScrCompositorEntryRectGet(pEntry)->yTop) + pDstRect->yTop; 459 525 } 460 526 … … 468 534 bool fInvert = !(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS); 469 535 470 crFbBltImg(pSrcImg, &ScaledEntryPoint, fInvert, &Intersection, & ScaledSrcPoint, pImg);536 crFbBltImg(pSrcImg, &ScaledEntryPoint, fInvert, &Intersection, &ZeroPoint, pImg); 471 537 472 538 CrTdBltDataReleaseScaled(pTex, pSrcImg); … … 503 569 } 504 570 571 const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor); 572 573 CR_BLITTER_IMG FbImg; 574 575 crFbImgFromFb(hFb, &FbImg); 576 577 for (uint32_t j = 0; j < c2DRects; ++j) 578 { 579 const RTRECT * p2DRect = &p2DRects[j]; 580 RTRECT ScaledReg; 581 /* scale */ 582 VBoxRectScaled(p2DRect, strX, strY, &ScaledReg); 583 /* translate */ 584 VBoxRectTranslate(&ScaledReg, pDstRect->xLeft, pDstRect->yTop); 585 586 for (uint32_t i = 0; i < cRects; ++i) 587 { 588 const RTRECT * pRect = &pRects[i]; 589 RTRECT Intersection; 590 591 VBoxRectIntersected(pRect, &ScaledReg, &Intersection); 592 if (VBoxRectIsZero(&Intersection)) 593 continue; 594 595 if (!fScale) 596 crFbBltImg(&FbImg, &DstPoint, false, &Intersection, &ZeroPoint, pImg); 597 else 598 crFbBltImgScaledRects(&FbImg, &DstPoint, false, &Intersection, &ZeroPoint, strX, strY, pImg); 599 } 600 } 601 } 602 603 end: 604 605 if (pEnteredTex) 606 CrTdBltLeave(pEnteredTex); 607 608 if (pEnteredBlitter) 609 CrBltLeave(pEnteredBlitter); 610 611 VBoxVrListClear(&List); 612 613 return rc; 614 } 615 616 static int crFbBltGetContentsScaleCPU(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg) 617 { 618 int32_t srcWidth = pSrcRect->xRight - pSrcRect->xLeft; 619 int32_t srcHeight = pSrcRect->yBottom - pSrcRect->yTop; 620 int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft; 621 int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop; 622 623 RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop}; 624 float strX = ((float)dstWidth) / srcWidth; 625 float strY = ((float)dstHeight) / srcHeight; 626 627 RTRECT DstRect; 628 VBoxRectUnscaled(pDstRect, strX, strY, &DstRect); 629 DstRect.xRight = DstRect.xLeft + srcWidth; 630 DstRect.yBottom = DstRect.yTop + srcHeight; 631 632 /* destination is bigger than the source, do 3D data stretching with CPU */ 633 CR_BLITTER_IMG Img; 634 Img.cbData = srcWidth * srcHeight * 4; 635 Img.pvData = RTMemAlloc(Img.cbData); 636 if (!Img.pvData) 637 { 638 WARN(("RTMemAlloc Failed")); 639 return VERR_NO_MEMORY; 640 } 641 Img.enmFormat = pImg->enmFormat; 642 Img.width = srcWidth; 643 Img.height = srcHeight; 644 Img.bpp = pImg->bpp; 645 Img.pitch = Img.width * 4; 646 647 int rc = CrFbBltGetContents(hFb, pSrcRect, &DstRect, cRects, pRects, &Img); 648 if (RT_SUCCESS(rc)) 649 { 650 CrBmpScale32((uint8_t *)pImg->pvData, 651 pImg->pitch, 652 pImg->width, pImg->height, 653 (const uint8_t *)Img.pvData, 654 Img.pitch, 655 Img.width, Img.height); 656 } 657 else 658 WARN(("CrFbBltGetContents failed %d", rc)); 659 660 RTMemFree(Img.pvData); 661 662 return rc; 663 664 } 665 666 int CrFbBltGetContents(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg) 667 { 668 uint32_t srcWidth = pSrcRect->xRight - pSrcRect->xLeft; 669 uint32_t srcHeight = pSrcRect->yBottom - pSrcRect->yTop; 670 uint32_t dstWidth = pDstRect->xRight - pDstRect->xLeft; 671 uint32_t dstHeight = pDstRect->yBottom - pDstRect->yTop; 672 if ((srcWidth == dstWidth 673 && srcHeight == dstHeight) 674 || !CrFbHas3DData(hFb) 675 || (srcWidth * srcHeight > dstWidth * dstHeight)) 676 { 677 return crFbBltGetContentsDirect(hFb, pSrcRect, pDstRect, cRects, pRects, pImg); 678 } 679 680 return crFbBltGetContentsScaleCPU(hFb, pSrcRect, pDstRect, cRects, pRects, pImg); 681 } 682 683 #if 0 684 static int crFbBltPutContentsVram(HCR_FRAMEBUFFER hFb, const RTPOINT *pDstPoint, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg, float strX, float strY) 685 { 686 const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor); 687 const RTPOINT ZeroPoint = {0}; 688 689 uint32_t fbWidth = (pCompRect->xRight - pCompRect->xLeft); 690 uint32_t fbHeight = pCompRect->yBottom - pCompRect->yTop; 691 692 uint32_t stretchedWidth = CR_FLOAT_RCAST(uint32_t, strX * fbWidth); 693 uint32_t stretchedHeight = CR_FLOAT_RCAST(uint32_t, strY * fbHeight); 694 695 CR_BLITTER_IMG FbImg; 696 697 bool fScale = fbWidth != stretchedWidth || fbHeight != stretchedHeight; 698 699 crFbImgFromFb(hFb, &FbImg); 700 701 RTRECT Intersection; 702 703 for (uint32_t i = 0; i < cRects; ++i) 704 { 705 const RTRECT * pRect = &pRects[i]; 706 VBoxRectIntersected(pRect, pCompRect, &Intersection); 707 708 if (VBoxRectIsZero(&Intersection)) 709 continue; 710 711 if (!fScale) 712 crFbBltImg(pImg, pDstPoint, false, &Intersection, &ZeroPoint, &FbImg); 713 else 714 crFbBltImgScaled(pImg, pDstPoint, false, &Intersection, &ZeroPoint, strX, strY, &FbImg); 715 } 716 717 return VINF_SUCCESS; 718 } 719 720 int CrFbBltPutContents(HCR_FRAMEBUFFER hFb, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg) 721 { 722 RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop}; 723 float strX = ((float)pImg->width) / (pDstRect->xRight - pDstRect->xLeft); 724 float strY = ((float)pImg->height) / (pDstRect->yBottom - pDstRect->yTop); 725 726 int rc = CrFbEntryRegionsAdd(hFb, NULL, const RTPOINT *pPos, cRects, pRects, true) 727 if (!hFb->cUpdating) 728 { 729 WARN(("not updating\n")); 730 return VERR_INVALID_STATE; 731 } 732 } 733 734 int CrFbBltPutContentsNe(HCR_FRAMEBUFFER hFb, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg) 735 { 736 uint32_t cCompRects; 737 const RTRECT *pCompRects; 738 int rc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cCompRects, NULL, NULL, &pCompRects); 739 if (!RT_SUCCESS(rc)) 740 { 741 WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc)); 742 return rc; 743 } 744 745 bool fRegChanged = false; 746 for (uint32_t i = 0; i < cCompRects; ++i) 747 { 748 const RTRECT *pCompRect = pCompRects[i]; 749 for (uint32_t j = 0; j < cRects; ++j) 750 { 751 const RTRECT *pRect = pRects[j]; 752 if (VBoxRectIsIntersect(pCompRect, pRect)) 753 { 754 fRegChanged = true; 755 break; 756 } 757 } 758 } 759 760 if (fRegChanged) 761 { 762 rc = CrFbUpdateBegin(hFb); 763 if (RT_SUCCESS(rc)) 764 { 765 rc = CrFbBltPutContents(hFb, pDstRect, cRects, pRects, pImg); 766 if (!RT_SUCCESS(rc)) 767 WARN(("CrFbBltPutContents failed rc %d", rc)); 768 CrFbUpdateEnd(hFb); 769 } 770 else 771 WARN(("CrFbUpdateBegin failed rc %d", rc)); 772 773 return rc; 774 } 775 776 return crFbBltPutContentsVram(HCR_FRAMEBUFFER hFb, const RTPOINT *pDstPoint, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg, float strX, float strY); 777 778 const RTPOINT ZeroPoint = {0, 0}; 779 780 c2DRects = VBoxVrListRectsCount(&List); 781 if (c2DRects) 782 { 783 if (g_CrPresenter.cbTmpBuf2 < c2DRects * sizeof (RTRECT)) 784 { 785 if (g_CrPresenter.pvTmpBuf2) 786 RTMemFree(g_CrPresenter.pvTmpBuf2); 787 788 g_CrPresenter.cbTmpBuf2 = (c2DRects + 10) * sizeof (RTRECT); 789 g_CrPresenter.pvTmpBuf2 = RTMemAlloc(g_CrPresenter.cbTmpBuf2); 790 if (!g_CrPresenter.pvTmpBuf2) 791 { 792 WARN(("RTMemAlloc failed!")); 793 g_CrPresenter.cbTmpBuf2 = 0; 794 rc = VERR_NO_MEMORY; 795 goto end; 796 } 797 } 798 799 RTRECT *p2DRects = (RTRECT *)g_CrPresenter.pvTmpBuf2; 800 801 rc = VBoxVrListRectsGet(&List, c2DRects, p2DRects); 802 if (!RT_SUCCESS(rc)) 803 { 804 WARN(("VBoxVrListRectsGet failed, rc %d", rc)); 805 goto end; 806 } 807 505 808 RTPOINT Pos = {0}; 506 809 const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor); 507 810 508 uint32_t fbWidth = (pCompRect->xRight - pCompRect->xLeft);509 uint32_t fbHeight = pCompRect->yBottom - pCompRect->yTop;510 511 uint32_t stretchedWidth = CR_FLOAT_RCAST(uint32_t, strX * fbWidth);512 uint32_t stretchedHeight = CR_FLOAT_RCAST(uint32_t, strY * fbHeight);513 514 811 CR_BLITTER_IMG FbImg; 515 516 bool fScale = fbWidth != stretchedWidth || fbHeight != stretchedHeight;517 812 518 813 crFbImgFromFb(hFb, &FbImg); … … 549 844 return rc; 550 845 } 551 552 static int crFbBltGetContentsScaleCPU(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg) 553 { 554 uint32_t srcWidth = pSrcRect->xRight - pSrcRect->xLeft; 555 uint32_t srcHeight = pSrcRect->yBottom - pSrcRect->yTop; 556 557 /* destination is bigger than the source, do 3D data stretching with CPU */ 558 CR_BLITTER_IMG Img; 559 Img.cbData = srcWidth * srcHeight * 4; 560 Img.pvData = RTMemAlloc(Img.cbData); 561 if (!Img.pvData) 562 { 563 WARN(("RTMemAlloc Failed")); 564 return VERR_NO_MEMORY; 565 } 566 Img.enmFormat = pImg->enmFormat; 567 Img.width = srcWidth; 568 Img.height = srcHeight; 569 Img.bpp = pImg->bpp; 570 Img.pitch = Img.width * 4; 571 572 int rc = CrFbBltGetContents(hFb, pSrcRect, cRects, pRects, &Img); 573 if (RT_SUCCESS(rc)) 574 { 575 CrBmpScale32((uint8_t *)pImg->pvData, 576 pImg->pitch, 577 pImg->width, pImg->height, 578 (const uint8_t *)Img.pvData, 579 Img.pitch, 580 Img.width, Img.height); 581 } 582 else 583 WARN(("CrFbBltGetContents failed %d", rc)); 584 585 RTMemFree(Img.pvData); 586 587 return rc; 588 589 } 590 591 int CrFbBltGetContents(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg) 592 { 593 uint32_t srcWidth = pSrcRect->xRight - pSrcRect->xLeft; 594 uint32_t srcHeight = pSrcRect->yBottom - pSrcRect->yTop; 595 if ((srcWidth == pImg->width 596 && srcHeight == pImg->height) 597 || !CrFbHas3DData(hFb) 598 || (srcWidth * srcHeight > pImg->width * pImg->height)) 599 { 600 return crFbBltGetContentsDirect(hFb, pSrcRect, cRects, pRects, pImg); 601 } 602 603 return crFbBltGetContentsScaleCPU(hFb, pSrcRect, cRects, pRects, pImg); 604 } 605 846 #endif 606 847 607 848 int CrFbResize(CR_FRAMEBUFFER *pFb, const struct VBVAINFOSCREEN * pScreen, void *pvVRAM) … … 4473 4714 uint8_t *pu8Buf = g_pvVRamBase + offVRAM; 4474 4715 texId = 0; 4716 // cr_server.CrCmdClientInfo.pfnCltScrUpdateBegin(cr_server.CrCmdClientInfo.hCltScr); 4475 4717 /*todo: notify VGA device to perform updates */ 4476 4718 } … … 4512 4754 uint8_t *pu8Buf = g_pvVRamBase + offVRAM; 4513 4755 4514 RTRECT Rect; 4515 Rect.xLeft = pBlt->Pos.x; 4516 Rect.yTop = pBlt->Pos.y; 4517 Rect.xRight = Rect.xLeft + pScreen->u32Width; 4518 Rect.yBottom = Rect.yTop + pScreen->u32Height; 4756 RTRECT SrcRect; 4757 SrcRect.xLeft = 0; 4758 SrcRect.yTop = 0; 4759 SrcRect.xRight = pScreen->u32Width; 4760 SrcRect.yBottom = pScreen->u32Height; 4761 RTRECT DstRect; 4762 DstRect.xLeft = pBlt->Pos.x; 4763 DstRect.yTop = pBlt->Pos.y; 4764 DstRect.xRight = DstRect.xLeft + pScreen->u32Width; 4765 DstRect.yBottom = DstRect.yTop + pScreen->u32Height; 4519 4766 CR_BLITTER_IMG Img; 4520 4767 crFbImgFromScreenVram(pScreen, pu8Buf, &Img); 4521 int rc = CrFbBltGetContents(hFb, & Rect, cRects, pRects, &Img);4768 int rc = CrFbBltGetContents(hFb, &SrcRect, &DstRect, cRects, pRects, &Img); 4522 4769 if (!RT_SUCCESS(rc)) 4523 4770 { -
trunk/src/VBox/Main/include/DisplayImpl.h
r50677 r50754 174 174 void handleCrHgsmiControlCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam); 175 175 #endif 176 176 int handleCrHgcmCtlSubmit(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, 177 PFNCRCTLCOMPLETION pfnCompletion, 178 void *pvCompletion); 177 179 #if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL) 178 180 void handleCrAsyncCmdCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam); … … 271 273 static DECLCALLBACK(void) displayCrHgsmiControlCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext); 272 274 #endif 273 275 static DECLCALLBACK(int) displayCrHgcmCtlSubmit(PPDMIDISPLAYCONNECTOR pInterface, 276 struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, 277 PFNCRCTLCOMPLETION pfnCompletion, 278 void *pvCompletion); 279 static DECLCALLBACK(void) displayCrHgcmCtlSubmitCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext); 274 280 #ifdef VBOX_WITH_HGSMI 275 281 static DECLCALLBACK(int) displayVBVAEnable(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId, PVBVAHOSTFLAGS pHostFlags); -
trunk/src/VBox/Main/src-client/DisplayImpl.cpp
r50677 r50754 4304 4304 void Display::handleCrHgsmiCommandProcess(PVBOXVDMACMD_CHROMIUM_CMD pCmd, uint32_t cbCmd) 4305 4305 { 4306 int rc = VERR_ INVALID_FUNCTION;4306 int rc = VERR_NOT_SUPPORTED; 4307 4307 VBOXHGCMSVCPARM parm; 4308 4308 parm.type = VBOX_HGCM_SVC_PARM_PTR; … … 4332 4332 void Display::handleCrHgsmiControlProcess(PVBOXVDMACMD_CHROMIUM_CTL pCtl, uint32_t cbCtl) 4333 4333 { 4334 int rc = VERR_ INVALID_FUNCTION;4334 int rc = VERR_NOT_SUPPORTED; 4335 4335 VBOXHGCMSVCPARM parm; 4336 4336 parm.type = VBOX_HGCM_SVC_PARM_PTR; … … 4383 4383 } 4384 4384 #endif 4385 4386 DECLCALLBACK(void) Display::displayCrHgcmCtlSubmitCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext) 4387 { 4388 VBOXCRCMDCTL *pCmd = (VBOXCRCMDCTL*)pParam->u.pointer.addr; 4389 if (pCmd->pfnInternal) 4390 ((PFNCRCTLCOMPLETION)pCmd->pfnInternal)(pCmd, pParam->u.pointer.size, result, pvContext); 4391 } 4392 4393 int Display::handleCrHgcmCtlSubmit(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, 4394 PFNCRCTLCOMPLETION pfnCompletion, 4395 void *pvCompletion) 4396 { 4397 VMMDev *pVMMDev = mParent->getVMMDev(); 4398 if (!pVMMDev) 4399 { 4400 AssertMsgFailed(("no vmmdev\n")); 4401 return VERR_INVALID_STATE; 4402 } 4403 4404 Assert(mhCrOglSvc); 4405 VBOXHGCMSVCPARM parm; 4406 parm.type = VBOX_HGCM_SVC_PARM_PTR; 4407 parm.u.pointer.addr = pCmd; 4408 parm.u.pointer.size = cbCmd; 4409 4410 pCmd->pfnInternal = (void(*)())pfnCompletion; 4411 int rc = pVMMDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_CTL, &parm, displayCrHgcmCtlSubmitCompletion, pvCompletion); 4412 if (!RT_SUCCESS(rc)) 4413 AssertMsgFailed(("hgcmHostFastCallAsync failed rc %n", rc)); 4414 4415 return rc; 4416 } 4417 4418 DECLCALLBACK(int) Display::displayCrHgcmCtlSubmit(PPDMIDISPLAYCONNECTOR pInterface, 4419 struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, 4420 PFNCRCTLCOMPLETION pfnCompletion, 4421 void *pvCompletion) 4422 { 4423 PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface); 4424 Display *pThis = pDrv->pDisplay; 4425 return pThis->handleCrHgcmCtlSubmit(pCmd, cbCmd, pfnCompletion, pvCompletion); 4426 } 4385 4427 4386 4428 #if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL) … … 5007 5049 pThis->IConnector.pfnCrHgsmiControlProcess = Display::displayCrHgsmiControlProcess; 5008 5050 #endif 5051 pThis->IConnector.pfnCrHgcmCtlSubmit = Display::displayCrHgcmCtlSubmit; 5009 5052 #ifdef VBOX_WITH_HGSMI 5010 5053 pThis->IConnector.pfnVBVAEnable = Display::displayVBVAEnable;
Note:
See TracChangeset
for help on using the changeset viewer.