VOID APIENTRY VBoxDispDrvDisableSurface(DHPDEV dhpdev) { PVBOXDISPDEV pDev = (PVBOXDISPDEV)dhpdev; LOGF_ENTER(); if (pDev->surface.hSurface) { EngDeleteSurface(pDev->surface.hSurface); pDev->surface.hSurface = NULL; } if (pDev->surface.psoBitmap) { Assert(pDev->surface.hBitmap); EngUnlockSurface(pDev->surface.psoBitmap); pDev->surface.psoBitmap = NULL; } if (pDev->surface.hBitmap) { EngDeleteSurface((HSURF) pDev->surface.hBitmap); pDev->surface.hBitmap = NULL; } int rc; rc = VBoxDispMPUnmapMemory(pDev); VBOX_WARNRC(rc); LOGF_LEAVE(); }
void VBoxDispVHWAInit(PVBOXDISPDEV pDev) { VHWAQUERYINFO info; int rc; rc = VBoxDispMPVHWAQueryInfo(pDev->hDriver, &info); VBOX_WARNRC(rc); if (RT_SUCCESS(rc)) { pDev->vhwa.offVramBase = info.offVramBase; } }
ULONG APIENTRY VBoxDispDrvEscape(SURFOBJ *pso, ULONG iEsc, ULONG cjIn, PVOID pvIn, ULONG cjOut, PVOID pvOut) { PVBOXDISPDEV pDev = (PVBOXDISPDEV)pso->dhpdev; LOGF_ENTER(); switch (iEsc) { #ifdef VBOX_WITH_CROGL case OPENGL_GETINFO: { if (pvOut && cjOut >= sizeof(OPENGL_INFO)) { POPENGL_INFO pInfo = (POPENGL_INFO)pvOut; pInfo->dwVersion = 2; pInfo->dwDriverVersion = 1; pInfo->szDriverName[0] = 'V'; pInfo->szDriverName[1] = 'B'; pInfo->szDriverName[2] = 'o'; pInfo->szDriverName[3] = 'x'; pInfo->szDriverName[4] = 'O'; pInfo->szDriverName[5] = 'G'; pInfo->szDriverName[6] = 'L'; pInfo->szDriverName[7] = 0; LOG(("OPENGL_GETINFO ok")); return cjOut; } else { WARN(("OPENGL_GETINFO invalid parms")); return 0; } } case QUERYESCSUPPORT: { if (pvIn && cjIn == sizeof(DWORD)) { DWORD nEscapeQuery = *(DWORD *)pvIn; if (nEscapeQuery==OPENGL_GETINFO) { LOG(("QUERYESCSUPPORT OPENGL_GETINFO")); return 1; } else { LOG(("QUERYESCSUPPORT unsupported query %d", nEscapeQuery)); return 0; } } else { WARN(("QUERYESCSUPPORT invalid parms")); return 0; } } #endif case VBOXESC_ISVRDPACTIVE: { if (pDev && pDev->vbvaCtx.pVBVA && pDev->vbvaCtx.pVBVA->hostFlags.u32HostEvents&VBVA_F_MODE_VRDP) { LOGF(("VBOXESC_ISVRDPACTIVE: 1")); return 1; } LOGF(("VBOXESC_ISVRDPACTIVE: 0")); return 0; } case VBOXESC_SETVISIBLEREGION: { LOGF(("VBOXESC_SETVISIBLEREGION")); LPRGNDATA lpRgnData = (LPRGNDATA)pvIn; DWORD cRects; if ( cjIn >= sizeof(RGNDATAHEADER) && pvIn && lpRgnData->rdh.dwSize == sizeof(RGNDATAHEADER) && lpRgnData->rdh.iType == RDH_RECTANGLES && (cRects = lpRgnData->rdh.nCount) <= _1M && cjIn == cRects * (uint64_t)sizeof(RECT) + sizeof(RGNDATAHEADER)) { /** @todo this whole conversion thing could maybe be skipped * since RTRECT matches the RECT layout. */ #if 0 AssertCompile(sizeof(RTRECT) == sizeof(RECT)); AssertCompileMembersSameSizeAndOffset(RTRECT, xLeft, RECT, left); AssertCompileMembersSameSizeAndOffset(RTRECT, xBottom, RECT, bottom); AssertCompileMembersSameSizeAndOffset(RTRECT, xRight, RECT, right); AssertCompileMembersSameSizeAndOffset(RTRECT, xTop, RECT, top); rc = VBoxDispMPSetVisibleRegion(pDev->hDriver, (PRTRECT)&lpRgnData->Buffer[0], cRects); VBOX_WARNRC(rc); #else DWORD i; PRTRECT pRTRect; int rc; RECT *pRect = (RECT *)&lpRgnData->Buffer; pRTRect = (PRTRECT) EngAllocMem(0, cRects*sizeof(RTRECT), MEM_ALLOC_TAG); if (!pRTRect) { WARN(("failed to allocate %d bytes", cRects*sizeof(RTRECT))); break; } for (i = 0; i < cRects; ++i) { LOG(("New visible rectangle (%d,%d) (%d,%d)", pRect[i].left, pRect[i].bottom, pRect[i].right, pRect[i].top)); pRTRect[i].xLeft = pRect[i].left; pRTRect[i].yBottom = pRect[i].bottom; pRTRect[i].xRight = pRect[i].right; pRTRect[i].yTop = pRect[i].top; } rc = VBoxDispMPSetVisibleRegion(pDev->hDriver, pRTRect, cRects); VBOX_WARNRC(rc); EngFreeMem(pRTRect); #endif if (RT_SUCCESS(rc)) { LOGF_LEAVE(); return 1; } } else { if (pvIn) { WARN(("check failed rdh.dwSize=%x iType=%d size=%d expected size=%d", lpRgnData->rdh.dwSize, lpRgnData->rdh.iType, cjIn, lpRgnData->rdh.nCount * sizeof(RECT) + sizeof(RGNDATAHEADER))); } } break; } default: { LOG(("unsupported iEsc %#x", iEsc)); } } LOGF_LEAVE(); return 0; }
/* First function which is called after entry point, provides info about device to GDI. * Returns pointer to our driver private info structure which would be passed by GDI to our other callbacks. */ DHPDEV APIENTRY VBoxDispDrvEnablePDEV(DEVMODEW *pdm, LPWSTR pwszLogAddress, ULONG cPat, HSURF *phsurfPatterns, ULONG cjCaps, ULONG *pdevcaps, ULONG cjDevInfo, DEVINFO *pdi, HDEV hdev, PWSTR pwszDeviceName, HANDLE hDriver) { PVBOXDISPDEV pDev = NULL; GDIINFO gdiInfo; DEVINFO devInfo; int rc; /* Next 3 are only used for printer drivers */ NOREF(pwszLogAddress); NOREF(cPat); NOREF(phsurfPatterns); NOREF(pwszDeviceName); LOGF_ENTER(); pDev = (PVBOXDISPDEV) EngAllocMem(FL_ZERO_MEMORY, sizeof(VBOXDISPDEV), MEM_ALLOC_TAG); if (!pDev) { WARN(("EngAllocMem failed!\n")); return NULL; } pDev->hDriver = hDriver; /* Initialize device structure and query miniport to fill device and gdi infos */ rc = VBoxDispInitDevice(pDev, pdm, &gdiInfo, &devInfo); if (RT_FAILURE(rc)) { VBOX_WARNRC(rc); EngFreeMem(pDev); return NULL; } /* Initialize mouse pointer caps */ rc = VBoxDispInitPointerCaps(pDev, &devInfo); if (RT_FAILURE(rc)) { VBOX_WARNRC(rc); } /* Initialize palette */ rc = VBoxDispInitPalette(pDev, &devInfo); if (RT_FAILURE(rc)) { VBOX_WARNRC(rc); EngFreeMem(pDev); return NULL; } if(g_EngineVersionDDI >= DDI_DRIVER_VERSION_NT5) { devInfo.flGraphicsCaps2 |= GCAPS2_RESERVED1; } /* Copy gathered info to supplied buffers */ memcpy(pdevcaps, &gdiInfo, min(sizeof(GDIINFO), cjCaps)); memcpy(pdi, &devInfo, min(sizeof(DEVINFO), cjDevInfo)); LOGF_LEAVE(); return (DHPDEV)pDev; }
/* Called to get supported DirectDraw caps */ BOOL APIENTRY VBoxDispDrvGetDirectDrawInfo(DHPDEV dhpdev, DD_HALINFO *pHalInfo, DWORD *pdwNumHeaps, VIDEOMEMORY *pvmList, DWORD *pdwNumFourCCCodes, DWORD *pdwFourCC) { PVBOXDISPDEV pDev = (PVBOXDISPDEV)dhpdev; LOGF_ENTER(); VBoxDispGetDDHalInfo(pDev, pHalInfo); #ifdef VBOX_WITH_VIDEOHWACCEL int rc; if (!pvmList && !pdwFourCC) /* first call */ { rc = VBoxDispVHWAInitHostInfo1(pDev); VBOX_WARNRC_NOBP(rc); } if (pDev->vhwa.bEnabled) { rc = VBoxDispVHWAUpdateDDHalInfo(pDev, pHalInfo); VBOX_WARNRC(rc); pDev->vhwa.bEnabled = RT_SUCCESS(rc); } #endif /* we could only have 1 heap, so it's not really a list */ if (pvmList && pDev->layout.cbDDrawHeap>0) { pvmList->dwFlags = VIDMEM_ISLINEAR; pvmList->fpStart = pDev->layout.offDDrawHeap; pvmList->fpEnd = pDev->layout.offDDrawHeap + pDev->layout.cbDDrawHeap - 1; #ifdef VBOX_WITH_VIDEOHWACCEL if (pDev->vhwa.bEnabled) { pvmList->ddsCaps.dwCaps = 0; } else #endif { pvmList->ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; } pvmList->ddsCapsAlt.dwCaps = 0; } /* Always report number of heaps and supported FourCC's*/ *pdwNumHeaps = (pDev->layout.cbDDrawHeap>0) ? 1:0; #ifndef VBOX_WITH_VIDEOHWACCEL *pdwNumFourCCCodes = 0; #else if (pDev->vhwa.bEnabled) { *pdwNumFourCCCodes = pDev->vhwa.numFourCC; if (pdwFourCC && pDev->vhwa.numFourCC) { rc = VBoxDispVHWAInitHostInfo2(pDev, pdwFourCC); VBOX_WARNRC(rc); if (RT_FAILURE(rc)) { *pdwNumFourCCCodes = 0; pDev->vhwa.numFourCC = 0; } } pHalInfo->GetDriverInfo = VBoxDispDDGetDriverInfo; pHalInfo->dwFlags |= DDHALINFO_GETDRIVERINFOSET; } #endif LOGF_LEAVE(); return TRUE; }
/* Lock specified area of surface */ DWORD APIENTRY VBoxDispDDLock(PDD_LOCKDATA lpLock) { PVBOXDISPDEV pDev = (PVBOXDISPDEV) lpLock->lpDD->dhpdev; LOGF_ENTER(); DD_SURFACE_LOCAL* pSurf = lpLock->lpDDSurface; lpLock->ddRVal = DD_OK; #if 0 #ifdef VBOX_WITH_VIDEOHWACCEL if(pDev->vhwa.bEnabled) { PVBOXVHWASURFDESC pDesc = (PVBOXVHWASURFDESC) pSurf->lpGbl->dwReserved1; RECTL tmpRect, *pRect; if (!pDesc) { WARN(("!pDesc, memory overwrite somewhere?")); lpLock->ddRVal = DDERR_GENERIC; return DDHAL_DRIVER_HANDLED; } /* Check if host is still processing drawing commands */ if (ASMAtomicUoReadU32(&pDesc->cPendingBltsSrc) || ASMAtomicUoReadU32(&pDesc->cPendingFlipsCurr) || ASMAtomicUoReadU32(&pDesc->cPendingBltsDst) || ASMAtomicUoReadU32(&pDesc->cPendingFlipsTarg)) { VBoxDispVHWACommandCheckHostCmds(pDev); if(ASMAtomicUoReadU32(&pDesc->cPendingBltsSrc) || ASMAtomicUoReadU32(&pDesc->cPendingFlipsCurr) || ASMAtomicUoReadU32(&pDesc->cPendingBltsDst) || ASMAtomicUoReadU32(&pDesc->cPendingFlipsTarg)) { lpLock->ddRVal = DDERR_WASSTILLDRAWING; return DDHAL_DRIVER_HANDLED; } } if (lpLock->bHasRect) { pRect = &lpLock->rArea; } else { tmpRect.left = 0; tmpRect.top = 0; tmpRect.right = pSurf->lpGbl->wWidth-1; tmpRect.bottom = pSurf->lpGbl->wHeight-1; pRect = &tmpRect; } if (lpLock->dwFlags & DDLOCK_DISCARDCONTENTS) { VBoxDispVHWARegionTrySubstitute(&pDesc->NonupdatedMemRegion, pRect); VBoxDispVHWARegionAdd(&pDesc->UpdatedMemRegion, pRect); } else if (!VBoxDispVHWARegionIntersects(&pDesc->NonupdatedMemRegion, pRect)) { VBoxDispVHWARegionAdd(&pDesc->UpdatedMemRegion, pRect); } else { VBOXVHWACMD *pCmd; pCmd = VBoxDispVHWACommandCreate(pDev, VBOXVHWACMD_TYPE_SURF_LOCK, sizeof(VBOXVHWACMD_SURF_LOCK)); if (pCmd) { VBOXVHWACMD_SURF_LOCK *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_LOCK); memset(pBody, 0, sizeof(VBOXVHWACMD_SURF_LOCK)); pBody->u.in.offSurface = VBoxDispVHWAVramOffsetFromPDEV(pDev, pSurf->lpGbl->fpVidMem); VBoxDispVHWAFromRECTL(&pBody->u.in.rect, &pDesc->NonupdatedMemRegion.Rect); pBody->u.in.rectValid = 1; pBody->u.in.hSurf = pDesc->hHostHandle; /* wait for the surface to be locked and memory buffer updated */ VBoxDispVHWACommandSubmit(pDev, pCmd); VBOX_WARNRC(pCmd->rc); VBoxDispVHWACommandRelease(pDev, pCmd); VBoxDispVHWARegionClear(&pDesc->NonupdatedMemRegion); } else { WARN(("VBoxDispVHWACommandCreate failed!")); lpLock->ddRVal = DDERR_GENERIC; } } return DDHAL_DRIVER_NOTHANDLED; } #endif /*VBOX_WITH_VIDEOHWACCEL*/ #endif /* We only care about primary surface as we'd have to report dirty rectangles to the host in the DDUnlock*/ if (pSurf->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) { pDev->ddpsLock.bLocked = TRUE; if (lpLock->bHasRect) { pDev->ddpsLock.rect = lpLock->rArea; } else { pDev->ddpsLock.rect.left = 0; pDev->ddpsLock.rect.top = 0; pDev->ddpsLock.rect.right = pDev->mode.ulWidth; pDev->ddpsLock.rect.bottom = pDev->mode.ulHeight; } } LOGF_LEAVE(); return DDHAL_DRIVER_NOTHANDLED; }
/* Called to create DirectDraw surface. * Note: we always return DDHAL_DRIVER_NOTHANDLED, which asks DirectDraw memory manager * to perform actual memory allocation in our DDraw heap. */ DWORD APIENTRY VBoxDispDDCreateSurface(PDD_CREATESURFACEDATA lpCreateSurface) { PVBOXDISPDEV pDev = (PVBOXDISPDEV) lpCreateSurface->lpDD->dhpdev; LOGF_ENTER(); PDD_SURFACE_LOCAL pSurf = lpCreateSurface->lplpSList[0]; if (pSurf->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) { LOG(("primary surface")); pSurf->lpGbl->fpVidMem = 0; } else { LOG(("non primary surface")); pSurf->lpGbl->fpVidMem = DDHAL_PLEASEALLOC_BLOCKSIZE; } pSurf->lpGbl->dwReserved1 = 0; #ifdef VBOX_WITH_VIDEOHWACCEL if(pDev->vhwa.bEnabled) { VBOXVHWACMD* pCmd; pCmd = VBoxDispVHWACommandCreate(pDev, VBOXVHWACMD_TYPE_SURF_CREATE, sizeof(VBOXVHWACMD_SURF_CREATE)); if (pCmd) { VBOXVHWACMD_SURF_CREATE *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_CREATE); PVBOXVHWASURFDESC pDesc; int rc; memset(pBody, 0, sizeof(VBOXVHWACMD_SURF_CREATE)); rc = VBoxDispVHWAFromDDSURFACEDESC(&pBody->SurfInfo, lpCreateSurface->lpDDSurfaceDesc); VBOX_WARNRC(rc); pBody->SurfInfo.surfCaps = VBoxDispVHWAFromDDSCAPS(pSurf->ddsCaps.dwCaps); pBody->SurfInfo.flags |= DDSD_CAPS; pBody->SurfInfo.height = pSurf->lpGbl->wHeight; pBody->SurfInfo.width = pSurf->lpGbl->wWidth; pBody->SurfInfo.flags |= DDSD_HEIGHT | DDSD_WIDTH; VBoxDispVHWAFromDDPIXELFORMAT(&pBody->SurfInfo.PixelFormat, &pSurf->lpGbl->ddpfSurface); pBody->SurfInfo.flags |= VBOXVHWA_SD_PIXELFORMAT; if (pSurf->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) { pBody->SurfInfo.offSurface = VBoxDispVHWAVramOffsetFromPDEV(pDev, 0); } else { pBody->SurfInfo.offSurface = VBOXVHWA_OFFSET64_VOID; } pDesc = VBoxDispVHWASurfDescAlloc(); if (pDesc) { VBoxDispVHWACommandSubmit(pDev, pCmd); if (RT_SUCCESS(pCmd->rc)) { uint32_t surfSizeX = pBody->SurfInfo.sizeX; uint32_t surfSizeY = pBody->SurfInfo.sizeY; pDesc->hHostHandle = pBody->SurfInfo.hSurf; if(!!(pSurf->ddsCaps.dwCaps & DDSCAPS_OVERLAY) && !!(pSurf->ddsCaps.dwCaps & DDSCAPS_VISIBLE)) { pDesc->bVisible = true; } pSurf->lpGbl->dwBlockSizeX = pBody->SurfInfo.sizeX; pSurf->lpGbl->dwBlockSizeY = pBody->SurfInfo.sizeY; pSurf->lpGbl->lPitch = pBody->SurfInfo.pitch; lpCreateSurface->lpDDSurfaceDesc->lPitch = pSurf->lpGbl->lPitch; lpCreateSurface->lpDDSurfaceDesc->dwFlags |= DDSD_PITCH; /*@todo: it's probably a memory leak, because DDDestroySurface wouldn't be called for * primary surfaces. */ pSurf->lpGbl->dwReserved1 = (ULONG_PTR)pDesc; } else { WARN(("VBoxDispVHWACommandSubmit failed with rc=%#x", rc)); VBoxDispVHWASurfDescFree(pDesc); } } else { WARN(("VBoxDispVHWASurfDescAlloc failed")); } VBoxDispVHWACommandRelease(pDev, pCmd); } else { WARN(("VBoxDispVHWACommandCreate failed")); } return DDHAL_DRIVER_NOTHANDLED; } #endif /*VBOX_WITH_VIDEOHWACCEL*/ LPDDSURFACEDESC pDesc = lpCreateSurface->lpDDSurfaceDesc; if (pDesc->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4) { pSurf->lpGbl->lPitch = RT_ALIGN_T(pSurf->lpGbl->wWidth/2, 32, LONG); } else if (pDesc->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) { pSurf->lpGbl->lPitch = RT_ALIGN_T(pSurf->lpGbl->wWidth, 32, LONG); } else { pSurf->lpGbl->lPitch = pSurf->lpGbl->wWidth*(pDesc->ddpfPixelFormat.dwRGBBitCount/8); } pSurf->lpGbl->dwBlockSizeX = pSurf->lpGbl->lPitch; pSurf->lpGbl->dwBlockSizeY = pSurf->lpGbl->wHeight; pDesc->lPitch = pSurf->lpGbl->lPitch; pDesc->dwFlags |= DDSD_PITCH; LOGF_LEAVE(); return DDHAL_DRIVER_NOTHANDLED; }