Esempio n. 1
0
PVBOXWDDM_VIDEOMODES_INFO VBoxWddmUpdateVideoModesInfoByMask(PVBOXMP_DEVEXT pExt, uint8_t *pScreenIdMask)
{
    for (int i = 0; i < VBoxCommonFromDeviceExt(pExt)->cDisplays; ++i)
    {
        if (ASMBitTest(pScreenIdMask, i))
            VBoxWddmInvalidateVideoModesInfo(pExt, i);
    }

    /* ensure we have all the rest populated */
    VBoxWddmGetAllVideoModesInfos(pExt);
    return g_aVBoxVideoModeInfos;
}
Esempio n. 2
0
static int vboxVBVAInformHost (PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO * pVbva, BOOL bEnable)
{
    int rc = VERR_NO_MEMORY;
    void *p = VBoxHGSMIBufferAlloc (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx,
                                  sizeof (VBVAENABLE_EX),
                                  HGSMI_CH_VBVA,
                                  VBVA_ENABLE);
    Assert(p);
    if (!p)
    {
        LOGREL(("HGSMIHeapAlloc failed"));
        rc = VERR_NO_MEMORY;
    }
    else
    {
        VBVAENABLE_EX *pEnableEx = (VBVAENABLE_EX *)p;
        pEnableEx->u32ScreenId = pVbva->srcId;

        VBVAENABLE *pEnable = &pEnableEx->Base;
        pEnable->u32Flags  = bEnable? VBVA_F_ENABLE: VBVA_F_DISABLE;
        pEnable->u32Flags |= VBVA_F_EXTENDED | VBVA_F_ABSOFFSET;
        pEnable->u32Offset = (uint32_t)pVbva->offVBVA;
        pEnable->i32Result = VERR_NOT_SUPPORTED;

        VBoxHGSMIBufferSubmit (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, p);

        if (bEnable)
        {
            rc = pEnable->i32Result;
            AssertRC(rc);
        }
        else
            rc = VINF_SUCCESS;

        VBoxHGSMIBufferFree (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, p);
    }
    return rc;
}
Esempio n. 3
0
/* Called for IOCTL_VIDEO_HGSMI_HANDLER_ENABLE.
 * Enables HGSMI miniport channel.
 */
BOOLEAN VBoxMPHgsmiHandlerEnable(PVBOXMP_DEVEXT pExt, HGSMIHANDLERENABLE *pChannel, PSTATUS_BLOCK pStatus)
{
    BOOLEAN bRC = TRUE;
    LOGF_ENTER();

    if (VBoxCommonFromDeviceExt(pExt)->bHGSMI)
    {
        int rc = VBoxVbvaChannelDisplayEnable(VBoxCommonFromDeviceExt(pExt), pExt->iDevice, pChannel->u8Channel);
        if (RT_FAILURE(rc))
        {
            pStatus->Status = ERROR_INVALID_NAME;
            bRC=FALSE;
        }
    }
    else
    {
        pStatus->Status = ERROR_INVALID_FUNCTION;
        bRC=FALSE;
    }

    LOGF_LEAVE();
    return bRC;
}
Esempio n. 4
0
/* Called for IOCTL_VIDEO_HGSMI_QUERY_CALLBACKS.
 * Returns HGSMI related callbacks.
 */
BOOLEAN VBoxMPHGSMIQueryCallbacks(PVBOXMP_DEVEXT pExt, HGSMIQUERYCALLBACKS *pCallbacks, PSTATUS_BLOCK pStatus)
{
    BOOLEAN bRC = TRUE;
    LOGF_ENTER();

    if (VBoxCommonFromDeviceExt(pExt)->bHGSMI)
    {
        pCallbacks->hContext = VBoxCommonFromDeviceExt(pExt);
        pCallbacks->pfnCompletionHandler = VBoxMPHGSMIHostCmdCompleteCB;
        pCallbacks->pfnRequestCommandsHandler = VBoxMPHGSMIHostCmdRequestCB;

        pStatus->Information = sizeof(HGSMIQUERYCALLBACKS);
    }
    else
    {
        pStatus->Status = ERROR_INVALID_FUNCTION;
        bRC=FALSE;
    }


    LOGF_LEAVE();
    return bRC;
}
Esempio n. 5
0
int vboxVhwaHlpGetSurfInfo(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pSurf)
{
    for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
    {
        PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[i];
        if (pSource->Vhwa.Settings.fFlags & VBOXVHWA_F_ENABLED)
        {
            int rc = vboxVhwaHlpGetSurfInfoForSource(pDevExt, pSurf, i);
            AssertRC(rc);
            return rc;
        }
    }
    AssertBreakpoint();
    return VERR_NOT_SUPPORTED;
}
Esempio n. 6
0
void VBoxWddmAdjustMode(PVBOXMP_DEVEXT pExt, PVBOXWDDM_ADJUSTVIDEOMODE pMode)
{
    pMode->fFlags = 0;

    if (pMode->Mode.Id >= (UINT)VBoxCommonFromDeviceExt(pExt)->cDisplays)
    {
        WARN(("invalid screen id (%d)", pMode->Mode.Id));
        pMode->fFlags = VBOXWDDM_ADJUSTVIDEOMODE_F_INVALISCREENID;
        return;
    }

    PVBOXWDDM_TARGET pTarget = &pExt->aTargets[pMode->Mode.Id];
    /* @todo: this info should go from the target actually */
    PVBOXWDDM_SOURCE pSource = &pExt->aSources[pMode->Mode.Id];

    UINT newWidth = pMode->Mode.Width;
    UINT newHeight = pMode->Mode.Height;
    UINT newBpp = pMode->Mode.BitsPerPixel;

    if (!VBoxMPValidateVideoModeParams(pExt, pMode->Mode.Id, newWidth, newHeight, newBpp))
    {
        PVBOXWDDM_SOURCE pSource = &pExt->aSources[pMode->Mode.Id];
        pMode->fFlags |= VBOXWDDM_ADJUSTVIDEOMODE_F_UNSUPPORTED;
    }

    if (pMode->Mode.Width != newWidth
            || pMode->Mode.Height != newHeight
            || pMode->Mode.BitsPerPixel != newBpp)
    {
        pMode->fFlags |= VBOXWDDM_ADJUSTVIDEOMODE_F_ADJUSTED;
        pMode->Mode.Width = newWidth;
        pMode->Mode.Height = newHeight;
        pMode->Mode.BitsPerPixel = newBpp;
    }

    if (pTarget->HeightVisible /* <- active */
            && pSource->AllocData.SurfDesc.width == pMode->Mode.Width
            && pSource->AllocData.SurfDesc.height == pMode->Mode.Height
            && pSource->AllocData.SurfDesc.bpp == pMode->Mode.BitsPerPixel)
    {
        pMode->fFlags |= VBOXWDDM_ADJUSTVIDEOMODE_F_CURRENT;
        if (pMode->fFlags & VBOXWDDM_ADJUSTVIDEOMODE_F_UNSUPPORTED)
        {
            WARN(("current mode is reported as unsupported"));
        }
    }
}
int VBoxMPCmnMapAdapterMemory(PVBOXMP_COMMON pCommon, void **ppv, uint32_t ulOffset, uint32_t ulSize)
{
    PVBOXMP_DEVEXT pPEXT = VBoxCommonToPrimaryExt(pCommon);

    LOGF(("0x%08X[0x%X]", ulOffset, ulSize));

    if (!ulSize)
    {
        WARN(("Illegal length 0!"));
        return ERROR_INVALID_PARAMETER;
    }

    PHYSICAL_ADDRESS FrameBuffer;
    FrameBuffer.QuadPart = VBoxCommonFromDeviceExt(pPEXT)->phVRAM.QuadPart + ulOffset;

    PVOID VideoRamBase = NULL;
    ULONG VideoRamLength = ulSize;
    VP_STATUS Status;
#ifndef VBOX_WITH_WDDM
    ULONG inIoSpace = 0;

    Status = VideoPortMapMemory(pPEXT, FrameBuffer, &VideoRamLength, &inIoSpace, &VideoRamBase);
#else
    NTSTATUS ntStatus = pPEXT->u.primary.DxgkInterface.DxgkCbMapMemory(pPEXT->u.primary.DxgkInterface.DeviceHandle,
            FrameBuffer,
            VideoRamLength,
            FALSE, /* IN BOOLEAN InIoSpace */
            FALSE, /* IN BOOLEAN MapToUserMode */
            MmNonCached, /* IN MEMORY_CACHING_TYPE CacheType */
            &VideoRamBase /*OUT PVOID *VirtualAddress*/
            );
    Assert(ntStatus == STATUS_SUCCESS);
    /* this is what VideoPortMapMemory returns according to the docs */
    Status = ntStatus == STATUS_SUCCESS ? NO_ERROR : ERROR_INVALID_PARAMETER;
#endif

    if (Status == NO_ERROR)
    {
        *ppv = VideoRamBase;
    }

    LOGF(("rc = %d", Status));

    return (Status==NO_ERROR) ? VINF_SUCCESS:VERR_INVALID_PARAMETER;
}
Esempio n. 8
0
/* do not wait for completion */
void vboxVhwaCommandSubmitAsynch(PVBOXMP_DEVEXT pDevExt, VBOXVHWACMD* pCmd, PFNVBOXVHWACMDCOMPLETION pfnCompletion, void * pContext)
{
    pCmd->GuestVBVAReserved1 = (uintptr_t)pfnCompletion;
    pCmd->GuestVBVAReserved2 = (uintptr_t)pContext;
    vbvaVhwaCommandRetain(pDevExt, pCmd);

    VBoxHGSMIBufferSubmit(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, pCmd);

    if(!(pCmd->Flags & VBOXVHWACMD_FLAG_HG_ASYNCH)
            || ((pCmd->Flags & VBOXVHWACMD_FLAG_GH_ASYNCH_NOCOMPLETION)
                    && (pCmd->Flags & VBOXVHWACMD_FLAG_HG_ASYNCH_RETURNED)))
    {
        /* the command is completed */
        pfnCompletion(pDevExt, pCmd, pContext);
    }

    vbvaVhwaCommandRelease(pDevExt, pCmd);
}
Esempio n. 9
0
/* Called for IOCTL_VIDEO_SET_POINTER_ATTR.
 * Sets pointer attributes.
 */
