VirtualBox

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

Last change on this file since 47918 was 38929, checked in by vboxsync, 13 years ago

Additions/common/VBoxVideo: mistyped name caused restoring the graphics mode to fail in the X.Org Additions

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.4 KB
Line 
1/* $Id: Modesetting.cpp 38929 2011-10-02 21:55:57Z vboxsync $ */
2/** @file
3 * VirtualBox Video driver, common code - HGSMI initialisation and helper
4 * functions.
5 */
6
7/*
8 * Copyright (C) 2006-2011 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19#include <VBox/VBoxVideoGuest.h>
20#include <VBox/VBoxVideo.h>
21#include <VBox/VBoxGuest.h>
22#include <VBox/Hardware/VBoxVideoVBE.h>
23#include <VBox/VMMDev.h>
24
25#include <iprt/asm.h>
26#include <iprt/log.h>
27
28/**
29 * Gets the count of virtual monitors attached to the guest via an HGSMI
30 * command
31 *
32 * @returns the right count on success or 1 on failure.
33 * @param pCtx the context containing the heap to use
34 */
35RTDECL(uint32_t) VBoxHGSMIGetMonitorCount(PHGSMIGUESTCOMMANDCONTEXT pCtx)
36{
37 /* Query the configured number of displays. */
38 uint32_t cDisplays = 0;
39 VBoxQueryConfHGSMI(pCtx, VBOX_VBVA_CONF32_MONITOR_COUNT, &cDisplays);
40 LogFunc(("cDisplays = %d\n", cDisplays));
41 if (cDisplays == 0 || cDisplays > VBOX_VIDEO_MAX_SCREENS)
42 /* Host reported some bad value. Continue in the 1 screen mode. */
43 cDisplays = 1;
44 return cDisplays;
45}
46
47
48/**
49 * Returns the size of the video RAM in bytes.
50 *
51 * @returns the size
52 */
53RTDECL(uint32_t) VBoxVideoGetVRAMSize(void)
54{
55 /** @note A 32bit read on this port returns the VRAM size. */
56 return VBoxVideoCmnPortReadUlong(VBE_DISPI_IOPORT_DATA);
57}
58
59
60/**
61 * Check whether this hardware allows the display width to have non-multiple-
62 * of-eight values.
63 *
64 * @returns true if any width is allowed, false otherwise.
65 */
66RTDECL(bool) VBoxVideoAnyWidthAllowed(void)
67{
68 unsigned DispiId;
69 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
70 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID_ANYX);
71 DispiId = VBoxVideoCmnPortReadUshort(VBE_DISPI_IOPORT_DATA);
72 return (DispiId == VBE_DISPI_ID_ANYX);
73}
74
75
76/**
77 * Tell the host about how VRAM is divided up between each screen via an HGSMI
78 * command. It is acceptable to specifiy identical data for each screen if
79 * they share a single framebuffer.
80 *
81 * @returns iprt status code, either VERR_NO_MEMORY or the status returned by
82 * @a pfnFill
83 * @todo What was I thinking of with that callback function? It
84 * would be much simpler to just pass in a structure in normal
85 * memory and copy it.
86 * @param pCtx the context containing the heap to use
87 * @param u32Count the number of screens we are activating
88 * @param pfnFill a callback which initialises the VBVAINFOVIEW structures
89 * for all screens
90 * @param pvData context data for @a pfnFill
91 */
92RTDECL(int) VBoxHGSMISendViewInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx,
93 uint32_t u32Count,
94 PFNHGSMIFILLVIEWINFO pfnFill,
95 void *pvData)
96{
97 int rc;
98 /* Issue the screen info command. */
99 void *p = VBoxHGSMIBufferAlloc(pCtx, sizeof(VBVAINFOVIEW) * u32Count,
100 HGSMI_CH_VBVA, VBVA_INFO_VIEW);
101 if (p)
102 {
103 VBVAINFOVIEW *pInfo = (VBVAINFOVIEW *)p;
104 rc = pfnFill(pvData, pInfo, u32Count);
105 if (RT_SUCCESS(rc))
106 VBoxHGSMIBufferSubmit (pCtx, p);
107 VBoxHGSMIBufferFree(pCtx, p);
108 }
109 else
110 rc = VERR_NO_MEMORY;
111 return rc;
112}
113
114
115/**
116 * Set a video mode using port registers. This must be done for the first
117 * screen before every HGSMI modeset and also works when HGSM is not enabled.
118 * @param cWidth the mode width
119 * @param cHeight the mode height
120 * @param cVirtWidth the mode pitch
121 * @param cBPP the colour depth of the mode
122 * @param fFlags flags for the mode. These will be or-ed with the
123 * default _ENABLED flag, so unless you are restoring
124 * a saved mode or have special requirements you can pass
125 * zero here.
126 * @param cx the horizontal panning offset
127 * @param cy the vertical panning offset
128 */
129RTDECL(void) VBoxVideoSetModeRegisters(uint16_t cWidth, uint16_t cHeight,
130 uint16_t cVirtWidth, uint16_t cBPP,
131 uint16_t fFlags, uint16_t cx,
132 uint16_t cy)
133{
134 /* set the mode characteristics */
135 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
136 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA, cWidth);
137 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
138 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA, cHeight);
139 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
140 VBE_DISPI_INDEX_VIRT_WIDTH);
141 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA, cVirtWidth);
142 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
143 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA, cBPP);
144 /* enable the mode */
145 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
146 VBE_DISPI_INDEX_ENABLE);
147 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA,
148 fFlags | VBE_DISPI_ENABLED);
149 /* Panning registers */
150 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
151 VBE_DISPI_INDEX_X_OFFSET);
152 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA, cx);
153 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
154 VBE_DISPI_INDEX_Y_OFFSET);
155 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA, cy);
156 /** @todo read from the port to see if the mode switch was successful */
157}
158
159
160/**
161 * Get the video mode for the first screen using the port registers. All
162 * parameters are optional
163 * @returns true if the VBE mode returned is active, false if we are in VGA
164 * mode
165 * @note If anyone else needs additional register values just extend the
166 * function with additional parameters and fix any existing callers.
167 * @param pcWidth where to store the mode width
168 * @param pcHeight where to store the mode height
169 * @param pcVirtWidth where to store the mode pitch
170 * @param pcBPP where to store the colour depth of the mode
171 * @param pfFlags where to store the flags for the mode
172 */
173RTDECL(bool) VBoxVideoGetModeRegisters(uint16_t *pcWidth, uint16_t *pcHeight,
174 uint16_t *pcVirtWidth, uint16_t *pcBPP,
175 uint16_t *pfFlags)
176{
177 uint16_t fFlags;
178
179 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
180 VBE_DISPI_INDEX_ENABLE);
181 fFlags = VBoxVideoCmnPortReadUshort(VBE_DISPI_IOPORT_DATA);
182 if (pcWidth)
183 {
184 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
185 VBE_DISPI_INDEX_XRES);
186 *pcWidth = VBoxVideoCmnPortReadUshort(VBE_DISPI_IOPORT_DATA);
187 }
188 if (pcHeight)
189 {
190 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
191 VBE_DISPI_INDEX_YRES);
192 *pcHeight = VBoxVideoCmnPortReadUshort(VBE_DISPI_IOPORT_DATA);
193 }
194 if (pcVirtWidth)
195 {
196 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
197 VBE_DISPI_INDEX_VIRT_WIDTH);
198 *pcVirtWidth = VBoxVideoCmnPortReadUshort(VBE_DISPI_IOPORT_DATA);
199 }
200 if (pcBPP)
201 {
202 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
203 VBE_DISPI_INDEX_BPP);
204 *pcBPP = VBoxVideoCmnPortReadUshort(VBE_DISPI_IOPORT_DATA);
205 }
206 if (pfFlags)
207 *pfFlags = fFlags;
208 return RT_BOOL(fFlags & VBE_DISPI_ENABLED);
209}
210
211
212/**
213 * Disable our extended graphics mode and go back to VGA mode.
214 */
215RTDECL(void) VBoxVideoDisableVBE(void)
216{
217 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
218 VBE_DISPI_INDEX_ENABLE);
219 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA, 0);
220}
221
222
223/**
224 * Set a video mode via an HGSMI request. The views must have been
225 * initialised first using @a VBoxHGSMISendViewInfo and if the mode is being
226 * set on the first display then it must be set first using registers.
227 * @param cDisplay the screen number
228 * @param cOriginX the horizontal displacement relative to the first screen
229 * @param cOriginY the vertical displacement relative to the first screen
230 * @param offStart the offset of the visible area of the framebuffer
231 * relative to the framebuffer start
232 * @param cbPitch the offset in bytes between the starts of two adjecent
233 * scan lines in video RAM
234 * @param cWidth the mode width
235 * @param cHeight the mode height
236 * @param cBPP the colour depth of the mode
237 */
238RTDECL(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}
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