VirtualBox

source: vbox/trunk/src/VBox/Additions/common/VBoxVideo/Modesetting.cpp@ 69366

Last change on this file since 69366 was 69309, checked in by vboxsync, 7 years ago

common/VBoxVideo: scm update and todo regarding syntax checking/library

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