diff options
Diffstat (limited to 'src/VBox/Main/src-all/DisplayUtils.cpp')
-rw-r--r-- | src/VBox/Main/src-all/DisplayUtils.cpp | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/src/VBox/Main/src-all/DisplayUtils.cpp b/src/VBox/Main/src-all/DisplayUtils.cpp new file mode 100644 index 00000000..a75001d3 --- /dev/null +++ b/src/VBox/Main/src-all/DisplayUtils.cpp @@ -0,0 +1,225 @@ +/* $Id: DisplayUtils.cpp $ */ +/** @file + * Implementation of IDisplay helpers, currently only used in VBoxSVC. + */ + +/* + * Copyright (C) 2010-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#include <DisplayUtils.h> + +#include <iprt/log.h> +#include <VBox/err.h> +#include <VBox/vmm/ssm.h> +#include <VBoxVideo.h> + +int readSavedDisplayScreenshot(SsmStream &ssmStream, const Utf8Str &strStateFilePath, + uint32_t u32Type, uint8_t **ppu8Data, uint32_t *pcbData, + uint32_t *pu32Width, uint32_t *pu32Height) +{ + LogFlowFunc(("u32Type = %d [%s]\n", u32Type, strStateFilePath.c_str())); + + /** @todo cache read data */ + if (strStateFilePath.isEmpty()) + { + /* No saved state data. */ + return VERR_NOT_SUPPORTED; + } + + uint8_t *pu8Data = NULL; + uint32_t cbData = 0; + uint32_t u32Width = 0; + uint32_t u32Height = 0; + + PSSMHANDLE pSSM; + int vrc = ssmStream.open(strStateFilePath.c_str(), false /*fWrite*/, &pSSM); + if (RT_SUCCESS(vrc)) + { + uint32_t uVersion; + vrc = SSMR3Seek(pSSM, "DisplayScreenshot", 1100 /*iInstance*/, &uVersion); + if (RT_SUCCESS(vrc)) + { + if (uVersion == sSSMDisplayScreenshotVer) + { + uint32_t cBlocks; + vrc = SSMR3GetU32(pSSM, &cBlocks); + AssertRCReturn(vrc, vrc); + + for (uint32_t i = 0; i < cBlocks; i++) + { + uint32_t cbBlock; + vrc = SSMR3GetU32(pSSM, &cbBlock); + AssertRCBreak(vrc); + + uint32_t typeOfBlock; + vrc = SSMR3GetU32(pSSM, &typeOfBlock); + AssertRCBreak(vrc); + + LogFlowFunc(("[%d] type %d, size %d bytes\n", i, typeOfBlock, cbBlock)); + + if (typeOfBlock == u32Type) + { + if (cbBlock > 2 * sizeof(uint32_t)) + { + cbData = (uint32_t)(cbBlock - 2 * sizeof(uint32_t)); + pu8Data = (uint8_t *)RTMemAlloc(cbData); + if (pu8Data == NULL) + { + vrc = VERR_NO_MEMORY; + break; + } + + vrc = SSMR3GetU32(pSSM, &u32Width); + AssertRCBreak(vrc); + vrc = SSMR3GetU32(pSSM, &u32Height); + AssertRCBreak(vrc); + vrc = SSMR3GetMem(pSSM, pu8Data, cbData); + AssertRCBreak(vrc); + } + else + { + /* No saved state data. */ + vrc = VERR_NOT_SUPPORTED; + } + + break; + } + else + { + /* displaySSMSaveScreenshot did not write any data, if + * cbBlock was == 2 * sizeof (uint32_t). + */ + if (cbBlock > 2 * sizeof (uint32_t)) + { + vrc = SSMR3Skip(pSSM, cbBlock); + AssertRCBreak(vrc); + } + } + } + } + else + { + vrc = VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION; + } + } + + ssmStream.close(); + } + + if (RT_SUCCESS(vrc)) + { + if (u32Type == 0 && cbData % 4 != 0) + { + /* Bitmap is 32bpp, so data is invalid. */ + vrc = VERR_SSM_UNEXPECTED_DATA; + } + } + + if (RT_SUCCESS(vrc)) + { + *ppu8Data = pu8Data; + *pcbData = cbData; + *pu32Width = u32Width; + *pu32Height = u32Height; + LogFlowFunc(("cbData %d, u32Width %d, u32Height %d\n", cbData, u32Width, u32Height)); + } + + LogFlowFunc(("vrc %Rrc\n", vrc)); + return vrc; +} + +void freeSavedDisplayScreenshot(uint8_t *pu8Data) +{ + /** @todo not necessary when caching is implemented. */ + RTMemFree(pu8Data); +} + +int readSavedGuestScreenInfo(SsmStream &ssmStream, const Utf8Str &strStateFilePath, + uint32_t u32ScreenId, uint32_t *pu32OriginX, uint32_t *pu32OriginY, + uint32_t *pu32Width, uint32_t *pu32Height, uint16_t *pu16Flags) +{ + LogFlowFunc(("u32ScreenId = %d [%s]\n", u32ScreenId, strStateFilePath.c_str())); + + /** @todo cache read data */ + if (strStateFilePath.isEmpty()) + { + /* No saved state data. */ + return VERR_NOT_SUPPORTED; + } + + PSSMHANDLE pSSM; + int vrc = ssmStream.open(strStateFilePath.c_str(), false /*fWrite*/, &pSSM); + if (RT_SUCCESS(vrc)) + { + uint32_t uVersion; + vrc = SSMR3Seek(pSSM, "DisplayData", 0 /*iInstance*/, &uVersion); + if (RT_SUCCESS(vrc)) + { + /* Starting from sSSMDisplayVer2 we have pu32Width and pu32Height. + * Starting from sSSMDisplayVer3 we have all the rest of parameters we need. */ + if (uVersion >= sSSMDisplayVer2) + { + uint32_t cMonitors; + SSMR3GetU32(pSSM, &cMonitors); + if (u32ScreenId > cMonitors) + { + vrc = VERR_INVALID_PARAMETER; + } + else + { + if (uVersion == sSSMDisplayVer2) + { + /* Skip all previous monitors, each 5 uint32_t, and the first 3 uint32_t entries. */ + SSMR3Skip(pSSM, u32ScreenId * 5 * sizeof(uint32_t) + 3 * sizeof(uint32_t)); + SSMR3GetU32(pSSM, pu32Width); + SSMR3GetU32(pSSM, pu32Height); + *pu32OriginX = 0; + *pu32OriginY = 0; + *pu16Flags = VBVA_SCREEN_F_ACTIVE; + } + else + { + /* Skip all previous monitors, each 8 uint32_t, and the first 3 uint32_t entries. */ + SSMR3Skip(pSSM, u32ScreenId * 8 * sizeof(uint32_t) + 3 * sizeof(uint32_t)); + SSMR3GetU32(pSSM, pu32Width); + SSMR3GetU32(pSSM, pu32Height); + SSMR3GetU32(pSSM, pu32OriginX); + SSMR3GetU32(pSSM, pu32OriginY); + uint32_t u32Flags = 0; + SSMR3GetU32(pSSM, &u32Flags); + *pu16Flags = (uint16_t)u32Flags; + } + } + } + else + { + vrc = VERR_NOT_SUPPORTED; + } + } + + ssmStream.close(); + } + + LogFlowFunc(("vrc %Rrc\n", vrc)); + return vrc; +} + |