VirtualBox

Changeset 50831 in vbox for trunk/src/VBox/Devices/Graphics


Ignore:
Timestamp:
Mar 20, 2014 5:40:50 PM (11 years ago)
Author:
vboxsync
Message:

crOpnGL: new command submission continued

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp

    r50812 r50831  
    2222#include <iprt/asm.h>
    2323#include <iprt/list.h>
     24#include <iprt/param.h>
    2425
    2526#include "DevVGA.h"
     
    11571158}
    11581159
    1159 
    1160 /*
    1161  * @returns
    1162  *
     1160/**
     1161 * @param fIn - whether this is a page in or out op.
     1162 * the direction is VRA#M - related, so fIn == true - transfer to VRAM); false - transfer from VRAM
    11631163 */
    1164 static int vboxVDMACrCmdProcess(struct VBOXVDMAHOST *pVdma, uint8_t* pu8Cmd, uint32_t cbCmd)
     1164static int vboxVDMACrCmdVbvaProcessPagingEl(PPDMDEVINS pDevIns, const VBOXCMDVBVA_SYSMEMEL *pMemEl, uint8_t *pu8Vram, uint8_t *pu8VramMax, uint8_t **ppu8VramNext, bool fIn)
     1165{
     1166    uint32_t u32Cpages = pMemEl->cPagesAfterFirst + 1;
     1167    RTGCPHYS phPage = (pMemEl->iPage1 | (pMemEl->iPage2 << 20));
     1168    PGMPAGEMAPLOCK Lock;
     1169    uint32_t cbCopy = u32Cpages * PAGE_SIZE;
     1170    uint8_t* pu8VramNext = pu8Vram + cbCopy;
     1171
     1172    if (pu8VramNext <= pu8Vram && pu8VramNext > pu8VramMax)
     1173    {
     1174        WARN(("invalid copy size"));
     1175        return VERR_INVALID_PARAMETER;
     1176    }
     1177
     1178    int rc;
     1179    if (fIn)
     1180    {
     1181        for (uint32_t i = 0; i < u32Cpages; ++i)
     1182        {
     1183            const void * pvPage;
     1184            rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, phPage, 0, &pvPage, &Lock);
     1185            if (!RT_SUCCESS(rc))
     1186            {
     1187                WARN(("PDMDevHlpPhysGCPhys2CCPtrReadOnly failed %d", rc));
     1188                return rc;
     1189            }
     1190
     1191            memcpy(pu8Vram, pvPage, PAGE_SIZE);
     1192
     1193            PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock);
     1194
     1195            pu8Vram += PAGE_SIZE;
     1196        }
     1197    }
     1198    else
     1199    {
     1200        for (uint32_t i = 0; i < u32Cpages; ++i)
     1201        {
     1202            void * pvPage;
     1203            rc = PDMDevHlpPhysGCPhys2CCPtr(pDevIns, phPage, 0, &pvPage, &Lock);
     1204            if (!RT_SUCCESS(rc))
     1205            {
     1206                WARN(("PDMDevHlpPhysGCPhys2CCPtr failed %d", rc));
     1207                return rc;
     1208            }
     1209
     1210            memcpy(pvPage, pu8Vram, PAGE_SIZE);
     1211
     1212            PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock);
     1213
     1214            pu8Vram += PAGE_SIZE;
     1215        }
     1216    }
     1217
     1218    if (ppu8VramNext)
     1219        *ppu8VramNext = pu8VramNext;
     1220
     1221    return VINF_SUCCESS;
     1222}
     1223
     1224static int vboxVDMACrCmdVbvaProcessPagingEls(PPDMDEVINS pDevIns, const VBOXCMDVBVA_SYSMEMEL *pMemEl, uint32_t cMemEls, uint8_t *pu8Vram, uint8_t *pu8VramMax, uint8_t **ppu8VramNext, bool fIn)
     1225{
     1226    uint8_t *pu8VramNext = pu8Vram;
     1227    for (uint32_t i = 0; i < cMemEls; ++i, ++pMemEl)
     1228    {
     1229        int rc = vboxVDMACrCmdVbvaProcessPagingEl(pDevIns, pMemEl, pu8Vram, pu8VramMax, &pu8VramNext, fIn);
     1230        if (!RT_SUCCESS(rc))
     1231        {
     1232            WARN(("vboxVDMACrCmdVbvaProcessPagingEl failed %d", rc));
     1233            return rc;
     1234        }
     1235    }
     1236
     1237    if (ppu8VramNext)
     1238        *ppu8VramNext = pu8VramNext;
     1239
     1240    return VINF_SUCCESS;
     1241}
     1242
     1243static int8_t vboxVDMACrCmdVbvaPagingDataInit(PVGASTATE pVGAState, const VBOXCMDVBVA_HDR *pCmd, uint32_t cbCmd,
     1244                            const VBOXCMDVBVA_SYSMEMEL **ppSysMem, uint32_t *pcSysMem,
     1245                            uint8_t **ppu8Vram, uint8_t **ppu8VramMax, bool *pfIn)
     1246{
     1247    if (cbCmd < sizeof (VBOXCMDVBVA_PAGING_TRANSFER))
     1248    {
     1249        WARN(("cmd too small"));
     1250        return -1;
     1251    }
     1252
     1253    uint32_t cSysMem = cbCmd - RT_OFFSETOF(VBOXCMDVBVA_PAGING_TRANSFER, aSysMem);
     1254    if (cSysMem % sizeof (VBOXCMDVBVA_SYSMEMEL))
     1255    {
     1256        WARN(("invalid cmd size"));
     1257        return -1;
     1258    }
     1259    cSysMem /= sizeof (VBOXCMDVBVA_SYSMEMEL);
     1260
     1261    VBOXCMDVBVA_PAGING_TRANSFER *pTransfer = (VBOXCMDVBVA_PAGING_TRANSFER*)pCmd;
     1262    VBOXCMDVBVAOFFSET offVRAM = pTransfer->Alloc.u.offVRAM;
     1263    if (offVRAM & PAGE_OFFSET_MASK)
     1264    {
     1265        WARN(("offVRAM address is not on page boundary\n"));
     1266        return -1;
     1267    }
     1268    const VBOXCMDVBVA_SYSMEMEL *pSysMem = pTransfer->aSysMem;
     1269
     1270    uint8_t * pu8VramBase = pVGAState->vram_ptrR3;
     1271    uint8_t *pu8VramMax = pu8VramBase + pVGAState->vram_size;
     1272    if (pTransfer->Alloc.u.offVRAM >= pVGAState->vram_size)
     1273    {
     1274        WARN(("invalid vram offset"));
     1275        return -1;
     1276    }
     1277
     1278    uint8_t *pu8Vram = pu8VramBase + pTransfer->Alloc.u.offVRAM;
     1279    bool fIn = (pTransfer->Hdr.u8Flags & VBOXCMDVBVA_OPF_PAGING_TRANSFER_IN);
     1280
     1281    *ppSysMem = pSysMem;
     1282    *pcSysMem = cSysMem;
     1283    *ppu8Vram = pu8Vram;
     1284    *ppu8VramMax = pu8VramMax;
     1285    *pfIn = fIn;
     1286    return 0;
     1287}
     1288
     1289static int8_t vboxVDMACrCmdVbvaProcessCmdData(struct VBOXVDMAHOST *pVdma, const VBOXCMDVBVA_HDR *pCmd, uint32_t cbCmd)
     1290{
     1291    switch (pCmd->u8OpCode)
     1292    {
     1293        case VBOXCMDVBVA_OPTYPE_NOPCMD:
     1294            return 0;
     1295        case VBOXCMDVBVA_OPTYPE_PAGING_TRANSFER:
     1296        {
     1297            PVGASTATE pVGAState = pVdma->pVGAState;
     1298            const VBOXCMDVBVA_SYSMEMEL *pSysMem;
     1299            uint32_t cSysMem;
     1300            uint8_t *pu8Vram;
     1301            uint8_t *pu8VramMax;
     1302            bool fIn;
     1303            int8_t i8Result = vboxVDMACrCmdVbvaPagingDataInit(pVGAState, pCmd, cbCmd,
     1304                                                                &pSysMem, &cSysMem,
     1305                                                                &pu8Vram, &pu8VramMax, &fIn);
     1306            if (i8Result < 0)
     1307            {
     1308                WARN(("vboxVDMACrCmdVbvaPagingDataInit failed %d", i8Result));
     1309                return i8Result;
     1310            }
     1311
     1312            PPDMDEVINS pDevIns = pVGAState->pDevInsR3;
     1313            int rc = vboxVDMACrCmdVbvaProcessPagingEls(pDevIns, pSysMem, cSysMem, pu8Vram, pu8VramMax, &pu8Vram, fIn);
     1314            if (!RT_SUCCESS(rc))
     1315            {
     1316                WARN(("vboxVDMACrCmdVbvaProcessPagingEls failed %d", rc));
     1317                return -1;
     1318            }
     1319
     1320            return 0;
     1321        }
     1322        case VBOXCMDVBVA_OPTYPE_PAGING_FILL:
     1323            WARN(("VBOXCMDVBVA_OPTYPE_PAGING_FILL not implemented"));
     1324            return -1;
     1325        default:
     1326            return pVdma->CrSrvInfo.pfnCmd(pVdma->CrSrvInfo.hSvr, pCmd, cbCmd);
     1327    }
     1328}
     1329
     1330#if 0
     1331typedef struct VBOXCMDVBVA_PAGING_TRANSFER
     1332{
     1333    VBOXCMDVBVA_HDR Hdr;
     1334    /* for now can only contain offVRAM.
     1335     * paging transfer can NOT be initiated for allocations having host 3D object (hostID) associated */
     1336    VBOXCMDVBVA_ALLOCINFO Alloc;
     1337    uint32_t u32Reserved;
     1338    VBOXCMDVBVA_SYSMEMEL aSysMem[1];
     1339} VBOXCMDVBVA_PAGING_TRANSFER;
     1340#endif
     1341
     1342AssertCompile(sizeof (VBOXCMDVBVA_HDR) == 8);
     1343AssertCompile(sizeof (VBOXCMDVBVA_ALLOCINFO) == 4);
     1344AssertCompile(sizeof (VBOXCMDVBVA_SYSMEMEL) == 8);
     1345AssertCompile(!(PAGE_SIZE % sizeof (VBOXCMDVBVA_SYSMEMEL)));
     1346AssertCompile(!(sizeof (VBOXCMDVBVA_PAGING_TRANSFER) % 8));
     1347
     1348#define VBOXCMDVBVA_NUM_SYSMEMEL_PER_PAGE (PAGE_SIZE / sizeof (VBOXCMDVBVA_SYSMEMEL))
     1349
     1350static int8_t vboxVDMACrCmdVbvaProcess(struct VBOXVDMAHOST *pVdma, const VBOXCMDVBVA_HDR *pCmd, uint32_t cbCmd)
     1351{
     1352    switch (pCmd->u8OpCode)
     1353    {
     1354        case VBOXCMDVBVA_OPTYPE_SYSMEMCMD:
     1355        {
     1356            VBOXCMDVBVA_SYSMEMCMD *pSysmemCmd = (VBOXCMDVBVA_SYSMEMCMD*)pCmd;
     1357            const VBOXCMDVBVA_HDR *pRealCmd;
     1358            uint32_t cbRealCmd = pCmd->u8Flags;
     1359            cbRealCmd |= (pCmd->u.u8PrimaryID << 8);
     1360            if (cbRealCmd < sizeof (VBOXCMDVBVA_HDR))
     1361            {
     1362                WARN(("invalid sysmem cmd size"));
     1363                return -1;
     1364            }
     1365
     1366            RTGCPHYS phPage = pSysmemCmd->phSysMem;
     1367            if (phPage & PAGE_OFFSET_MASK)
     1368            {
     1369                WARN(("cmd address is not on page boundary\n"));
     1370                return -1;
     1371            }
     1372
     1373            PGMPAGEMAPLOCK Lock;
     1374            PVGASTATE pVGAState = pVdma->pVGAState;
     1375            PPDMDEVINS pDevIns = pVGAState->pDevInsR3;
     1376            const void * pvCmd;
     1377            int rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, phPage, 0, &pvCmd, &Lock);
     1378            if (!RT_SUCCESS(rc))
     1379            {
     1380                WARN(("PDMDevHlpPhysGCPhys2CCPtrReadOnly failed %d\n", rc));
     1381                return -1;
     1382            }
     1383
     1384            pRealCmd = (const VBOXCMDVBVA_HDR *)pvCmd;
     1385
     1386            if (cbRealCmd <= PAGE_SIZE)
     1387            {
     1388                uint8_t i8Result = vboxVDMACrCmdVbvaProcessCmdData(pVdma, pRealCmd, cbRealCmd);
     1389                PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock);
     1390                return i8Result;
     1391            }
     1392
     1393            int8_t i8Result = 0;
     1394
     1395            switch (pRealCmd->u8OpCode)
     1396            {
     1397                case VBOXCMDVBVA_OPTYPE_PAGING_TRANSFER:
     1398                {
     1399                    const VBOXCMDVBVA_SYSMEMEL *pSysMem;
     1400                    uint32_t cSysMem;
     1401                    uint8_t *pu8Vram;
     1402                    uint8_t *pu8VramMax;
     1403                    bool fIn;
     1404                    i8Result = vboxVDMACrCmdVbvaPagingDataInit(pVGAState, pCmd, cbCmd,
     1405                                                                        &pSysMem, &cSysMem,
     1406                                                                        &pu8Vram, &pu8VramMax, &fIn);
     1407                    if (i8Result < 0)
     1408                    {
     1409                        WARN(("vboxVDMACrCmdVbvaPagingDataInit failed %d", i8Result));
     1410                        return i8Result;
     1411                    }
     1412
     1413                    uint32_t cCurSysMem = PAGE_SIZE - RT_OFFSETOF(VBOXCMDVBVA_PAGING_TRANSFER, aSysMem);
     1414                    cCurSysMem /= sizeof (VBOXCMDVBVA_SYSMEMEL);
     1415                    Assert(cCurSysMem < cSysMem);
     1416
     1417                    do
     1418                    {
     1419                        rc = vboxVDMACrCmdVbvaProcessPagingEls(pDevIns, pSysMem, cCurSysMem, pu8Vram, pu8VramMax, &pu8Vram, fIn);
     1420                        if (!RT_SUCCESS(rc))
     1421                        {
     1422                            WARN(("vboxVDMACrCmdVbvaProcessPagingEls failed %d", rc));
     1423                            i8Result = -1;
     1424                            break;
     1425                        }
     1426
     1427                        Assert(cSysMem >= cCurSysMem);
     1428                        cSysMem -= cCurSysMem;
     1429
     1430                        if (!cSysMem)
     1431                            break;
     1432
     1433                        PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock);
     1434
     1435                        phPage += PAGE_SIZE;
     1436
     1437                        rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, phPage, 0, &pvCmd, &Lock);
     1438                        if (!RT_SUCCESS(rc))
     1439                        {
     1440                            WARN(("PDMDevHlpPhysGCPhys2CCPtrReadOnly failed %d\n", rc));
     1441                            return -1;
     1442                        }
     1443
     1444                        if (cSysMem > VBOXCMDVBVA_NUM_SYSMEMEL_PER_PAGE)
     1445                            cCurSysMem = VBOXCMDVBVA_NUM_SYSMEMEL_PER_PAGE;
     1446                        else
     1447                            cCurSysMem = cSysMem;
     1448                    } while (1);
     1449                    break;
     1450                }
     1451                default:
     1452                    WARN(("command can not be splitted"));
     1453                    i8Result = -1;
     1454                    break;
     1455            }
     1456
     1457            PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock);
     1458            return i8Result;
     1459        }
     1460        default:
     1461            return vboxVDMACrCmdVbvaProcessCmdData(pVdma, pCmd, cbCmd);
     1462    }
     1463}
     1464
     1465static void vboxVDMACrCmdProcess(struct VBOXVDMAHOST *pVdma, uint8_t* pu8Cmd, uint32_t cbCmd)
    11651466{
    11661467    if (*pu8Cmd == VBOXCMDVBVA_OPTYPE_NOP)
    1167         return VINF_EOF;
     1468        return;
     1469
     1470    if (cbCmd < sizeof (VBOXCMDVBVA_HDR))
     1471    {
     1472        WARN(("invalid command size"));
     1473        return;
     1474    }
    11681475
    11691476    PVBOXCMDVBVA_HDR pCmd = (PVBOXCMDVBVA_HDR)pu8Cmd;
     
    11731480    {
    11741481        Assert(pCmd->u8State == VBOXCMDVBVA_STATE_CANCELLED);
    1175         return VINF_EOF;
    1176     }
    1177 
    1178     /* come commands can be handled right away? */
    1179     switch (pCmd->u8OpCode)
    1180     {
    1181         case VBOXCMDVBVA_OPTYPE_NOPCMD:
    1182             pCmd->u.i8Result = 0;
    1183             return VINF_EOF;
    1184         default:
    1185             return VINF_SUCCESS;
    1186     }
    1187 }
    1188 
    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->u.i8Result = -1;
    1217     }
    1218     return VINF_SUCCESS;
     1482        return;
     1483    }
     1484
     1485    pCmd->u.i8Result = vboxVDMACrCmdVbvaProcess(pVdma, pCmd, cbCmd);
    12191486}
    12201487
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette