VirtualBox

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

Last change on this file since 43310 was 43310, checked in by vboxsync, 12 years ago

Additions/x11/vboxvideo: small efficiency fix.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 8.9 KB
Line 
1/** @file
2 * VirtualBox X11 Additions graphics driver 2D acceleration functions
3 */
4
5/*
6 * Copyright (C) 2006-2007 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/**************************************************************************
36* Main functions *
37**************************************************************************/
38
39/**
40 * Callback function called by the X server to tell us about dirty
41 * rectangles in the video buffer.
42 *
43 * @param pScreen pointer to the information structure for the current
44 * screen
45 * @param iRects Number of dirty rectangles to update
46 * @param aRects Array of structures containing the coordinates of the
47 * rectangles
48 */
49static void
50vboxHandleDirtyRect(ScrnInfoPtr pScrn, int iRects, BoxPtr aRects)
51{
52 VBVACMDHDR cmdHdr;
53 VBOXPtr pVBox;
54 int i;
55 unsigned j;
56
57 pVBox = pScrn->driverPrivate;
58 if (pVBox->fHaveHGSMI == FALSE || !pScrn->vtSema)
59 return;
60
61 for (j = 0; j < pVBox->cScreens; ++j)
62 {
63 /* Just continue quietly if VBVA is not currently active. */
64 struct VBVABUFFER *pVBVA = pVBox->aVbvaCtx[j].pVBVA;
65 if ( !pVBVA
66 || !(pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_ENABLED))
67 continue;
68 for (i = 0; i < iRects; ++i)
69 {
70 if ( aRects[i].x1 > pVBox->aScreenLocation[j].x
71 + pVBox->aScreenLocation[j].cx
72 || aRects[i].y1 > pVBox->aScreenLocation[j].y
73 + pVBox->aScreenLocation[j].cy
74 || aRects[i].x2 < pVBox->aScreenLocation[j].x
75 || aRects[i].y2 < pVBox->aScreenLocation[j].y)
76 continue;
77 cmdHdr.x = (int16_t)aRects[i].x1;
78 cmdHdr.y = (int16_t)aRects[i].y1;
79 cmdHdr.w = (uint16_t)(aRects[i].x2 - aRects[i].x1);
80 cmdHdr.h = (uint16_t)(aRects[i].y2 - aRects[i].y1);
81
82#if 0
83 TRACE_LOG("display=%u, x=%d, y=%d, w=%d, h=%d\n",
84 j, cmdHdr.x, cmdHdr.y, cmdHdr.w, cmdHdr.h);
85#endif
86
87 if (VBoxVBVABufferBeginUpdate(&pVBox->aVbvaCtx[j],
88 &pVBox->guestCtx))
89 {
90 VBoxVBVAWrite(&pVBox->aVbvaCtx[j], &pVBox->guestCtx, &cmdHdr,
91 sizeof(cmdHdr));
92 VBoxVBVABufferEndUpdate(&pVBox->aVbvaCtx[j]);
93 }
94 }
95 }
96}
97
98/** Callback to fill in the view structures */
99static int
100vboxFillViewInfo(void *pvVBox, struct VBVAINFOVIEW *pViews, uint32_t cViews)
101{
102 VBOXPtr pVBox = (VBOXPtr)pvVBox;
103 unsigned i;
104 for (i = 0; i < cViews; ++i)
105 {
106 pViews[i].u32ViewIndex = i;
107 pViews[i].u32ViewOffset = 0;
108 pViews[i].u32ViewSize = pVBox->cbView;
109 pViews[i].u32MaxScreenSize = pVBox->cbFBMax;
110 }
111 return VINF_SUCCESS;
112}
113
114/**
115 * Initialise VirtualBox's accelerated video extensions.
116 *
117 * @returns TRUE on success, FALSE on failure
118 */
119static Bool
120vboxInitVbva(int scrnIndex, ScreenPtr pScreen, VBOXPtr pVBox)
121{
122 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
123 int rc = VINF_SUCCESS;
124
125 /* Why is this here? In case things break before we have found the real
126 * count? */
127 pVBox->cScreens = 1;
128 if (!VBoxHGSMIIsSupported())
129 {
130 xf86DrvMsg(scrnIndex, X_ERROR, "The graphics device does not seem to support HGSMI. Disableing video acceleration.\n");
131 return FALSE;
132 }
133
134 /* Set up the dirty rectangle handler. It will be added into a function
135 * chain and gets removed when the screen is cleaned up. */
136 if (ShadowFBInit2(pScreen, NULL, vboxHandleDirtyRect) != TRUE)
137 {
138 xf86DrvMsg(scrnIndex, X_ERROR,
139 "Unable to install dirty rectangle handler for VirtualBox graphics acceleration.\n");
140 return FALSE;
141 }
142 return TRUE;
143}
144
145/**
146 * Initialise VirtualBox's accelerated video extensions.
147 *
148 * @returns TRUE on success, FALSE on failure
149 */
150static Bool
151vboxSetupVRAMVbva(ScrnInfoPtr pScrn, VBOXPtr pVBox)
152{
153 int rc = VINF_SUCCESS;
154 unsigned i;
155 uint32_t offVRAMBaseMapping, offGuestHeapMemory, cbGuestHeapMemory;
156 void *pvGuestHeapMemory;
157
158 if (!pVBox->fHaveHGSMI)
159 return FALSE;
160 VBoxHGSMIGetBaseMappingInfo(pScrn->videoRam * 1024, &offVRAMBaseMapping,
161 NULL, &offGuestHeapMemory, &cbGuestHeapMemory,
162 NULL);
163 pvGuestHeapMemory = ((uint8_t *)pVBox->base) + offVRAMBaseMapping
164 + offGuestHeapMemory;
165 TRACE_LOG("video RAM: %u KB, guest heap offset: 0x%x, cbGuestHeapMemory: %u\n",
166 pScrn->videoRam, offVRAMBaseMapping + offGuestHeapMemory,
167 cbGuestHeapMemory);
168 rc = VBoxHGSMISetupGuestContext(&pVBox->guestCtx, pvGuestHeapMemory,
169 cbGuestHeapMemory,
170 offVRAMBaseMapping + offGuestHeapMemory);
171 if (RT_FAILURE(rc))
172 {
173 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set up the guest-to-host communication context, rc=%d\n", rc);
174 return FALSE;
175 }
176 pVBox->cbView = pVBox->cbFBMax = offVRAMBaseMapping;
177 pVBox->cScreens = VBoxHGSMIGetMonitorCount(&pVBox->guestCtx);
178 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested monitor count: %u\n",
179 pVBox->cScreens);
180 for (i = 0; i < pVBox->cScreens; ++i)
181 {
182 pVBox->cbFBMax -= VBVA_MIN_BUFFER_SIZE;
183 pVBox->aoffVBVABuffer[i] = pVBox->cbFBMax;
184 TRACE_LOG("VBVA buffer offset for screen %u: 0x%lx\n", i,
185 (unsigned long) pVBox->cbFBMax);
186 VBoxVBVASetupBufferContext(&pVBox->aVbvaCtx[i],
187 pVBox->aoffVBVABuffer[i],
188 VBVA_MIN_BUFFER_SIZE);
189 }
190 TRACE_LOG("Maximum framebuffer size: %lu (0x%lx)\n",
191 (unsigned long) pVBox->cbFBMax,
192 (unsigned long) pVBox->cbFBMax);
193 rc = VBoxHGSMISendViewInfo(&pVBox->guestCtx, pVBox->cScreens,
194 vboxFillViewInfo, (void *)pVBox);
195 if (RT_FAILURE(rc))
196 {
197 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to send the view information to the host, rc=%d\n", rc);
198 return FALSE;
199 }
200 return TRUE;
201}
202
203Bool
204vbox_open(ScrnInfoPtr pScrn, ScreenPtr pScreen, VBOXPtr pVBox)
205{
206 TRACE_ENTRY();
207
208 pVBox->fHaveHGSMI = vboxInitVbva(pScrn->scrnIndex, pScreen, pVBox);
209 return pVBox->fHaveHGSMI;
210}
211
212Bool
213vbox_device_available(VBOXPtr pVBox)
214{
215 return pVBox->useDevice;
216}
217
218/**
219 * Inform VBox that we will supply it with dirty rectangle information
220 * and install the dirty rectangle handler.
221 *
222 * @returns TRUE for success, FALSE for failure
223 * @param pScrn Pointer to a structure describing the X screen in use
224 */
225Bool
226vboxEnableVbva(ScrnInfoPtr pScrn)
227{
228 bool rc = TRUE;
229 int scrnIndex = pScrn->scrnIndex;
230 unsigned i;
231 VBOXPtr pVBox = pScrn->driverPrivate;
232
233 TRACE_ENTRY();
234 if (!vboxSetupVRAMVbva(pScrn, pVBox))
235 return FALSE;
236 for (i = 0; i < pVBox->cScreens; ++i)
237 {
238 struct VBVABUFFER *pVBVA;
239
240 pVBVA = (struct VBVABUFFER *) ( ((uint8_t *)pVBox->base)
241 + pVBox->aoffVBVABuffer[i]);
242 if (!VBoxVBVAEnable(&pVBox->aVbvaCtx[i], &pVBox->guestCtx, pVBVA, i))
243 rc = FALSE;
244 }
245 if (!rc)
246 {
247 /* Request not accepted - disable for old hosts. */
248 xf86DrvMsg(scrnIndex, X_ERROR,
249 "Failed to enable screen update reporting for at least one virtual monitor.\n");
250 vboxDisableVbva(pScrn);
251 }
252 return rc;
253}
254
255/**
256 * Inform VBox that we will stop supplying it with dirty rectangle
257 * information. This function is intended to be called when an X
258 * virtual terminal is disabled, or the X server is terminated.
259 *
260 * @returns TRUE for success, FALSE for failure
261 * @param pScrn Pointer to a structure describing the X screen in use
262 */
263void
264vboxDisableVbva(ScrnInfoPtr pScrn)
265{
266 int rc;
267 int scrnIndex = pScrn->scrnIndex;
268 unsigned i;
269 VBOXPtr pVBox = pScrn->driverPrivate;
270
271 TRACE_ENTRY();
272 if (!pVBox->fHaveHGSMI) /* Ths function should not have been called */
273 return;
274 for (i = 0; i < pVBox->cScreens; ++i)
275 VBoxVBVADisable(&pVBox->aVbvaCtx[i], &pVBox->guestCtx, i);
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