VirtualBox

source: vbox/trunk/src/VBox/Additions/common/VBoxVideo/VBVABase.cpp@ 68848

最後變更 在這個檔案從68848是 68848,由 vboxsync 提交於 7 年 前

Additions/linux/drm: lots of formatting changes to match kernel style.
bugref:8524: Additions/linux: play nicely with distribution-installed Additions

This change makes a lot of formatting changes to the Linux Additions drm
driver, with no intended changes to functionality, and much of the
formatting change done using the sed script which installs the driver
sources to the Additions archive. Hans de Goede's clean-up of the driver for
submission to staging is the base for these changes.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 11.4 KB
 
1/* $Id: VBVABase.cpp 68848 2017-09-24 16:58:46Z vboxsync $ */
2/** @file
3 * VirtualBox Video driver, common code - VBVA initialisation and helper
4 * functions.
5 */
6
7/*
8 * Copyright (C) 2006-2017 Oracle Corporation
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
24 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26 * OTHER DEALINGS IN THE SOFTWARE.
27 */
28
29#include <VBoxVideoGuest.h>
30#include <VBoxVideoIPRT.h>
31#include <HGSMIChannels.h>
32
33/*
34 * There is a hardware ring buffer in the graphics device video RAM, formerly
35 * in the VBox VMMDev PCI memory space.
36 * All graphics commands go there serialized by VBoxVBVABufferBeginUpdate.
37 * and vboxHwBufferEndUpdate.
38 *
39 * off32Free is writing position. off32Data is reading position.
40 * off32Free == off32Data means buffer is empty.
41 * There must be always gap between off32Data and off32Free when data
42 * are in the buffer.
43 * Guest only changes off32Free, host changes off32Data.
44 */
45
46/* Forward declarations of internal functions. */
47static void vboxHwBufferFlush(PHGSMIGUESTCOMMANDCONTEXT pCtx);
48static void vboxHwBufferPlaceDataAt(PVBVABUFFERCONTEXT pCtx, const void *p,
49 uint32_t cb, uint32_t offset);
50static bool vboxHwBufferWrite(PVBVABUFFERCONTEXT pCtx,
51 PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
52 const void *p, uint32_t cb);
53
54
55static bool vboxVBVAInformHost(PVBVABUFFERCONTEXT pCtx,
56 PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
57 int32_t cScreen, bool bEnable)
58{
59 bool bRc = false;
60
61#if 0 /* All callers check this */
62 if (ppdev->bHGSMISupported)
63#endif
64 {
65 void *p = VBoxHGSMIBufferAlloc(pHGSMICtx,
66 sizeof (VBVAENABLE_EX),
67 HGSMI_CH_VBVA,
68 VBVA_ENABLE);
69 if (!p)
70 {
71 // LogFunc(("HGSMIHeapAlloc failed\n"));
72 }
73 else
74 {
75 VBVAENABLE_EX *pEnable = (VBVAENABLE_EX *)p;
76
77 pEnable->Base.u32Flags = bEnable? VBVA_F_ENABLE: VBVA_F_DISABLE;
78 pEnable->Base.u32Offset = pCtx->offVRAMBuffer;
79 pEnable->Base.i32Result = VERR_NOT_SUPPORTED;
80 if (cScreen >= 0)
81 {
82 pEnable->Base.u32Flags |= VBVA_F_EXTENDED | VBVA_F_ABSOFFSET;
83 pEnable->u32ScreenId = cScreen;
84 }
85
86 VBoxHGSMIBufferSubmit(pHGSMICtx, p);
87
88 if (bEnable)
89 {
90 bRc = RT_SUCCESS(pEnable->Base.i32Result);
91 }
92 else
93 {
94 bRc = true;
95 }
96
97 VBoxHGSMIBufferFree(pHGSMICtx, p);
98 }
99 }
100
101 return bRc;
102}
103
104/*
105 * Public hardware buffer methods.
106 */
107DECLHIDDEN(bool) VBoxVBVAEnable(PVBVABUFFERCONTEXT pCtx,
108 PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
109 VBVABUFFER *pVBVA, int32_t cScreen)
110{
111 bool bRc = false;
112
113 // LogFlowFunc(("pVBVA %p\n", pVBVA));
114
115#if 0 /* All callers check this */
116 if (ppdev->bHGSMISupported)
117#endif
118 {
119 // LogFunc(("pVBVA %p vbva off 0x%x\n", pVBVA, pCtx->offVRAMBuffer));
120
121 pVBVA->hostFlags.u32HostEvents = 0;
122 pVBVA->hostFlags.u32SupportedOrders = 0;
123 pVBVA->off32Data = 0;
124 pVBVA->off32Free = 0;
125 memset(pVBVA->aRecords, 0, sizeof (pVBVA->aRecords));
126 pVBVA->indexRecordFirst = 0;
127 pVBVA->indexRecordFree = 0;
128 pVBVA->cbPartialWriteThreshold = 256;
129 pVBVA->cbData = pCtx->cbBuffer - sizeof (VBVABUFFER) + sizeof (pVBVA->au8Data);
130
131 pCtx->fHwBufferOverflow = false;
132 pCtx->pRecord = NULL;
133 pCtx->pVBVA = pVBVA;
134
135 bRc = vboxVBVAInformHost(pCtx, pHGSMICtx, cScreen, true);
136 }
137
138 if (!bRc)
139 {
140 VBoxVBVADisable(pCtx, pHGSMICtx, cScreen);
141 }
142
143 return bRc;
144}
145
146DECLHIDDEN(void) VBoxVBVADisable(PVBVABUFFERCONTEXT pCtx,
147 PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
148 int32_t cScreen)
149{
150 // LogFlowFunc(("\n"));
151
152 pCtx->fHwBufferOverflow = false;
153 pCtx->pRecord = NULL;
154 pCtx->pVBVA = NULL;
155
156 vboxVBVAInformHost(pCtx, pHGSMICtx, cScreen, false);
157
158 return;
159}
160
161DECLHIDDEN(bool) VBoxVBVABufferBeginUpdate(PVBVABUFFERCONTEXT pCtx,
162 PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx)
163{
164 bool bRc = false;
165
166 // LogFunc(("flags = 0x%08X\n", pCtx->pVBVA? pCtx->pVBVA->u32HostEvents: -1));
167
168 if ( pCtx->pVBVA
169 && (pCtx->pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_ENABLED))
170 {
171 uint32_t indexRecordNext;
172
173 Assert(!pCtx->fHwBufferOverflow);
174 Assert(pCtx->pRecord == NULL);
175
176 indexRecordNext = (pCtx->pVBVA->indexRecordFree + 1) % VBVA_MAX_RECORDS;
177
178 if (indexRecordNext == pCtx->pVBVA->indexRecordFirst)
179 {
180 /* All slots in the records queue are used. */
181 vboxHwBufferFlush (pHGSMICtx);
182 }
183
184 if (indexRecordNext == pCtx->pVBVA->indexRecordFirst)
185 {
186 /* Even after flush there is no place. Fail the request. */
187 // LogFunc(("no space in the queue of records!!! first %d, last %d\n",
188 // pCtx->pVBVA->indexRecordFirst, pCtx->pVBVA->indexRecordFree));
189 }
190 else
191 {
192 /* Initialize the record. */
193 VBVARECORD *pRecord = &pCtx->pVBVA->aRecords[pCtx->pVBVA->indexRecordFree];
194
195 pRecord->cbRecord = VBVA_F_RECORD_PARTIAL;
196
197 pCtx->pVBVA->indexRecordFree = indexRecordNext;
198
199 // LogFunc(("indexRecordNext = %d\n", indexRecordNext));
200
201 /* Remember which record we are using. */
202 pCtx->pRecord = pRecord;
203
204 bRc = true;
205 }
206 }
207
208 return bRc;
209}
210
211DECLHIDDEN(void) VBoxVBVABufferEndUpdate(PVBVABUFFERCONTEXT pCtx)
212{
213 VBVARECORD *pRecord;
214
215 // LogFunc(("\n"));
216
217 Assert(pCtx->pVBVA);
218
219 pRecord = pCtx->pRecord;
220 Assert(pRecord && (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL));
221
222 /* Mark the record completed. */
223 pRecord->cbRecord &= ~VBVA_F_RECORD_PARTIAL;
224
225 pCtx->fHwBufferOverflow = false;
226 pCtx->pRecord = NULL;
227
228 return;
229}
230
231/*
232 * Private operations.
233 */
234static uint32_t vboxHwBufferAvail (const VBVABUFFER *pVBVA)
235{
236 int32_t i32Diff = pVBVA->off32Data - pVBVA->off32Free;
237
238 return i32Diff > 0? i32Diff: pVBVA->cbData + i32Diff;
239}
240
241static void vboxHwBufferFlush(PHGSMIGUESTCOMMANDCONTEXT pCtx)
242{
243 /* Issue the flush command. */
244 void *p = VBoxHGSMIBufferAlloc(pCtx,
245 sizeof (VBVAFLUSH),
246 HGSMI_CH_VBVA,
247 VBVA_FLUSH);
248 if (!p)
249 {
250 // LogFunc(("HGSMIHeapAlloc failed\n"));
251 }
252 else
253 {
254 VBVAFLUSH *pFlush = (VBVAFLUSH *)p;
255
256 pFlush->u32Reserved = 0;
257
258 VBoxHGSMIBufferSubmit(pCtx, p);
259
260 VBoxHGSMIBufferFree(pCtx, p);
261 }
262
263 return;
264}
265
266static void vboxHwBufferPlaceDataAt(PVBVABUFFERCONTEXT pCtx, const void *p,
267 uint32_t cb, uint32_t offset)
268{
269 VBVABUFFER *pVBVA = pCtx->pVBVA;
270 uint32_t u32BytesTillBoundary = pVBVA->cbData - offset;
271 uint8_t *dst = &pVBVA->au8Data[offset];
272 int32_t i32Diff = cb - u32BytesTillBoundary;
273
274 if (i32Diff <= 0)
275 {
276 /* Chunk will not cross buffer boundary. */
277 memcpy (dst, p, cb);
278 }
279 else
280 {
281 /* Chunk crosses buffer boundary. */
282 memcpy (dst, p, u32BytesTillBoundary);
283 memcpy (&pVBVA->au8Data[0], (uint8_t *)p + u32BytesTillBoundary, i32Diff);
284 }
285
286 return;
287}
288
289static bool vboxHwBufferWrite(PVBVABUFFERCONTEXT pCtx,
290 PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
291 const void *p, uint32_t cb)
292{
293 VBVARECORD *pRecord;
294 uint32_t cbHwBufferAvail;
295
296 uint32_t cbWritten = 0;
297
298 VBVABUFFER *pVBVA = pCtx->pVBVA;
299 Assert(pVBVA);
300
301 if (!pVBVA || pCtx->fHwBufferOverflow)
302 {
303 return false;
304 }
305
306 Assert(pVBVA->indexRecordFirst != pVBVA->indexRecordFree);
307
308 pRecord = pCtx->pRecord;
309 Assert(pRecord && (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL));
310
311 // LogFunc(("%d\n", cb));
312
313 cbHwBufferAvail = vboxHwBufferAvail (pVBVA);
314
315 while (cb > 0)
316 {
317 uint32_t cbChunk = cb;
318
319 // LogFunc(("pVBVA->off32Free %d, pRecord->cbRecord 0x%08X, cbHwBufferAvail %d, cb %d, cbWritten %d\n",
320 // pVBVA->off32Free, pRecord->cbRecord, cbHwBufferAvail, cb, cbWritten));
321
322 if (cbChunk >= cbHwBufferAvail)
323 {
324 // LogFunc(("1) avail %d, chunk %d\n", cbHwBufferAvail, cbChunk));
325
326 vboxHwBufferFlush (pHGSMICtx);
327
328 cbHwBufferAvail = vboxHwBufferAvail (pVBVA);
329
330 if (cbChunk >= cbHwBufferAvail)
331 {
332 // LogFunc(("no place for %d bytes. Only %d bytes available after flush. Going to partial writes.\n",
333 // cb, cbHwBufferAvail));
334
335 if (cbHwBufferAvail <= pVBVA->cbPartialWriteThreshold)
336 {
337 // LogFunc(("Buffer overflow!!!\n"));
338 pCtx->fHwBufferOverflow = true;
339 Assert(false);
340 return false;
341 }
342
343 cbChunk = cbHwBufferAvail - pVBVA->cbPartialWriteThreshold;
344 }
345 }
346
347 Assert(cbChunk <= cb);
348 Assert(cbChunk <= vboxHwBufferAvail (pVBVA));
349
350 vboxHwBufferPlaceDataAt (pCtx, (uint8_t *)p + cbWritten, cbChunk, pVBVA->off32Free);
351
352 pVBVA->off32Free = (pVBVA->off32Free + cbChunk) % pVBVA->cbData;
353 pRecord->cbRecord += cbChunk;
354 cbHwBufferAvail -= cbChunk;
355
356 cb -= cbChunk;
357 cbWritten += cbChunk;
358 }
359
360 return true;
361}
362
363/*
364 * Public writer to the hardware buffer.
365 */
366DECLHIDDEN(bool) VBoxVBVAWrite(PVBVABUFFERCONTEXT pCtx,
367 PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
368 const void *pv, uint32_t cb)
369{
370 return vboxHwBufferWrite (pCtx, pHGSMICtx, pv, cb);
371}
372
373DECLHIDDEN(bool) VBoxVBVAOrderSupported(PVBVABUFFERCONTEXT pCtx, unsigned code)
374{
375 VBVABUFFER *pVBVA = pCtx->pVBVA;
376
377 if (!pVBVA)
378 {
379 return false;
380 }
381
382 if (pVBVA->hostFlags.u32SupportedOrders & (1 << code))
383 {
384 return true;
385 }
386
387 return false;
388}
389
390DECLHIDDEN(void) VBoxVBVASetupBufferContext(PVBVABUFFERCONTEXT pCtx,
391 uint32_t offVRAMBuffer,
392 uint32_t cbBuffer)
393{
394 pCtx->offVRAMBuffer = offVRAMBuffer;
395 pCtx->cbBuffer = cbBuffer;
396}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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