1e07dc26bSmrg/* 2e07dc26bSmrg * Copyright (C) 2006-2017 Oracle Corporation 3e07dc26bSmrg * 4e07dc26bSmrg * Permission is hereby granted, free of charge, to any person obtaining a 5e07dc26bSmrg * copy of this software and associated documentation files (the "Software"), 6e07dc26bSmrg * to deal in the Software without restriction, including without limitation 7e07dc26bSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8e07dc26bSmrg * and/or sell copies of the Software, and to permit persons to whom the 9e07dc26bSmrg * Software is furnished to do so, subject to the following conditions: 10e07dc26bSmrg * 11e07dc26bSmrg * The above copyright notice and this permission notice shall be included in 12e07dc26bSmrg * all copies or substantial portions of the Software. 13e07dc26bSmrg * 14e07dc26bSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15e07dc26bSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16e07dc26bSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17e07dc26bSmrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18e07dc26bSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19e07dc26bSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20e07dc26bSmrg * OTHER DEALINGS IN THE SOFTWARE. 21e07dc26bSmrg */ 22e07dc26bSmrg 23e07dc26bSmrg#include <VBoxVideoGuest.h> 24e07dc26bSmrg#include <VBoxVideoVBE.h> 25e07dc26bSmrg#include <HGSMIChannels.h> 26e07dc26bSmrg 27e07dc26bSmrg#ifndef VBOX_GUESTR3XF86MOD 28e07dc26bSmrg# include <VBoxVideoIPRT.h> 29e07dc26bSmrg#endif 30e07dc26bSmrg 31e07dc26bSmrg/** 32e07dc26bSmrg * Gets the count of virtual monitors attached to the guest via an HGSMI 33e07dc26bSmrg * command 34e07dc26bSmrg * 35e07dc26bSmrg * @returns the right count on success or 1 on failure. 36e07dc26bSmrg * @param pCtx the context containing the heap to use 37e07dc26bSmrg */ 38e07dc26bSmrgDECLHIDDEN(uint32_t) VBoxHGSMIGetMonitorCount(PHGSMIGUESTCOMMANDCONTEXT pCtx) 39e07dc26bSmrg{ 40e07dc26bSmrg /* Query the configured number of displays. */ 41e07dc26bSmrg uint32_t cDisplays = 0; 42e07dc26bSmrg VBoxQueryConfHGSMI(pCtx, VBOX_VBVA_CONF32_MONITOR_COUNT, &cDisplays); 43e07dc26bSmrg // LogFunc(("cDisplays = %d\n", cDisplays)); 44e07dc26bSmrg if (cDisplays == 0 || cDisplays > VBOX_VIDEO_MAX_SCREENS) 45e07dc26bSmrg /* Host reported some bad value. Continue in the 1 screen mode. */ 46e07dc26bSmrg cDisplays = 1; 47e07dc26bSmrg return cDisplays; 48e07dc26bSmrg} 49e07dc26bSmrg 50e07dc26bSmrg 51e07dc26bSmrg/** 52e07dc26bSmrg * Returns the size of the video RAM in bytes. 53e07dc26bSmrg * 54e07dc26bSmrg * @returns the size 55e07dc26bSmrg */ 56e07dc26bSmrgDECLHIDDEN(uint32_t) VBoxVideoGetVRAMSize(void) 57e07dc26bSmrg{ 58e07dc26bSmrg /** @note A 32bit read on this port returns the VRAM size. */ 59e07dc26bSmrg return VBVO_PORT_READ_U32(VBE_DISPI_IOPORT_DATA); 60e07dc26bSmrg} 61e07dc26bSmrg 62e07dc26bSmrg 63e07dc26bSmrg/** 64e07dc26bSmrg * Check whether this hardware allows the display width to have non-multiple- 65e07dc26bSmrg * of-eight values. 66e07dc26bSmrg * 67e07dc26bSmrg * @returns true if any width is allowed, false otherwise. 68e07dc26bSmrg */ 69e07dc26bSmrgDECLHIDDEN(bool) VBoxVideoAnyWidthAllowed(void) 70e07dc26bSmrg{ 71e07dc26bSmrg unsigned DispiId; 72e07dc26bSmrg VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID); 73e07dc26bSmrg VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID_ANYX); 74e07dc26bSmrg DispiId = VBVO_PORT_READ_U16(VBE_DISPI_IOPORT_DATA); 75e07dc26bSmrg return (DispiId == VBE_DISPI_ID_ANYX); 76e07dc26bSmrg} 77e07dc26bSmrg 78e07dc26bSmrg 79e07dc26bSmrg/** 80e07dc26bSmrg * Tell the host about how VRAM is divided up between each screen via an HGSMI 81636c353eSmrg * command. It is acceptable to specify identical data for each screen if 82e07dc26bSmrg * they share a single framebuffer. 83e07dc26bSmrg * 84e07dc26bSmrg * @returns iprt status code, either VERR_NO_MEMORY or the status returned by 85e07dc26bSmrg * @a pfnFill 86e07dc26bSmrg * @todo What was I thinking of with that callback function? It 87e07dc26bSmrg * would be much simpler to just pass in a structure in normal 88e07dc26bSmrg * memory and copy it. 89e07dc26bSmrg * @param pCtx the context containing the heap to use 90e07dc26bSmrg * @param u32Count the number of screens we are activating 91e07dc26bSmrg * @param pfnFill a callback which initialises the VBVAINFOVIEW structures 92e07dc26bSmrg * for all screens 93e07dc26bSmrg * @param pvData context data for @a pfnFill 94e07dc26bSmrg */ 95e07dc26bSmrgDECLHIDDEN(int) VBoxHGSMISendViewInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx, 96e07dc26bSmrg uint32_t u32Count, 97e07dc26bSmrg PFNHGSMIFILLVIEWINFO pfnFill, 98e07dc26bSmrg void *pvData) 99e07dc26bSmrg{ 100e07dc26bSmrg int rc; 101e07dc26bSmrg /* Issue the screen info command. */ 102e07dc26bSmrg void *p = VBoxHGSMIBufferAlloc(pCtx, sizeof(VBVAINFOVIEW) * u32Count, 103e07dc26bSmrg HGSMI_CH_VBVA, VBVA_INFO_VIEW); 104e07dc26bSmrg if (p) 105e07dc26bSmrg { 106e07dc26bSmrg VBVAINFOVIEW *pInfo = (VBVAINFOVIEW *)p; 107e07dc26bSmrg rc = pfnFill(pvData, pInfo, u32Count); 108e07dc26bSmrg if (RT_SUCCESS(rc)) 109e07dc26bSmrg VBoxHGSMIBufferSubmit (pCtx, p); 110e07dc26bSmrg VBoxHGSMIBufferFree(pCtx, p); 111e07dc26bSmrg } 112e07dc26bSmrg else 113e07dc26bSmrg rc = VERR_NO_MEMORY; 114e07dc26bSmrg return rc; 115e07dc26bSmrg} 116e07dc26bSmrg 117e07dc26bSmrg 118e07dc26bSmrg/** 119e07dc26bSmrg * Set a video mode using port registers. This must be done for the first 120e07dc26bSmrg * screen before every HGSMI modeset and also works when HGSM is not enabled. 121e07dc26bSmrg * @param cWidth the mode width 122e07dc26bSmrg * @param cHeight the mode height 123e07dc26bSmrg * @param cVirtWidth the mode pitch 124e07dc26bSmrg * @param cBPP the colour depth of the mode 125e07dc26bSmrg * @param fFlags flags for the mode. These will be or-ed with the 126e07dc26bSmrg * default _ENABLED flag, so unless you are restoring 127e07dc26bSmrg * a saved mode or have special requirements you can pass 128e07dc26bSmrg * zero here. 129e07dc26bSmrg * @param cx the horizontal panning offset 130e07dc26bSmrg * @param cy the vertical panning offset 131e07dc26bSmrg */ 132e07dc26bSmrgDECLHIDDEN(void) VBoxVideoSetModeRegisters(uint16_t cWidth, uint16_t cHeight, 133e07dc26bSmrg uint16_t cVirtWidth, uint16_t cBPP, 134e07dc26bSmrg uint16_t fFlags, uint16_t cx, 135e07dc26bSmrg uint16_t cy) 136e07dc26bSmrg{ 137e07dc26bSmrg /* set the mode characteristics */ 138e07dc26bSmrg VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES); 139e07dc26bSmrg VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA, cWidth); 140e07dc26bSmrg VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES); 141e07dc26bSmrg VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA, cHeight); 142e07dc26bSmrg VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX, 143e07dc26bSmrg VBE_DISPI_INDEX_VIRT_WIDTH); 144e07dc26bSmrg VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA, cVirtWidth); 145e07dc26bSmrg VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP); 146e07dc26bSmrg VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA, cBPP); 147e07dc26bSmrg /* enable the mode */ 148e07dc26bSmrg VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX, 149e07dc26bSmrg VBE_DISPI_INDEX_ENABLE); 150e07dc26bSmrg VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA, 151e07dc26bSmrg fFlags | VBE_DISPI_ENABLED); 152e07dc26bSmrg /* Panning registers */ 153e07dc26bSmrg VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX, 154e07dc26bSmrg VBE_DISPI_INDEX_X_OFFSET); 155e07dc26bSmrg VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA, cx); 156e07dc26bSmrg VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX, 157e07dc26bSmrg VBE_DISPI_INDEX_Y_OFFSET); 158e07dc26bSmrg VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA, cy); 159e07dc26bSmrg /** @todo read from the port to see if the mode switch was successful */ 160e07dc26bSmrg} 161e07dc26bSmrg 162e07dc26bSmrg 163e07dc26bSmrg/** 164e07dc26bSmrg * Get the video mode for the first screen using the port registers. All 165e07dc26bSmrg * parameters are optional 166e07dc26bSmrg * @returns true if the VBE mode returned is active, false if we are in VGA 167e07dc26bSmrg * mode 168e07dc26bSmrg * @note If anyone else needs additional register values just extend the 169e07dc26bSmrg * function with additional parameters and fix any existing callers. 170e07dc26bSmrg * @param pcWidth where to store the mode width 171e07dc26bSmrg * @param pcHeight where to store the mode height 172e07dc26bSmrg * @param pcVirtWidth where to store the mode pitch 173e07dc26bSmrg * @param pcBPP where to store the colour depth of the mode 174e07dc26bSmrg * @param pfFlags where to store the flags for the mode 175e07dc26bSmrg */ 176e07dc26bSmrgDECLHIDDEN(bool) VBoxVideoGetModeRegisters(uint16_t *pcWidth, uint16_t *pcHeight, 177e07dc26bSmrg uint16_t *pcVirtWidth, uint16_t *pcBPP, 178e07dc26bSmrg uint16_t *pfFlags) 179e07dc26bSmrg{ 180e07dc26bSmrg uint16_t fFlags; 181e07dc26bSmrg 182e07dc26bSmrg VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX, 183e07dc26bSmrg VBE_DISPI_INDEX_ENABLE); 184e07dc26bSmrg fFlags = VBVO_PORT_READ_U16(VBE_DISPI_IOPORT_DATA); 185e07dc26bSmrg if (pcWidth) 186e07dc26bSmrg { 187e07dc26bSmrg VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX, 188e07dc26bSmrg VBE_DISPI_INDEX_XRES); 189e07dc26bSmrg *pcWidth = VBVO_PORT_READ_U16(VBE_DISPI_IOPORT_DATA); 190e07dc26bSmrg } 191e07dc26bSmrg if (pcHeight) 192e07dc26bSmrg { 193e07dc26bSmrg VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX, 194e07dc26bSmrg VBE_DISPI_INDEX_YRES); 195e07dc26bSmrg *pcHeight = VBVO_PORT_READ_U16(VBE_DISPI_IOPORT_DATA); 196e07dc26bSmrg } 197e07dc26bSmrg if (pcVirtWidth) 198e07dc26bSmrg { 199e07dc26bSmrg VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX, 200e07dc26bSmrg VBE_DISPI_INDEX_VIRT_WIDTH); 201e07dc26bSmrg *pcVirtWidth = VBVO_PORT_READ_U16(VBE_DISPI_IOPORT_DATA); 202e07dc26bSmrg } 203e07dc26bSmrg if (pcBPP) 204e07dc26bSmrg { 205e07dc26bSmrg VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX, 206e07dc26bSmrg VBE_DISPI_INDEX_BPP); 207e07dc26bSmrg *pcBPP = VBVO_PORT_READ_U16(VBE_DISPI_IOPORT_DATA); 208e07dc26bSmrg } 209e07dc26bSmrg if (pfFlags) 210e07dc26bSmrg *pfFlags = fFlags; 211e07dc26bSmrg return !!(fFlags & VBE_DISPI_ENABLED); 212e07dc26bSmrg} 213e07dc26bSmrg 214e07dc26bSmrg 215e07dc26bSmrg/** 216e07dc26bSmrg * Disable our extended graphics mode and go back to VGA mode. 217e07dc26bSmrg */ 218e07dc26bSmrgDECLHIDDEN(void) VBoxVideoDisableVBE(void) 219e07dc26bSmrg{ 220e07dc26bSmrg VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX, 221e07dc26bSmrg VBE_DISPI_INDEX_ENABLE); 222e07dc26bSmrg VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA, 0); 223e07dc26bSmrg} 224e07dc26bSmrg 225e07dc26bSmrg 226e07dc26bSmrg/** 227e07dc26bSmrg * Set a video mode via an HGSMI request. The views must have been 228e07dc26bSmrg * initialised first using @a VBoxHGSMISendViewInfo and if the mode is being 229e07dc26bSmrg * set on the first display then it must be set first using registers. 230e07dc26bSmrg * @param pCtx The context containing the heap to use. 231e07dc26bSmrg * @param cDisplay the screen number 232e07dc26bSmrg * @param cOriginX the horizontal displacement relative to the first screen 233e07dc26bSmrg * @param cOriginY the vertical displacement relative to the first screen 234e07dc26bSmrg * @param offStart the offset of the visible area of the framebuffer 235e07dc26bSmrg * relative to the framebuffer start 236e07dc26bSmrg * @param cbPitch the offset in bytes between the starts of two adjecent 237e07dc26bSmrg * scan lines in video RAM 238e07dc26bSmrg * @param cWidth the mode width 239e07dc26bSmrg * @param cHeight the mode height 240e07dc26bSmrg * @param cBPP the colour depth of the mode 241e07dc26bSmrg * @param fFlags flags 242e07dc26bSmrg */ 243e07dc26bSmrgDECLHIDDEN(void) VBoxHGSMIProcessDisplayInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx, 244e07dc26bSmrg uint32_t cDisplay, 245e07dc26bSmrg int32_t cOriginX, 246e07dc26bSmrg int32_t cOriginY, 247e07dc26bSmrg uint32_t offStart, 248e07dc26bSmrg uint32_t cbPitch, 249e07dc26bSmrg uint32_t cWidth, 250e07dc26bSmrg uint32_t cHeight, 251e07dc26bSmrg uint16_t cBPP, 252e07dc26bSmrg uint16_t fFlags) 253e07dc26bSmrg{ 254e07dc26bSmrg /* Issue the screen info command. */ 255e07dc26bSmrg void *p = VBoxHGSMIBufferAlloc(pCtx, 256e07dc26bSmrg sizeof (VBVAINFOSCREEN), 257e07dc26bSmrg HGSMI_CH_VBVA, 258e07dc26bSmrg VBVA_INFO_SCREEN); 259e07dc26bSmrg if (!p) 260e07dc26bSmrg { 261e07dc26bSmrg // LogFunc(("HGSMIHeapAlloc failed\n")); 262e07dc26bSmrg } 263e07dc26bSmrg else 264e07dc26bSmrg { 265e07dc26bSmrg VBVAINFOSCREEN *pScreen = (VBVAINFOSCREEN *)p; 266e07dc26bSmrg 267e07dc26bSmrg pScreen->u32ViewIndex = cDisplay; 268e07dc26bSmrg pScreen->i32OriginX = cOriginX; 269e07dc26bSmrg pScreen->i32OriginY = cOriginY; 270e07dc26bSmrg pScreen->u32StartOffset = offStart; 271e07dc26bSmrg pScreen->u32LineSize = cbPitch; 272e07dc26bSmrg pScreen->u32Width = cWidth; 273e07dc26bSmrg pScreen->u32Height = cHeight; 274e07dc26bSmrg pScreen->u16BitsPerPixel = cBPP; 275e07dc26bSmrg pScreen->u16Flags = fFlags; 276e07dc26bSmrg 277e07dc26bSmrg VBoxHGSMIBufferSubmit(pCtx, p); 278e07dc26bSmrg 279e07dc26bSmrg VBoxHGSMIBufferFree(pCtx, p); 280e07dc26bSmrg } 281e07dc26bSmrg} 282e07dc26bSmrg 283e07dc26bSmrg 284e07dc26bSmrg/** Report the rectangle relative to which absolute pointer events should be 285e07dc26bSmrg * expressed. This information remains valid until the next VBVA resize event 286e07dc26bSmrg * for any screen, at which time it is reset to the bounding rectangle of all 287e07dc26bSmrg * virtual screens. 288e07dc26bSmrg * @param pCtx The context containing the heap to use. 289636c353eSmrg * @param cOriginX Upper left X coordinate relative to the first screen. 290636c353eSmrg * @param cOriginY Upper left Y coordinate relative to the first screen. 291e07dc26bSmrg * @param cWidth Rectangle width. 292e07dc26bSmrg * @param cHeight Rectangle height. 293e07dc26bSmrg * @returns iprt status code. 294e07dc26bSmrg * @returns VERR_NO_MEMORY HGSMI heap allocation failed. 295e07dc26bSmrg */ 296e07dc26bSmrgDECLHIDDEN(int) VBoxHGSMIUpdateInputMapping(PHGSMIGUESTCOMMANDCONTEXT pCtx, int32_t cOriginX, int32_t cOriginY, 297e07dc26bSmrg uint32_t cWidth, uint32_t cHeight) 298e07dc26bSmrg{ 299e07dc26bSmrg int rc = VINF_SUCCESS; 300e07dc26bSmrg VBVAREPORTINPUTMAPPING *p; 301e07dc26bSmrg // Log(("%s: cOriginX=%d, cOriginY=%d, cWidth=%u, cHeight=%u\n", __PRETTY_FUNCTION__, (int)cOriginX, (int)cOriginX, 302e07dc26bSmrg // (unsigned)cWidth, (unsigned)cHeight)); 303e07dc26bSmrg 304e07dc26bSmrg /* Allocate the IO buffer. */ 305e07dc26bSmrg p = (VBVAREPORTINPUTMAPPING *)VBoxHGSMIBufferAlloc(pCtx, sizeof(VBVAREPORTINPUTMAPPING), HGSMI_CH_VBVA, 306e07dc26bSmrg VBVA_REPORT_INPUT_MAPPING); 307e07dc26bSmrg if (p) 308e07dc26bSmrg { 309e07dc26bSmrg /* Prepare data to be sent to the host. */ 310e07dc26bSmrg p->x = cOriginX; 311e07dc26bSmrg p->y = cOriginY; 312e07dc26bSmrg p->cx = cWidth; 313e07dc26bSmrg p->cy = cHeight; 314e07dc26bSmrg rc = VBoxHGSMIBufferSubmit(pCtx, p); 315e07dc26bSmrg /* Free the IO buffer. */ 316e07dc26bSmrg VBoxHGSMIBufferFree(pCtx, p); 317e07dc26bSmrg } 318e07dc26bSmrg else 319e07dc26bSmrg rc = VERR_NO_MEMORY; 320e07dc26bSmrg // LogFunc(("rc = %d\n", rc)); 321e07dc26bSmrg return rc; 322e07dc26bSmrg} 323e07dc26bSmrg 324e07dc26bSmrg 325e07dc26bSmrg/** 326e07dc26bSmrg * Get most recent video mode hints. 327e07dc26bSmrg * @param pCtx the context containing the heap to use 328e07dc26bSmrg * @param cScreens the number of screens to query hints for, starting at 0. 329e07dc26bSmrg * @param paHints array of VBVAMODEHINT structures for receiving the hints. 330e07dc26bSmrg * @returns iprt status code 331e07dc26bSmrg * @returns VERR_NO_MEMORY HGSMI heap allocation failed. 332e07dc26bSmrg * @returns VERR_NOT_SUPPORTED Host does not support this command. 333e07dc26bSmrg */ 334e07dc26bSmrgDECLHIDDEN(int) VBoxHGSMIGetModeHints(PHGSMIGUESTCOMMANDCONTEXT pCtx, 335e07dc26bSmrg unsigned cScreens, VBVAMODEHINT *paHints) 336e07dc26bSmrg{ 337e07dc26bSmrg int rc; 338e07dc26bSmrg void *p; 339e07dc26bSmrg 340e07dc26bSmrg AssertPtr(paHints); 341e07dc26bSmrg if (!paHints) 342e07dc26bSmrg return VERR_INVALID_POINTER; 343e07dc26bSmrg 344e07dc26bSmrg p = VBoxHGSMIBufferAlloc(pCtx, sizeof(VBVAQUERYMODEHINTS) 345e07dc26bSmrg + cScreens * sizeof(VBVAMODEHINT), 346e07dc26bSmrg HGSMI_CH_VBVA, VBVA_QUERY_MODE_HINTS); 347e07dc26bSmrg if (!p) 348e07dc26bSmrg { 349e07dc26bSmrg // LogFunc(("HGSMIHeapAlloc failed\n")); 350e07dc26bSmrg return VERR_NO_MEMORY; 351e07dc26bSmrg } 352e07dc26bSmrg else 353e07dc26bSmrg { 354e07dc26bSmrg VBVAQUERYMODEHINTS *pQuery = (VBVAQUERYMODEHINTS *)p; 355e07dc26bSmrg 356e07dc26bSmrg pQuery->cHintsQueried = cScreens; 357e07dc26bSmrg pQuery->cbHintStructureGuest = sizeof(VBVAMODEHINT); 358e07dc26bSmrg pQuery->rc = VERR_NOT_SUPPORTED; 359e07dc26bSmrg 360e07dc26bSmrg VBoxHGSMIBufferSubmit(pCtx, p); 361e07dc26bSmrg rc = pQuery->rc; 362e07dc26bSmrg if (RT_SUCCESS(rc)) 363e07dc26bSmrg memcpy(paHints, ((uint8_t *)p) + sizeof(VBVAQUERYMODEHINTS), 364e07dc26bSmrg cScreens * sizeof(VBVAMODEHINT)); 365e07dc26bSmrg 366e07dc26bSmrg VBoxHGSMIBufferFree(pCtx, p); 367e07dc26bSmrg } 368e07dc26bSmrg return rc; 369e07dc26bSmrg} 370e07dc26bSmrg 371e07dc26bSmrg 372e07dc26bSmrg/** 373e07dc26bSmrg * Query the supported flags in VBVAINFOSCREEN::u16Flags. 374e07dc26bSmrg * 375e07dc26bSmrg * @returns The mask of VBVA_SCREEN_F_* flags or 0 if host does not support the request. 376e07dc26bSmrg * @param pCtx the context containing the heap to use 377e07dc26bSmrg */ 378e07dc26bSmrgDECLHIDDEN(uint16_t) VBoxHGSMIGetScreenFlags(PHGSMIGUESTCOMMANDCONTEXT pCtx) 379e07dc26bSmrg{ 380e07dc26bSmrg uint32_t u32Flags = 0; 381e07dc26bSmrg int rc = VBoxQueryConfHGSMI(pCtx, VBOX_VBVA_CONF32_SCREEN_FLAGS, &u32Flags); 382e07dc26bSmrg // LogFunc(("u32Flags = 0x%x rc %Rrc\n", u32Flags, rc)); 383e07dc26bSmrg if (RT_FAILURE(rc) || u32Flags > UINT16_MAX) 384e07dc26bSmrg u32Flags = 0; 385e07dc26bSmrg return (uint16_t)u32Flags; 386e07dc26bSmrg} 387