BOOLEAN VBoxMPSetPointerAttr(PVBOXMP_DEVEXT pExt, PVIDEO_POINTER_ATTRIBUTES pPointerAttrs, uint32_t cbLen, PSTATUS_BLOCK pStatus)
{
    BOOLEAN bRC;

    LOGF_ENTER();

    if (VBoxQueryHostWantsAbsolute())
    {
        bRC = VBoxMPCmnUpdatePointerShape(VBoxCommonFromDeviceExt(pExt), pPointerAttrs, cbLen);
    }
    else
    {
        LOG(("Fallback to sw pointer."));
        pStatus->Status = ERROR_INVALID_FUNCTION;
        bRC = FALSE;
    }

    LOGF_LEAVE();
    return bRC;
}
Esempio n. 10
0
int VBoxCmdVbvaCreate(PVBOXMP_DEVEXT pDevExt, VBOXCMDVBVA *pVbva, ULONG offBuffer, ULONG cbBuffer)
{
    memset(pVbva, 0, sizeof (*pVbva));

    int rc = VBoxMPCmnMapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt),
                                       (void**)&pVbva->Vbva.pVBVA,
                                       offBuffer,
                                       cbBuffer);
    if (RT_SUCCESS(rc))
    {
        Assert(pVbva->Vbva.pVBVA);
        VBoxVBVAExSetupBufferContext(&pVbva->Vbva, offBuffer, cbBuffer, voxCmdVbvaFlushCb, pDevExt);
    }
    else
    {
        WARN(("VBoxMPCmnMapAdapterMemory failed rc %d", rc));
    }

    return rc;
}
Esempio n. 11
0
/* Called for IOCTL_VIDEO_VHWA_QUERY_INFO.
 * Returns framebuffer offset.
 */
BOOLEAN VBoxMPVhwaQueryInfo(PVBOXMP_DEVEXT pExt, VHWAQUERYINFO *pInfo, PSTATUS_BLOCK pStatus)
{
    BOOLEAN bRC = TRUE;
    LOGF_ENTER();

    if (VBoxCommonFromDeviceExt(pExt)->bHGSMI)
    {
        pInfo->offVramBase = (ULONG_PTR)pExt->ulFrameBufferOffset;

        pStatus->Information = sizeof (VHWAQUERYINFO);
    }
    else
    {
        pStatus->Status = ERROR_INVALID_FUNCTION;
        bRC=FALSE;
    }

    LOGF_LEAVE();
    return bRC;
}
Esempio n. 12
0
/* Called for IOCTL_VIDEO_SHARE_VIDEO_MEMORY.
 * Maps FrameBuffer as a linear frame buffer to a caller's virtual adress space. (obsolete).
 */
BOOLEAN VBoxMPShareVideoMemory(PVBOXMP_DEVEXT pExt, PVIDEO_SHARE_MEMORY pShareMem,
                               PVIDEO_SHARE_MEMORY_INFORMATION pShareMemInfo, PSTATUS_BLOCK pStatus)
{
    PHYSICAL_ADDRESS shareAddress;
    ULONG inIoSpace = 0;
    ULONG offset, size;
    PVOID virtualAddress;
    ULONG ulMaxFBSize;

    LOGF_ENTER();

    ulMaxFBSize = pExt->pPrimary->u.primary.ulMaxFrameBufferSize;
    offset = pShareMem->ViewOffset;
    size = pShareMem->ViewSize;
    virtualAddress = pShareMem->ProcessHandle;
    VBOXMPIOCTL_HIDE(pShareMem);

    if ((offset>ulMaxFBSize) || ((offset+size)>ulMaxFBSize))
    {
        WARN(("share failed offset:size(%#x:%#x) > %#x fb size.", offset, size, ulMaxFBSize));
        pStatus->Status = ERROR_INVALID_PARAMETER;
        return FALSE;
    }

    shareAddress.QuadPart = VBoxCommonFromDeviceExt(pExt)->phVRAM.QuadPart + pExt->ulFrameBufferOffset;

    pStatus->Status = VideoPortMapMemory(pExt, shareAddress, &size, &inIoSpace, &virtualAddress);

    if (NO_ERROR == pStatus->Status)
    {
        pShareMemInfo->SharedViewOffset = offset;
        pShareMemInfo->SharedViewSize = size;
        pShareMemInfo->VirtualAddress = virtualAddress;

        pStatus->Information = sizeof(VIDEO_SHARE_MEMORY_INFORMATION);
    }

    VBOXMPIOCTL_UNHIDE();
    LOGF_LEAVE();
    return NO_ERROR == pStatus->Status;
}
Esempio n. 13
0
/* Called for IOCTL_VIDEO_HGSMI_QUERY_PORTPROCS.
 * Returns video port api function pointers.
 */
BOOLEAN VBoxMPHGSMIQueryPortProcs(PVBOXMP_DEVEXT pExt, HGSMIQUERYCPORTPROCS *pProcs, PSTATUS_BLOCK pStatus)
{
    BOOLEAN bRC = TRUE;
    LOGF_ENTER();

    if (VBoxCommonFromDeviceExt(pExt)->bHGSMI)
    {
        pProcs->pContext = pExt->pPrimary;
        pProcs->VideoPortProcs = pExt->pPrimary->u.primary.VideoPortProcs;

        pStatus->Information = sizeof(HGSMIQUERYCPORTPROCS);
    }
    else
    {
        pStatus->Status = ERROR_INVALID_FUNCTION;
        bRC=FALSE;
    }

    LOGF_LEAVE();
    return bRC;
}
Esempio n. 14
0
int vboxVbvaCreate(PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva, ULONG offBuffer, ULONG cbBuffer, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId)
{
    memset(pVbva, 0, sizeof(VBOXVBVAINFO));

    KeInitializeSpinLock(&pVbva->Lock);

    int rc = VBoxMPCmnMapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt),
                                       (void**)&pVbva->pVBVA,
                                       offBuffer,
                                       cbBuffer);
    AssertRC(rc);
    if (RT_SUCCESS(rc))
    {
        Assert(pVbva->pVBVA);
        pVbva->offVBVA = offBuffer;
        pVbva->cbVBVA = cbBuffer;
        pVbva->srcId = srcId;
    }

    return rc;
}
Esempio n. 15
0
/* Called for IOCTL_VIDEO_ENABLE_POINTER/IOCTL_VIDEO_DISABLE_POINTER.
 * Hides pointer or makes it visible depending on bEnable value passed.
 */
