VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Miniport/Helper.cpp@ 28264

Last change on this file since 28264 was 28264, checked in by vboxsync, 15 years ago

VideoModeSupported for multimonitor. (xTracker 4655)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.8 KB
Line 
1/** @file
2 *
3 * VBoxGuest -- VirtualBox Win 2000/XP guest video driver
4 *
5 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
6 *
7 * This file is part of VirtualBox Open Source Edition (OSE), as
8 * available from http://www.virtualbox.org. This file is free software;
9 * you can redistribute it and/or modify it under the terms of the GNU
10 * General Public License (GPL) as published by the Free Software
11 * Foundation, in version 2 as it comes in the "COPYING" file of the
12 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
13 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
14 *
15 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
16 * Clara, CA 95054 USA or visit http://www.sun.com if you need
17 * additional information or have any questions.
18 */
19
20// enable backdoor logging
21//#define LOG_ENABLED
22#ifndef VBOXWDDM
23extern "C"
24{
25# include <ntddk.h>
26}
27#else
28# include "VBoxVideo.h"
29#endif
30
31#include <VBox/err.h>
32
33#include <VBox/VBoxGuestLib.h>
34
35#ifndef VBOXWDDM
36/* the video miniport headers not compatible with the NT DDK headers */
37typedef struct _VIDEO_POINTER_ATTRIBUTES
38{
39 ULONG Flags;
40 ULONG Width;
41 ULONG Height;
42 ULONG WidthInBytes;
43 ULONG Enable;
44 SHORT Column;
45 SHORT Row;
46 UCHAR Pixels[1];
47} VIDEO_POINTER_ATTRIBUTES, *PVIDEO_POINTER_ATTRIBUTES;
48#define VIDEO_MODE_COLOR_POINTER 0x04 // 1 if a color hardware pointer is
49 // supported.
50#endif /* #ifndef VBOXWDDM */
51
52#include "Helper.h"
53
54#ifdef DEBUG_misha
55bool g_bVBoxVDbgBreakF = true;
56bool g_bVBoxVDbgBreakFv = false;
57#endif
58
59/**
60 * Globals
61 */
62/* note: should not do that but we can't use these datatypes in the global header */
63
64#pragma alloc_text(PAGE, vboxQueryDisplayRequest)
65#pragma alloc_text(PAGE, vboxLikesVideoMode)
66#pragma alloc_text(PAGE, vboxGetHeightReduction)
67#pragma alloc_text(PAGE, vboxQueryPointerPos)
68#pragma alloc_text(PAGE, vboxQueryHostWantsAbsolute)
69#pragma alloc_text(PAGE, vboxQueryWinVersion)
70
71BOOLEAN vboxQueryDisplayRequest(uint32_t *xres, uint32_t *yres, uint32_t *bpp, uint32_t *pDisplayId)
72{
73 BOOLEAN bRC = FALSE;
74
75 dprintf(("VBoxVideo::vboxQueryDisplayRequest: xres = 0x%p, yres = 0x%p bpp = 0x%p\n", xres, yres, bpp));
76
77 VMMDevDisplayChangeRequest2 *req = NULL;
78
79 int rc = VbglGRAlloc ((VMMDevRequestHeader **)&req, sizeof (VMMDevDisplayChangeRequest2), VMMDevReq_GetDisplayChangeRequest2);
80
81 if (RT_FAILURE(rc))
82 {
83 dprintf(("VBoxVideo::vboxQueryDisplayRequest: ERROR allocating request, rc = %Rrc\n", rc));
84 }
85 else
86 {
87 req->eventAck = 0;
88
89 rc = VbglGRPerform (&req->header);
90
91 if (RT_SUCCESS(rc))
92 {
93 if (xres)
94 *xres = req->xres;
95 if (yres)
96 *yres = req->yres;
97 if (bpp)
98 *bpp = req->bpp;
99 if (pDisplayId)
100 *pDisplayId = req->display;
101 dprintf(("VBoxVideo::vboxQueryDisplayRequest: returning %d x %d @ %d for %d\n",
102 req->xres, req->yres, req->bpp, req->display));
103 bRC = TRUE;
104 }
105 else
106 {
107 dprintf(("VBoxVideo::vboxQueryDisplayRequest: ERROR querying display request from VMMDev. "
108 "rc = %Rrc\n", rc));
109 }
110
111 VbglGRFree (&req->header);
112 }
113
114 return bRC;
115}
116
117BOOLEAN vboxLikesVideoMode(uint32_t display, uint32_t width, uint32_t height, uint32_t bpp)
118{
119 BOOLEAN bRC = FALSE;
120
121 VMMDevVideoModeSupportedRequest2 *req2 = NULL;
122
123 int rc = VbglGRAlloc((VMMDevRequestHeader**)&req2, sizeof(VMMDevVideoModeSupportedRequest2), VMMDevReq_VideoModeSupported2);
124 if (RT_FAILURE(rc))
125 {
126 dprintf(("VBoxVideo::vboxLikesVideoMode: ERROR allocating request, rc = %Rrc\n", rc));
127 /* Most likely the VBoxGuest driver is not loaded.
128 * To get at least the video working, report the mode as supported.
129 */
130 bRC = TRUE;
131 }
132 else
133 {
134 req2->display = display;
135 req2->width = width;
136 req2->height = height;
137 req2->bpp = bpp;
138 rc = VbglGRPerform(&req2->header);
139 if (RT_SUCCESS(rc) && RT_SUCCESS(req2->header.rc))
140 {
141 bRC = req2->fSupported;
142 }
143 else
144 {
145 /* Retry using old inteface. */
146 AssertCompile(sizeof(VMMDevVideoModeSupportedRequest2) >= sizeof(VMMDevVideoModeSupportedRequest));
147 VMMDevVideoModeSupportedRequest *req = (VMMDevVideoModeSupportedRequest *)req2;
148 req->header.size = sizeof(VMMDevVideoModeSupportedRequest);
149 req->header.version = VMMDEV_REQUEST_HEADER_VERSION;
150 req->header.requestType = VMMDevReq_VideoModeSupported;
151 req->header.rc = VERR_GENERAL_FAILURE;
152 req->header.reserved1 = 0;
153 req->header.reserved2 = 0;
154 req->width = width;
155 req->height = height;
156 req->bpp = bpp;
157
158 rc = VbglGRPerform(&req->header);
159 if (RT_SUCCESS(rc) && RT_SUCCESS(req->header.rc))
160 {
161 bRC = req->fSupported;
162 }
163 else
164 {
165 dprintf(("VBoxVideo::vboxLikesVideoMode: ERROR querying video mode supported status from VMMDev."
166 "rc = %Rrc\n", rc));
167 }
168 }
169 VbglGRFree(&req2->header);
170 }
171
172 dprintf(("VBoxVideo::vboxLikesVideoMode: width: %d, height: %d, bpp: %d -> %s\n", width, height, bpp, (bRC == 1) ? "OK" : "FALSE"));
173
174 return bRC;
175}
176
177ULONG vboxGetHeightReduction()
178{
179 ULONG retHeight = 0;
180
181 dprintf(("VBoxVideo::vboxGetHeightReduction\n"));
182
183 VMMDevGetHeightReductionRequest *req = NULL;
184
185 int rc = VbglGRAlloc((VMMDevRequestHeader**)&req, sizeof(VMMDevGetHeightReductionRequest), VMMDevReq_GetHeightReduction);
186 if (RT_FAILURE(rc))
187 {
188 dprintf(("VBoxVideo::vboxGetHeightReduction: ERROR allocating request, rc = %Rrc\n", rc));
189 }
190 else
191 {
192 rc = VbglGRPerform(&req->header);
193 if (RT_SUCCESS(rc))
194 {
195 retHeight = (ULONG)req->heightReduction;
196 }
197 else
198 {
199 dprintf(("VBoxVideo::vboxGetHeightReduction: ERROR querying height reduction value from VMMDev. "
200 "rc = %Rrc\n", rc));
201 }
202 VbglGRFree(&req->header);
203 }
204
205 dprintf(("VBoxVideoMode::vboxGetHeightReduction: returning %d\n", retHeight));
206 return retHeight;
207}
208
209static BOOLEAN vboxQueryPointerPosInternal (uint16_t *pointerXPos, uint16_t *pointerYPos)
210{
211 BOOLEAN bRC = FALSE;
212
213 /* Activate next line only when really needed; floods the log very quickly! */
214 /*dprintf(("VBoxVideo::vboxQueryPointerPosInternal: pointerXPos = %p, pointerYPos = %p\n", pointerXPos, pointerYPos));*/
215
216 VMMDevReqMouseStatus *req = NULL;
217
218 int rc = VbglGRAlloc ((VMMDevRequestHeader **)&req, sizeof (VMMDevReqMouseStatus), VMMDevReq_GetMouseStatus);
219
220 if (RT_FAILURE(rc))
221 {
222 dprintf(("VBoxVideo::vboxQueryPointerPosInternal: ERROR allocating request, rc = %Rrc\n", rc));
223 }
224 else
225 {
226 rc = VbglGRPerform (&req->header);
227
228 if (RT_SUCCESS(rc))
229 {
230 if (req->mouseFeatures & VMMDEV_MOUSE_HOST_CAN_ABSOLUTE)
231 {
232 if (pointerXPos)
233 {
234 *pointerXPos = req->pointerXPos;
235 }
236
237 if (pointerYPos)
238 {
239 *pointerYPos = req->pointerYPos;
240 }
241
242 bRC = TRUE;
243 }
244 }
245 else
246 {
247 dprintf(("VBoxVideo::vboxQueryPointerPosInternal: ERROR querying mouse capabilities from VMMDev. "
248 "rc = %Rrc\n", rc));
249 }
250
251 VbglGRFree (&req->header);
252 }
253
254 return bRC;
255}
256
257/**
258 * Return the current absolute mouse position in normalized format
259 * (between 0 and 0xFFFF).
260 *
261 * @returns BOOLEAN success indicator
262 * @param pointerXPos address of result variable for x pos
263 * @param pointerYPos address of result variable for y pos
264 */
265BOOLEAN vboxQueryPointerPos(uint16_t *pointerXPos, uint16_t *pointerYPos)
266{
267 if (!pointerXPos || !pointerYPos)
268 {
269 return FALSE;
270 }
271
272 return vboxQueryPointerPosInternal (pointerXPos, pointerYPos);
273}
274
275/**
276 * Returns whether the host wants us to take absolute coordinates.
277 *
278 * @returns BOOLEAN TRUE if the host wants to send absolute coordinates.
279 */
280BOOLEAN vboxQueryHostWantsAbsolute (void)
281{
282 return vboxQueryPointerPosInternal (NULL, NULL);
283}
284
285winVersion_t vboxQueryWinVersion()
286{
287 static winVersion_t winVersion = UNKNOWN_WINVERSION;
288 ULONG majorVersion;
289 ULONG minorVersion;
290 ULONG buildNumber;
291
292 if (winVersion != UNKNOWN_WINVERSION)
293 return winVersion;
294
295 PsGetVersion(&majorVersion, &minorVersion, &buildNumber, NULL);
296
297 dprintf(("VBoxVideo::vboxQueryWinVersion: running on Windows NT version %d.%d, build %d\n",
298 majorVersion, minorVersion, buildNumber));
299 if(majorVersion == 6)
300 {
301 if (minorVersion == 1)
302 winVersion = WIN7;
303 else if (minorVersion == 0)
304 winVersion = WINVISTA; /* Or Windows Server 2008. */
305 }
306 else if (majorVersion == 5)
307 {
308 if (minorVersion >= 1)
309 {
310 winVersion = WINXP;
311 } else
312 {
313 winVersion = WIN2K;
314 }
315 }
316 else if (majorVersion == 4)
317 {
318 winVersion = WINNT4;
319 }
320 else
321 {
322 dprintf(("VBoxVideo::vboxQueryWinVersion: NT4 required!\n"));
323 }
324 return winVersion;
325}
326
327#ifndef VBOX_WITH_HGSMI
328/**
329 * Sends the pointer shape to the VMMDev
330 *
331 * @returns success indicator
332 * @param pointerAttr pointer description
333 */
334BOOLEAN vboxUpdatePointerShape(PVIDEO_POINTER_ATTRIBUTES pointerAttr, uint32_t cbLength)
335{
336 uint32_t cbData = 0;
337
338 if (pointerAttr->Enable & VBOX_MOUSE_POINTER_SHAPE)
339 {
340 cbData = ((((pointerAttr->Width + 7) / 8) * pointerAttr->Height + 3) & ~3)
341 + pointerAttr->Width * 4 * pointerAttr->Height;
342 }
343
344 if (cbData > cbLength - sizeof(VIDEO_POINTER_ATTRIBUTES))
345 {
346 dprintf(("vboxUpdatePointerShape: calculated pointer data size is too big (%d bytes, limit %d)\n",
347 cbData, cbLength - sizeof(VIDEO_POINTER_ATTRIBUTES)));
348 return FALSE;
349 }
350
351 BOOLEAN bRC = FALSE;
352
353 VMMDevReqMousePointer *req = NULL;
354
355 int rc = VbglGRAlloc ((VMMDevRequestHeader **)&req, sizeof (VMMDevReqMousePointer) + cbData, VMMDevReq_SetPointerShape);
356
357 if (RT_FAILURE(rc))
358 {
359 dprintf(("VBoxVideo::vboxUpdatePointerShape: ERROR allocating request, rc = %Rrc\n", rc));
360 }
361 else
362 {
363 /* Activate next line only when really needed; floods the log very quickly! */
364 /*dprintf(("VBoxVideo::vboxUpdatePointerShape: req->u32Version = %08X\n", req->header.version));*/
365
366 /* We have our custom flags in the field */
367 req->fFlags = pointerAttr->Enable & 0xFFFF;
368
369 /* Even if pointer is invisible, we have to pass following data,
370 * so host could create the pointer with initial status - invisible
371 */
372 req->xHot = (pointerAttr->Enable >> 16) & 0xFF;
373 req->yHot = (pointerAttr->Enable >> 24) & 0xFF;
374 req->width = pointerAttr->Width;
375 req->height = pointerAttr->Height;
376
377 if (req->fFlags & VBOX_MOUSE_POINTER_SHAPE)
378 {
379 /* copy the actual pointer data */
380 memcpy (req->pointerData, pointerAttr->Pixels, cbData);
381 }
382
383 rc = VbglGRPerform (&req->header);
384
385 if (RT_SUCCESS(rc) && RT_SUCCESS(req->header.rc))
386 {
387 bRC = TRUE;
388 }
389 else
390 {
391 dprintf(("VBoxVideo::vboxUpdatePointerShape: ERROR querying mouse capabilities from VMMDev. "
392 "rc = %Rrc\n", rc));
393 }
394
395 dprintf(("VBoxVideo::vboxUpdatePointerShape: req->u32Version = %08X\n", req->header.version));
396
397 VbglGRFree (&req->header);
398 }
399
400 return bRC;
401}
402#endif /* VBOX_WITH_HGSMI */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette