VirtualBox

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

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

Additions/linux/drm: fix wrong order in Linux outb/w/l uses.
bugref:8524: Additions/linux: play nicely with distribution-installed Additions

Linux reverses the parameter order of I/O out commands compared to everyone
else I know, and we were blindly replacing our VBVO_PORT_WRITE_ functions
with Linux out ones without touching the parameters. Fixing this requires
some not very nice use of sed. Improvements welcome.

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