VirtualBox

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

Last change on this file since 60180 was 60083, checked in by vboxsync, 9 years ago

bugref:8288: Additions/x11: rework VBoxClient video mode hint handling: reworked the display parts of VBoxClient. Now they only use standard X11 mechanisms for any recent server version, which means that the same code works with the kernel and the user-space driver, and also wait for about two seconds before changing the mode, cancelling if some one else is faster, to avoid interfering with mechanisms provided by the desktop environment. With old servers we get mode hints from a property updated by the driver. The user space driver code has been updated to match, and has also dropped pre-HGSMI mechanisms for getting mode hints.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 8.5 KB
Line 
1/* $Id: vbva.c 60083 2016-03-17 18:40:28Z vboxsync $ */
2/** @file
3 * VirtualBox X11 Additions graphics driver 2D acceleration functions
4 */
5
6/*
7 * Copyright (C) 2006-2012 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include <VBox/VMMDev.h>
19#include <VBox/VBoxGuestLib.h>
20
21#include <iprt/string.h>
22#include "compiler.h"
23
24#include "vboxvideo.h"
25
26#ifdef XORG_7X
27# include <stdlib.h>
28#endif
29
30/**************************************************************************
31* Main functions *
32**************************************************************************/
33
34/**
35 * Callback function called by the X server to tell us about dirty
36 * rectangles in the video buffer.
37 *
38 * @param pScreen pointer to the information structure for the current
39 * screen
40 * @param iRects Number of dirty rectangles to update
41 * @param aRects Array of structures containing the coordinates of the
42 * rectangles
43 */
44void vbvxHandleDirtyRect(ScrnInfoPtr pScrn, int iRects, BoxPtr aRects)
45{
46 VBVACMDHDR cmdHdr;
47 VBOXPtr pVBox;
48 int i;
49 unsigned j;
50
51 pVBox = pScrn->driverPrivate;
52 if (!pScrn->vtSema)
53 return;
54
55 for (j = 0; j < pVBox->cScreens; ++j)
56 {
57 /* Just continue quietly if VBVA is not currently active. */
58 struct VBVABUFFER *pVBVA = pVBox->pScreens[j].aVbvaCtx.pVBVA;
59 if ( !pVBVA
60 || !(pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_ENABLED))
61 continue;
62 for (i = 0; i < iRects; ++i)
63 {
64 if ( aRects[i].x1 > pVBox->pScreens[j].aScreenLocation.x
65 + pVBox->pScreens[j].aScreenLocation.cx
66 || aRects[i].y1 > pVBox->pScreens[j].aScreenLocation.y
67 + pVBox->pScreens[j].aScreenLocation.cy
68 || aRects[i].x2 < pVBox->pScreens[j].aScreenLocation.x
69 || aRects[i].y2 < pVBox->pScreens[j].aScreenLocation.y)
70 continue;
71 cmdHdr.x = (int16_t)aRects[i].x1 - pVBox->pScreens[0].aScreenLocation.x;
72 cmdHdr.y = (int16_t)aRects[i].y1 - pVBox->pScreens[0].aScreenLocation.y;
73 cmdHdr.w = (uint16_t)(aRects[i].x2 - aRects[i].x1);
74 cmdHdr.h = (uint16_t)(aRects[i].y2 - aRects[i].y1);
75
76#if 0
77 TRACE_LOG("display=%u, x=%d, y=%d, w=%d, h=%d\n",
78 j, cmdHdr.x, cmdHdr.y, cmdHdr.w, cmdHdr.h);
79#endif
80
81 if (VBoxVBVABufferBeginUpdate(&pVBox->pScreens[j].aVbvaCtx,
82 &pVBox->guestCtx))
83 {
84 VBoxVBVAWrite(&pVBox->pScreens[j].aVbvaCtx, &pVBox->guestCtx, &cmdHdr,
85 sizeof(cmdHdr));
86 VBoxVBVABufferEndUpdate(&pVBox->pScreens[j].aVbvaCtx);
87 }
88 }
89 }
90}
91
92static DECLCALLBACK(void *) hgsmiEnvAlloc(void *pvEnv, HGSMISIZE cb)
93{
94 NOREF(pvEnv);
95 return calloc(1, cb);
96}
97
98static DECLCALLBACK(void) hgsmiEnvFree(void *pvEnv, void *pv)
99{
100 NOREF(pvEnv);
101 free(pv);
102}
103
104static HGSMIENV g_hgsmiEnv =
105{
106 NULL,
107 hgsmiEnvAlloc,
108 hgsmiEnvFree
109};
110
111/**
112 * Calculate the location in video RAM of and initialise the heap for guest to
113 * host messages. In the VirtualBox 4.3 and earlier Guest Additions this
114 * function creates the heap structures directly in guest video RAM, so it
115 * needs to be called whenever video RAM is (re-)set-up.
116 */
117void vbvxSetUpHGSMIHeapInGuest(VBOXPtr pVBox, uint32_t cbVRAM)
118{
119 int rc;
120 uint32_t offVRAMBaseMapping, offGuestHeapMemory, cbGuestHeapMemory;
121 void *pvGuestHeapMemory;
122
123 VBoxHGSMIGetBaseMappingInfo(cbVRAM, &offVRAMBaseMapping, NULL, &offGuestHeapMemory, &cbGuestHeapMemory, NULL);
124 pvGuestHeapMemory = ((uint8_t *)pVBox->base) + offVRAMBaseMapping + offGuestHeapMemory;
125 rc = VBoxHGSMISetupGuestContext(&pVBox->guestCtx, pvGuestHeapMemory, cbGuestHeapMemory,
126 offVRAMBaseMapping + offGuestHeapMemory, &g_hgsmiEnv);
127 VBVXASSERT(RT_SUCCESS(rc), ("Failed to set up the guest-to-host message buffer heap, rc=%d\n", rc));
128 pVBox->cbView = offVRAMBaseMapping;
129}
130
131/** Callback to fill in the view structures */
132static DECLCALLBACK(int) vboxFillViewInfo(void *pvVBox, struct VBVAINFOVIEW *pViews, uint32_t cViews)
133{
134 VBOXPtr pVBox = (VBOXPtr)pvVBox;
135 unsigned i;
136 for (i = 0; i < cViews; ++i)
137 {
138 pViews[i].u32ViewIndex = i;
139 pViews[i].u32ViewOffset = 0;
140 pViews[i].u32ViewSize = pVBox->cbView;
141 pViews[i].u32MaxScreenSize = pVBox->cbFBMax;
142 }
143 return VINF_SUCCESS;
144}
145
146/**
147 * Initialise VirtualBox's accelerated video extensions.
148 *
149 * @returns TRUE on success, FALSE on failure
150 */
151static Bool vboxSetupVRAMVbva(VBOXPtr pVBox)
152{
153 int rc = VINF_SUCCESS;
154 unsigned i;
155
156 pVBox->cbFBMax = pVBox->cbView;
157 for (i = 0; i < pVBox->cScreens; ++i)
158 {
159 pVBox->cbFBMax -= VBVA_MIN_BUFFER_SIZE;
160 pVBox->pScreens[i].aoffVBVABuffer = pVBox->cbFBMax;
161 TRACE_LOG("VBVA buffer offset for screen %u: 0x%lx\n", i,
162 (unsigned long) pVBox->cbFBMax);
163 VBoxVBVASetupBufferContext(&pVBox->pScreens[i].aVbvaCtx,
164 pVBox->pScreens[i].aoffVBVABuffer,
165 VBVA_MIN_BUFFER_SIZE);
166 }
167 TRACE_LOG("Maximum framebuffer size: %lu (0x%lx)\n",
168 (unsigned long) pVBox->cbFBMax,
169 (unsigned long) pVBox->cbFBMax);
170 rc = VBoxHGSMISendViewInfo(&pVBox->guestCtx, pVBox->cScreens,
171 vboxFillViewInfo, (void *)pVBox);
172 VBVXASSERT(RT_SUCCESS(rc), ("Failed to send the view information to the host, rc=%d\n", rc));
173 return TRUE;
174}
175
176static bool haveHGSMIModeHintAndCursorReportingInterface(VBOXPtr pVBox)
177{
178 uint32_t fModeHintReporting, fCursorReporting;
179
180 return RT_SUCCESS(VBoxQueryConfHGSMI(&pVBox->guestCtx, VBOX_VBVA_CONF32_MODE_HINT_REPORTING, &fModeHintReporting))
181 && RT_SUCCESS(VBoxQueryConfHGSMI(&pVBox->guestCtx, VBOX_VBVA_CONF32_GUEST_CURSOR_REPORTING, &fCursorReporting))
182 && fModeHintReporting == VINF_SUCCESS
183 && fCursorReporting == VINF_SUCCESS;
184}
185
186static bool hostHasScreenBlankingFlag(VBOXPtr pVBox)
187{
188 uint32_t fScreenFlags;
189
190 return RT_SUCCESS(VBoxQueryConfHGSMI(&pVBox->guestCtx, VBOX_VBVA_CONF32_SCREEN_FLAGS, &fScreenFlags))
191 && fScreenFlags & VBVA_SCREEN_F_BLANK;
192}
193
194/**
195 * Inform VBox that we will supply it with dirty rectangle information
196 * and install the dirty rectangle handler.
197 *
198 * @returns TRUE for success, FALSE for failure
199 * @param pScrn Pointer to a structure describing the X screen in use
200 */
201Bool
202vboxEnableVbva(ScrnInfoPtr pScrn)
203{
204 bool rc = TRUE;
205 unsigned i;
206 VBOXPtr pVBox = pScrn->driverPrivate;
207
208 TRACE_ENTRY();
209 if (!vboxSetupVRAMVbva(pVBox))
210 return FALSE;
211 for (i = 0; i < pVBox->cScreens; ++i)
212 {
213 struct VBVABUFFER *pVBVA;
214
215 pVBVA = (struct VBVABUFFER *) ( ((uint8_t *)pVBox->base)
216 + pVBox->pScreens[i].aoffVBVABuffer);
217 if (!VBoxVBVAEnable(&pVBox->pScreens[i].aVbvaCtx, &pVBox->guestCtx,
218 pVBVA, i))
219 rc = FALSE;
220 }
221 VBVXASSERT(rc, ("Failed to enable screen update reporting for at least one virtual monitor.\n"));
222#ifdef VBOXVIDEO_13
223 VBoxHGSMISendCapsInfo(&pVBox->guestCtx, VBVACAPS_VIDEO_MODE_HINTS | VBVACAPS_DISABLE_CURSOR_INTEGRATION);
224#else
225 VBoxHGSMISendCapsInfo(&pVBox->guestCtx, VBVACAPS_DISABLE_CURSOR_INTEGRATION);
226#endif
227 pVBox->fHaveHGSMIModeHints = haveHGSMIModeHintAndCursorReportingInterface(pVBox);
228 pVBox->fHostHasScreenBlankingFlag = hostHasScreenBlankingFlag(pVBox);
229 return rc;
230}
231
232/**
233 * Inform VBox that we will stop supplying it with dirty rectangle
234 * information. This function is intended to be called when an X
235 * virtual terminal is disabled, or the X server is terminated.
236 *
237 * @returns TRUE for success, FALSE for failure
238 * @param pScrn Pointer to a structure describing the X screen in use
239 */
240void
241vboxDisableVbva(ScrnInfoPtr pScrn)
242{
243 unsigned i;
244 VBOXPtr pVBox = pScrn->driverPrivate;
245
246 TRACE_ENTRY();
247 for (i = 0; i < pVBox->cScreens; ++i)
248 VBoxVBVADisable(&pVBox->pScreens[i].aVbvaCtx, &pVBox->guestCtx, i);
249}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette