[26719] | 1 | /* $Id: UIFrameBufferDirectDraw.cpp 33540 2010-10-28 09:27:05Z vboxsync $ */
|
---|
[382] | 2 | /** @file
|
---|
| 3 | *
|
---|
| 4 | * VBox frontends: Qt GUI ("VirtualBox"):
|
---|
| 5 | * DDRAW framebuffer implementation
|
---|
| 6 | */
|
---|
| 7 |
|
---|
| 8 | /*
|
---|
[28800] | 9 | * Copyright (C) 2006-2007 Oracle Corporation
|
---|
[382] | 10 | *
|
---|
| 11 | * This file is part of VirtualBox Open Source Edition (OSE), as
|
---|
| 12 | * available from http://www.virtualbox.org. This file is free software;
|
---|
| 13 | * you can redistribute it and/or modify it under the terms of the GNU
|
---|
[5999] | 14 | * General Public License (GPL) as published by the Free Software
|
---|
| 15 | * Foundation, in version 2 as it comes in the "COPYING" file of the
|
---|
| 16 | * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
|
---|
| 17 | * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
|
---|
[382] | 18 | */
|
---|
| 19 |
|
---|
[26823] | 20 | #ifdef VBOX_GUI_USE_DDRAW
|
---|
[382] | 21 |
|
---|
[25526] | 22 | #ifdef VBOX_WITH_PRECOMPILED_HEADERS
|
---|
| 23 | # include "precomp.h"
|
---|
| 24 | #else /* !VBOX_WITH_PRECOMPILED_HEADERS */
|
---|
[382] | 25 |
|
---|
[26823] | 26 | /* Local includes */
|
---|
| 27 | # include "UIFrameBufferDirectDraw.h"
|
---|
| 28 | # include "UIMachineView.h"
|
---|
[382] | 29 |
|
---|
[26823] | 30 | # include <iprt/param.h>
|
---|
| 31 | # include <iprt/alloc.h>
|
---|
[382] | 32 |
|
---|
[26823] | 33 | /* Global includes */
|
---|
| 34 | # include <QApplication>
|
---|
| 35 |
|
---|
[25526] | 36 | #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
|
---|
[382] | 37 |
|
---|
| 38 | #define LOGDDRAW Log
|
---|
| 39 |
|
---|
[26823] | 40 | // TODO_NEW_CORE
|
---|
| 41 | #if 0
|
---|
[382] | 42 | /* @todo
|
---|
| 43 | * - when paused in Guest VRAM mode after pause the screen is dimmed. because VRAM is dimmed.
|
---|
| 44 | * - when GUI window is resized, somehow take this into account, blit only visible parts.
|
---|
| 45 | */
|
---|
| 46 |
|
---|
| 47 | /*
|
---|
| 48 | * Helpers.
|
---|
| 49 | */
|
---|
| 50 | static LPDIRECTDRAW7 getDDRAW (void)
|
---|
| 51 | {
|
---|
| 52 | LPDIRECTDRAW7 pDDRAW = NULL;
|
---|
| 53 | LPDIRECTDRAW iface = NULL;
|
---|
| 54 |
|
---|
| 55 | HRESULT rc = DirectDrawCreate (NULL, &iface, NULL);
|
---|
| 56 |
|
---|
| 57 | if (rc != DD_OK)
|
---|
| 58 | {
|
---|
| 59 | LOGDDRAW(("DDRAW: Could not create DirectDraw interface rc= 0x%08X\n", rc));
|
---|
| 60 | }
|
---|
| 61 | else
|
---|
| 62 | {
|
---|
| 63 | rc = iface->QueryInterface (IID_IDirectDraw7, (void**)&pDDRAW);
|
---|
| 64 |
|
---|
| 65 | if (rc != DD_OK)
|
---|
| 66 | {
|
---|
| 67 | LOGDDRAW(("DDRAW: Could not query DirectDraw 7 interface rc = 0x%08X\n", rc));
|
---|
| 68 | }
|
---|
| 69 | else
|
---|
| 70 | {
|
---|
| 71 | rc = pDDRAW->SetCooperativeLevel (NULL, DDSCL_NORMAL);
|
---|
| 72 |
|
---|
| 73 | if (rc != DD_OK)
|
---|
| 74 | {
|
---|
| 75 | LOGDDRAW(("DDRAW: Could not set the DirectDraw cooperative level rc = 0x%08X\n", rc));
|
---|
| 76 | pDDRAW->Release ();
|
---|
| 77 | }
|
---|
| 78 | }
|
---|
| 79 |
|
---|
| 80 | iface->Release();
|
---|
| 81 | }
|
---|
| 82 |
|
---|
| 83 | return rc == DD_OK? pDDRAW: NULL;
|
---|
| 84 | }
|
---|
| 85 |
|
---|
| 86 | static LPDIRECTDRAWSURFACE7 createPrimarySurface (LPDIRECTDRAW7 pDDRAW)
|
---|
| 87 | {
|
---|
| 88 | LPDIRECTDRAWSURFACE7 pPrimarySurface = NULL;
|
---|
| 89 |
|
---|
| 90 | DDSURFACEDESC2 sd;
|
---|
| 91 | memset (&sd, 0, sizeof (sd));
|
---|
| 92 | sd.dwSize = sizeof (sd);
|
---|
[4531] | 93 | sd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
|
---|
[382] | 94 | sd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
|
---|
[4531] | 95 | sd.dwBackBufferCount = 0;
|
---|
[382] | 96 |
|
---|
| 97 | HRESULT rc = pDDRAW->CreateSurface (&sd, &pPrimarySurface, NULL);
|
---|
| 98 |
|
---|
| 99 | if (rc != DD_OK)
|
---|
| 100 | {
|
---|
| 101 | LOGDDRAW(("DDRAW: Could not create primary DirectDraw surface rc = 0x%08X\n", rc));
|
---|
| 102 | }
|
---|
| 103 |
|
---|
| 104 | return rc == DD_OK? pPrimarySurface: NULL;
|
---|
| 105 | }
|
---|
| 106 |
|
---|
| 107 | static LPDIRECTDRAWCLIPPER createClipper (LPDIRECTDRAW7 pDDRAW, HWND hwnd)
|
---|
| 108 | {
|
---|
| 109 | LPDIRECTDRAWCLIPPER pClipper = NULL;
|
---|
| 110 |
|
---|
| 111 | HRESULT rc = pDDRAW->CreateClipper (0, &pClipper, NULL);
|
---|
| 112 |
|
---|
| 113 | if (rc != DD_OK)
|
---|
| 114 | {
|
---|
| 115 | LOGDDRAW(("DDRAW: Could not create DirectDraw clipper rc = 0x%08X\n", rc));
|
---|
| 116 | }
|
---|
| 117 | else
|
---|
| 118 | {
|
---|
| 119 | rc = pClipper->SetHWnd (0, hwnd);
|
---|
| 120 |
|
---|
| 121 | if (rc != DD_OK)
|
---|
| 122 | {
|
---|
| 123 | LOGDDRAW(("DDRAW: Could not set the HWND on clipper rc = 0x%08X\n", rc));
|
---|
| 124 | pClipper->Release ();
|
---|
| 125 | }
|
---|
| 126 | }
|
---|
| 127 |
|
---|
| 128 | return rc == DD_OK? pClipper: NULL;
|
---|
| 129 | }
|
---|
| 130 |
|
---|
| 131 | //
|
---|
| 132 | // VBoxDDRAWFrameBuffer class
|
---|
| 133 | /////////////////////////////////////////////////////////////////////////////
|
---|
| 134 |
|
---|
| 135 | /** @class VBoxDDRAWFrameBuffer
|
---|
| 136 | *
|
---|
| 137 | * The VBoxDDRAWFrameBuffer class is a class that implements the IFrameBuffer
|
---|
| 138 | * interface and uses Win32 DirectDraw to store and render VM display data.
|
---|
| 139 | */
|
---|
| 140 |
|
---|
| 141 | VBoxDDRAWFrameBuffer::VBoxDDRAWFrameBuffer (VBoxConsoleView *aView) :
|
---|
| 142 | VBoxFrameBuffer (aView),
|
---|
| 143 | mDDRAW (NULL),
|
---|
| 144 | mClipper (NULL),
|
---|
| 145 | mSurface (NULL),
|
---|
| 146 | mPrimarySurface (NULL),
|
---|
[3761] | 147 | mPixelFormat (FramebufferPixelFormat_FOURCC_RGB),
|
---|
| 148 | mUsesGuestVRAM (false),
|
---|
[382] | 149 | mWndX (0),
|
---|
| 150 | mWndY (0),
|
---|
[3761] | 151 | mSynchronousUpdates (true)
|
---|
[382] | 152 | {
|
---|
| 153 | memset (&mSurfaceDesc, 0, sizeof (mSurfaceDesc));
|
---|
| 154 |
|
---|
[3761] | 155 | LOGDDRAW (("DDRAW: Creating\n"));
|
---|
[382] | 156 |
|
---|
| 157 | /* Release all created objects if something will go wrong. */
|
---|
| 158 | BOOL bReleaseObjects = TRUE;
|
---|
| 159 |
|
---|
| 160 | mDDRAW = getDDRAW ();
|
---|
| 161 |
|
---|
| 162 | if (mDDRAW)
|
---|
| 163 | {
|
---|
| 164 | mClipper = createClipper (mDDRAW, mView->viewport()->winId());
|
---|
| 165 |
|
---|
| 166 | if (mClipper)
|
---|
| 167 | {
|
---|
| 168 | mPrimarySurface = createPrimarySurface (mDDRAW);
|
---|
| 169 |
|
---|
| 170 | if (mPrimarySurface)
|
---|
| 171 | {
|
---|
| 172 | mPrimarySurface->SetClipper (mClipper);
|
---|
| 173 |
|
---|
| 174 | VBoxResizeEvent *re =
|
---|
[7207] | 175 | new VBoxResizeEvent (FramebufferPixelFormat_Opaque,
|
---|
[3761] | 176 | NULL, 0, 0, 640, 480);
|
---|
[382] | 177 |
|
---|
| 178 | if (re)
|
---|
| 179 | {
|
---|
| 180 | resizeEvent (re);
|
---|
| 181 | delete re;
|
---|
| 182 |
|
---|
| 183 | if (mSurface)
|
---|
| 184 | {
|
---|
| 185 | /* Everything was initialized. */
|
---|
| 186 | bReleaseObjects = FALSE;
|
---|
| 187 | }
|
---|
| 188 | }
|
---|
| 189 | }
|
---|
| 190 | }
|
---|
| 191 | }
|
---|
| 192 |
|
---|
| 193 | if (bReleaseObjects)
|
---|
| 194 | {
|
---|
| 195 | releaseObjects();
|
---|
| 196 | }
|
---|
| 197 | }
|
---|
| 198 |
|
---|
| 199 | VBoxDDRAWFrameBuffer::~VBoxDDRAWFrameBuffer()
|
---|
| 200 | {
|
---|
| 201 | releaseObjects();
|
---|
| 202 | }
|
---|
| 203 |
|
---|
| 204 | void VBoxDDRAWFrameBuffer::releaseObjects()
|
---|
| 205 | {
|
---|
| 206 | deleteSurface ();
|
---|
| 207 |
|
---|
| 208 | if (mPrimarySurface)
|
---|
| 209 | {
|
---|
| 210 | if (mClipper)
|
---|
| 211 | {
|
---|
| 212 | mPrimarySurface->SetClipper (NULL);
|
---|
| 213 | }
|
---|
| 214 |
|
---|
| 215 | mPrimarySurface->Release ();
|
---|
| 216 | mPrimarySurface = NULL;
|
---|
| 217 | }
|
---|
| 218 |
|
---|
| 219 | if (mClipper)
|
---|
| 220 | {
|
---|
| 221 | mClipper->Release();
|
---|
| 222 | mClipper = NULL;
|
---|
| 223 | }
|
---|
| 224 |
|
---|
| 225 | if (mDDRAW)
|
---|
| 226 | {
|
---|
| 227 | mDDRAW->Release();
|
---|
| 228 | mDDRAW = NULL;
|
---|
| 229 | }
|
---|
| 230 | }
|
---|
| 231 |
|
---|
| 232 | /** @note This method is called on EMT from under this object's lock */
|
---|
| 233 | STDMETHODIMP VBoxDDRAWFrameBuffer::NotifyUpdate (ULONG aX, ULONG aY,
|
---|
[19817] | 234 | ULONG aW, ULONG aH)
|
---|
[382] | 235 | {
|
---|
| 236 | LOGDDRAW(("DDRAW: NotifyUpdate %d,%d %dx%d\n", aX, aY, aW, aH));
|
---|
| 237 |
|
---|
| 238 | if (mSynchronousUpdates)
|
---|
| 239 | {
|
---|
[9495] | 240 | //#warning check me!
|
---|
| 241 | mView->viewport()->update (aX, aY, aW, aH);
|
---|
[382] | 242 | }
|
---|
| 243 | else
|
---|
| 244 | {
|
---|
| 245 | drawRect (aX, aY, aW, aH);
|
---|
| 246 | }
|
---|
| 247 |
|
---|
| 248 | return S_OK;
|
---|
| 249 | }
|
---|
| 250 |
|
---|
| 251 | void VBoxDDRAWFrameBuffer::paintEvent (QPaintEvent *pe)
|
---|
| 252 | {
|
---|
[3761] | 253 | LOGDDRAW (("DDRAW: paintEvent %d,%d %dx%d\n",
|
---|
| 254 | pe->rect().x(), pe->rect().y(),
|
---|
| 255 | pe->rect().width(), pe->rect().height()));
|
---|
[382] | 256 |
|
---|
[3761] | 257 | drawRect (pe->rect().x(), pe->rect().y(),
|
---|
| 258 | pe->rect().width(), pe->rect().height());
|
---|
[382] | 259 | }
|
---|
| 260 |
|
---|
| 261 | void VBoxDDRAWFrameBuffer::resizeEvent (VBoxResizeEvent *re)
|
---|
| 262 | {
|
---|
[3761] | 263 | LOGDDRAW (("DDRAW: resizeEvent %d, %p, %d %d %dx%d\n",
|
---|
| 264 | re->pixelFormat(), re->VRAM(), re->bitsPerPixel(),
|
---|
| 265 | re->bytesPerLine(), re->width(), re->height()));
|
---|
[382] | 266 |
|
---|
| 267 | VBoxFrameBuffer::resizeEvent (re);
|
---|
| 268 |
|
---|
[3761] | 269 | bool ok = createSurface (re->pixelFormat(), re->VRAM (), re->bitsPerPixel(),
|
---|
| 270 | re->bytesPerLine (), re->width(), re->height());
|
---|
[7207] | 271 | if (!ok && re->pixelFormat() != FramebufferPixelFormat_Opaque)
|
---|
[3761] | 272 | {
|
---|
| 273 | /* try to create a fallback surface with indirect buffer
|
---|
| 274 | * (only if haven't done so already) */
|
---|
[7207] | 275 | ok = createSurface (FramebufferPixelFormat_Opaque,
|
---|
[3761] | 276 | NULL, 0, 0, re->width(), re->height());
|
---|
| 277 | }
|
---|
[382] | 278 |
|
---|
[3761] | 279 | Assert (ok);
|
---|
[382] | 280 |
|
---|
[3761] | 281 | getWindowPosition();
|
---|
| 282 |
|
---|
[10149] | 283 | //#warning: port me
|
---|
| 284 | // mView->setBackgroundMode (Qt::NoBackground);
|
---|
[382] | 285 | }
|
---|
| 286 |
|
---|
| 287 | void VBoxDDRAWFrameBuffer::moveEvent (QMoveEvent *me)
|
---|
| 288 | {
|
---|
[3761] | 289 | getWindowPosition();
|
---|
[382] | 290 | }
|
---|
| 291 |
|
---|
| 292 | /*
|
---|
| 293 | * Private methods.
|
---|
| 294 | */
|
---|
| 295 |
|
---|
[3761] | 296 | /**
|
---|
| 297 | * Creates a new surface in the requested format.
|
---|
| 298 | * On success, returns @c true and assigns the created surface to mSurface
|
---|
| 299 | * and its definition to mSurfaceDesc. On failure, returns @c false.
|
---|
| 300 | *
|
---|
[7207] | 301 | * If @a aPixelFormat is other than FramebufferPixelFormat_Opaque,
|
---|
[3761] | 302 | * then the method will attempt to attach @a aVRAM directly to the created
|
---|
| 303 | * surface. If this fails, the caller may call this method again with
|
---|
[7207] | 304 | * @a aPixelFormat set to FramebufferPixelFormat_Opaque to try
|
---|
[3761] | 305 | * setting up an indirect fallback buffer for the surface. This opeartion may
|
---|
| 306 | * theoretically also fail.
|
---|
| 307 | *
|
---|
[33540] | 308 | * @note Deletes the existing surface before attempting to create a new one.
|
---|
[382] | 309 | */
|
---|
[3761] | 310 | bool VBoxDDRAWFrameBuffer::createSurface (ULONG aPixelFormat, uchar *aVRAM,
|
---|
| 311 | ULONG aBitsPerPixel, ULONG aBytesPerLine,
|
---|
| 312 | ULONG aWidth, ULONG aHeight)
|
---|
[382] | 313 | {
|
---|
[3761] | 314 | deleteSurface();
|
---|
[382] | 315 |
|
---|
| 316 | DDSURFACEDESC2 sd;
|
---|
| 317 |
|
---|
| 318 | /* Prepare the surface description structure. */
|
---|
| 319 | memset (&sd, 0, sizeof (sd));
|
---|
| 320 |
|
---|
| 321 | sd.dwSize = sizeof (sd);
|
---|
| 322 | sd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH |
|
---|
| 323 | DDSD_LPSURFACE | DDSD_PITCH | DDSD_PIXELFORMAT;
|
---|
| 324 |
|
---|
| 325 | sd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
|
---|
[3761] | 326 | sd.dwWidth = aWidth;
|
---|
| 327 | sd.dwHeight = aHeight;
|
---|
[382] | 328 |
|
---|
| 329 | /* Setup the desired pixel format on the surface. */
|
---|
| 330 |
|
---|
| 331 | sd.ddpfPixelFormat.dwSize = sizeof (sd.ddpfPixelFormat);
|
---|
| 332 | sd.ddpfPixelFormat.dwFlags = DDPF_RGB;
|
---|
| 333 |
|
---|
[3761] | 334 | if (aPixelFormat == FramebufferPixelFormat_FOURCC_RGB)
|
---|
[382] | 335 | {
|
---|
[3761] | 336 | /* Try to use the guest VRAM directly */
|
---|
[382] | 337 |
|
---|
[3761] | 338 | switch (aBitsPerPixel)
|
---|
[382] | 339 | {
|
---|
[3761] | 340 | case 32:
|
---|
| 341 | sd.ddpfPixelFormat.dwRGBBitCount = 32;
|
---|
| 342 | sd.ddpfPixelFormat.dwRBitMask = 0x00FF0000;
|
---|
| 343 | sd.ddpfPixelFormat.dwGBitMask = 0x0000FF00;
|
---|
| 344 | sd.ddpfPixelFormat.dwBBitMask = 0x000000FF;
|
---|
| 345 | break;
|
---|
| 346 | case 24:
|
---|
| 347 | sd.ddpfPixelFormat.dwRGBBitCount = 24;
|
---|
| 348 | sd.ddpfPixelFormat.dwRBitMask = 0x00FF0000;
|
---|
| 349 | sd.ddpfPixelFormat.dwGBitMask = 0x0000FF00;
|
---|
| 350 | sd.ddpfPixelFormat.dwBBitMask = 0x000000FF;
|
---|
| 351 | break;
|
---|
| 352 | case 16:
|
---|
| 353 | sd.ddpfPixelFormat.dwRGBBitCount = 16;
|
---|
| 354 | sd.ddpfPixelFormat.dwRBitMask = 0xF800;
|
---|
| 355 | sd.ddpfPixelFormat.dwGBitMask = 0x07E0;
|
---|
| 356 | sd.ddpfPixelFormat.dwBBitMask = 0x001F;
|
---|
| 357 | break;
|
---|
| 358 | default:
|
---|
[4531] | 359 | /* we don't directly support any other color depth */
|
---|
[3761] | 360 | return false;
|
---|
| 361 | }
|
---|
[382] | 362 |
|
---|
[3761] | 363 | sd.lPitch = (LONG) aBytesPerLine;
|
---|
| 364 |
|
---|
| 365 | sd.lpSurface = aVRAM;
|
---|
| 366 | mUsesGuestVRAM = true;
|
---|
| 367 |
|
---|
| 368 | mPixelFormat = FramebufferPixelFormat_FOURCC_RGB;
|
---|
[382] | 369 | }
|
---|
[3761] | 370 | else
|
---|
[7207] | 371 | if (aPixelFormat != FramebufferPixelFormat_Opaque)
|
---|
[382] | 372 | {
|
---|
[4531] | 373 | /* we don't directly support any other pixel format */
|
---|
[3761] | 374 | return false;
|
---|
[382] | 375 | }
|
---|
| 376 | else
|
---|
| 377 | {
|
---|
[3761] | 378 | /* for the Opaque format, we use the indirect memory buffer as a
|
---|
| 379 | * 32 bpp surface. */
|
---|
| 380 |
|
---|
| 381 | sd.ddpfPixelFormat.dwRGBBitCount = 32;
|
---|
| 382 | sd.ddpfPixelFormat.dwRBitMask = 0x00FF0000;
|
---|
| 383 | sd.ddpfPixelFormat.dwGBitMask = 0x0000FF00;
|
---|
| 384 | sd.ddpfPixelFormat.dwBBitMask = 0x000000FF;
|
---|
| 385 |
|
---|
| 386 | sd.lPitch = sd.dwWidth * 4;
|
---|
| 387 |
|
---|
| 388 | /* Allocate the memory buffer for the surface */
|
---|
[382] | 389 | sd.lpSurface = RTMemAlloc (sd.lPitch * sd.dwHeight);
|
---|
[3761] | 390 | if (sd.lpSurface == NULL)
|
---|
| 391 | {
|
---|
| 392 | LOGDDRAW (("DDRAW: could not allocate memory for surface.\n"));
|
---|
| 393 | return false;
|
---|
| 394 | }
|
---|
| 395 | mUsesGuestVRAM = false;
|
---|
[382] | 396 |
|
---|
[3761] | 397 | mPixelFormat = FramebufferPixelFormat_FOURCC_RGB;
|
---|
[382] | 398 | }
|
---|
| 399 |
|
---|
[3761] | 400 | /* create the surface */
|
---|
| 401 | HRESULT rc = mDDRAW->CreateSurface (&sd, &mSurface, NULL);
|
---|
[382] | 402 |
|
---|
| 403 | if (rc != DD_OK)
|
---|
| 404 | {
|
---|
[3761] | 405 | LOGDDRAW (("DDRAW: Could not create DirectDraw surface, rc=0x%08X\n", rc));
|
---|
| 406 | deleteSurface();
|
---|
| 407 | return false;
|
---|
[382] | 408 | }
|
---|
[4531] | 409 |
|
---|
[3761] | 410 | /* Initialize the surface description member. It will be used to obtain
|
---|
| 411 | * address, bpp and bpl. */
|
---|
| 412 | mSurfaceDesc = sd;
|
---|
[4531] | 413 |
|
---|
[3761] | 414 | LOGDDRAW(("DDRAW: Created %s surface: format = %d, address = %p\n",
|
---|
| 415 | mUsesGuestVRAM ? "GuestVRAM": "system memory",
|
---|
| 416 | aPixelFormat, address ()));
|
---|
| 417 |
|
---|
| 418 | if (!mUsesGuestVRAM)
|
---|
[382] | 419 | {
|
---|
[3761] | 420 | /* Clear just created surface. */
|
---|
| 421 | memset (address(), 0, bytesPerLine() * height());
|
---|
[382] | 422 | }
|
---|
| 423 |
|
---|
[3761] | 424 | return true;
|
---|
[382] | 425 | }
|
---|
| 426 |
|
---|
| 427 | void VBoxDDRAWFrameBuffer::deleteSurface ()
|
---|
| 428 | {
|
---|
| 429 | if (mSurface)
|
---|
| 430 | {
|
---|
| 431 | mSurface->Release ();
|
---|
| 432 | mSurface = NULL;
|
---|
| 433 |
|
---|
[3761] | 434 | if (!mUsesGuestVRAM)
|
---|
[382] | 435 | {
|
---|
| 436 | RTMemFree (mSurfaceDesc.lpSurface);
|
---|
| 437 | }
|
---|
| 438 |
|
---|
| 439 | memset (&mSurfaceDesc, '\0', sizeof (mSurfaceDesc));
|
---|
[3761] | 440 | mUsesGuestVRAM = false;
|
---|
[382] | 441 | }
|
---|
| 442 | }
|
---|
| 443 |
|
---|
[3761] | 444 | /**
|
---|
| 445 | * Draws a rectangular area of guest screen DDRAW surface onto the
|
---|
[382] | 446 | * host screen primary surface.
|
---|
| 447 | */
|
---|
| 448 | void VBoxDDRAWFrameBuffer::drawRect (ULONG x, ULONG y, ULONG w, ULONG h)
|
---|
| 449 | {
|
---|
[3761] | 450 | LOGDDRAW (("DDRAW: drawRect: %d,%d, %dx%d\n", x, y, w, h));
|
---|
[382] | 451 |
|
---|
| 452 | if (mSurface && w > 0 && h > 0)
|
---|
| 453 | {
|
---|
| 454 | RECT rectSrc;
|
---|
| 455 | RECT rectDst;
|
---|
| 456 |
|
---|
| 457 | rectSrc.left = x;
|
---|
| 458 | rectSrc.right = x + w;
|
---|
| 459 | rectSrc.top = y;
|
---|
| 460 | rectSrc.bottom = y + h;
|
---|
| 461 |
|
---|
| 462 | rectDst.left = mWndX + x;
|
---|
| 463 | rectDst.right = rectDst.left + w;
|
---|
| 464 | rectDst.top = mWndY + y;
|
---|
| 465 | rectDst.bottom = rectDst.top + h;
|
---|
| 466 |
|
---|
| 467 | /* DDBLT_ASYNC performs this blit asynchronously through the
|
---|
| 468 | * first in, first out (FIFO) hardware in the order received.
|
---|
| 469 | * If no room is available in the FIFO hardware, the call fails.
|
---|
| 470 | * DDBLT_WAIT waits if blitter is busy, and returns as soon as the
|
---|
| 471 | * blit can be set up or another error occurs.
|
---|
| 472 | *
|
---|
| 473 | * I assume that DDBLT_WAIT will also wait for a room in the FIFO.
|
---|
| 474 | */
|
---|
| 475 | HRESULT rc = mPrimarySurface->Blt (&rectDst, mSurface, &rectSrc, DDBLT_ASYNC | DDBLT_WAIT, NULL);
|
---|
| 476 |
|
---|
| 477 | if (rc != DD_OK)
|
---|
| 478 | {
|
---|
| 479 | /* Repeat without DDBLT_ASYNC. */
|
---|
| 480 | LOGDDRAW(("DDRAW: drawRect: async blit failed rc = 0x%08X\n", rc));
|
---|
| 481 | rc = mPrimarySurface->Blt (&rectDst, mSurface, &rectSrc, DDBLT_WAIT, NULL);
|
---|
| 482 |
|
---|
| 483 | if (rc != DD_OK)
|
---|
| 484 | {
|
---|
| 485 | LOGDDRAW(("DDRAW: drawRect: sync blit failed rc = 0x%08X\n", rc));
|
---|
| 486 | }
|
---|
| 487 | }
|
---|
| 488 | }
|
---|
| 489 |
|
---|
| 490 | return;
|
---|
| 491 | }
|
---|
| 492 |
|
---|
| 493 | void VBoxDDRAWFrameBuffer::getWindowPosition (void)
|
---|
| 494 | {
|
---|
| 495 | // if (mPrimarySurface)
|
---|
| 496 | // {
|
---|
| 497 | // /* Lock surface to synchronize with Blt in drawRect. */
|
---|
| 498 | // DDSURFACEDESC2 sd;
|
---|
| 499 | // memset (&sd, 0, sizeof (sd));
|
---|
| 500 | // sd.dwSize = sizeof (sd);
|
---|
| 501 | //
|
---|
| 502 | // HRESULT rc = mPrimarySurface->Lock (NULL, &sd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
|
---|
| 503 | // LOGDDRAW(("DDRAW: getWindowPosition rc = 0x%08X\n", rc));
|
---|
| 504 | // }
|
---|
| 505 |
|
---|
| 506 | RECT rect;
|
---|
| 507 | GetWindowRect (mView->viewport()->winId(), &rect);
|
---|
| 508 | mWndX = rect.left;
|
---|
| 509 | mWndY = rect.top;
|
---|
| 510 |
|
---|
| 511 | // if (mPrimarySurface)
|
---|
| 512 | // {
|
---|
| 513 | // mPrimarySurface->Unlock (NULL);
|
---|
| 514 | // }
|
---|
| 515 | }
|
---|
| 516 |
|
---|
[26823] | 517 | #endif
|
---|
[26719] | 518 |
|
---|
[26823] | 519 | #endif /* VBOX_GUI_USE_DDRAW */
|
---|
| 520 |
|
---|