BOOLEAN VBoxMPEnablePointer(PVBOXMP_DEVEXT pExt, BOOLEAN bEnable, PSTATUS_BLOCK pStatus)
{
    BOOLEAN bRC = TRUE;
    LOGF_ENTER();

    if (VBoxQueryHostWantsAbsolute())
    {
        /* Check if it's not shown already. */
        if (bEnable == pExt->pPrimary->u.primary.fMouseHidden)
        {
            VIDEO_POINTER_ATTRIBUTES attrs;

            /* Visible and No Shape means show the pointer, 0 means hide pointer.
             * It's enough to init only this field.
             */
            attrs.Enable = bEnable ? VBOX_MOUSE_POINTER_VISIBLE:0;


            /* Pass info to the host. */
            bRC = VBoxMPCmnUpdatePointerShape(VBoxCommonFromDeviceExt(pExt), &attrs, sizeof(attrs));

            if (bRC)
            {
                /* Update device state. */
                pExt->pPrimary->u.primary.fMouseHidden = !bEnable;
            }
        }
    }
    else
    {
        pStatus->Status = ERROR_INVALID_FUNCTION;
        bRC = FALSE;
    }

    LOGF_LEAVE();
    return bRC;
}
Esempio n. 16
0
int vboxVbvaCreate(PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva, ULONG offBuffer, ULONG cbBuffer, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId)
{
    memset(pVbva, 0, sizeof(VBOXVBVAINFO));

    KeInitializeSpinLock(&pVbva->Lock);

    int rc = VBoxMPCmnMapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt),
                                       (void**)&pVbva->Vbva.pVBVA,
                                       offBuffer,
                                       cbBuffer);
    if (RT_SUCCESS(rc))
    {
        Assert(pVbva->Vbva.pVBVA);
        VBoxVBVASetupBufferContext(&pVbva->Vbva, offBuffer, cbBuffer);
        pVbva->srcId = srcId;
    }
    else
    {
        WARN(("VBoxMPCmnMapAdapterMemory failed rc %d", rc));
    }


    return rc;
}
Esempio n. 17
0
/* Called to enumerate child devices of our adapter, attached monitor(s) in our case */
static VP_STATUS
VBoxDrvGetVideoChildDescriptor(PVOID HwDeviceExtension, PVIDEO_CHILD_ENUM_INFO ChildEnumInfo,
                               PVIDEO_CHILD_TYPE VideoChildType, PUCHAR pChildDescriptor, PULONG pUId,
                               PULONG pUnused)
{
    PVBOXMP_DEVEXT pExt = (PVBOXMP_DEVEXT) HwDeviceExtension;

    PAGED_CODE();
    LOGF_ENTER();

    if (ChildEnumInfo->ChildIndex>0)
    {
        if ((int)ChildEnumInfo->ChildIndex <= VBoxCommonFromDeviceExt(pExt)->cDisplays)
        {
            *VideoChildType = Monitor;
            *pUId = ChildEnumInfo->ChildIndex;

            LOGF_LEAVE();
            return VIDEO_ENUM_MORE_DEVICES;
        }
    }
    LOGF_LEAVE();
    return ERROR_NO_MORE_DEVICES;
}
Esempio n. 18
0
/* Called for IOCTL_VIDEO_MAP_VIDEO_MEMORY.
 * Maps FrameBuffer and video RAM to a caller's virtual adress space.
 */
BOOLEAN VBoxMPMapVideoMemory(PVBOXMP_DEVEXT pExt, PVIDEO_MEMORY pRequestedAddress,
                             PVIDEO_MEMORY_INFORMATION pMapInfo, PSTATUS_BLOCK pStatus)
{
    PHYSICAL_ADDRESS framebuffer;
    ULONG inIoSpace = 0;

    LOGF(("framebuffer offset %#x", pExt->ulFrameBufferOffset));

    framebuffer.QuadPart = VBoxCommonFromDeviceExt(pExt)->phVRAM.QuadPart + pExt->ulFrameBufferOffset;

    pMapInfo->VideoRamBase = pRequestedAddress->RequestedVirtualAddress;
    VBOXMPIOCTL_HIDE(pRequestedAddress);
    pMapInfo->VideoRamLength = pExt->pPrimary->u.primary.ulMaxFrameBufferSize;

    pStatus->Status = VideoPortMapMemory(pExt, framebuffer, &pMapInfo->VideoRamLength,
                                         &inIoSpace, &pMapInfo->VideoRamBase);

    if (NO_ERROR == pStatus->Status)
    {
        pMapInfo->FrameBufferBase = (PUCHAR)pMapInfo->VideoRamBase;
        pMapInfo->FrameBufferLength =
            VBoxMPXpdmCurrentVideoMode(pExt)->VisScreenHeight*
            VBoxMPXpdmCurrentVideoMode(pExt)->ScreenStride;

        pStatus->Information = sizeof(VIDEO_MEMORY_INFORMATION);

        /* Save the new framebuffer size */
        pExt->ulFrameBufferSize = pMapInfo->FrameBufferLength;
        HGSMIAreaInitialize(&pExt->areaDisplay, pMapInfo->FrameBufferBase,
                            pMapInfo->FrameBufferLength, pExt->ulFrameBufferOffset);
    }

    VBOXMPIOCTL_UNHIDE();
    LOGF_LEAVE();
    return NO_ERROR == pStatus->Status;
}
/* Process Video Request Packet. */
static BOOLEAN
VBoxDrvStartIO(PVOID HwDeviceExtension, PVIDEO_REQUEST_PACKET RequestPacket)
{
    PVBOXMP_DEVEXT pExt = (PVBOXMP_DEVEXT) HwDeviceExtension;
    PSTATUS_BLOCK  pStatus = RequestPacket->StatusBlock;
    BOOLEAN        bResult = FALSE;

    PAGED_CODE();

    LOGF(("IOCTL %#x, fn(%#x)", RequestPacket->IoControlCode, (RequestPacket->IoControlCode >> 2) & 0xFFF));

    pStatus->Status = NO_ERROR;

    switch (RequestPacket->IoControlCode)
    {
        /* ==================== System VRPs ==================== */

        /*Maps FrameBuffer and video RAM to a caller's virtual adress space.*/
        case IOCTL_VIDEO_MAP_VIDEO_MEMORY:
        {
            STARTIO_IN(VIDEO_MEMORY, pMemory);
            STARTIO_OUT(VIDEO_MEMORY_INFORMATION, pMemInfo);

            bResult = VBoxMPMapVideoMemory(pExt, pMemory, pMemInfo, pStatus);
            break;
        }

        /*Unmaps previously mapped FrameBuffer and video RAM from caller's virtual adress space.*/
        case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY:
        {
            STARTIO_IN(VIDEO_MEMORY, pMemory);

            bResult = VBoxMPUnmapVideoMemory(pExt, pMemory, pStatus);
            break;
        }

        /*Maps FrameBuffer as a linear frame buffer to a caller's virtual adress space. (obsolete)*/
        case IOCTL_VIDEO_SHARE_VIDEO_MEMORY:
        {
            STARTIO_IN(VIDEO_SHARE_MEMORY, pShareMemory);
            STARTIO_OUT(VIDEO_SHARE_MEMORY_INFORMATION, pShareMemInfo);

            bResult = VBoxMPShareVideoMemory(pExt, pShareMemory, pShareMemInfo, pStatus);
            break;
        }

        /*Unmaps framebuffer previously mapped with IOCTL_VIDEO_SHARE_VIDEO_MEMORY*/
        case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY:
        {
            STARTIO_IN(VIDEO_SHARE_MEMORY, pShareMemory);

            bResult = VBoxMPUnshareVideoMemory(pExt, pShareMemory, pStatus);
            break;
        }

        /*Reset device to a state it comes at system boot time.*/
        case IOCTL_VIDEO_RESET_DEVICE:
        {
            bResult = VBoxMPResetDevice(pExt, pStatus);
            break;
        }

        /*Set adapter video mode.*/
        case IOCTL_VIDEO_SET_CURRENT_MODE:
        {
            STARTIO_IN(VIDEO_MODE, pMode);

            bResult = VBoxMPSetCurrentMode(pExt, pMode, pStatus);
            break;
        }

        /*Returns information about current video mode.*/
        case IOCTL_VIDEO_QUERY_CURRENT_MODE:
        {
            STARTIO_OUT(VIDEO_MODE_INFORMATION, pModeInfo);

            bResult = VBoxMPQueryCurrentMode(pExt, pModeInfo, pStatus);
            break;
        }

        /* Returns count of supported video modes and structure size in bytes,
         * used to allocate buffer for the following IOCTL_VIDEO_QUERY_AVAIL_MODES call.
         */
        case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
        {
            STARTIO_OUT(VIDEO_NUM_MODES, pNumModes);

            bResult = VBoxMPQueryNumAvailModes(pExt, pNumModes, pStatus);
            break;
        }

        /* Returns information about supported video modes. */
        case IOCTL_VIDEO_QUERY_AVAIL_MODES:
        {
            PVIDEO_MODE_INFORMATION pModes = (PVIDEO_MODE_INFORMATION) RequestPacket->OutputBuffer;

            if (RequestPacket->OutputBufferLength < VBoxMPXpdmGetVideoModesCount(pExt)*sizeof(VIDEO_MODE_INFORMATION))
            {
                pStatus->Status = ERROR_INSUFFICIENT_BUFFER;
                break;
            }

            bResult = VBoxMPQueryAvailModes(pExt, pModes, pStatus);
            break;
        }

        /* Sets adapter's color registers, have to be implemented if we support palette based modes. */
        case IOCTL_VIDEO_SET_COLOR_REGISTERS:
        {
            STARTIO_IN(VIDEO_CLUT, pClut);

            if (RequestPacket->InputBufferLength < (sizeof(VIDEO_CLUT) + pClut->NumEntries * sizeof(ULONG)))
            {
                pStatus->Status = ERROR_INSUFFICIENT_BUFFER;
                break;
            }

            bResult = VBoxMPSetColorRegisters(pExt, pClut, pStatus);
            break;
        }

        /* Sets pointer attributes. */
        case IOCTL_VIDEO_SET_POINTER_ATTR:
        {
            STARTIO_IN(VIDEO_POINTER_ATTRIBUTES, pPointerAttrs);

            bResult = VBoxMPSetPointerAttr(pExt, pPointerAttrs, RequestPacket->InputBufferLength, pStatus);
            break;
        }

        /* Makes pointer visible. */
        case IOCTL_VIDEO_ENABLE_POINTER:
        {
            bResult = VBoxMPEnablePointer(pExt, TRUE, pStatus);
            break;
        }

        /* Hides pointer. */
        case IOCTL_VIDEO_DISABLE_POINTER:
        {
            bResult = VBoxMPEnablePointer(pExt, FALSE, pStatus);
            break;
        }

        /* Sets pointer position, is called after IOCTL_VIDEO_ENABLE_POINTER. */
        case IOCTL_VIDEO_SET_POINTER_POSITION:
        {
            STARTIO_IN(VIDEO_POINTER_POSITION, pPos);

            NOREF(pPos); /** @todo set pointer position*/
            bResult = VBoxMPEnablePointer(pExt, TRUE, pStatus);
            break;
        }

        /* Query pointer position. */
        case IOCTL_VIDEO_QUERY_POINTER_POSITION:
        {
            STARTIO_OUT(VIDEO_POINTER_POSITION, pPos);

            bResult = VBoxMPQueryPointerPosition(pExt, pPos, pStatus);
            break;
        }

        /* Query supported hardware pointer feaures. */
        case IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES:
        {
            STARTIO_OUT(VIDEO_POINTER_CAPABILITIES, pCaps);

            bResult = VBoxMPQueryPointerCapabilities(pExt, pCaps, pStatus);
            break;
        }

        /* Query pointer attributes. (optional) */
        case IOCTL_VIDEO_QUERY_POINTER_ATTR:
        {
            STARTIO_OUT(VIDEO_POINTER_ATTRIBUTES, pPointerAttrs);

            NOREF(pPointerAttrs); /* Not Implemented */
            pStatus->Status = ERROR_INVALID_FUNCTION;

            bResult = FALSE;
            break;
        }

        /* Called when a secondary adapter is about to be enabled/disabled. */
        case IOCTL_VIDEO_SWITCH_DUALVIEW:
        {
            STARTIO_IN(ULONG, pAttach);

            LOGF(("IOCTL_VIDEO_SWITCH_DUALVIEW: [%d] attach = %d", pExt->iDevice, *pAttach));

            if (pExt->iDevice>0)
            {
                pExt->u.secondary.bEnabled = (BOOLEAN)(*pAttach);

                /* Inform the host.
                 * Currently only about secondary devices, because the driver does not support
                 * disconnecting the primary display (it does not allow to change the primary display).
                 */
                if (!pExt->u.secondary.bEnabled)
                {
                    PVBOXMP_COMMON pCommon = VBoxCommonFromDeviceExt(pExt);
                    if (pCommon->bHGSMI)
                    {
                        VBoxHGSMIProcessDisplayInfo(&pCommon->guestCtx, pExt->iDevice,
                                                    /* cOriginX = */ 0, /* cOriginY = */ 0,
                                                    /* offStart = */ 0, /* cbPitch = */ 0,
                                                    /* cWidth = */ 0, /* cHeight = */ 0, /* cBPP = */ 0,
                                                    VBVA_SCREEN_F_ACTIVE | VBVA_SCREEN_F_DISABLED);
                    }
                }
            }

            bResult = TRUE;
            break;
        }

        /* Called to get child device status */
        case IOCTL_VIDEO_GET_CHILD_STATE:
        {
            STARTIO_IN(ULONG, pChildIndex);
            STARTIO_OUT(ULONG, pChildState);

            LOGF(("IOCTL_VIDEO_GET_CHILD_STATE: [%d] idx = %d", pExt->iDevice, *pChildIndex));

            if (*pChildIndex>0 && *pChildIndex<=(ULONG)VBoxCommonFromDeviceExt(pExt)->cDisplays)
            {
                *pChildState = VIDEO_CHILD_ACTIVE;
                pStatus->Information = sizeof(ULONG);
                bResult = TRUE;
            }
            else
            {
                pStatus->Status = ERROR_INVALID_PARAMETER;
                bResult = FALSE;
            }

            break;
        }

        /* ==================== VirtualBox specific VRPs ==================== */

        /* Called by the display driver when it is ready to switch to VBVA operation mode. */
        case IOCTL_VIDEO_VBVA_ENABLE:
        {
            STARTIO_IN(ULONG, pEnable);
            STARTIO_OUT(VBVAENABLERESULT, pResult);

            bResult = VBoxMPVBVAEnable(pExt, (BOOLEAN)*pEnable, pResult, pStatus);
            break;
        }

        /* Called by the display driver when it recieves visible regions information. */
        case IOCTL_VIDEO_VBOX_SETVISIBLEREGION:
        {
            STARTIO_IN(RTRECT, pRects);

            uint32_t cRects = RequestPacket->InputBufferLength/sizeof(RTRECT);
            /*Sanity check*/
            if (   cRects > _1M
                || RequestPacket->InputBufferLength != cRects * sizeof(RTRECT))
            {
                pStatus->Status = ERROR_INSUFFICIENT_BUFFER;
                break;
            }

            bResult = VBoxMPSetVisibleRegion(cRects, pRects, pStatus);
            break;
        }

        /* Returns video port api function pointers. */
        case IOCTL_VIDEO_HGSMI_QUERY_PORTPROCS:
        {
            STARTIO_OUT(HGSMIQUERYCPORTPROCS, pProcs);

            bResult = VBoxMPHGSMIQueryPortProcs(pExt, pProcs, pStatus);
            break;
        }

        /* Returns HGSMI related callbacks. */
        case IOCTL_VIDEO_HGSMI_QUERY_CALLBACKS:
        {
            STARTIO_OUT(HGSMIQUERYCALLBACKS, pCallbacks);

            bResult = VBoxMPHGSMIQueryCallbacks(pExt, pCallbacks, pStatus);
            break;
        }

        /* Returns hgsmi info for this adapter. */
        case IOCTL_VIDEO_QUERY_HGSMI_INFO:
        {
            STARTIO_OUT(QUERYHGSMIRESULT, pResult);

            bResult = VBoxMPQueryHgsmiInfo(pExt, pResult, pStatus);
            break;
        }

        /* Enables HGSMI miniport channel. */
        case IOCTL_VIDEO_HGSMI_HANDLER_ENABLE:
        {
            STARTIO_IN(HGSMIHANDLERENABLE, pChannel);

            bResult = VBoxMPHgsmiHandlerEnable(pExt, pChannel, pStatus);
            break;
        }

        case IOCTL_VIDEO_HGSMI_HANDLER_DISABLE:
        {
            /** @todo not implemented */
            break;
        }

#ifdef VBOX_WITH_VIDEOHWACCEL
        /* Returns framebuffer offset. */
        case IOCTL_VIDEO_VHWA_QUERY_INFO:
        {
            STARTIO_OUT(VHWAQUERYINFO, pInfo);

            bResult = VBoxMPVhwaQueryInfo(pExt, pInfo, pStatus);
            break;
        }
#endif

        case IOCTL_VIDEO_VBOX_ISANYX:
        {
            STARTIO_OUT(uint32_t, pu32AnyX);
            *pu32AnyX = VBoxCommonFromDeviceExt(pExt)->fAnyX;
            pStatus->Information = sizeof (uint32_t);
            bResult = TRUE;
            break;
        }

        case IOCTL_VIDEO_QUERY_VBOXVIDEO_INFO:
        {
            STARTIO_IN(ULONG, pulInfoLevel);
            if (*pulInfoLevel == VBOXVIDEO_INFO_LEVEL_REGISTRY_FLAGS)
            {
                STARTIO_OUT(ULONG, pulFlags);
                bResult = VBoxMPQueryRegistryFlags(pExt, pulFlags, pStatus);
            }
            else
            {
                pStatus->Status = ERROR_INVALID_PARAMETER;
                bResult = FALSE;
            }

            break;
        }

        default:
        {
            WARN(("unsupported IOCTL %#x, fn(%#x)", RequestPacket->IoControlCode, (RequestPacket->IoControlCode >> 2) & 0xFFF));
            RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
        }
    }

    if (!bResult)
    {
        pStatus->Information = NULL;
    }

    VBOXMP_WARN_VPS(pStatus->Status);
    LOGF_LEAVE();
    return TRUE;
}
Esempio n. 20
0
static void vboxMpCrShgsmiBufferFree(PVBOXMP_DEVEXT pDevExt, void *pvBuffer)
{
    VBoxSHGSMIHeapBufferFree(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, pvBuffer);
}
Esempio n. 21
0
static void* vboxMpCrShgsmiBufferFromOffset(PVBOXMP_DEVEXT pDevExt, VBOXVIDEOOFFSET offBuffer)
{
    return HGSMIOffsetToPointer(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx.Heap.area, (HGSMIOFFSET)offBuffer);
}
Esempio n. 22
0
static VBOXVIDEOOFFSET vboxMpCrShgsmiBufferOffset(PVBOXMP_DEVEXT pDevExt, void *pvBuffer)
{
    return (VBOXVIDEOOFFSET)HGSMIPointerToOffset(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx.Heap.area, (const HGSMIBUFFERHEADER *)pvBuffer);
}
Esempio n. 23
0
static void* vboxMpCrShgsmiBufferAlloc(PVBOXMP_DEVEXT pDevExt, HGSMISIZE cbData)
{
    return VBoxSHGSMIHeapBufferAlloc(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, cbData);
}
Esempio n. 24
0
void VBoxCreateDisplays(PVBOXMP_DEVEXT pExt, PVIDEO_PORT_CONFIG_INFO pConfigInfo)
{
    LOGF_ENTER();

    PVBOXMP_COMMON pCommon = VBoxCommonFromDeviceExt(pExt);
    VBOXVIDEOPORTPROCS *pAPI = &pExt->u.primary.VideoPortProcs;

    if (pCommon->bHGSMI)
    {
        if (pAPI->fSupportedTypes & VBOXVIDEOPORTPROCS_CSD)
        {
            PVBOXMP_DEVEXT pPrev = pExt;
            ULONG iDisplay, cDisplays;

            cDisplays = pCommon->cDisplays;
            pCommon->cDisplays = 1;

            for (iDisplay=1; iDisplay<cDisplays; ++iDisplay)
            {
                PVBOXMP_DEVEXT pSExt = NULL;
                VP_STATUS rc;

                /* If VIDEO_DUALVIEW_REMOVABLE is passed as the 3rd parameter, then
                 * the guest does not allow to choose the primary screen.
                 */
                rc = pAPI->pfnCreateSecondaryDisplay(pExt, (PVOID*)&pSExt, 0);
                VBOXMP_WARN_VPS(rc);

                if (rc != NO_ERROR)
                {
                    break;
                }
                LOG(("created secondary device %p", pSExt));

                pSExt->pNext = NULL;
                pSExt->pPrimary = pExt;
                pSExt->iDevice = iDisplay;
                pSExt->ulFrameBufferOffset  = 0;
                pSExt->ulFrameBufferSize    = 0;
                pSExt->u.secondary.bEnabled = FALSE;

                /* Update the list pointers */
                pPrev->pNext = pSExt;
                pPrev = pSExt;

                /* Take the successfully created display into account. */
                pCommon->cDisplays++;
            }
        }
        else
        {
            /* Even though VM could be configured to have multiply monitors,
             * we can't support it on this windows version.
             */
            pCommon->cDisplays = 1;
        }
    }

    /* Now when the number of monitors is known and extensions are created,
     * calculate the layout of framebuffers.
     */
    VBoxComputeFrameBufferSizes(pExt);

    /*Report our screen configuration to host*/
    if (pCommon->bHGSMI)
    {
        int rc;
        rc = VBoxHGSMISendViewInfo(&pCommon->guestCtx, pCommon->cDisplays, VBoxVbvaInitInfoDisplayCB, (void *) pExt);

        if (RT_FAILURE (rc))
        {
            WARN(("VBoxHGSMISendViewInfo failed with rc=%#x, HGSMI disabled", rc));
            pCommon->bHGSMI = FALSE;
        }
    }

    LOGF_LEAVE();
}
Esempio n. 25
0
static void vboxVhwaInitSrc(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId)
{
    Assert(srcId < (D3DDDI_VIDEO_PRESENT_SOURCE_ID)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
    VBOXVHWA_INFO *pSettings = &pDevExt->aSources[srcId].Vhwa.Settings;
    memset (pSettings, 0, sizeof (VBOXVHWA_INFO));

    vboxVhwaHlpOverlayListInit(pDevExt, srcId);

    VBOXVHWACMD_QUERYINFO1* pInfo1 = vboxVhwaQueryHostInfo1(pDevExt, srcId);
    if (pInfo1)
    {
        if ((pInfo1->u.out.cfgFlags & VBOXVHWA_CFG_ENABLED)
                && pInfo1->u.out.numOverlays)
        {
            if ((pInfo1->u.out.caps & VBOXVHWA_CAPS_OVERLAY)
                    && (pInfo1->u.out.caps & VBOXVHWA_CAPS_OVERLAYSTRETCH)
                    && (pInfo1->u.out.surfaceCaps & VBOXVHWA_SCAPS_OVERLAY)
                    && (pInfo1->u.out.surfaceCaps & VBOXVHWA_SCAPS_FLIP)
                    && (pInfo1->u.out.surfaceCaps & VBOXVHWA_SCAPS_LOCALVIDMEM)
                    && pInfo1->u.out.numOverlays)
            {
                pSettings->fFlags |= VBOXVHWA_F_ENABLED;

                if (pInfo1->u.out.caps & VBOXVHWA_CAPS_COLORKEY)
                {
                    if (pInfo1->u.out.colorKeyCaps & VBOXVHWA_CKEYCAPS_SRCOVERLAY)
                    {
                        pSettings->fFlags |= VBOXVHWA_F_CKEY_SRC;
                        /* todo: VBOXVHWA_CKEYCAPS_SRCOVERLAYONEACTIVE ? */
                    }

                    if (pInfo1->u.out.colorKeyCaps & VBOXVHWA_CKEYCAPS_DESTOVERLAY)
                    {
                        pSettings->fFlags |= VBOXVHWA_F_CKEY_DST;
                        /* todo: VBOXVHWA_CKEYCAPS_DESTOVERLAYONEACTIVE ? */
                    }
                }

                pSettings->cOverlaysSupported = pInfo1->u.out.numOverlays;

                pSettings->cFormats = 0;

                pSettings->aFormats[pSettings->cFormats] = D3DDDIFMT_X8R8G8B8;
                ++pSettings->cFormats;

                if (pInfo1->u.out.numFourCC
                        && (pInfo1->u.out.caps & VBOXVHWA_CAPS_OVERLAYFOURCC))
                {
                    VBOXVHWACMD_QUERYINFO2* pInfo2 = vboxVhwaQueryHostInfo2(pDevExt, srcId, pInfo1->u.out.numFourCC);
                    if (pInfo2)
                    {
                        for (uint32_t i = 0; i < pInfo2->numFourCC; ++i)
                        {
                            pSettings->aFormats[pSettings->cFormats] = (D3DDDIFORMAT)pInfo2->FourCC[i];
                            ++pSettings->cFormats;
                        }
                        vboxVhwaFreeHostInfo2(pDevExt, pInfo2);
                    }
                }
            }
        }
        vboxVhwaFreeHostInfo1(pDevExt, pInfo1);
    }
}
Esempio n. 26
0
/* Updates missing video mode params with current values,
 * Checks if resulting mode is liked by the host and fits into VRAM.
 * Returns TRUE if resulting mode could be used.
 */
static BOOLEAN
VBoxMPValidateVideoModeParams(PVBOXMP_DEVEXT pExt, uint32_t iDisplay, uint32_t &xres, uint32_t &yres, uint32_t &bpp)
{
    /* Make sure all important video mode values are set */
    if (VBoxMPIsStartingUp(pExt, iDisplay))
    {
        /* Use stored custom values only if nothing was read from host. */
        xres = xres ? xres:g_CustomVideoModes[iDisplay].VisScreenWidth;
        yres = yres ? yres:g_CustomVideoModes[iDisplay].VisScreenHeight;
        bpp  = bpp  ? bpp :g_CustomVideoModes[iDisplay].BitsPerPlane;
    }
    else
    {
        /* Use current values for field which weren't read from host. */
#ifdef VBOX_XPDM_MINIPORT
        xres = xres ? xres:pExt->CurrentModeWidth;
        yres = yres ? yres:pExt->CurrentModeHeight;
        bpp  = bpp  ? bpp :pExt->CurrentModeBPP;
#else
        PVBOXWDDM_ALLOC_DATA pAllocData = pExt->aSources[iDisplay].pPrimaryAllocation ?
                  &pExt->aSources[iDisplay].pPrimaryAllocation->AllocData
                : &pExt->aSources[iDisplay].AllocData;
        xres = xres ? xres:pAllocData->SurfDesc.width;
        yres = yres ? yres:pAllocData->SurfDesc.height;
        /* VBox WDDM driver does not allow 24 modes since OS could choose the 24bit mode as default in that case,
         * the pExt->aSources[iDisplay].AllocData.SurfDesc.bpp could be initially 24 though,
         * i.e. when driver occurs the current mode on driver load via DxgkCbAcquirePostDisplayOwnership
         * and until driver reports the supported modes
         * This is true for Win8 Display-Only driver currently since DxgkCbAcquirePostDisplayOwnership is only used by it
         *
         * This is why we need to adjust the current mode bpp to the value we actually report as supported */
        bpp  = bpp  ? bpp : VBoxMPAdjustBpp(pAllocData->SurfDesc.bpp);
#endif
    }

    /* Round down width to be a multiple of 8 if necessary */
    if (!VBoxCommonFromDeviceExt(pExt)->fAnyX)
    {
        xres &= 0xFFF8;
    }

    /* We always need bpp to be set */
    if (!bpp)
    {
        bpp=32;
    }

    if (!VBoxMPValidateVideoModeParamsGuest(pExt, iDisplay, xres, yres, bpp))
    {
        WARN(("GUEST does not like special mode %dx%d:%d for display %d", xres, yres, bpp, iDisplay));
        return FALSE;
    }

    /* Check if host likes this mode */
    if (!VBoxLikesVideoMode(iDisplay, xres, yres, bpp))
    {
        WARN_NOBP(("HOST does not like special mode %dx%d:%d for display %d", xres, yres, bpp, iDisplay));
        return FALSE;
    }

#ifdef VBOX_XPDM_MINIPORT
    ULONG vramSize = pExt->pPrimary->u.primary.ulMaxFrameBufferSize;
#else
    ULONG vramSize = vboxWddmVramCpuVisibleSegmentSize(pExt);
    vramSize /= pExt->u.primary.commonInfo.cDisplays;
# ifdef VBOX_WDDM_WIN8
    if (!g_VBoxDisplayOnly)
# endif
    {
        /* at least two surfaces will be needed: primary & shadow */
        vramSize /= 2;
    }
    vramSize &= ~PAGE_OFFSET_MASK;
#endif

    /* Check that values are valid and mode fits into VRAM */
    if (!xres || !yres
        || !((bpp == 16)
#ifdef VBOX_WITH_8BPP_MODES
             || (bpp == 8)
#endif
             || (bpp == 24)
             || (bpp == 32)))
    {
        LOG(("invalid params for special mode %dx%d:%d", xres, yres, bpp));
        return FALSE;
    }



    if ((xres * yres * (bpp / 8) >= vramSize))
    {
        /* Store values of last reported release log message to avoid log flooding. */
        static uint32_t s_xresNoVRAM=0, s_yresNoVRAM=0, s_bppNoVRAM=0;

        LOG(("not enough VRAM for video mode %dx%dx%dbpp. Available: %d bytes. Required: more than %d bytes.",
             xres, yres, bpp, vramSize, xres * yres * (bpp / 8)));

        s_xresNoVRAM = xres;
        s_yresNoVRAM = yres;
        s_bppNoVRAM = bpp;

        return FALSE;
    }

    return TRUE;
}
Esempio n. 27
0
void VBoxMPCmnInitCustomVideoModes(PVBOXMP_DEVEXT pExt)
{
    VBOXMPCMNREGISTRY Registry;
    VP_STATUS rc;
    int iMode;

    LOGF_ENTER();

    rc = VBoxMPCmnRegInit(pExt, &Registry);
    VBOXMP_WARN_VPS(rc);

    /* Initialize all custom modes to the 800x600x32 */
    VBoxFillVidModeInfo(&g_CustomVideoModes[0], 800, 600, 32, 0, 0);
    for (iMode=1; iMode<RT_ELEMENTS(g_CustomVideoModes); ++iMode)
    {
        g_CustomVideoModes[iMode] = g_CustomVideoModes[0];
    }

    /* Read stored custom resolution info from registry */
    for (iMode=0; iMode<VBoxCommonFromDeviceExt(pExt)->cDisplays; ++iMode)
    {
        uint32_t CustomXRes = 0, CustomYRes = 0, CustomBPP = 0;

        if (iMode==0)
        {
            /*First name without a suffix*/
            rc = VBoxMPCmnRegQueryDword(Registry, L"CustomXRes", &CustomXRes);
            VBOXMP_WARN_VPS_NOBP(rc);
            rc = VBoxMPCmnRegQueryDword(Registry, L"CustomYRes", &CustomYRes);
            VBOXMP_WARN_VPS_NOBP(rc);
            rc = VBoxMPCmnRegQueryDword(Registry, L"CustomBPP", &CustomBPP);
            VBOXMP_WARN_VPS_NOBP(rc);
        }
        else
        {
            wchar_t keyname[32];
            swprintf(keyname, L"CustomXRes%d", iMode);
            rc = VBoxMPCmnRegQueryDword(Registry, keyname, &CustomXRes);
            VBOXMP_WARN_VPS_NOBP(rc);
            swprintf(keyname, L"CustomYRes%d", iMode);
            rc = VBoxMPCmnRegQueryDword(Registry, keyname, &CustomYRes);
            VBOXMP_WARN_VPS_NOBP(rc);
            swprintf(keyname, L"CustomBPP%d", iMode);
            rc = VBoxMPCmnRegQueryDword(Registry, keyname, &CustomBPP);
            VBOXMP_WARN_VPS_NOBP(rc);
        }

        LOG(("got stored custom resolution[%d] %dx%dx%d", iMode, CustomXRes, CustomYRes, CustomBPP));

        if (CustomXRes || CustomYRes || CustomBPP)
        {
            if (CustomXRes == 0)
            {
                CustomXRes = g_CustomVideoModes[iMode].VisScreenWidth;
            }
            if (CustomYRes == 0)
            {
                CustomYRes = g_CustomVideoModes[iMode].VisScreenHeight;
            }
            if (CustomBPP == 0)
            {
                CustomBPP = g_CustomVideoModes[iMode].BitsPerPlane;
            }

            if (VBoxMPValidateVideoModeParamsGuest(pExt, iMode, CustomXRes, CustomYRes, CustomBPP))
            {
                VBoxFillVidModeInfo(&g_CustomVideoModes[iMode], CustomXRes, CustomYRes, CustomBPP, 0, 0);
            }
        }
    }

    rc = VBoxMPCmnRegFini(Registry);
    VBOXMP_WARN_VPS(rc);
    LOGF_LEAVE();
}
static VBOXVIDEOOFFSET vboxMpCrShgsmiBufferOffset(PVBOXMP_DEVEXT pDevExt, void RT_UNTRUSTED_VOLATILE_HOST *pvBuffer)
{
    return (VBOXVIDEOOFFSET)HGSMIPointerToOffset(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx.Heap.area, pvBuffer);
}
/* Checks if we have a device supported by our driver and initialize
 * our driver/card specific information.
 * In particular we obtain VM monitors configuration and configure related structures.
 */
static VP_STATUS
VBoxDrvFindAdapter(IN PVOID HwDeviceExtension, IN PVOID HwContext, IN PWSTR ArgumentString,
                   IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo, OUT PUCHAR Again)
{
    RT_NOREF(HwContext,  ArgumentString, Again);
    PVBOXMP_DEVEXT pExt = (PVBOXMP_DEVEXT) HwDeviceExtension;
    VP_STATUS rc;
    USHORT DispiId;
    ULONG cbVRAM = VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES;
    PHYSICAL_ADDRESS phVRAM = {0};
    ULONG ulApertureSize = 0;

    PAGED_CODE();
    LOGF_ENTER();

    /* Init video port api */
    VBoxSetupVideoPortAPI(pExt, ConfigInfo);

    VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
    VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID2);
    DispiId = VideoPortReadPortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA);

    if (DispiId != VBE_DISPI_ID2)
    {
        WARN(("VBE card not found, returning ERROR_DEV_NOT_EXIST"));
        return ERROR_DEV_NOT_EXIST;
    }
    LOG(("found the VBE card"));

    /*
     * Query the adapter's memory size. It's a bit of a hack, we just read
     * an ULONG from the data port without setting an index before.
     */
    cbVRAM = VideoPortReadPortUlong((PULONG)VBE_DISPI_IOPORT_DATA);

    /* Write hw information to registry, so that it's visible in windows property dialog */
    rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.ChipType",
                                        g_wszVBoxChipType, sizeof(g_wszVBoxChipType));
    VBOXMP_WARN_VPS(rc);
    rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.DacType",
                                        g_wszVBoxDACType, sizeof(g_wszVBoxDACType));
    VBOXMP_WARN_VPS(rc);
    rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.MemorySize",
                                        &cbVRAM, sizeof(ULONG));
    VBOXMP_WARN_VPS(rc);
    rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.AdapterString",
                                        g_wszVBoxAdapterString, sizeof(g_wszVBoxAdapterString));
    VBOXMP_WARN_VPS(rc);
    rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.BiosString",
                                        g_wszVBoxBiosString, sizeof(g_wszVBoxBiosString));
    VBOXMP_WARN_VPS(rc);

    /* Call VideoPortGetAccessRanges to ensure interrupt info in ConfigInfo gets set up
     * and to get LFB aperture data.
     */
    {
        VIDEO_ACCESS_RANGE tmpRanges[4];
        ULONG slot = 0;

        VideoPortZeroMemory(tmpRanges, sizeof(tmpRanges));

        if (VBoxQueryWinVersion(NULL) == WINVERSION_NT4)
        {
            /* NT crashes if either of 'vendorId, 'deviceId' or 'slot' parameters is NULL,
             * and needs PCI ids for a successful VideoPortGetAccessRanges call.
             */
            ULONG vendorId = 0x80EE;
            ULONG deviceId = 0xBEEF;
            rc = VideoPortGetAccessRanges(pExt, 0, NULL, RT_ELEMENTS(tmpRanges), tmpRanges,
                                          &vendorId, &deviceId, &slot);
        }
        else
        {
            rc = VideoPortGetAccessRanges(pExt, 0, NULL, RT_ELEMENTS(tmpRanges), tmpRanges, NULL, NULL, &slot);
        }
        VBOXMP_WARN_VPS(rc);
        if (rc != NO_ERROR) {
            return rc;
        }

        /* The first non-IO range is the framebuffer. We require that information. */
        for (int iRange = 0; iRange < RT_ELEMENTS(tmpRanges); ++iRange)
        {
            if (!tmpRanges[iRange].RangeInIoSpace)
            {
                phVRAM = tmpRanges[iRange].RangeStart;
                ulApertureSize = tmpRanges[iRange].RangeLength;
                break;
            }
        }
    }

    /* Initialize VBoxGuest library, which is used for requests which go through VMMDev. */
    rc = VbglR0InitClient();
    VBOXMP_WARN_VPS(rc);

    /* Preinitialize the primary extension. */
    pExt->pNext                   = NULL;
    pExt->pPrimary                = pExt;
    pExt->iDevice                 = 0;
    pExt->ulFrameBufferOffset     = 0;
    pExt->ulFrameBufferSize       = 0;
    pExt->u.primary.ulVbvaEnabled = 0;
    VideoPortZeroMemory(&pExt->areaDisplay, sizeof(HGSMIAREA));

    /* Guest supports only HGSMI, the old VBVA via VMMDev is not supported. Old
     * code will be ifdef'ed and later removed.
     * The host will however support both old and new interface to keep compatibility
     * with old guest additions.
     */
    VBoxSetupDisplaysHGSMI(&pExt->u.primary.commonInfo, phVRAM, ulApertureSize, cbVRAM, 0);

    /* Check if the chip restricts horizontal resolution or not.
     * Must be done after VBoxSetupDisplaysHGSMI, because it initializes the common structure.
     */
    VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
    VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID_ANYX);
    DispiId = VideoPortReadPortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA);

    if (DispiId == VBE_DISPI_ID_ANYX)
        VBoxCommonFromDeviceExt(pExt)->fAnyX = TRUE;
    else
        VBoxCommonFromDeviceExt(pExt)->fAnyX = FALSE;

    if (pExt->u.primary.commonInfo.bHGSMI)
    {
        LOGREL(("using HGSMI"));
        VBoxCreateDisplays(pExt, ConfigInfo);
    }

    /** @todo pretend success to make the driver work. */
    rc = NO_ERROR;

    LOGF_LEAVE();
    VBOXMP_WARN_VPS(rc);
    return rc;
}
Esempio n. 30
0
/* Helper function to dynamically build our table of standard video
 * modes. We take the amount of VRAM and create modes with standard
 * geometries until we've either reached the maximum number of modes
 * or the available VRAM does not allow for additional modes.
 * We also check registry for manually added video modes.
 * Returns number of modes added to the table.
 */
