Changeset 33561 in vbox for trunk/src/VBox/GuestHost/OpenGL/util/vboxhgcm.c
- Timestamp:
- Oct 28, 2010 2:28:37 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/GuestHost/OpenGL/util/vboxhgcm.c
r33366 r33561 46 46 #include <VBox/HostServices/VBoxCrOpenGLSvc.h> 47 47 48 #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) 49 #include <VBox/VBoxCrHgsmi.h> 50 #endif 51 52 //#define IN_GUEST 48 53 //#if defined(IN_GUEST) 49 54 //#define VBOX_WITH_CRHGSMIPROFILE … … 52 57 #include <iprt/time.h> 53 58 #include <stdio.h> 54 55 #ifdef VBOX_WITH_CRHGSMI56 #include <VBox/VBoxCrHgsmi.h>57 #endif58 59 59 60 typedef struct VBOXCRHGSMIPROFILE … … 170 171 int iGuestDrv; 171 172 #endif 173 #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) 174 bool bHgsmiOn; 175 #endif 172 176 } CRVBOXHGCMDATA; 173 177 … … 181 185 ,CR_VBOXHGCM_DDRAW_SURFACE 182 186 #endif 187 #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) 188 ,CR_VBOXHGCM_UHGSMI_BUFFER 189 #endif 183 190 } CRVBOXHGCMBUFFERKIND; 184 191 … … 188 195 uint32_t magic; 189 196 CRVBOXHGCMBUFFERKIND kind; 190 uint32_t len; 191 uint32_t allocated; 197 union 198 { 199 struct 200 { 201 uint32_t len; 202 uint32_t allocated; 203 }; 204 205 #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) 206 PVBOXUHGSMI_BUFFER pBuffer; 207 #endif 208 }; 192 209 #ifdef RT_OS_WINDOWS 193 210 LPDIRECTDRAWSURFACE pDDS; … … 199 216 #define FALSE false 200 217 #define INVALID_HANDLE_VALUE (-1) 218 #endif 219 220 221 #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) 222 typedef struct CRVBOXHGSMI_CLIENT { 223 PVBOXUHGSMI pHgsmi; 224 PVBOXUHGSMI_BUFFER pCmdBuffer; 225 PVBOXUHGSMI_BUFFER pHGBuffer; 226 void *pvHGBuffer; 227 CRBufferPool *bufpool; 228 } CRVBOXHGSMI_CLIENT, *PCRVBOXHGSMI_CLIENT; 229 230 /* add sizeof header + page align */ 231 #define CRVBOXHGSMI_PAGE_ALIGN(_s) (((_s) + 0xfff) & ~0xfff) 232 #define CRVBOXHGSMI_BUF_HDR_SIZE() (sizeof (CRVBOXHGCMBUFFER)) 233 #define CRVBOXHGSMI_BUF_SIZE(_s) CRVBOXHGSMI_PAGE_ALIGN((_s) + CRVBOXHGSMI_BUF_HDR_SIZE()) 234 #define CRVBOXHGSMI_BUF_LOCK_SIZE(_s) ((_s) + CRVBOXHGSMI_BUF_HDR_SIZE()) 235 #define CRVBOXHGSMI_BUF_DATA(_p) ((void*)(((CRVBOXHGCMBUFFER*)(_p)) + 1)) 236 #define CRVBOXHGSMI_BUF_HDR(_p) (((CRVBOXHGCMBUFFER*)(_p)) - 1) 237 #define CRVBOXHGSMI_BUF_OFFSET(_st2, _st1) ((uint32_t)(((uint8_t*)(_st2)) - ((uint8_t*)(_st1)))) 238 239 DECLINLINE(PCRVBOXHGSMI_CLIENT) _crVBoxHGSMIClientGet(CRConnection *conn) 240 { 241 PCRVBOXHGSMI_CLIENT pClient = (PCRVBOXHGSMI_CLIENT)VBoxCrHgsmiQueryClient(); 242 Assert(pClient); 243 return pClient; 244 } 245 246 static PVBOXUHGSMI_BUFFER _crVBoxHGSMIBufAlloc(PCRVBOXHGSMI_CLIENT pClient, uint32_t cbSize) 247 { 248 PVBOXUHGSMI_BUFFER buf; 249 int rc; 250 251 buf = (PVBOXUHGSMI_BUFFER ) crBufferPoolPop(pClient->bufpool, cbSize); 252 253 if (!buf) 254 { 255 crDebug("Buffer pool %p was empty; allocating new %d byte buffer.", 256 (void *) pClient->bufpool, 257 cbSize); 258 rc = pClient->pHgsmi->pfnBufferCreate(pClient->pHgsmi, cbSize, 259 VBOXUHGSMI_SYNCHOBJECT_TYPE_NONE, NULL, 260 &buf); 261 AssertRC(rc); 262 if (RT_FAILURE(rc)) 263 crWarning("Failed to Create a buffer of size(%d), rc(%d)\n", cbSize, rc); 264 } 265 return buf; 266 } 267 268 static PVBOXUHGSMI_BUFFER _crVBoxHGSMIBufFromHdr(CRVBOXHGCMBUFFER *pHdr) 269 { 270 PVBOXUHGSMI_BUFFER pBuf; 271 int rc; 272 CRASSERT(pHdr->magic == CR_VBOXHGCM_BUFFER_MAGIC); 273 CRASSERT(pHdr->kind == CR_VBOXHGCM_UHGSMI_BUFFER); 274 pBuf = pHdr->pBuffer; 275 rc = pBuf->pfnUnlock(pBuf); 276 AssertRC(rc); 277 if (RT_FAILURE(rc)) 278 { 279 return NULL; 280 } 281 return pBuf; 282 } 283 284 static void _crVBoxHGSMIBufFree(PCRVBOXHGSMI_CLIENT pClient, PVBOXUHGSMI_BUFFER pBuf) 285 { 286 crBufferPoolPush(pClient->bufpool, pBuf, pBuf->cbBuffer); 287 } 288 289 static CRVBOXHGSMIHDR *_crVBoxHGSMICmdBufferLock(PCRVBOXHGSMI_CLIENT pClient, uint32_t cbBuffer) 290 { 291 /* in theory it is OK to use one cmd buffer for asynch cmd submission 292 * because bDiscard flag should result in allocating a new memory backend if the 293 * allocation is still in use. 294 * However, NOTE: since one and the same semaphore synch event is used for completion notification, 295 * for the notification mechanism working as expected 296 * 1. host must complete commands in the same order as it receives them 297 * (to avoid situation when guest receives notification for another command completion) 298 * 2. guest must eventually wait for command completion unless he specified bDoNotSignalCompletion 299 * 3. guest must wait for command completion in the same order as it submits them 300 * in case we can not satisfy any of the above, we should introduce multiple command buffers */ 301 CRVBOXHGSMIHDR * pHdr; 302 VBOXUHGSMI_BUFFER_LOCK_FLAGS fFlags; 303 int rc; 304 fFlags.Value = 0; 305 fFlags.bDiscard = 1; 306 rc = pClient->pCmdBuffer->pfnLock(pClient->pCmdBuffer, 0, cbBuffer, fFlags, (void**)&pHdr); 307 AssertRC(rc); 308 if (RT_SUCCESS(rc)) 309 return pHdr; 310 311 crWarning("Failed to Lock the command buffer of size(%d), rc(%d)\n", cbBuffer, rc); 312 return NULL; 313 } 314 315 static CRVBOXHGSMIHDR *_crVBoxHGSMICmdBufferLockRo(PCRVBOXHGSMI_CLIENT pClient, uint32_t cbBuffer) 316 { 317 /* in theory it is OK to use one cmd buffer for asynch cmd submission 318 * because bDiscard flag should result in allocating a new memory backend if the 319 * allocation is still in use. 320 * However, NOTE: since one and the same semaphore synch event is used for completion notification, 321 * for the notification mechanism working as expected 322 * 1. host must complete commands in the same order as it receives them 323 * (to avoid situation when guest receives notification for another command completion) 324 * 2. guest must eventually wait for command completion unless he specified bDoNotSignalCompletion 325 * 3. guest must wait for command completion in the same order as it submits them 326 * in case we can not satisfy any of the above, we should introduce multiple command buffers */ 327 CRVBOXHGSMIHDR * pHdr; 328 VBOXUHGSMI_BUFFER_LOCK_FLAGS fFlags; 329 int rc; 330 fFlags.Value = 0; 331 fFlags.bReadOnly = 1; 332 rc = pClient->pCmdBuffer->pfnLock(pClient->pCmdBuffer, 0, cbBuffer, fFlags, (void**)&pHdr); 333 AssertRC(rc); 334 if (RT_FAILURE(rc)) 335 crWarning("Failed to Lock the command buffer of size(%d), rc(%d)\n", cbBuffer, rc); 336 return pHdr; 337 } 338 339 static void _crVBoxHGSMICmdBufferUnlock(PCRVBOXHGSMI_CLIENT pClient) 340 { 341 int rc = pClient->pCmdBuffer->pfnUnlock(pClient->pCmdBuffer); 342 AssertRC(rc); 343 if (RT_FAILURE(rc)) 344 crWarning("Failed to Unlock the command buffer rc(%d)\n", rc); 345 } 346 347 static int32_t _crVBoxHGSMICmdBufferGetRc(PCRVBOXHGSMI_CLIENT pClient) 348 { 349 CRVBOXHGSMIHDR * pHdr; 350 VBOXUHGSMI_BUFFER_LOCK_FLAGS fFlags; 351 int rc; 352 353 fFlags.Value = 0; 354 fFlags.bReadOnly = 1; 355 rc = pClient->pCmdBuffer->pfnLock(pClient->pCmdBuffer, 0, sizeof (*pHdr), fFlags, (void**)&pHdr); 356 AssertRC(rc); 357 if (RT_FAILURE(rc)) 358 { 359 crWarning("Failed to Lock the command buffer of size(%d), rc(%d)\n", sizeof (*pHdr), rc); 360 return rc; 361 } 362 363 rc = pHdr->result; 364 AssertRC(rc); 365 pClient->pCmdBuffer->pfnUnlock(pClient->pCmdBuffer); 366 367 return rc; 368 } 369 370 DECLINLINE(PVBOXUHGSMI_BUFFER) _crVBoxHGSMIRecvBufGet(PCRVBOXHGSMI_CLIENT pClient) 371 { 372 if (pClient->pvHGBuffer) 373 { 374 int rc = pClient->pHGBuffer->pfnUnlock(pClient->pHGBuffer); 375 if (RT_FAILURE(rc)) 376 { 377 return NULL; 378 } 379 pClient->pvHGBuffer = NULL; 380 } 381 return pClient->pHGBuffer; 382 } 383 384 DECLINLINE(void*) _crVBoxHGSMIRecvBufData(PCRVBOXHGSMI_CLIENT pClient, uint32_t cbBuffer) 385 { 386 VBOXUHGSMI_BUFFER_LOCK_FLAGS fFlags; 387 int rc; 388 Assert(!pClient->pvHGBuffer); 389 fFlags.Value = 0; 390 rc = pClient->pHGBuffer->pfnLock(pClient->pHGBuffer, 0, cbBuffer, fFlags, &pClient->pvHGBuffer); 391 AssertRC(rc); 392 if (RT_SUCCESS(rc)) 393 { 394 return pClient->pvHGBuffer; 395 } 396 return NULL; 397 } 398 399 DECLINLINE(void) _crVBoxHGSMIFillCmd(VBOXUHGSMI_BUFFER_SUBMIT *pSubm, PCRVBOXHGSMI_CLIENT pClient, uint32_t cbData) 400 { 401 pSubm->pBuf = pClient->pCmdBuffer; 402 pSubm->offData = 0; 403 pSubm->cbData = cbData; 404 pSubm->fFlags.Value = 0; 405 pSubm->fFlags.bDoNotRetire = 1; 406 // pSubm->fFlags.bDoNotSignalCompletion = 1; /* <- we do not need that actually since 407 // * in case we want completion, 408 // * we will block in _crVBoxHGSMICmdBufferGetRc (when locking the buffer) 409 // * which is needed for getting the result */ 410 } 411 412 #ifdef RT_OS_WINDOWS 413 #define CRVBOXHGSMI_BUF_WAIT(_pBub) WaitForSingleObject((_pBub)->hSynch, INFINITE); 414 #else 415 # error "Port Me!!" 416 #endif 417 418 DECLINLINE(void) _crVBoxHGSMIWaitCmd(PCRVBOXHGSMI_CLIENT pClient) 419 { 420 int rc = CRVBOXHGSMI_BUF_WAIT(pClient->pCmdBuffer); 421 Assert(rc == 0); 422 } 201 423 #endif 202 424 … … 843 1065 844 1066 hgcm_buffer->len = len; 845 846 1067 _crVBoxHGCMReadBytes(conn, hgcm_buffer + 1, len); 847 1068 … … 1141 1362 } 1142 1363 1364 #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) 1365 DECLCALLBACK(HVBOXCRHGSMI_CLIENT) _crVBoxHGSMIClientCreate(PVBOXUHGSMI pHgsmi) 1366 { 1367 PCRVBOXHGSMI_CLIENT pClient = crAlloc(sizeof (CRVBOXHGSMI_CLIENT)); 1368 1369 if (pClient) 1370 { 1371 int rc; 1372 pClient->pHgsmi = pHgsmi; 1373 rc = pHgsmi->pfnBufferCreate(pHgsmi, CRVBOXHGSMI_PAGE_ALIGN(1), 1374 VBOXUHGSMI_SYNCHOBJECT_TYPE_EVENT, 1375 NULL, 1376 &pClient->pCmdBuffer); 1377 AssertRC(rc); 1378 if (RT_SUCCESS(rc)) 1379 { 1380 rc = pHgsmi->pfnBufferCreate(pHgsmi, CRVBOXHGSMI_PAGE_ALIGN(0x800000), 1381 VBOXUHGSMI_SYNCHOBJECT_TYPE_EVENT, 1382 NULL, 1383 &pClient->pHGBuffer); 1384 AssertRC(rc); 1385 if (RT_SUCCESS(rc)) 1386 { 1387 pClient->pvHGBuffer = NULL; 1388 pClient->bufpool = crBufferPoolInit(16); 1389 return (HVBOXCRHGSMI_CLIENT) pClient; 1390 } 1391 } 1392 } 1393 1394 return NULL; 1395 } 1396 1397 DECLCALLBACK(void) _crVBoxHGSMIClientDestroy(HVBOXCRHGSMI_CLIENT hClient) 1398 { 1399 Assert(0); 1400 1401 /* @todo */ 1402 } 1403 1404 bool _crVBoxHGSMIInit() 1405 { 1406 int bHasHGSMI = -1; 1407 1408 if (bHasHGSMI < 0) 1409 { 1410 int rc; 1411 VBOXCRHGSMI_CALLBACKS Callbacks; 1412 Callbacks.pfnClientCreate = _crVBoxHGSMIClientCreate; 1413 Callbacks.pfnClientDestroy = _crVBoxHGSMIClientDestroy; 1414 rc = VBoxCrHgsmiInit(&Callbacks); 1415 AssertRC(rc); 1416 if (RT_SUCCESS(rc)) 1417 bHasHGSMI = 1; 1418 else 1419 bHasHGSMI = 0; 1420 } 1421 1422 Assert(bHasHGSMI); 1423 1424 return bHasHGSMI; 1425 } 1426 1427 void _crVBoxHGSMITearDown() 1428 { 1429 VBoxCrHgsmiTerm(); 1430 } 1431 1432 static void *_crVBoxHGSMIDoAlloc(CRConnection *conn, PCRVBOXHGSMI_CLIENT pClient) 1433 { 1434 PVBOXUHGSMI_BUFFER buf; 1435 CRVBOXHGCMBUFFER *pData = NULL; 1436 uint32_t cbSize = conn->buffer_size; 1437 int rc; 1438 1439 buf = _crVBoxHGSMIBufAlloc(pClient, CRVBOXHGSMI_BUF_SIZE(cbSize)); 1440 Assert(buf); 1441 if (buf) 1442 { 1443 VBOXUHGSMI_BUFFER_LOCK_FLAGS fFlags; 1444 buf->pvUserData = pClient; 1445 fFlags.Value = 0; 1446 fFlags.bDiscard = 1; 1447 rc = buf->pfnLock(buf, 0, CRVBOXHGSMI_BUF_LOCK_SIZE(cbSize), fFlags, (void**)&pData); 1448 if (RT_SUCCESS(rc)) 1449 { 1450 pData->magic = CR_VBOXHGCM_BUFFER_MAGIC; 1451 pData->kind = CR_VBOXHGCM_UHGSMI_BUFFER; 1452 pData->pBuffer = buf; 1453 } 1454 else 1455 { 1456 crWarning("Failed to Lock the buffer, rc(%d)\n", rc); 1457 } 1458 return CRVBOXHGSMI_BUF_DATA(pData); 1459 } 1460 1461 /* fall back */ 1462 return _crVBoxHGCMAlloc(conn); 1463 } 1464 1465 static void _crVBoxHGSMIFree(CRConnection *conn, void *buf) 1466 { 1467 CRVBOXHGCMBUFFER *hgcm_buffer = (CRVBOXHGCMBUFFER *) buf - 1; 1468 1469 CRASSERT(hgcm_buffer->magic == CR_VBOXHGCM_BUFFER_MAGIC); 1470 1471 if (hgcm_buffer->kind == CR_VBOXHGCM_UHGSMI_BUFFER) 1472 { 1473 PVBOXUHGSMI_BUFFER pBuf = _crVBoxHGSMIBufFromHdr(hgcm_buffer); 1474 PCRVBOXHGSMI_CLIENT pClient = (PCRVBOXHGSMI_CLIENT)pBuf->pvUserData; 1475 pBuf->pfnUnlock(pBuf); 1476 _crVBoxHGSMIBufFree(pClient, pBuf); 1477 } 1478 else 1479 { 1480 _crVBoxHGCMFree(conn, buf); 1481 } 1482 } 1483 1484 static void *crVBoxHGSMIAlloc(CRConnection *conn) 1485 { 1486 PCRVBOXHGSMI_CLIENT pClient; 1487 void *pvBuf; 1488 1489 VBOXCRHGSMIPROFILE_FUNC_PROLOGUE(); 1490 1491 pClient = _crVBoxHGSMIClientGet(conn); 1492 if (pClient) 1493 { 1494 pvBuf = _crVBoxHGSMIDoAlloc(conn, pClient); 1495 Assert(pvBuf); 1496 } 1497 else 1498 { 1499 pvBuf = _crVBoxHGCMAlloc(conn); 1500 } 1501 1502 VBOXCRHGSMIPROFILE_FUNC_EPILOGUE(); 1503 1504 return pvBuf; 1505 } 1506 1507 static void crVBoxHGSMIFree(CRConnection *conn, void *buf) 1508 { 1509 VBOXCRHGSMIPROFILE_FUNC_PROLOGUE(); 1510 _crVBoxHGSMIFree(conn, buf); 1511 VBOXCRHGSMIPROFILE_FUNC_EPILOGUE(); 1512 } 1513 1514 static void _crVBoxHGSMIPollHost(CRConnection *conn, PCRVBOXHGSMI_CLIENT pClient) 1515 { 1516 CRVBOXHGSMIREAD *parms = (CRVBOXHGSMIREAD *)_crVBoxHGSMICmdBufferLock(pClient, sizeof (*parms)); 1517 int rc; 1518 VBOXUHGSMI_BUFFER_SUBMIT aSubmit[2]; 1519 PVBOXUHGSMI_BUFFER pRecvBuffer; 1520 uint32_t cbBuffer; 1521 1522 Assert(parms); 1523 1524 parms->hdr.result = VERR_WRONG_ORDER; 1525 parms->hdr.u32ClientID = conn->u32ClientID; 1526 parms->hdr.u32Function = SHCRGL_GUEST_FN_READ; 1527 // parms->hdr.u32Reserved = 0; 1528 1529 CRASSERT(!conn->pBuffer); //make sure there's no data to process 1530 parms->iBuffer = 1; 1531 parms->cbBuffer = 0; 1532 1533 _crVBoxHGSMICmdBufferUnlock(pClient); 1534 1535 pRecvBuffer = _crVBoxHGSMIRecvBufGet(pClient); 1536 Assert(pRecvBuffer); 1537 if (!pRecvBuffer) 1538 return; 1539 1540 _crVBoxHGSMIFillCmd(&aSubmit[0], pClient, sizeof (*parms)); 1541 1542 aSubmit[1].pBuf = pRecvBuffer; 1543 aSubmit[1].offData = 0; 1544 aSubmit[1].cbData = pRecvBuffer->cbBuffer; 1545 aSubmit[1].fFlags.Value = 0; 1546 aSubmit[1].fFlags.bHostWriteOnly = 1; 1547 1548 rc = pClient->pHgsmi->pfnBufferSubmitAsynch(pClient->pHgsmi, aSubmit, 2); 1549 AssertRC(rc); 1550 if (RT_FAILURE(rc)) 1551 { 1552 crWarning("pfnBufferSubmitAsynch failed with %d \n", rc); 1553 return; 1554 } 1555 1556 _crVBoxHGSMIWaitCmd(pClient); 1557 1558 parms = (CRVBOXHGSMIREAD *)_crVBoxHGSMICmdBufferLockRo(pClient, sizeof (*parms)); 1559 Assert(parms); 1560 if (!parms) 1561 { 1562 crWarning("_crVBoxHGSMICmdBufferLockRo failed\n"); 1563 return; 1564 } 1565 1566 if (RT_SUCCESS(parms->hdr.result)) 1567 cbBuffer = parms->cbBuffer; 1568 else 1569 cbBuffer = 0; 1570 1571 _crVBoxHGSMICmdBufferUnlock(pClient); 1572 1573 if (cbBuffer) 1574 { 1575 void *pvData = _crVBoxHGSMIRecvBufData(pClient, cbBuffer); 1576 Assert(pvData); 1577 if (pvData) 1578 { 1579 conn->pBuffer = pvData; 1580 conn->cbBuffer = cbBuffer; 1581 } 1582 } 1583 } 1584 1585 static void _crVBoxHGSMIReadExact(CRConnection *conn, PCRVBOXHGSMI_CLIENT pClient) 1586 { 1587 _crVBoxHGSMIPollHost(conn, pClient); 1588 1589 if (conn->cbBuffer) 1590 _crVBoxHGCMReceiveMessage(conn); 1591 } 1592 1593 /* Same as crVBoxHGCMWriteExact, but combined with read of writeback data. 1594 * This halves the number of HGCM calls we do, 1595 * most likely crVBoxHGCMPollHost shouldn't be called at all now. 1596 */ 1597 static void 1598 _crVBoxHGSMIWriteReadExact(CRConnection *conn, PCRVBOXHGSMI_CLIENT pClient, void *buf, uint32_t offBuffer, unsigned int len, bool bIsBuffer) 1599 { 1600 CRVBOXHGSMIWRITEREAD *parms = (CRVBOXHGSMIWRITEREAD*)_crVBoxHGSMICmdBufferLock(pClient, sizeof (*parms)); 1601 int rc; 1602 VBOXUHGSMI_BUFFER_SUBMIT aSubmit[3]; 1603 PVBOXUHGSMI_BUFFER pBuf = NULL; 1604 VBOXUHGSMI_BUFFER_LOCK_FLAGS fFlags; 1605 // uint32_t cbBuffer; 1606 1607 parms->hdr.result = VERR_WRONG_ORDER; 1608 parms->hdr.u32ClientID = conn->u32ClientID; 1609 parms->hdr.u32Function = SHCRGL_GUEST_FN_WRITE_READ; 1610 // parms->hdr.u32Reserved = 0; 1611 1612 parms->iBuffer = 1; 1613 1614 CRASSERT(!conn->pBuffer); //make sure there's no data to process 1615 parms->iWriteback = 2; 1616 parms->cbWriteback = 0; 1617 1618 _crVBoxHGSMICmdBufferUnlock(pClient); 1619 1620 if (!bIsBuffer) 1621 { 1622 void *pvBuf; 1623 pBuf = _crVBoxHGSMIBufAlloc(pClient, len); 1624 Assert(pBuf); 1625 if (!pBuf) 1626 { 1627 /* fallback */ 1628 crVBoxHGCMWriteReadExact(conn, buf, len, CR_VBOXHGCM_USERALLOCATED); 1629 return; 1630 } 1631 1632 Assert(!offBuffer); 1633 1634 offBuffer = 0; 1635 fFlags.Value = 0; 1636 fFlags.bDiscard = 1; 1637 fFlags.bWriteOnly = 1; 1638 rc = pBuf->pfnLock(pBuf, 0, len, fFlags, &pvBuf); 1639 AssertRC(rc); 1640 if (RT_SUCCESS(rc)) 1641 { 1642 memcpy(pvBuf, buf, len); 1643 rc = pBuf->pfnUnlock(pBuf); 1644 AssertRC(rc); 1645 CRASSERT(RT_SUCCESS(rc)); 1646 } 1647 else 1648 { 1649 _crVBoxHGSMIBufFree(pClient, pBuf); 1650 /* fallback */ 1651 crVBoxHGCMWriteReadExact(conn, buf, len, CR_VBOXHGCM_USERALLOCATED); 1652 return; 1653 } 1654 } 1655 else 1656 { 1657 pBuf = (PVBOXUHGSMI_BUFFER)buf; 1658 } 1659 1660 do 1661 { 1662 PVBOXUHGSMI_BUFFER pRecvBuffer = _crVBoxHGSMIRecvBufGet(pClient); 1663 Assert(pRecvBuffer); 1664 if (!pRecvBuffer) 1665 { 1666 break; 1667 } 1668 1669 _crVBoxHGSMIFillCmd(&aSubmit[0], pClient, sizeof (*parms)); 1670 1671 aSubmit[1].pBuf = pBuf; 1672 aSubmit[1].offData = offBuffer; 1673 aSubmit[1].cbData = len; 1674 aSubmit[1].fFlags.Value = 0; 1675 aSubmit[1].fFlags.bHostReadOnly = 1; 1676 1677 aSubmit[2].pBuf = pRecvBuffer; 1678 aSubmit[2].offData = 0; 1679 aSubmit[2].cbData = pRecvBuffer->cbBuffer; 1680 aSubmit[2].fFlags.Value = 0; 1681 1682 rc = pClient->pHgsmi->pfnBufferSubmitAsynch(pClient->pHgsmi, aSubmit, 3); 1683 AssertRC(rc); 1684 if (RT_FAILURE(rc)) 1685 { 1686 crWarning("pfnBufferSubmitAsynch failed with %d \n", rc); 1687 break; 1688 } 1689 1690 _crVBoxHGSMIWaitCmd(pClient); 1691 1692 parms = (CRVBOXHGSMIWRITEREAD *)_crVBoxHGSMICmdBufferLockRo(pClient, sizeof (*parms)); 1693 Assert(parms); 1694 if (parms) 1695 { 1696 uint32_t cbWriteback = parms->cbWriteback; 1697 rc = parms->hdr.result; 1698 _crVBoxHGSMICmdBufferUnlock(pClient); 1699 #ifdef DEBUG 1700 parms = NULL; 1701 #endif 1702 if (RT_SUCCESS(rc)) 1703 { 1704 if (cbWriteback) 1705 { 1706 void *pvData = _crVBoxHGSMIRecvBufData(pClient, cbWriteback); 1707 Assert(pvData); 1708 if (pvData) 1709 { 1710 conn->pBuffer = pvData; 1711 conn->cbBuffer = cbWriteback; 1712 _crVBoxHGCMReceiveMessage(conn); 1713 } 1714 } 1715 } 1716 else if (VERR_BUFFER_OVERFLOW == rc) 1717 { 1718 PVBOXUHGSMI_BUFFER pOldBuf = pClient->pHGBuffer; 1719 Assert(!pClient->pvHGBuffer); 1720 CRASSERT(cbWriteback>pClient->pHGBuffer->cbBuffer); 1721 crDebug("Reallocating host buffer from %d to %d bytes", conn->cbHostBufferAllocated, cbWriteback); 1722 1723 rc = pClient->pHgsmi->pfnBufferCreate(pClient->pHgsmi, CRVBOXHGSMI_PAGE_ALIGN(cbWriteback), 1724 VBOXUHGSMI_SYNCHOBJECT_TYPE_NONE, NULL, &pClient->pHGBuffer); 1725 AssertRC(rc); 1726 CRASSERT(RT_SUCCESS(rc)); 1727 if (RT_SUCCESS(rc)) 1728 { 1729 rc = pOldBuf->pfnDestroy(pOldBuf); 1730 CRASSERT(RT_SUCCESS(rc)); 1731 1732 _crVBoxHGSMIReadExact(conn, pClient/*, cbWriteback*/); 1733 } 1734 else 1735 { 1736 crFree(conn->pHostBuffer); 1737 conn->cbHostBufferAllocated = cbWriteback; 1738 conn->pHostBuffer = crAlloc(conn->cbHostBufferAllocated); 1739 crVBoxHGCMReadExact(conn, NULL, cbWriteback); 1740 } 1741 } 1742 else 1743 { 1744 crWarning("SHCRGL_GUEST_FN_WRITE_READ (%i) failed with %x \n", len, rc); 1745 } 1746 } 1747 else 1748 { 1749 crWarning("_crVBoxHGSMICmdBufferLockRo failed\n"); 1750 break; 1751 } 1752 } while (0); 1753 1754 if (!bIsBuffer) 1755 _crVBoxHGSMIBufFree(pClient, pBuf); 1756 1757 return; 1758 } 1759 1760 static void _crVBoxHGSMIWriteExact(CRConnection *conn, PCRVBOXHGSMI_CLIENT pClient, PVBOXUHGSMI_BUFFER pBuf, uint32_t offStart, unsigned int len) 1761 { 1762 int rc; 1763 int32_t callRes; 1764 VBOXUHGSMI_BUFFER_SUBMIT aSubmit[2]; 1765 1766 #ifdef IN_GUEST 1767 if (conn->u32InjectClientID) 1768 { 1769 CRVBOXHGSMIINJECT *parms = (CRVBOXHGSMIINJECT *)_crVBoxHGSMICmdBufferLock(pClient, sizeof (*parms)); 1770 Assert(parms); 1771 if (!parms) 1772 { 1773 return; 1774 } 1775 1776 parms->hdr.result = VERR_WRONG_ORDER; 1777 parms->hdr.u32ClientID = conn->u32ClientID; 1778 parms->hdr.u32Function = SHCRGL_GUEST_FN_INJECT; 1779 // parms->hdr.u32Reserved = 0; 1780 1781 parms->u32ClientID = conn->u32InjectClientID; 1782 1783 parms->iBuffer = 1; 1784 _crVBoxHGSMICmdBufferUnlock(pClient); 1785 1786 _crVBoxHGSMIFillCmd(&aSubmit[0], pClient, sizeof (*parms)); 1787 1788 aSubmit[1].pBuf = pBuf; 1789 aSubmit[1].offData = offStart; 1790 aSubmit[1].cbData = len; 1791 aSubmit[1].fFlags.Value = 0; 1792 aSubmit[1].fFlags.bHostReadOnly = 1; 1793 1794 rc = pClient->pHgsmi->pfnBufferSubmitAsynch(pClient->pHgsmi, aSubmit, 2); 1795 AssertRC(rc); 1796 if (RT_SUCCESS(rc)) 1797 { 1798 _crVBoxHGSMIWaitCmd(pClient); 1799 /* @todo: do we need to wait for completion actually? 1800 * NOTE: in case we do not need completion, 1801 * we MUST specify bDoNotSignalCompletion flag for the command buffer */ 1802 // CRVBOXHGSMI_BUF_WAIT(pClient->pCmdBuffer); 1803 1804 callRes = _crVBoxHGSMICmdBufferGetRc(pClient); 1805 } 1806 } 1807 else 1808 #endif 1809 { 1810 CRVBOXHGSMIWRITE * parms = (CRVBOXHGSMIWRITE *)_crVBoxHGSMICmdBufferLock(pClient, sizeof (*parms));; 1811 1812 parms->hdr.result = VERR_WRONG_ORDER; 1813 parms->hdr.u32ClientID = conn->u32ClientID; 1814 parms->hdr.u32Function = SHCRGL_GUEST_FN_WRITE; 1815 // parms->hdr.u32Reserved = 0; 1816 1817 parms->iBuffer = 1; 1818 _crVBoxHGSMICmdBufferUnlock(pClient); 1819 1820 _crVBoxHGSMIFillCmd(&aSubmit[0], pClient, sizeof (*parms)); 1821 1822 aSubmit[1].pBuf = pBuf; 1823 aSubmit[1].offData = offStart; 1824 aSubmit[1].cbData = len; 1825 aSubmit[1].fFlags.Value = 0; 1826 aSubmit[1].fFlags.bHostReadOnly = 1; 1827 1828 rc = pClient->pHgsmi->pfnBufferSubmitAsynch(pClient->pHgsmi, aSubmit, 2); 1829 AssertRC(rc); 1830 if (RT_SUCCESS(rc)) 1831 { 1832 _crVBoxHGSMIWaitCmd(pClient); 1833 /* @todo: do we need to wait for completion actually? 1834 * NOTE: in case we do not need completion, 1835 * we MUST specify bDoNotSignalCompletion flag for the command buffer */ 1836 // CRVBOXHGSMI_BUF_WAIT(pClient->pCmdBuffer); 1837 1838 callRes = _crVBoxHGSMICmdBufferGetRc(pClient); 1839 } 1840 } 1841 1842 if (RT_FAILURE(rc) || RT_FAILURE(callRes)) 1843 { 1844 crWarning("SHCRGL_GUEST_FN_WRITE failed with %x %x\n", rc, callRes); 1845 } 1846 } 1847 1848 static void crVBoxHGSMISend(CRConnection *conn, void **bufp, 1849 const void *start, unsigned int len) 1850 { 1851 PCRVBOXHGSMI_CLIENT pClient; 1852 PVBOXUHGSMI_BUFFER pBuf; 1853 CRVBOXHGCMBUFFER *hgcm_buffer; 1854 1855 VBOXCRHGSMIPROFILE_FUNC_PROLOGUE(); 1856 1857 if (!bufp) /* We're sending a user-allocated buffer. */ 1858 { 1859 pClient = _crVBoxHGSMIClientGet(conn); 1860 if (pClient) 1861 { 1862 #ifndef IN_GUEST 1863 //@todo remove temp buffer allocation in unpacker 1864 /* we're at the host side, so just store data until guest polls us */ 1865 _crVBoxHGCMWriteBytes(conn, start, len); 1866 #else 1867 CRASSERT(!conn->u32InjectClientID); 1868 crDebug("SHCRGL: sending userbuf with %d bytes\n", len); 1869 _crVBoxHGSMIWriteReadExact(conn, pClient, (void*)start, 0, len, false); 1870 #endif 1871 VBOXCRHGSMIPROFILE_FUNC_EPILOGUE(); 1872 return; 1873 } 1874 1875 /* fallback */ 1876 crVBoxHGCMSend(conn, bufp, start, len); 1877 VBOXCRHGSMIPROFILE_FUNC_EPILOGUE(); 1878 return; 1879 } 1880 1881 hgcm_buffer = (CRVBOXHGCMBUFFER *) *bufp - 1; 1882 Assert(hgcm_buffer->magic == CR_VBOXHGCM_BUFFER_MAGIC); 1883 if (hgcm_buffer->kind != CR_VBOXHGCM_UHGSMI_BUFFER) 1884 { 1885 /* fallback */ 1886 crVBoxHGCMSend(conn, bufp, start, len); 1887 VBOXCRHGSMIPROFILE_FUNC_EPILOGUE(); 1888 return; 1889 } 1890 1891 /* The region [start .. start + len + 1] lies within a buffer that 1892 * was allocated with crVBoxHGCMAlloc() and can be put into the free 1893 * buffer pool when we're done sending it. 1894 */ 1895 1896 pBuf = _crVBoxHGSMIBufFromHdr(hgcm_buffer); 1897 Assert(pBuf); 1898 if (!pBuf) 1899 { 1900 crVBoxHGCMSend(conn, bufp, start, len); 1901 VBOXCRHGSMIPROFILE_FUNC_EPILOGUE(); 1902 return; 1903 } 1904 1905 pClient = (PCRVBOXHGSMI_CLIENT)pBuf->pvUserData; 1906 1907 /* Length would be passed as part of HGCM pointer description 1908 * No need to prepend it to the buffer 1909 */ 1910 #ifdef IN_GUEST 1911 if (conn->u32InjectClientID) 1912 { 1913 _crVBoxHGSMIWriteExact(conn, pClient, pBuf, CRVBOXHGSMI_BUF_OFFSET(start, *bufp) + CRVBOXHGSMI_BUF_HDR_SIZE(), len); 1914 } 1915 else 1916 #endif 1917 { 1918 _crVBoxHGSMIWriteReadExact(conn, pClient, pBuf, CRVBOXHGSMI_BUF_OFFSET(start, *bufp) + CRVBOXHGSMI_BUF_HDR_SIZE(), len, true); 1919 } 1920 1921 /* Reclaim this pointer for reuse */ 1922 _crVBoxHGSMIBufFree(pClient, pBuf); 1923 /* Since the buffer's now in the 'free' buffer pool, the caller can't 1924 * use it any more. Setting bufp to NULL will make sure the caller 1925 * doesn't try to re-use the buffer. 1926 */ 1927 *bufp = NULL; 1928 1929 VBOXCRHGSMIPROFILE_FUNC_EPILOGUE(); 1930 } 1931 1932 static void crVBoxHGSMIWriteExact(CRConnection *conn, const void *buf, unsigned int len) 1933 { 1934 VBOXCRHGSMIPROFILE_FUNC_PROLOGUE(); 1935 Assert(0); 1936 1937 CRASSERT(0); 1938 // PCRVBOXHGSMI_CLIENT pClient; 1939 // PVBOXUHGSMI_BUFFER pBuf = _crVBoxHGSMIBufFromMemPtr(buf); 1940 // if (!pBuf) 1941 // return; 1942 // pClient = (PCRVBOXHGSMI_CLIENT)pBuf->pvUserData; 1943 // _crVBoxHGSMIWriteExact(conn, pClient, pBuf, 0, len); 1944 // _crVBoxHGSMIBufFree(pClient, pBuf); 1945 VBOXCRHGSMIPROFILE_FUNC_EPILOGUE(); 1946 } 1947 1948 static void crVBoxHGSMISingleRecv(CRConnection *conn, void *buf, unsigned int len) 1949 { 1950 // PCRVBOXHGSMI_CLIENT pClient; 1951 // PVBOXUHGSMI_BUFFER pBuf; 1952 VBOXCRHGSMIPROFILE_FUNC_PROLOGUE(); 1953 // pBuf = _crVBoxHGSMIBufFromMemPtr(buf); 1954 // Assert(pBuf); 1955 Assert(0); 1956 CRASSERT(0); 1957 // if (!pBuf) 1958 // { 1959 // VBOXCRHGSMIPROFILE_FUNC_EPILOGUE(); 1960 // return; 1961 // } 1962 // pClient = (PCRVBOXHGSMI_CLIENT)pBuf->pvUserData; 1963 // _crVBoxHGSMIReadExact(conn, pClient); 1964 VBOXCRHGSMIPROFILE_FUNC_EPILOGUE(); 1965 } 1966 1967 static void crVBoxHGSMIReceiveMessage(CRConnection *conn) 1968 { 1969 VBOXCRHGSMIPROFILE_FUNC_PROLOGUE(); 1970 1971 Assert(0); 1972 1973 _crVBoxHGCMReceiveMessage(conn); 1974 VBOXCRHGSMIPROFILE_FUNC_EPILOGUE(); 1975 } 1976 1977 /* 1978 * Called on host side only, to "accept" client connection 1979 */ 1980 static void crVBoxHGSMIAccept( CRConnection *conn, const char *hostname, unsigned short port ) 1981 { 1982 VBOXCRHGSMIPROFILE_FUNC_PROLOGUE(); 1983 Assert(0); 1984 1985 CRASSERT(conn && conn->pHostBuffer); 1986 #ifdef IN_GUEST 1987 CRASSERT(FALSE); 1988 #endif 1989 VBOXCRHGSMIPROFILE_FUNC_EPILOGUE(); 1990 } 1991 1992 static int crVBoxHGSMIDoConnect( CRConnection *conn ) 1993 { 1994 return crVBoxHGCMDoConnect(conn); 1995 } 1996 1997 static void crVBoxHGSMIDoDisconnect( CRConnection *conn ) 1998 { 1999 crVBoxHGCMDoDisconnect(conn); 2000 } 2001 2002 static void crVBoxHGSMIInstantReclaim(CRConnection *conn, CRMessage *mess) 2003 { 2004 VBOXCRHGSMIPROFILE_FUNC_PROLOGUE(); 2005 Assert(0); 2006 2007 _crVBoxHGSMIFree(conn, mess); 2008 CRASSERT(FALSE); 2009 2010 VBOXCRHGSMIPROFILE_FUNC_EPILOGUE(); 2011 } 2012 2013 static void crVBoxHGSMIHandleNewMessage( CRConnection *conn, CRMessage *msg, unsigned int len ) 2014 { 2015 VBOXCRHGSMIPROFILE_FUNC_PROLOGUE(); 2016 Assert(0); 2017 2018 CRASSERT(FALSE); 2019 VBOXCRHGSMIPROFILE_FUNC_EPILOGUE(); 2020 } 2021 #endif 2022 1143 2023 void crVBoxHGCMInit(CRNetReceiveFuncList *rfl, CRNetCloseFuncList *cfl, unsigned int mtu) 1144 2024 { … … 1155 2035 1156 2036 g_crvboxhgcm.initialized = 1; 2037 2038 #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) 2039 g_crvboxhgcm.bHgsmiOn = _crVBoxHGSMIInit(); 2040 #endif 1157 2041 1158 2042 g_crvboxhgcm.num_conns = 0; … … 1241 2125 g_crvboxhgcm.conns = NULL; 1242 2126 2127 #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) 2128 if (g_crvboxhgcm.bHgsmiOn) 2129 { 2130 _crVBoxHGSMITearDown(); 2131 } 2132 #endif 2133 1243 2134 #ifdef RT_OS_WINDOWS 1244 2135 if (g_crvboxhgcm.pDirectDraw) … … 1258 2149 CRASSERT(g_crvboxhgcm.initialized); 1259 2150 1260 conn->type = CR_VBOXHGCM; 1261 conn->Alloc = crVBoxHGCMAlloc; 1262 conn->Send = crVBoxHGCMSend; 1263 conn->SendExact = crVBoxHGCMWriteExact; 1264 conn->Recv = crVBoxHGCMSingleRecv; 1265 conn->RecvMsg = crVBoxHGCMReceiveMessage; 1266 conn->Free = crVBoxHGCMFree; 1267 conn->Accept = crVBoxHGCMAccept; 1268 conn->Connect = crVBoxHGCMDoConnect; 1269 conn->Disconnect = crVBoxHGCMDoDisconnect; 1270 conn->InstantReclaim = crVBoxHGCMInstantReclaim; 1271 conn->HandleNewMessage = crVBoxHGCMHandleNewMessage; 2151 #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) 2152 if (g_crvboxhgcm.bHgsmiOn) 2153 { 2154 conn->type = CR_VBOXHGCM; 2155 conn->Alloc = crVBoxHGSMIAlloc; 2156 conn->Send = crVBoxHGSMISend; 2157 conn->SendExact = crVBoxHGSMIWriteExact; 2158 conn->Recv = crVBoxHGSMISingleRecv; 2159 conn->RecvMsg = crVBoxHGSMIReceiveMessage; 2160 conn->Free = crVBoxHGSMIFree; 2161 conn->Accept = crVBoxHGSMIAccept; 2162 conn->Connect = crVBoxHGSMIDoConnect; 2163 conn->Disconnect = crVBoxHGSMIDoDisconnect; 2164 conn->InstantReclaim = crVBoxHGSMIInstantReclaim; 2165 conn->HandleNewMessage = crVBoxHGSMIHandleNewMessage; 2166 } 2167 else 2168 #endif 2169 { 2170 conn->type = CR_VBOXHGCM; 2171 conn->Alloc = crVBoxHGCMAlloc; 2172 conn->Send = crVBoxHGCMSend; 2173 conn->SendExact = crVBoxHGCMWriteExact; 2174 conn->Recv = crVBoxHGCMSingleRecv; 2175 conn->RecvMsg = crVBoxHGCMReceiveMessage; 2176 conn->Free = crVBoxHGCMFree; 2177 conn->Accept = crVBoxHGCMAccept; 2178 conn->Connect = crVBoxHGCMDoConnect; 2179 conn->Disconnect = crVBoxHGCMDoDisconnect; 2180 conn->InstantReclaim = crVBoxHGCMInstantReclaim; 2181 conn->HandleNewMessage = crVBoxHGCMHandleNewMessage; 2182 } 1272 2183 conn->index = g_crvboxhgcm.num_conns; 1273 2184 conn->sizeof_buffer_header = sizeof(CRVBOXHGCMBUFFER); … … 1321 2232 if (!conn->pBuffer) 1322 2233 { 1323 crVBoxHGCMPollHost(conn); 2234 #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) 2235 PCRVBOXHGSMI_CLIENT pClient; 2236 if (g_crvboxhgcm.bHgsmiOn && !!(pClient = _crVBoxHGSMIClientGet(conn))) 2237 { 2238 _crVBoxHGSMIPollHost(conn, pClient); 2239 } 2240 else 2241 #endif 2242 { 2243 crVBoxHGCMPollHost(conn); 2244 } 1324 2245 } 1325 2246 }
Note:
See TracChangeset
for help on using the changeset viewer.