VirtualBox

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

Last change on this file since 37291 was 35999, checked in by vboxsync, 14 years ago

Additions/common/VBoxVideo: fix an index write.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.0 KB
Line 
1/* $Id: Modesetting.cpp 35999 2011-02-16 17:38:01Z vboxsync $ */
2/** @file
3 * VirtualBox Video driver, common code - HGSMI initialisation and helper
4 * functions.
5 */
6
7/*
8 * Copyright (C) 2006-2010 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 * Tell the host about how VRAM is divided up between each screen via an HGSMI
50 * command. It is acceptable to specifiy identical data for each screen if
51 * they share a single framebuffer.
52 *
53 * @returns iprt status code, either VERR_NO_MEMORY or the status returned by
54 * @a pfnFill
55 * @param pCtx the context containing the heap to use
56 * @param u32Count the number of screens we are activating
57 * @param pfnFill a callback which initialises the VBVAINFOVIEW structures
58 * for all screens
59 * @param pvData context data for @a pfnFill
60 */
61RTDECL(int) VBoxHGSMISendViewInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx,
62 uint32_t u32Count,
63 PFNHGSMIFILLVIEWINFO pfnFill,
64 void *pvData)
65{
66 int rc;
67 /* Issue the screen info command. */
68 void *p = VBoxHGSMIBufferAlloc(pCtx, sizeof(VBVAINFOVIEW) * u32Count,
69 HGSMI_CH_VBVA, VBVA_INFO_VIEW);
70 if (p)
71 {
72 VBVAINFOVIEW *pInfo = (VBVAINFOVIEW *)p;
73 rc = pfnFill(pvData, pInfo, u32Count);
74 if (RT_SUCCESS(rc))
75 VBoxHGSMIBufferSubmit (pCtx, p);
76 VBoxHGSMIBufferFree(pCtx, p);
77 }
78 else
79 rc = VERR_NO_MEMORY;
80 return rc;
81}
82
83
84/**
85 * Set a video mode using port registers. This must be done for the first
86 * screen before every HGSMI modeset and also works when HGSM is not enabled.
87 * @param cWidth the mode width
88 * @param cHeight the mode height
89 * @param cVirtWidth the mode pitch
90 * @param cBPP the colour depth of the mode
91 * @param fFlags flags for the mode. These will be or-ed with the
92 * default _ENABLED flag, so unless you are restoring
93 * a saved mode or have special requirements you can pass
94 * zero here.
95 * @param cx the horizontal panning offset
96 * @param cy the vertical panning offset
97 */
98RTDECL(void) VBoxVideoSetModeRegisters(uint16_t cWidth, uint16_t cHeight,
99 uint16_t cVirtWidth, uint16_t cBPP,
100 uint16_t fFlags, uint16_t cx,
101 uint16_t cy)
102{
103 /* set the mode characteristics */
104 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
105 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA, cWidth);
106 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
107 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA, cHeight);
108 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
109 VBE_DISPI_INDEX_VIRT_WIDTH);
110 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA, cVirtWidth);
111 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
112 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA, cBPP);
113 /* enable the mode */
114 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
115 VBE_DISPI_INDEX_ENABLE);
116 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA,
117 fFlags | VBE_DISPI_ENABLED);
118 /* Panning registers */
119 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
120 VBE_DISPI_INDEX_X_OFFSET);
121 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA, cx);
122 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
123 VBE_DISPI_INDEX_Y_OFFSET);
124 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA, cy);
125 /** @todo read from the port to see if the mode switch was successful */
126}
127
128
129/**
130 * Get the video mode for the first screen using the port registers. All
131 * parameters are optional
132 * @returns true if the VBE mode returned is active, false if we are in VGA
133 * mode
134 * @note If anyone else needs additional register values just extend the
135 * function with additional parameters and fix any existing callers.
136 * @param pcWidth where to store the mode width
137 * @param pcHeight where to store the mode height
138 * @param pcVirtWidth where to store the mode pitch
139 * @param pcBPP where to store the colour depth of the mode
140 * @param pfFlags where to store the flags for the mode
141 */
142RTDECL(bool) VBoxVideoGetModeRegisters(uint16_t *pcWidth, uint16_t *pcHeight,
143 uint16_t *pcVirtWidth, uint16_t *pcBPP,
144 uint16_t *pfFlags)
145{
146 uint16_t fFlags;
147
148 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
149 VBE_DISPI_ENABLED);
150 fFlags = VBoxVideoCmnPortReadUshort(VBE_DISPI_IOPORT_DATA);
151 if (pcWidth)
152 {
153 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
154 VBE_DISPI_INDEX_XRES);
155 *pcWidth = VBoxVideoCmnPortReadUshort(VBE_DISPI_IOPORT_DATA);
156 }
157 if (pcHeight)
158 {
159 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
160 VBE_DISPI_INDEX_YRES);
161 *pcHeight = VBoxVideoCmnPortReadUshort(VBE_DISPI_IOPORT_DATA);
162 }
163 if (pcVirtWidth)
164 {
165 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
166 VBE_DISPI_INDEX_VIRT_WIDTH);
167 *pcVirtWidth = VBoxVideoCmnPortReadUshort(VBE_DISPI_IOPORT_DATA);
168 }
169 if (pcBPP)
170 {
171 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
172 VBE_DISPI_INDEX_BPP);
173 *pcBPP = VBoxVideoCmnPortReadUshort(VBE_DISPI_IOPORT_DATA);
174 }
175 if (pfFlags)
176 *pfFlags = fFlags;
177 return RT_BOOL(fFlags & VBE_DISPI_ENABLED);
178}
179
180
181/**
182 * Get the video mode for the first screen using the port registers. All
183 * parameters are optional
184 * @note If anyone else needs additional values just extend the function with
185 * additional parameters and fix any existing callers.
186 * @param pcWidth where to store the mode width
187 * @param pcHeight where to store the mode height
188 * @param pcVirtWidth where to store the mode pitch
189 * @param pcBPP where to store the colour depth of the mode
190 * @param pfFlags where to store the flags for the mode
191 */
192RTDECL(void) VBoxVideoDisableVBE(void)
193{
194 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX,
195 VBE_DISPI_INDEX_ENABLE);
196 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA, 0);
197}
198
199
200/**
201 * Set a video mode via an HGSMI request. The views must have been
202 * initialised first using @a VBoxHGSMISendViewInfo and if the mode is being
203 * set on the first display then it must be set first using registers.
204 * @param cDisplay the screen number
205 * @param cOriginX the horizontal displacement relative to the first screen
206 * @param cOriginY the vertical displacement relative to the first screen
207 * @param offStart the offset of the visible area of the framebuffer
208 * relative to the framebuffer start
209 * @param cbPitch the offset in bytes between the starts of two adjecent
210 * scan lines in video RAM
211 * @param cWidth the mode width
212 * @param cHeight the mode height
213 * @param cBPP the colour depth of the mode
214 */
215RTDECL(void) VBoxHGSMIProcessDisplayInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx,
216 uint32_t cDisplay,
217 int32_t cOriginX,
218 int32_t cOriginY,
219 uint32_t offStart,
220 uint32_t cbPitch,
221 uint32_t cWidth,
222 uint32_t cHeight,
223 uint16_t cBPP,
224 uint16_t fFlags)
225{
226 /* Issue the screen info command. */
227 void *p = VBoxHGSMIBufferAlloc(pCtx,
228 sizeof (VBVAINFOSCREEN),
229 HGSMI_CH_VBVA,
230 VBVA_INFO_SCREEN);
231 if (!p)
232 {
233 LogFunc(("HGSMIHeapAlloc failed\n"));
234 }
235 else
236 {
237 VBVAINFOSCREEN *pScreen = (VBVAINFOSCREEN *)p;
238
239 pScreen->u32ViewIndex = cDisplay;
240 pScreen->i32OriginX = cOriginX;
241 pScreen->i32OriginY = cOriginY;
242 pScreen->u32StartOffset = offStart;
243 pScreen->u32LineSize = cbPitch;
244 pScreen->u32Width = cWidth;
245 pScreen->u32Height = cHeight;
246 pScreen->u16BitsPerPixel = cBPP;
247 pScreen->u16Flags = fFlags;
248
249 VBoxHGSMIBufferSubmit(pCtx, p);
250
251 VBoxHGSMIBufferFree(pCtx, p);
252 }
253}
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