9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * VBox XPDM Display driver, DirectDraw callbacks
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Copyright (C) 2011 Oracle Corporation
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * available from http://www.virtualbox.org. This file is free software;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * General Public License (GPL) as published by the Free Software
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync/* Called to check if our driver can create surface with requested attributes */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncDWORD APIENTRY VBoxDispDDCanCreateSurface(PDD_CANCREATESURFACEDATA lpCanCreateSurface)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync PVBOXDISPDEV pDev = (PVBOXDISPDEV) lpCanCreateSurface->lpDD->dhpdev;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync PDD_SURFACEDESC lpDDS = lpCanCreateSurface->lpDDSurfaceDesc;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync uint32_t unsupportedSCaps = VBoxDispVHWAUnsupportedDDSCAPS(lpDDS->ddsCaps.dwCaps);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync WARN(("unsupported ddscaps: %#x", unsupportedSCaps));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync unsupportedSCaps = VBoxDispVHWAUnsupportedDDPFS(lpDDS->ddpfPixelFormat.dwFlags);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync WARN(("unsupported pixel format: %#x", unsupportedSCaps));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync lpCanCreateSurface->ddRVal = DDERR_INVALIDPIXELFORMAT;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pCmd = VBoxDispVHWACommandCreate(pDev, VBOXVHWACMD_TYPE_SURF_CANCREATE, sizeof(VBOXVHWACMD_SURF_CANCREATE));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync VBOXVHWACMD_SURF_CANCREATE *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_CANCREATE);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync memset(pBody, 0, sizeof(VBOXVHWACMD_SURF_CANCREATE));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync rc = VBoxDispVHWAFromDDSURFACEDESC(&pBody->SurfInfo, lpDDS);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pBody->u.in.bIsDifferentPixelFormat = lpCanCreateSurface->bIsDifferentPixelFormat;
ccbb9941eeafd9ec56b8ed048910198240e6caaavboxsync WARN(("pBody->u.out.ErrInfo = %#x", pBody->u.out.ErrInfo));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync WARN(("VBoxDispVHWACommandSubmit failed with rc=%#x", rc));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync#endif /*VBOX_WITH_VIDEOHWACCEL*/
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (lpCanCreateSurface->bIsDifferentPixelFormat && (lpDDS->ddpfPixelFormat.dwFlags & DDPF_FOURCC))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync/* Called to create DirectDraw surface.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Note: we always return DDHAL_DRIVER_NOTHANDLED, which asks DirectDraw memory manager
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * to perform actual memory allocation in our DDraw heap.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncDWORD APIENTRY VBoxDispDDCreateSurface(PDD_CREATESURFACEDATA lpCreateSurface)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync PVBOXDISPDEV pDev = (PVBOXDISPDEV) lpCreateSurface->lpDD->dhpdev;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync PDD_SURFACE_LOCAL pSurf = lpCreateSurface->lplpSList[0];
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (pSurf->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pSurf->lpGbl->fpVidMem = DDHAL_PLEASEALLOC_BLOCKSIZE;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pCmd = VBoxDispVHWACommandCreate(pDev, VBOXVHWACMD_TYPE_SURF_CREATE, sizeof(VBOXVHWACMD_SURF_CREATE));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync VBOXVHWACMD_SURF_CREATE *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_CREATE);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync rc = VBoxDispVHWAFromDDSURFACEDESC(&pBody->SurfInfo, lpCreateSurface->lpDDSurfaceDesc);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pBody->SurfInfo.surfCaps = VBoxDispVHWAFromDDSCAPS(pSurf->ddsCaps.dwCaps);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync VBoxDispVHWAFromDDPIXELFORMAT(&pBody->SurfInfo.PixelFormat, &pSurf->lpGbl->ddpfSurface);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (pSurf->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pBody->SurfInfo.offSurface = VBoxDispVHWAVramOffsetFromPDEV(pDev, 0);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pBody->SurfInfo.offSurface = VBOXVHWA_OFFSET64_VOID;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pSurf->lpGbl->dwBlockSizeX = pBody->SurfInfo.sizeX;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pSurf->lpGbl->dwBlockSizeY = pBody->SurfInfo.sizeY;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync lpCreateSurface->lpDDSurfaceDesc->lPitch = pSurf->lpGbl->lPitch;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync lpCreateSurface->lpDDSurfaceDesc->dwFlags |= DDSD_PITCH;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /*@todo: it's probably a memory leak, because DDDestroySurface wouldn't be called for
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * primary surfaces.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync WARN(("VBoxDispVHWACommandSubmit failed with rc=%#x", rc));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync#endif /*VBOX_WITH_VIDEOHWACCEL*/
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync LPDDSURFACEDESC pDesc = lpCreateSurface->lpDDSurfaceDesc;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (pDesc->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pSurf->lpGbl->lPitch = RT_ALIGN_T(pSurf->lpGbl->wWidth/2, 32, LONG);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (pDesc->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pSurf->lpGbl->lPitch = RT_ALIGN_T(pSurf->lpGbl->wWidth, 32, LONG);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pSurf->lpGbl->lPitch = pSurf->lpGbl->wWidth*(pDesc->ddpfPixelFormat.dwRGBBitCount/8);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pSurf->lpGbl->dwBlockSizeY = pSurf->lpGbl->wHeight;
b0a3d0ec5780199a2f379da63c59ccf48f1a73b9vboxsync/* Called to destroy DirectDraw surface,
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * in particular we should free vhwa resources allocated on VBoxDispDDCreateSurface.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Note: we're always returning DDHAL_DRIVER_NOTHANDLED because we rely on DirectDraw memory manager.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncDWORD APIENTRY VBoxDispDDDestroySurface(PDD_DESTROYSURFACEDATA lpDestroySurface)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync PVBOXDISPDEV pDev = (PVBOXDISPDEV) lpDestroySurface->lpDD->dhpdev;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pCmd = VBoxDispVHWACommandCreate(pDev, VBOXVHWACMD_TYPE_SURF_DESTROY, sizeof(VBOXVHWACMD_SURF_DESTROY));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync VBOXVHWACMD_SURF_DESTROY *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_DESTROY);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync PVBOXVHWASURFDESC pDesc = (PVBOXVHWASURFDESC)lpDestroySurface->lpDDSurface->lpGbl->dwReserved1;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync memset(pBody, 0, sizeof(VBOXVHWACMD_SURF_DESTROY));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync lpDestroySurface->lpDDSurface->lpGbl->dwReserved1 = (ULONG_PTR)NULL;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync#endif /*VBOX_WITH_VIDEOHWACCEL*/
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync/* Called before first DDLock/after last DDUnlock to map/unmap surface memory from given process address space
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * We go easy way and map whole framebuffer and offscreen DirectDraw heap every time.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncDWORD APIENTRY VBoxDispDDMapMemory(PDD_MAPMEMORYDATA lpMapMemory)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync PVBOXDISPDEV pDev = (PVBOXDISPDEV) lpMapMemory->lpDD->dhpdev;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync smem.ViewSize = pDev->layout.offDDrawHeap + pDev->layout.cbDDrawHeap;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync rc = VBoxDispMPShareVideoMemory(pDev->hDriver, &smem, &smemInfo);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync lpMapMemory->fpProcess = (FLATPTR) smemInfo.VirtualAddress;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync smem.RequestedVirtualAddress = (PVOID) lpMapMemory->fpProcess;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync rc = VBoxDispMPUnshareVideoMemory(pDev->hDriver, &smem);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync/* Lock specified area of surface */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync PVBOXDISPDEV pDev = (PVBOXDISPDEV) lpLock->lpDD->dhpdev;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync PVBOXVHWASURFDESC pDesc = (PVBOXVHWASURFDESC) pSurf->lpGbl->dwReserved1;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* Check if host is still processing drawing commands */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync VBoxDispVHWARegionTrySubstitute(&pDesc->NonupdatedMemRegion, pRect);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync VBoxDispVHWARegionAdd(&pDesc->UpdatedMemRegion, pRect);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync else if (!VBoxDispVHWARegionIntersects(&pDesc->NonupdatedMemRegion, pRect))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync VBoxDispVHWARegionAdd(&pDesc->UpdatedMemRegion, pRect);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pCmd = VBoxDispVHWACommandCreate(pDev, VBOXVHWACMD_TYPE_SURF_LOCK, sizeof(VBOXVHWACMD_SURF_LOCK));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync VBOXVHWACMD_SURF_LOCK *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_LOCK);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pBody->u.in.offSurface = VBoxDispVHWAVramOffsetFromPDEV(pDev, pSurf->lpGbl->fpVidMem);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync VBoxDispVHWAFromRECTL(&pBody->u.in.rect, &pDesc->NonupdatedMemRegion.Rect);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* wait for the surface to be locked and memory buffer updated */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync VBoxDispVHWARegionClear(&pDesc->NonupdatedMemRegion);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync#endif /*VBOX_WITH_VIDEOHWACCEL*/
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* We only care about primary surface as we'd have to report dirty rectangles to the host in the DDUnlock*/
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (pSurf->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync/* Unlock previously locked surface */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncDWORD APIENTRY VBoxDispDDUnlock(PDD_UNLOCKDATA lpUnlock)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync PVBOXDISPDEV pDev = (PVBOXDISPDEV) lpUnlock->lpDD->dhpdev;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync PVBOXVHWASURFDESC pDesc = (PVBOXVHWASURFDESC) pSurf->lpGbl->dwReserved1;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if((pSurf->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) && pDesc->UpdatedMemRegion.bValid
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync && VBoxVBVABufferBeginUpdate(&pDev->vbvaCtx, &pDev->hgsmi.ctx))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync vbvaReportDirtyRect(pDev, &pDesc->UpdatedMemRegion.Rect);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (pDev->vbvaCtx.pVBVA->hostFlags.u32HostEvents & VBOX_VIDEO_INFO_HOST_EVENTS_F_VRDP_RESET)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pDev->vbvaCtx.pVBVA->hostFlags.u32HostEvents &= ~VBOX_VIDEO_INFO_HOST_EVENTS_F_VRDP_RESET;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (pDev->vbvaCtx.pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_VRDP)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync vrdpReportDirtyRect(pDev, &pDesc->UpdatedMemRegion.Rect);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync || ((pSurf->ddsCaps.dwCaps & DDSCAPS_OVERLAY) && pDesc->bVisible))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pCmd = VBoxDispVHWACommandCreate (pDev, VBOXVHWACMD_TYPE_SURF_UNLOCK, sizeof(VBOXVHWACMD_SURF_UNLOCK));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync VBOXVHWACMD_SURF_UNLOCK *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_UNLOCK);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync VBoxDispVHWAFromRECTL(&pBody->u.in.xUpdatedMemRect, &pDesc->UpdatedMemRegion.Rect);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync VBoxDispVHWACommandSubmitAsynchAndComplete(pDev, pCmd);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync#endif /*VBOX_WITH_VIDEOHWACCEL*/
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (pDev->hgsmi.bSupported && VBoxVBVABufferBeginUpdate(&pDev->vbvaCtx, &pDev->hgsmi.ctx))
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (pDev->vbvaCtx.pVBVA->hostFlags.u32HostEvents & VBOX_VIDEO_INFO_HOST_EVENTS_F_VRDP_RESET)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pDev->vbvaCtx.pVBVA->hostFlags.u32HostEvents &= ~VBOX_VIDEO_INFO_HOST_EVENTS_F_VRDP_RESET;