Changeset 51708 in vbox for trunk/src/VBox/Frontends/VirtualBox
- Timestamp:
- Jun 24, 2014 2:04:57 PM (11 years ago)
- Location:
- trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGMachinePreview.cpp
r51531 r51708 131 131 void UIGMachinePreview::sltRecreatePreview() 132 132 { 133 /* Only do this if we are visible: */133 /* Skip invisible preview: */ 134 134 if (!isVisible()) 135 135 return; 136 136 137 /* Cleanup previ ew first: */137 /* Cleanup previous image: */ 138 138 if (m_pPreviewImg) 139 139 { … … 142 142 } 143 143 144 /* Fetch the latestmachine-state: */145 KMachineState machineState = m_machine.isNull() ? KMachineState_Null : m_machine.GetState();144 /* Fetch actual machine-state: */ 145 const KMachineState machineState = m_machine.isNull() ? KMachineState_Null : m_machine.GetState(); 146 146 147 147 /* We are creating preview only for assigned and accessible VMs: */ … … 149 149 m_vRect.width() > 0 && m_vRect.height() > 0) 150 150 { 151 QImage image(size().toSize(), QImage::Format_ARGB32); 152 image.fill(Qt::transparent); 153 QPainter painter(&image); 154 bool fDone = false; 155 156 /* Preview enabled? */ 151 /* Prepare image: */ 152 QImage image; 153 154 /* Preview update enabled? */ 157 155 if (m_pUpdateTimer->interval() > 0) 158 156 { 159 /* Use the image which may be included in the save state.*/160 if (machineState == KMachineState_Saved || machineState == KMachineState_Restoring)157 /* Depending on machine state: */ 158 switch (machineState) 161 159 { 162 ULONG width = 0, height = 0;163 QVector<BYTE> screenData = m_machine.ReadSavedScreenshotPNGToArray(0, width, height);164 if (screenData.size() != 0)160 /* If machine is in SAVED/RESTORING state: */ 161 case KMachineState_Saved: 162 case KMachineState_Restoring: 165 163 { 166 QImage shot = QImage::fromData(screenData.data(), screenData.size(), "PNG") 167 .scaled(m_vRect.size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); 168 dimImage(shot); 169 painter.drawImage(m_vRect.x(), m_vRect.y(), shot); 170 fDone = true; 164 /* Use the screenshot from saved-state if possible: */ 165 ULONG uWidth = 0, uHeight = 0; 166 QVector<BYTE> screenData = m_machine.ReadSavedScreenshotPNGToArray(0, uWidth, uHeight); 167 if (m_machine.isOk() && !screenData.isEmpty()) 168 { 169 /* Create image based on shallow copy or screenshot data, 170 * scale image down if necessary to the size possible to reflect: */ 171 image = QImage::fromData(screenData.data(), screenData.size(), "PNG") 172 .scaled(imageAspectRatioSize(m_vRect.size(), QSize(uWidth, uHeight)), 173 Qt::IgnoreAspectRatio, Qt::SmoothTransformation); 174 /* Dim image to give it required look: */ 175 dimImage(image); 176 } 177 break; 171 178 } 172 } 173 /* Use the current VM output. */ 174 else if (machineState == KMachineState_Running || machineState == KMachineState_Paused) 175 { 176 if (m_session.GetState() == KSessionState_Locked) 179 /* If machine is in RUNNING/PAUSED state: */ 180 case KMachineState_Running: 181 case KMachineState_Paused: 177 182 { 178 CVirtualBox vbox = vboxGlobal().virtualBox(); 179 if (vbox.isOk()) 183 /* Make sure session state is Locked: */ 184 if (m_session.GetState() != KSessionState_Locked) 185 break; 186 187 /* Make sure console is OK: */ 188 CConsole console = m_session.GetConsole(); 189 if (!m_session.isOk() || console.isNull()) 190 break; 191 /* Make sure display is OK: */ 192 CDisplay display = console.GetDisplay(); 193 if (!console.isOk() || display.isNull()) 194 break; 195 196 /* Calculate aspect-ratio size: */ 197 ULONG uGuestWidth, uGuestHeight, uBpp; 198 LONG iOriginX, iOriginY; 199 display.GetScreenResolution(0, uGuestWidth, uGuestHeight, uBpp, iOriginX, iOriginY); 200 const QSize size = imageAspectRatioSize(m_vRect.size(), QSize(uGuestWidth, uGuestHeight)); 201 202 /* Use direct VM content: */ 203 QVector<BYTE> screenData = display.TakeScreenShotToArray(0, size.width(), size.height()); 204 if (display.isOk() && !screenData.isEmpty()) 180 205 { 181 const CConsole& console = m_session.GetConsole(); 182 if (!console.isNull()) 206 /* Unfortunately we have to reorder the pixel data, 207 * cause the VBox API returns RGBA data, 208 * which is not a format QImage understand. */ 209 uint32_t *pData = (uint32_t*)screenData.data(); 210 for (int i = 0; i < screenData.size() / 4; ++i) 183 211 { 184 CDisplay display = console.GetDisplay(); 185 /* Todo: correct aspect radio */ 186 // ULONG w, h, bpp; 187 // LONG xOrigin, yOrigin; 188 // display.GetScreenResolution(0, w, h, bpp, xOrigin, yOrigin); 189 // QImage shot = QImage(w, h, QImage::Format_RGB32); 190 // shot.fill(Qt::black); 191 // display.TakeScreenShot(0, shot.bits(), shot.width(), shot.height()); 192 QVector<BYTE> screenData = display.TakeScreenShotToArray(0, m_vRect.width(), m_vRect.height()); 193 if (display.isOk() && screenData.size() != 0) 194 { 195 /* Unfortunately we have to reorder the pixel 196 * data, cause the VBox API returns RGBA data, 197 * which is not a format QImage understand. 198 * Todo: check for 32bit alignment, for both 199 * the data and the scanlines. Maybe we need to 200 * copy the data in any case. */ 201 uint32_t *d = (uint32_t*)screenData.data(); 202 for (int i = 0; i < screenData.size() / 4; ++i) 203 { 204 uint32_t e = d[i]; 205 d[i] = RT_MAKE_U32_FROM_U8(RT_BYTE3(e), RT_BYTE2(e), RT_BYTE1(e), RT_BYTE4(e)); 206 } 207 208 QImage shot = QImage((uchar*)d, m_vRect.width(), m_vRect.height(), QImage::Format_RGB32); 209 210 if (machineState == KMachineState_Paused) 211 dimImage(shot); 212 painter.drawImage(m_vRect.x(), m_vRect.y(), shot); 213 fDone = true; 214 } 212 uint32_t e = pData[i]; 213 pData[i] = RT_MAKE_U32_FROM_U8(RT_BYTE3(e), RT_BYTE2(e), RT_BYTE1(e), RT_BYTE4(e)); 215 214 } 215 /* Create image based on shallow copy or reordered data: */ 216 image = QImage((uchar*)pData, size.width(), size.height(), QImage::Format_RGB32); 217 /* Dim image to give it required look for PAUSED state: */ 218 if (machineState == KMachineState_Paused) 219 dimImage(image); 216 220 } 221 break; 217 222 } 223 default: 224 break; 218 225 } 219 226 } 220 227 221 if (fDone) 228 /* If image initialized: */ 229 if (!image.isNull()) 230 { 231 /* Shallow copy that image: */ 222 232 m_pPreviewImg = new QImage(image); 223 } 224 225 /* Redraw preview in any case! */ 233 /* And detach that copy: */ 234 m_pPreviewImg->bits(); 235 } 236 } 237 238 /* Redraw preview in any case: */ 226 239 update(); 227 240 } … … 285 298 if (m_pPreviewImg) 286 299 { 287 /* Draw empty background: */ 300 /* Draw black background: */ 301 pPainter->fillRect(m_vRect, Qt::black); 302 303 /* Draw empty monitor frame: */ 288 304 pPainter->drawPixmap(cr.x() + m_iMargin, cr.y() + m_iMargin, *m_pbgEmptyImage); 289 305 290 /* Draw that image: */ 291 pPainter->drawImage(0, 0, *m_pPreviewImg); 306 /* Move image to viewport center: */ 307 QRect imageRect(QPoint(0, 0), m_pPreviewImg->size()); 308 imageRect.moveCenter(m_vRect.center()); 309 /* Draw preview image: */ 310 pPainter->drawImage(imageRect.topLeft(), *m_pPreviewImg); 292 311 } 293 312 else 294 313 { 295 /* Draw full background: */314 /* Draw full monitor frame: */ 296 315 pPainter->drawPixmap(cr.x() + m_iMargin, cr.y() + m_iMargin, *m_pbgFullImage); 297 316 … … 386 405 } 387 406 407 /* static */ 408 QSize UIGMachinePreview::imageAspectRatioSize(const QSize &hostSize, const QSize &guestSize) 409 { 410 /* Calculate host/guest aspect-ratio: */ 411 const double dHostAspectRatio = (double)hostSize.width() / hostSize.height(); 412 const double dGuestAspectRatio = (double)guestSize.width() / guestSize.height(); 413 int iWidth = 0, iHeight = 0; 414 /* Guest-screen more thin by vertical than host-screen: */ 415 if (dGuestAspectRatio >= dHostAspectRatio) 416 { 417 /* Get host width: */ 418 iWidth = hostSize.width(); 419 /* And calculate height based on guest aspect ratio: */ 420 iHeight = (double)iWidth / dGuestAspectRatio; 421 /* But no more than host height: */ 422 iHeight = qMin(iHeight, hostSize.height()); 423 } 424 /* Host-screen more thin by vertical than guest-screen: */ 425 else 426 { 427 /* Get host height: */ 428 iHeight = hostSize.height(); 429 /* And calculate width based on guest aspect ratio: */ 430 iWidth = (double)iHeight * dGuestAspectRatio; 431 /* But no more than host width: */ 432 iWidth = qMin(iWidth, hostSize.width()); 433 } 434 /* Return actual size: */ 435 return QSize(iWidth, iHeight); 436 } 437 -
trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGMachinePreview.h
r51531 r51708 90 90 void stop(); 91 91 92 /** Calculates image size suitable to passed @a hostSize and @a guestSize. */ 93 static QSize imageAspectRatioSize(const QSize &hostSize, const QSize &guestSize); 94 92 95 /* Variables: */ 93 96 CSession m_session;
Note:
See TracChangeset
for help on using the changeset viewer.