status_t device_ioctl(void* cookie, uint32 msg, void* buf, size_t len) { TRACE("device_ioctl\n"); DeviceInfo* dev = (DeviceInfo*)cookie; switch (msg) { case B_GET_ACCELERANT_SIGNATURE: strcpy((char*)buf, "vboxvideo.accelerant"); return B_OK; case VBOXVIDEO_GET_PRIVATE_DATA: return user_memcpy(buf, &dev->sharedArea, sizeof(area_id)); case VBOXVIDEO_GET_DEVICE_NAME: if (user_strlcpy((char*)buf, gDeviceInfo.name, len) < B_OK) return B_BAD_ADDRESS; else return B_OK; case VBOXVIDEO_SET_DISPLAY_MODE: { display_mode* mode = (display_mode*)buf; VBoxVideoSetModeRegisters(mode->timing.h_display, mode->timing.v_display, mode->timing.h_display, get_depth_for_color_space(mode->space), 0, 0, 0); gDeviceInfo.sharedInfo->currentMode = *mode; return B_OK; } default: return B_BAD_VALUE; } }
/* Called for IOCTL_VIDEO_SET_CURRENT_MODE. * Sets adapter video mode. */ BOOLEAN VBoxMPSetCurrentMode(PVBOXMP_DEVEXT pExt, PVIDEO_MODE pMode, PSTATUS_BLOCK pStatus) { ULONG RequestedMode; VIDEO_MODE_INFORMATION *pModeInfo; LOGF(("mode=%#x", pMode->RequestedMode)); /* Get requested mode info */ RequestedMode = pMode->RequestedMode & ~(VIDEO_MODE_NO_ZERO_MEMORY|VIDEO_MODE_MAP_MEM_LINEAR); if (RequestedMode!=pMode->RequestedMode) { WARN(("ignoring set VIDEO_MODE_NO_ZERO_MEMORY or VIDEO_MODE_MAP_MEM_LINEAR")); } pModeInfo = VBoxMPCmnGetVideoModeInfo(RequestedMode-1); if (!pModeInfo) { pStatus->Status = ERROR_INVALID_PARAMETER; return FALSE; } LOG(("screen [%d] mode %d width %d, height %d, bpp %d", pExt->iDevice, pModeInfo->ModeIndex, pModeInfo->VisScreenWidth, pModeInfo->VisScreenHeight, pModeInfo->BitsPerPlane)); /* Update device info */ pExt->CurrentMode = RequestedMode; pExt->CurrentModeWidth = pModeInfo->VisScreenWidth; pExt->CurrentModeHeight = pModeInfo->VisScreenHeight; pExt->CurrentModeBPP = pModeInfo->BitsPerPlane; if (pExt->iDevice>0) { LOG(("skipping non-primary display %d", pExt->iDevice)); return TRUE; } /* Perform actual mode switch */ VBoxVideoSetModeRegisters((USHORT)pModeInfo->VisScreenWidth, (USHORT)pModeInfo->VisScreenHeight, (USHORT)pModeInfo->VisScreenWidth, (USHORT)pModeInfo->BitsPerPlane, 0, 0, 0); /*@todo read back from port to check if mode switch was successful */ LOGF_LEAVE(); return TRUE; }
/** Set a graphics mode. Poke any required values into registers, do an HGSMI * mode set and tell the host we support advanced graphics functions. This * procedure is complicated by the fact that X.Org can implicitly disable a * screen by resizing the virtual framebuffer so that the screen is no longer * inside it. We have to spot and handle this. */ Bool VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth, unsigned cHeight, int x, int y) { VBOXPtr pVBox = VBOXGetRec(pScrn); uint32_t offStart, cwReal = cWidth; TRACE_LOG("cDisplay=%u, cWidth=%u, cHeight=%u, x=%d, y=%d, displayWidth=%d\n", cDisplay, cWidth, cHeight, x, y, pScrn->displayWidth); offStart = y * pVBox->cbLine + x * vboxBPP(pScrn) / 8; /* Deactivate the screen if the mode - specifically the virtual width - is * too large for VRAM as we sometimes have to do this - see comments in * VBOXPreInit. */ if ( offStart + pVBox->cbLine * cHeight > pVBox->cbFBMax || pVBox->cbLine * pScrn->virtualY > pVBox->cbFBMax) return FALSE; /* Deactivate the screen if it is outside of the virtual framebuffer and * clamp it to lie inside if it is partly outside. */ if (x >= pScrn->displayWidth || x + (int) cWidth <= 0) return FALSE; else cwReal = RT_MIN((int) cWidth, pScrn->displayWidth - x); TRACE_LOG("pVBox->afDisabled[%u]=%d\n", cDisplay, (int)pVBox->afDisabled[cDisplay]); if (cDisplay == 0) VBoxVideoSetModeRegisters(cwReal, cHeight, pScrn->displayWidth, vboxBPP(pScrn), 0, x, y); /* Tell the host we support graphics */ if (vbox_device_available(pVBox)) vboxEnableGraphicsCap(pVBox); if (pVBox->fHaveHGSMI) { uint16_t fFlags = VBVA_SCREEN_F_ACTIVE; fFlags |= (pVBox->afDisabled[cDisplay] ? VBVA_SCREEN_F_DISABLED : 0); VBoxHGSMIProcessDisplayInfo(&pVBox->guestCtx, cDisplay, x, y, offStart, pVBox->cbLine, cwReal, cHeight, vboxBPP(pScrn), fFlags); } return TRUE; }