static uint32_t
VBoxMPFillModesTable(PVBOXMP_DEVEXT pExt, int iDisplay, PVIDEO_MODE_INFORMATION pModesTable, size_t tableSize,
                     int32_t *pPrefModeIdx)
{
    /* the resolution matrix */
    struct
    {
        uint16_t xRes;
        uint16_t yRes;
    } resolutionMatrix[] =
    {
        /* standard modes */
        { 640,   480 },
        { 800,   600 },
        { 1024,  768 },
        { 1152,  864 },
        { 1280,  960 },
        { 1280, 1024 },
        { 1400, 1050 },
        { 1600, 1200 },
        { 1920, 1440 },
#ifndef VBOX_WITH_WDDM
        /* multi screen modes with 1280x1024 */
        { 2560, 1024 },
        { 3840, 1024 },
        { 5120, 1024 },
        /* multi screen modes with 1600x1200 */
        { 3200, 1200 },
        { 4800, 1200 },
        { 6400, 1200 },
#endif
    };

#ifdef VBOX_XPDM_MINIPORT
    ULONG vramSize = pExt->pPrimary->u.primary.ulMaxFrameBufferSize;
#else
    ULONG vramSize = vboxWddmVramCpuVisibleSegmentSize(pExt);
    vramSize /= pExt->u.primary.commonInfo.cDisplays;
# ifdef VBOX_WDDM_WIN8
    if (!g_VBoxDisplayOnly)
# endif
    {
        /* at least two surfaces will be needed: primary & shadow */
        vramSize /= 2;
    }
    vramSize &= ~PAGE_OFFSET_MASK;
#endif

    uint32_t iMode=0, iPrefIdx=0;
    /* there are 4 color depths: 8, 16, 24 and 32bpp and we reserve 50% of the modes for other sources */
    size_t   maxModesPerColorDepth = VBOXMP_MAX_VIDEO_MODES / 2 / 4;

    /* Always add 800x600 video modes. Windows XP+ needs at least 800x600 resolution
     * and fallbacks to 800x600x4bpp VGA mode if the driver did not report suitable modes.
     * This resolution could be rejected by a low resolution host (netbooks, etc).
     */
#ifdef VBOX_WITH_8BPP_MODES
    int bytesPerPixel=1;
#else
    int bytesPerPixel=2;
#endif
    for (; bytesPerPixel<=4; bytesPerPixel++)
    {
        int bitsPerPixel = 8*bytesPerPixel;

        if (800*600*bytesPerPixel > (LONG)vramSize)
        {
            /* we don't have enough VRAM for this mode */
            continue;
        }

        if (!VBoxMPValidateVideoModeParamsGuest(pExt, iMode, 800, 600, bitsPerPixel))
            continue;

        VBoxFillVidModeInfo(&pModesTable[iMode], 800, 600, bitsPerPixel, iMode+1, 0);

        if (32==bitsPerPixel)
        {
            iPrefIdx = iMode;
        }
        ++iMode;
    }

    /* Query yoffset from the host */
    ULONG yOffset = VBoxGetHeightReduction();

    /* Iterate through our static resolution table and add supported video modes for different bpp's */
#ifdef VBOX_WITH_8BPP_MODES
    bytesPerPixel=1;
#else
    bytesPerPixel=2;
#endif
    for (; bytesPerPixel<=4; bytesPerPixel++)
    {
        int bitsPerPixel = 8*bytesPerPixel;
        size_t cAdded, resIndex;

        for (cAdded=0, resIndex=0; resIndex<RT_ELEMENTS(resolutionMatrix) && cAdded<maxModesPerColorDepth; resIndex++)
        {
            if (resolutionMatrix[resIndex].xRes * resolutionMatrix[resIndex].yRes * bytesPerPixel > (LONG)vramSize)
            {
                /* we don't have enough VRAM for this mode */
                continue;
            }

            if (yOffset == 0 && resolutionMatrix[resIndex].xRes == 800 && resolutionMatrix[resIndex].yRes == 600)
            {
                /* this mode was already added */
                continue;
            }

            if (
#ifdef VBOX_WDDM_MINIPORT
                    /* 1024x768 resolution is a minimal resolutions for win8 to make most metro apps run.
                     * For small host display resolutions, host will dislike the mode 1024x768 and above
                     * if the framebuffer window requires scrolling to fit the guest resolution.
                     * So add 1024x768 resolution for win8 guest to allow user switch to it */
                       (   (VBoxQueryWinVersion() != WIN8 && VBoxQueryWinVersion() != WIN81)
                        || resolutionMatrix[resIndex].xRes != 1024
                        || resolutionMatrix[resIndex].yRes != 768)
                    &&
#endif
                       !VBoxLikesVideoMode(iDisplay, resolutionMatrix[resIndex].xRes,
                                           resolutionMatrix[resIndex].yRes - yOffset, bitsPerPixel))
            {
                /* host doesn't like this mode */
                continue;
            }

            if (!VBoxMPValidateVideoModeParamsGuest(pExt, iDisplay, resolutionMatrix[resIndex].xRes, resolutionMatrix[resIndex].yRes, bitsPerPixel))
            {
                /* guest does not like this mode */
                continue;
            }

            /* Sanity check, we shouldn't ever get here */
            if (iMode >= tableSize)
            {
                WARN(("video modes table overflow!"));
                break;
            }

            VBoxFillVidModeInfo(&pModesTable[iMode], resolutionMatrix[resIndex].xRes, resolutionMatrix[resIndex].yRes, bitsPerPixel, iMode+1, yOffset);
            ++iMode;
            ++cAdded;
        }
    }

    /* Check registry for manually added modes, up to 128 entries is supported
     * Give up on the first error encountered.
     */
    VBOXMPCMNREGISTRY Registry;
    int fPrefSet=0;
    VP_STATUS rc;

    rc = VBoxMPCmnRegInit(pExt, &Registry);
    VBOXMP_WARN_VPS(rc);

    for (int curKey=0; curKey<128; curKey++)
    {
        if (iMode>=tableSize)
        {
            WARN(("ignoring possible custom mode(s), table is full!"));
            break;
        }

        wchar_t keyname[24];
        uint32_t xres, yres, bpp = 0;

        swprintf(keyname, L"CustomMode%dWidth", curKey);
        rc = VBoxMPCmnRegQueryDword(Registry, keyname, &xres);
        VBOXMP_CHECK_VPS_BREAK(rc);

        swprintf(keyname, L"CustomMode%dHeight", curKey);
        rc = VBoxMPCmnRegQueryDword(Registry, keyname, &yres);
        VBOXMP_CHECK_VPS_BREAK(rc);

        swprintf(keyname, L"CustomMode%dBPP", curKey);
        rc = VBoxMPCmnRegQueryDword(Registry, keyname, &bpp);
        VBOXMP_CHECK_VPS_BREAK(rc);

        LOG(("got custom mode[%u]=%ux%u:%u", curKey, xres, yres, bpp));

        /* round down width to be a multiple of 8 if necessary */
        if (!VBoxCommonFromDeviceExt(pExt)->fAnyX)
        {
            xres &= 0xFFF8;
        }

        if (   (xres > (1 << 16))
            || (yres > (1 << 16))
            || (   (bpp != 16)
                && (bpp != 24)
                && (bpp != 32)))
        {
            /* incorrect values */
            break;
        }

        /* does it fit within our VRAM? */
        if (xres * yres * (bpp / 8) > vramSize)
        {
            /* we don't have enough VRAM for this mode */
            break;
        }

        if (!VBoxLikesVideoMode(iDisplay, xres, yres, bpp))
        {
            /* host doesn't like this mode */
            break;
        }

        if (!VBoxMPValidateVideoModeParamsGuest(pExt, iDisplay, xres, yres, bpp))
        {
            /* guest does not like this mode */
            continue;
        }

        LOG(("adding video mode from registry."));

        VBoxFillVidModeInfo(&pModesTable[iMode], xres, yres, bpp, iMode+1, yOffset);

        if (!fPrefSet)
        {
            fPrefSet = 1;
            iPrefIdx = iMode;
        }
#ifdef VBOX_WDDM_MINIPORT
        /*check if the same mode has been added to the table already*/
        int foundIdx = VBoxMPFindVideoMode(pModesTable, iMode, &pModesTable[iMode]);

        if (foundIdx>=0)
        {
            if (iPrefIdx==iMode)
            {
                iPrefIdx=foundIdx;
            }
        }
        else
#endif
        {
            ++iMode;
        }
    }

    rc = VBoxMPCmnRegFini(Registry);
    VBOXMP_WARN_VPS(rc);

    if (pPrefModeIdx)
    {
        *pPrefModeIdx = iPrefIdx;
    }

    return iMode;
}