VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/vboxvideo/vbva.c@ 55262

Last change on this file since 55262 was 55262, checked in by vboxsync, 10 years ago

Additions/x11/vboxvideo: reverted temporary commit r99563.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 10.0 KB
Line 
1/** @file
2 * VirtualBox X11 Additions graphics driver 2D acceleration functions
3 */
4
5/*
6 * Copyright (C) 2006-2012 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 */
16
17#include <VBox/VMMDev.h>
18#include <VBox/VBoxGuestLib.h>
19
20#ifndef PCIACCESS
21# include <xf86Pci.h>
22# include <Pci.h>
23#endif
24
25#include "xf86.h"
26#define NEED_XF86_TYPES
27#include <iprt/string.h>
28#include "compiler.h"
29
30/* ShadowFB support */
31#include "shadowfb.h"
32
33#include "vboxvideo.h"
34
35#ifdef XORG_7X
36# include <stdlib.h>
37#endif
38
39/**************************************************************************
40* Main functions *
41**************************************************************************/
42
43/**
44 * Callback function called by the X server to tell us about dirty
45 * rectangles in the video buffer.
46 *
47 * @param pScreen pointer to the information structure for the current
48 * screen
49 * @param iRects Number of dirty rectangles to update
50 * @param aRects Array of structures containing the coordinates of the
51 * rectangles
52 */
53static void
54vboxHandleDirtyRect(ScrnInfoPtr pScrn, int iRects, BoxPtr aRects)
55{
56 VBVACMDHDR cmdHdr;
57 VBOXPtr pVBox;
58 int i;
59 unsigned j;
60
61 pVBox = pScrn->driverPrivate;
62 if (!pScrn->vtSema)
63 return;
64
65 for (j = 0; j < pVBox->cScreens; ++j)
66 {
67 /* Just continue quietly if VBVA is not currently active. */
68 struct VBVABUFFER *pVBVA = pVBox->pScreens[j].aVbvaCtx.pVBVA;
69 if ( !pVBVA
70 || !(pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_ENABLED))
71 continue;
72 for (i = 0; i < iRects; ++i)
73 {
74 if ( aRects[i].x1 > pVBox->pScreens[j].aScreenLocation.x
75 + pVBox->pScreens[j].aScreenLocation.cx
76 || aRects[i].y1 > pVBox->pScreens[j].aScreenLocation.y
77 + pVBox->pScreens[j].aScreenLocation.cy
78 || aRects[i].x2 < pVBox->pScreens[j].aScreenLocation.x
79 || aRects[i].y2 < pVBox->pScreens[j].aScreenLocation.y)
80 continue;
81 cmdHdr.x = (int16_t)aRects[i].x1;
82 cmdHdr.y = (int16_t)aRects[i].y1;
83 cmdHdr.w = (uint16_t)(aRects[i].x2 - aRects[i].x1);
84 cmdHdr.h = (uint16_t)(aRects[i].y2 - aRects[i].y1);
85
86#if 0
87 TRACE_LOG("display=%u, x=%d, y=%d, w=%d, h=%d\n",
88 j, cmdHdr.x, cmdHdr.y, cmdHdr.w, cmdHdr.h);
89#endif
90
91 if (VBoxVBVABufferBeginUpdate(&pVBox->pScreens[j].aVbvaCtx,
92 &pVBox->guestCtx))
93 {
94 VBoxVBVAWrite(&pVBox->pScreens[j].aVbvaCtx, &pVBox->guestCtx, &cmdHdr,
95 sizeof(cmdHdr));
96 VBoxVBVABufferEndUpdate(&pVBox->pScreens[j].aVbvaCtx);
97 }
98 }
99 }
100}
101
102/** Callback to fill in the view structures */
103static int
104vboxFillViewInfo(void *pvVBox, struct VBVAINFOVIEW *pViews, uint32_t cViews)
105{
106 VBOXPtr pVBox = (VBOXPtr)pvVBox;
107 unsigned i;
108 for (i = 0; i < cViews; ++i)
109 {
110 pViews[i].u32ViewIndex = i;
111 pViews[i].u32ViewOffset = 0;
112 pViews[i].u32ViewSize = pVBox->cbView;
113 pViews[i].u32MaxScreenSize = pVBox->cbFBMax;
114 }
115 return VINF_SUCCESS;
116}
117
118/**
119 * Initialise VirtualBox's accelerated video extensions.
120 *
121 * @returns TRUE on success, FALSE on failure
122 */
123static Bool
124vboxInitVbva(int scrnIndex, ScreenPtr pScreen, VBOXPtr pVBox)
125{
126 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
127 int rc = VINF_SUCCESS;
128
129 /* Why is this here? In case things break before we have found the real
130 * count? */
131 pVBox->cScreens = 1;
132 if (!VBoxHGSMIIsSupported())
133 {
134 xf86DrvMsg(scrnIndex, X_ERROR, "The graphics device does not seem to support HGSMI. Disableing video acceleration.\n");
135 return FALSE;
136 }
137
138 /* Set up the dirty rectangle handler. It will be added into a function
139 * chain and gets removed when the screen is cleaned up. */
140 if (ShadowFBInit2(pScreen, NULL, vboxHandleDirtyRect) != TRUE)
141 {
142 xf86DrvMsg(scrnIndex, X_ERROR,
143 "Unable to install dirty rectangle handler for VirtualBox graphics acceleration.\n");
144 return FALSE;
145 }
146 return TRUE;
147}
148
149static DECLCALLBACK(void *) hgsmiEnvAlloc(void *pvEnv, HGSMISIZE cb)
150{
151 NOREF(pvEnv);
152 return calloc(1, cb);
153}
154
155static DECLCALLBACK(void) hgsmiEnvFree(void *pvEnv, void *pv)
156{
157 NOREF(pvEnv);
158 free(pv);
159}
160
161static HGSMIENV g_hgsmiEnv =
162{
163 NULL,
164 hgsmiEnvAlloc,
165 hgsmiEnvFree
166};
167
168/**
169 * Initialise VirtualBox's accelerated video extensions.
170 *
171 * @returns TRUE on success, FALSE on failure
172 */
173static Bool
174vboxSetupVRAMVbva(ScrnInfoPtr pScrn, VBOXPtr pVBox)
175{
176 int rc = VINF_SUCCESS;
177 unsigned i;
178 uint32_t offVRAMBaseMapping, offGuestHeapMemory, cbGuestHeapMemory;
179 void *pvGuestHeapMemory;
180
181 VBoxHGSMIGetBaseMappingInfo(pScrn->videoRam * 1024, &offVRAMBaseMapping,
182 NULL, &offGuestHeapMemory, &cbGuestHeapMemory,
183 NULL);
184 pvGuestHeapMemory = ((uint8_t *)pVBox->base) + offVRAMBaseMapping
185 + offGuestHeapMemory;
186 TRACE_LOG("video RAM: %u KB, guest heap offset: 0x%x, cbGuestHeapMemory: %u\n",
187 pScrn->videoRam, offVRAMBaseMapping + offGuestHeapMemory,
188 cbGuestHeapMemory);
189 rc = VBoxHGSMISetupGuestContext(&pVBox->guestCtx, pvGuestHeapMemory,
190 cbGuestHeapMemory,
191 offVRAMBaseMapping + offGuestHeapMemory,
192 &g_hgsmiEnv);
193 if (RT_FAILURE(rc))
194 {
195 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set up the guest-to-host communication context, rc=%d\n", rc);
196 return FALSE;
197 }
198 pVBox->cbView = pVBox->cbFBMax = offVRAMBaseMapping;
199 pVBox->cScreens = VBoxHGSMIGetMonitorCount(&pVBox->guestCtx);
200 pVBox->pScreens = calloc(pVBox->cScreens, sizeof(*pVBox->pScreens));
201 if (pVBox->pScreens == NULL)
202 FatalError("Failed to allocate memory for screens array.\n");
203#ifdef VBOXVIDEO_13
204 pVBox->paVBVAModeHints = calloc(pVBox->cScreens,
205 sizeof(*pVBox->paVBVAModeHints));
206 if (pVBox->paVBVAModeHints == NULL)
207 FatalError("Failed to allocate memory for mode hints array.\n");
208#endif
209 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested monitor count: %u\n",
210 pVBox->cScreens);
211 for (i = 0; i < pVBox->cScreens; ++i)
212 {
213 pVBox->cbFBMax -= VBVA_MIN_BUFFER_SIZE;
214 pVBox->pScreens[i].aoffVBVABuffer = pVBox->cbFBMax;
215 TRACE_LOG("VBVA buffer offset for screen %u: 0x%lx\n", i,
216 (unsigned long) pVBox->cbFBMax);
217 VBoxVBVASetupBufferContext(&pVBox->pScreens[i].aVbvaCtx,
218 pVBox->pScreens[i].aoffVBVABuffer,
219 VBVA_MIN_BUFFER_SIZE);
220 }
221 TRACE_LOG("Maximum framebuffer size: %lu (0x%lx)\n",
222 (unsigned long) pVBox->cbFBMax,
223 (unsigned long) pVBox->cbFBMax);
224 rc = VBoxHGSMISendViewInfo(&pVBox->guestCtx, pVBox->cScreens,
225 vboxFillViewInfo, (void *)pVBox);
226 if (RT_FAILURE(rc))
227 {
228 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to send the view information to the host, rc=%d\n", rc);
229 return FALSE;
230 }
231 return TRUE;
232}
233
234void
235vbox_open(ScrnInfoPtr pScrn, ScreenPtr pScreen, VBOXPtr pVBox)
236{
237 TRACE_ENTRY();
238
239 if (!vboxInitVbva(pScrn->scrnIndex, pScreen, pVBox))
240 FatalError("failed to initialise vboxvideo graphics acceleration.\n");
241}
242
243/**
244 * Inform VBox that we will supply it with dirty rectangle information
245 * and install the dirty rectangle handler.
246 *
247 * @returns TRUE for success, FALSE for failure
248 * @param pScrn Pointer to a structure describing the X screen in use
249 */
250Bool
251vboxEnableVbva(ScrnInfoPtr pScrn)
252{
253 bool rc = TRUE;
254 int scrnIndex = pScrn->scrnIndex;
255 unsigned i;
256 VBOXPtr pVBox = pScrn->driverPrivate;
257
258 TRACE_ENTRY();
259 if (!vboxSetupVRAMVbva(pScrn, pVBox))
260 return FALSE;
261 for (i = 0; i < pVBox->cScreens; ++i)
262 {
263 struct VBVABUFFER *pVBVA;
264
265 pVBVA = (struct VBVABUFFER *) ( ((uint8_t *)pVBox->base)
266 + pVBox->pScreens[i].aoffVBVABuffer);
267 if (!VBoxVBVAEnable(&pVBox->pScreens[i].aVbvaCtx, &pVBox->guestCtx,
268 pVBVA, i))
269 rc = FALSE;
270 }
271 if (!rc)
272 {
273 /* Request not accepted - disable for old hosts. */
274 xf86DrvMsg(scrnIndex, X_ERROR,
275 "Failed to enable screen update reporting for at least one virtual monitor.\n");
276 vboxDisableVbva(pScrn);
277 }
278#ifdef VBOXVIDEO_13
279# ifdef RT_OS_LINUX
280 if (rc && pVBox->hACPIEventHandler != NULL)
281 /* We ignore the return value as the fall-back should be active
282 * anyway. */
283 VBoxHGSMISendCapsInfo(&pVBox->guestCtx, VBVACAPS_VIDEO_MODE_HINTS | VBVACAPS_DISABLE_CURSOR_INTEGRATION);
284# endif
285#endif
286 return rc;
287}
288
289/**
290 * Inform VBox that we will stop supplying it with dirty rectangle
291 * information. This function is intended to be called when an X
292 * virtual terminal is disabled, or the X server is terminated.
293 *
294 * @returns TRUE for success, FALSE for failure
295 * @param pScrn Pointer to a structure describing the X screen in use
296 */
297void
298vboxDisableVbva(ScrnInfoPtr pScrn)
299{
300 int rc;
301 int scrnIndex = pScrn->scrnIndex;
302 unsigned i;
303 VBOXPtr pVBox = pScrn->driverPrivate;
304
305 TRACE_ENTRY();
306 for (i = 0; i < pVBox->cScreens; ++i)
307 VBoxVBVADisable(&pVBox->pScreens[i].aVbvaCtx, &pVBox->guestCtx, i);
308}
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