VirtualBox

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

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

Additions/linux/drm: lots of formatting changes to match kernel style.
bugref:8524: Additions/linux: play nicely with distribution-installed Additions

This change makes a lot of formatting changes to the Linux Additions drm
driver, with no intended changes to functionality, and much of the
formatting change done using the sed script which installs the driver
sources to the Additions archive. Hans de Goede's clean-up of the driver for
submission to staging is the base for these changes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.6 KB
Line 
1/* $Id: Modesetting.cpp 68848 2017-09-24 16:58:46Z 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,
149 VBE_DISPI_INDEX_VIRT_WIDTH);
150 VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA, cVirtWidth);
151 VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
152 VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA, cBPP);
153 /* enable the mode */
154 VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX,
155 VBE_DISPI_INDEX_ENABLE);
156 VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA,
157 fFlags | VBE_DISPI_ENABLED);
158 /* Panning registers */
159 VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX,
160 VBE_DISPI_INDEX_X_OFFSET);
161 VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA, cx);
162 VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX,
163 VBE_DISPI_INDEX_Y_OFFSET);
164 VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA, cy);
165 /** @todo read from the port to see if the mode switch was successful */
166}
167
168
169/**
170 * Get the video mode for the first screen using the port registers. All
171 * parameters are optional
172 * @returns true if the VBE mode returned is active, false if we are in VGA
173 * mode
174 * @note If anyone else needs additional register values just extend the
175 * function with additional parameters and fix any existing callers.
176 * @param pcWidth where to store the mode width
177 * @param pcHeight where to store the mode height
178 * @param pcVirtWidth where to store the mode pitch
179 * @param pcBPP where to store the colour depth of the mode
180 * @param pfFlags where to store the flags for the mode
181 */
182DECLHIDDEN(bool) VBoxVideoGetModeRegisters(uint16_t *pcWidth, uint16_t *pcHeight,
183 uint16_t *pcVirtWidth, uint16_t *pcBPP,
184 uint16_t *pfFlags)
185{
186 uint16_t fFlags;
187
188 VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX,
189 VBE_DISPI_INDEX_ENABLE);
190 fFlags = VBVO_PORT_READ_U16(VBE_DISPI_IOPORT_DATA);
191 if (pcWidth)
192 {
193 VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX,
194 VBE_DISPI_INDEX_XRES);
195 *pcWidth = VBVO_PORT_READ_U16(VBE_DISPI_IOPORT_DATA);
196 }
197 if (pcHeight)
198 {
199 VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX,
200 VBE_DISPI_INDEX_YRES);
201 *pcHeight = VBVO_PORT_READ_U16(VBE_DISPI_IOPORT_DATA);
202 }
203 if (pcVirtWidth)
204 {
205 VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX,
206 VBE_DISPI_INDEX_VIRT_WIDTH);
207 *pcVirtWidth = VBVO_PORT_READ_U16(VBE_DISPI_IOPORT_DATA);
208 }
209 if (pcBPP)
210 {
211 VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX,
212 VBE_DISPI_INDEX_BPP);
213 *pcBPP = VBVO_PORT_READ_U16(VBE_DISPI_IOPORT_DATA);
214 }
215 if (pfFlags)
216 *pfFlags = fFlags;
217 return RT_BOOL(fFlags & VBE_DISPI_ENABLED);
218}
219
220
221/**
222 * Disable our extended graphics mode and go back to VGA mode.
223 */
224DECLHIDDEN(void) VBoxVideoDisableVBE(void)
225{
226 VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX,
227 VBE_DISPI_INDEX_ENABLE);
228 VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA, 0);
229}
230
231
232/**
233 * Set a video mode via an HGSMI request. The views must have been
234 * initialised first using @a VBoxHGSMISendViewInfo and if the mode is being
235 * set on the first display then it must be set first using registers.
236 * @param pCtx The context containing the heap to use.
237 * @param cDisplay the screen number
238 * @param cOriginX the horizontal displacement relative to the first screen
239 * @param cOriginY the vertical displacement relative to the first screen
240 * @param offStart the offset of the visible area of the framebuffer
241 * relative to the framebuffer start
242 * @param cbPitch the offset in bytes between the starts of two adjecent
243 * scan lines in video RAM
244 * @param cWidth the mode width
245 * @param cHeight the mode height
246 * @param cBPP the colour depth of the mode
247 * @param fFlags flags
248 */
249DECLHIDDEN(void) VBoxHGSMIProcessDisplayInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx,
250 uint32_t cDisplay,
251 int32_t cOriginX,
252 int32_t cOriginY,
253 uint32_t offStart,
254 uint32_t cbPitch,
255 uint32_t cWidth,
256 uint32_t cHeight,
257 uint16_t cBPP,
258 uint16_t fFlags)
259{
260 /* Issue the screen info command. */
261 void *p = VBoxHGSMIBufferAlloc(pCtx,
262 sizeof (VBVAINFOSCREEN),
263 HGSMI_CH_VBVA,
264 VBVA_INFO_SCREEN);
265 if (!p)
266 {
267 // LogFunc(("HGSMIHeapAlloc failed\n"));
268 }
269 else
270 {
271 VBVAINFOSCREEN *pScreen = (VBVAINFOSCREEN *)p;
272
273 pScreen->u32ViewIndex = cDisplay;
274 pScreen->i32OriginX = cOriginX;
275 pScreen->i32OriginY = cOriginY;
276 pScreen->u32StartOffset = offStart;
277 pScreen->u32LineSize = cbPitch;
278 pScreen->u32Width = cWidth;
279 pScreen->u32Height = cHeight;
280 pScreen->u16BitsPerPixel = cBPP;
281 pScreen->u16Flags = fFlags;
282
283 VBoxHGSMIBufferSubmit(pCtx, p);
284
285 VBoxHGSMIBufferFree(pCtx, p);
286 }
287}
288
289
290/** Report the rectangle relative to which absolute pointer events should be
291 * expressed. This information remains valid until the next VBVA resize event
292 * for any screen, at which time it is reset to the bounding rectangle of all
293 * virtual screens.
294 * @param pCtx The context containing the heap to use.
295 * @param cOriginX Upper left X co-ordinate relative to the first screen.
296 * @param cOriginY Upper left Y co-ordinate relative to the first screen.
297 * @param cWidth Rectangle width.
298 * @param cHeight Rectangle height.
299 * @returns iprt status code.
300 * @returns VERR_NO_MEMORY HGSMI heap allocation failed.
301 */
302DECLHIDDEN(int) VBoxHGSMIUpdateInputMapping(PHGSMIGUESTCOMMANDCONTEXT pCtx, int32_t cOriginX, int32_t cOriginY,
303 uint32_t cWidth, uint32_t cHeight)
304{
305 int rc = VINF_SUCCESS;
306 VBVAREPORTINPUTMAPPING *p;
307 // Log(("%s: cOriginX=%d, cOriginY=%d, cWidth=%u, cHeight=%u\n", __PRETTY_FUNCTION__, (int)cOriginX, (int)cOriginX,
308 // (unsigned)cWidth, (unsigned)cHeight));
309
310 /* Allocate the IO buffer. */
311 p = (VBVAREPORTINPUTMAPPING *)VBoxHGSMIBufferAlloc(pCtx, sizeof(VBVAREPORTINPUTMAPPING), HGSMI_CH_VBVA,
312 VBVA_REPORT_INPUT_MAPPING);
313 if (p)
314 {
315 /* Prepare data to be sent to the host. */
316 p->x = cOriginX;
317 p->y = cOriginY;
318 p->cx = cWidth;
319 p->cy = cHeight;
320 rc = VBoxHGSMIBufferSubmit(pCtx, p);
321 /* Free the IO buffer. */
322 VBoxHGSMIBufferFree(pCtx, p);
323 }
324 else
325 rc = VERR_NO_MEMORY;
326 // LogFunc(("rc = %d\n", rc));
327 return rc;
328}
329
330
331/**
332 * Get most recent video mode hints.
333 * @param pCtx the context containing the heap to use
334 * @param cScreens the number of screens to query hints for, starting at 0.
335 * @param paHints array of VBVAMODEHINT structures for receiving the hints.
336 * @returns iprt status code
337 * @returns VERR_NO_MEMORY HGSMI heap allocation failed.
338 * @returns VERR_NOT_SUPPORTED Host does not support this command.
339 */
340DECLHIDDEN(int) VBoxHGSMIGetModeHints(PHGSMIGUESTCOMMANDCONTEXT pCtx,
341 unsigned cScreens, VBVAMODEHINT *paHints)
342{
343 int rc;
344 void *p;
345
346 AssertPtr(paHints);
347 if (!VALID_PTR(paHints))
348 return VERR_INVALID_POINTER;
349
350 p = VBoxHGSMIBufferAlloc(pCtx, sizeof(VBVAQUERYMODEHINTS)
351 + cScreens * sizeof(VBVAMODEHINT),
352 HGSMI_CH_VBVA, VBVA_QUERY_MODE_HINTS);
353 if (!p)
354 {
355 // LogFunc(("HGSMIHeapAlloc failed\n"));
356 return VERR_NO_MEMORY;
357 }
358 else
359 {
360 VBVAQUERYMODEHINTS *pQuery = (VBVAQUERYMODEHINTS *)p;
361
362 pQuery->cHintsQueried = cScreens;
363 pQuery->cbHintStructureGuest = sizeof(VBVAMODEHINT);
364 pQuery->rc = VERR_NOT_SUPPORTED;
365
366 VBoxHGSMIBufferSubmit(pCtx, p);
367 rc = pQuery->rc;
368 if (RT_SUCCESS(rc))
369 memcpy(paHints, ((uint8_t *)p) + sizeof(VBVAQUERYMODEHINTS),
370 cScreens * sizeof(VBVAMODEHINT));
371
372 VBoxHGSMIBufferFree(pCtx, p);
373 }
374 return rc;
375}
376
377
378/**
379 * Query the supported flags in VBVAINFOSCREEN::u16Flags.
380 *
381 * @returns The mask of VBVA_SCREEN_F_* flags or 0 if host does not support the request.
382 * @param pCtx the context containing the heap to use
383 */
384DECLHIDDEN(uint16_t) VBoxHGSMIGetScreenFlags(PHGSMIGUESTCOMMANDCONTEXT pCtx)
385{
386 uint32_t u32Flags = 0;
387 int rc = VBoxQueryConfHGSMI(pCtx, VBOX_VBVA_CONF32_SCREEN_FLAGS, &u32Flags);
388 // LogFunc(("u32Flags = 0x%x rc %Rrc\n", u32Flags, rc));
389 if (RT_FAILURE(rc) || u32Flags > UINT16_MAX)
390 u32Flags = 0;
391 return (uint16_t)u32Flags;
392}
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