VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Display/vbox.c@ 17623

Last change on this file since 17623 was 17623, checked in by vboxsync, 16 years ago

HGSMI: the windows guest display drivers.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.9 KB
Line 
1/** @file
2 *
3 * VBoxGuest -- VirtualBox Win 2000/XP guest display driver
4 *
5 * VBox support functions.
6 *
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22#include "driver.h"
23
24#include <VBox/VBoxGuest.h>
25#include <VBox/err.h>
26#include <iprt/asm.h>
27
28/*
29 * There is a hardware ring buffer in the VBox VMMDev PCI memory space.
30 * All graphics commands go there serialized by vboxHwBufferBeginUpdate.
31 * and vboxHwBufferEndUpdate.
32 *
33 * off32Free is writing position. off32Data is reading position.
34 * off32Free == off32Data means buffer is empty.
35 * There must be always gap between off32Data and off32Free when data
36 * are in the buffer.
37 * Guest only changes off32Free, host changes off32Data.
38 */
39
40/* Forward declarations of internal functions. */
41static void vboxHwBufferFlush (PPDEV ppdev);
42static void vboxHwBufferPlaceDataAt (PPDEV ppdev, void *p, uint32_t cb, uint32_t offset);
43static BOOL vboxHwBufferWrite (PPDEV ppdev, const void *p, uint32_t cb);
44
45#ifndef VBOX_WITH_HGSMI
46/*
47 * Public hardware buffer methods.
48 */
49BOOL vboxVbvaEnable (PPDEV ppdev)
50{
51 BOOL bRc = FALSE;
52
53 ULONG returnedDataLength;
54 ULONG ulEnable = TRUE;
55
56 DISPDBG((1, "VBoxDisp::vboxVbvaEnable called\n"));
57
58 if (!ghsemHwBuffer)
59 {
60 return FALSE;
61 }
62
63 if (EngDeviceIoControl(ppdev->hDriver,
64 IOCTL_VIDEO_VBVA_ENABLE,
65 &ulEnable,
66 sizeof (ulEnable),
67 &ppdev->vbva,
68 sizeof (ppdev->vbva),
69 &returnedDataLength) == 0)
70 {
71 DISPDBG((1, "VBoxDisp::vboxVbvaEnable: vbva: pVbvaMemory = %p, pfnFlush = %p, pvFlush = %p.\n",
72 ppdev->vbva.pVbvaMemory, ppdev->vbva.pfnFlush, ppdev->vbva.pvFlush));
73
74 if (ppdev->vbva.pVbvaMemory
75 && ppdev->vbva.pfnFlush
76 && ppdev->vbva.pvFlush)
77 {
78 ppdev->fHwBufferOverflow = FALSE;
79 ppdev->pRecord = NULL;
80
81 /* All have been initialized. */
82 bRc = TRUE;
83 }
84 }
85
86 if (!bRc)
87 {
88 vboxVbvaDisable (ppdev);
89 }
90
91 return bRc;
92}
93
94void vboxVbvaDisable (PPDEV ppdev)
95{
96 DISPDBG((1, "VBoxDisp::vbvaDisable called.\n"));
97
98 RtlZeroMemory (&ppdev->vbva, sizeof (ppdev->vbva));
99
100 ppdev->fHwBufferOverflow = FALSE;
101 ppdev->pRecord = NULL;
102
103 return;
104}
105
106BOOL vboxHwBufferBeginUpdate (PPDEV ppdev)
107{
108 BOOL bRc = FALSE;
109
110 VBVAMEMORY *pVbvaMemory = ppdev->vbva.pVbvaMemory;
111
112 DISPDBG((1, "VBoxDisp::vboxHwBufferBeginUpdate called flags = 0x%08X\n", pVbvaMemory? pVbvaMemory->fu32ModeFlags: -1));
113
114 if ( pVbvaMemory
115 && (pVbvaMemory->fu32ModeFlags & VBVA_F_MODE_ENABLED))
116 {
117 uint32_t indexRecordNext;
118
119 EngAcquireSemaphore (ghsemHwBuffer);
120
121 VBVA_ASSERT (!ppdev->fHwBufferOverflow);
122 VBVA_ASSERT (ppdev->pRecord == NULL);
123
124 indexRecordNext = (pVbvaMemory->indexRecordFree + 1) % VBVA_MAX_RECORDS;
125
126 if (indexRecordNext == pVbvaMemory->indexRecordFirst)
127 {
128 /* All slots in the records queue are used. */
129 vboxHwBufferFlush (ppdev);
130 }
131
132 if (indexRecordNext == pVbvaMemory->indexRecordFirst)
133 {
134 /* Even after flush there is no place. Fail the request. */
135 DISPDBG((1, "VBoxDisp::vboxHwBufferBeginUpdate no space in the queue of records!!! first %d, last %d\n",
136 pVbvaMemory->indexRecordFirst, pVbvaMemory->indexRecordFree));
137 EngReleaseSemaphore (ghsemHwBuffer);
138 }
139 else
140 {
141 /* Initialize the record. */
142 VBVARECORD *pRecord = &pVbvaMemory->aRecords[pVbvaMemory->indexRecordFree];
143
144 pRecord->cbRecord = VBVA_F_RECORD_PARTIAL;
145
146 pVbvaMemory->indexRecordFree = indexRecordNext;
147
148 DISPDBG((1, "VBoxDisp::vboxHwBufferBeginUpdate indexRecordNext = %d\n", indexRecordNext));
149
150 /* Remember which record we are using. */
151 ppdev->pRecord = pRecord;
152
153 bRc = TRUE;
154 }
155 }
156
157 return bRc;
158}
159
160void vboxHwBufferEndUpdate (PPDEV ppdev)
161{
162 VBVAMEMORY *pVbvaMemory;
163 VBVARECORD *pRecord;
164
165 DISPDBG((1, "VBoxDisp::vboxHwBufferEndUpdate called\n"));
166
167 pVbvaMemory = ppdev->vbva.pVbvaMemory;
168 VBVA_ASSERT(pVbvaMemory);
169
170 pRecord = ppdev->pRecord;
171 VBVA_ASSERT (pRecord && (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL));
172
173 /* Mark the record completed. */
174 pRecord->cbRecord &= ~VBVA_F_RECORD_PARTIAL;
175
176 ppdev->fHwBufferOverflow = FALSE;
177 ppdev->pRecord = NULL;
178
179 EngReleaseSemaphore (ghsemHwBuffer);
180
181 return;
182}
183
184/*
185 * Private operations.
186 */
187static uint32_t vboxHwBufferAvail (VBVAMEMORY *pVbvaMemory)
188{
189 int32_t i32Diff = pVbvaMemory->off32Data - pVbvaMemory->off32Free;
190
191 return i32Diff > 0? i32Diff: VBVA_RING_BUFFER_SIZE + i32Diff;
192}
193
194static void vboxHwBufferFlush (PPDEV ppdev)
195{
196 VBVAMEMORY *pVbvaMemory = ppdev->vbva.pVbvaMemory;
197
198 VBVA_ASSERT (pVbvaMemory);
199
200 ppdev->vbva.pfnFlush (ppdev->vbva.pvFlush);
201
202 return;
203}
204
205static void vboxHwBufferPlaceDataAt (PPDEV ppdev, void *p, uint32_t cb, uint32_t offset)
206{
207 VBVAMEMORY *pVbvaMemory = ppdev->vbva.pVbvaMemory;
208
209 uint32_t u32BytesTillBoundary = VBVA_RING_BUFFER_SIZE - offset;
210 uint8_t *dst = &pVbvaMemory->au8RingBuffer[offset];
211 int32_t i32Diff = cb - u32BytesTillBoundary;
212
213 if (i32Diff <= 0)
214 {
215 /* Chunk will not cross buffer boundary. */
216 memcpy (dst, p, cb);
217 }
218 else
219 {
220 /* Chunk crosses buffer boundary. */
221 memcpy (dst, p, u32BytesTillBoundary);
222 memcpy (&pVbvaMemory->au8RingBuffer[0], (uint8_t *)p + u32BytesTillBoundary, i32Diff);
223 }
224
225 return;
226}
227
228static BOOL vboxHwBufferWrite (PPDEV ppdev, const void *p, uint32_t cb)
229{
230 VBVAMEMORY *pVbvaMemory;
231 VBVARECORD *pRecord;
232 uint32_t cbHwBufferAvail;
233
234 uint32_t cbWritten = 0;
235
236 VBVA_ASSERT(ppdev);
237
238 if (ppdev->fHwBufferOverflow)
239 {
240 return FALSE;
241 }
242
243 pVbvaMemory = ppdev->vbva.pVbvaMemory;
244 VBVA_ASSERT (pVbvaMemory->indexRecordFirst != pVbvaMemory->indexRecordFree);
245
246 pRecord = ppdev->pRecord;
247 VBVA_ASSERT (pRecord && (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL));
248
249 DISPDBG((1, "VW %d\n", cb));
250
251 cbHwBufferAvail = vboxHwBufferAvail (pVbvaMemory);
252
253 while (cb > 0)
254 {
255 uint32_t cbChunk = cb;
256
257// DISPDBG((1, "VBoxDisp::vboxHwBufferWrite pVbvaMemory->off32Free %d, pRecord->cbRecord 0x%08X, cbHwBufferAvail %d, cb %d, cbWritten %d\n", pVbvaMemory->off32Free, pRecord->cbRecord, cbHwBufferAvail, cb, cbWritten));
258
259 if (cbChunk >= cbHwBufferAvail)
260 {
261 DISPDBG((1, "VBoxDisp::vboxHwBufferWrite 1) avail %d, chunk %d\n", cbHwBufferAvail, cbChunk));
262
263 vboxHwBufferFlush (ppdev);
264
265 cbHwBufferAvail = vboxHwBufferAvail (pVbvaMemory);
266
267 if (cbChunk >= cbHwBufferAvail)
268 {
269 DISPDBG((1, "VBoxDisp::vboxHwBufferWrite: no place for %d bytes. Only %d bytes available after flush. Going to partial writes.\n", cb, cbHwBufferAvail));
270
271 if (cbHwBufferAvail <= VBVA_RING_BUFFER_THRESHOLD)
272 {
273 DISPDBG((1, "VBoxDisp::vboxHwBufferWrite: Buffer overflow!!!\n"));
274 ppdev->fHwBufferOverflow = TRUE;
275 VBVA_ASSERT(FALSE);
276 return FALSE;
277 }
278
279 cbChunk = cbHwBufferAvail - VBVA_RING_BUFFER_THRESHOLD;
280 }
281 }
282
283 VBVA_ASSERT(cbChunk <= cb);
284 VBVA_ASSERT(cbChunk <= vboxHwBufferAvail (pVbvaMemory));
285
286 vboxHwBufferPlaceDataAt (ppdev, (uint8_t *)p + cbWritten, cbChunk, pVbvaMemory->off32Free);
287
288 pVbvaMemory->off32Free = (pVbvaMemory->off32Free + cbChunk) % VBVA_RING_BUFFER_SIZE;
289 pRecord->cbRecord += cbChunk;
290 cbHwBufferAvail -= cbChunk;
291
292 cb -= cbChunk;
293 cbWritten += cbChunk;
294 }
295
296 return TRUE;
297}
298
299/*
300 * Public writer to hardware buffer.
301 */
302BOOL vboxWrite (PPDEV ppdev, const void *pv, uint32_t cb)
303{
304 return vboxHwBufferWrite (ppdev, pv, cb);
305}
306
307BOOL vboxOrderSupported (PPDEV ppdev, unsigned code)
308{
309 VBVAMEMORY *pVbvaMemory;
310
311 pVbvaMemory = ppdev->vbva.pVbvaMemory;
312
313 if (pVbvaMemory->fu32ModeFlags & VBVA_F_MODE_VRDP_ORDER_MASK)
314 {
315 /* Order masking enabled. */
316 if (pVbvaMemory->fu32SupportedOrders & (1 << code))
317 {
318 return TRUE;
319 }
320 }
321
322 return FALSE;
323}
324
325void VBoxProcessDisplayInfo(PPDEV ppdev)
326{
327 DWORD returnedDataLength;
328
329 DISPDBG((1, "Process: %d,%d\n", ppdev->ptlDevOrg.x, ppdev->ptlDevOrg.y));
330
331 EngDeviceIoControl(ppdev->hDriver,
332 IOCTL_VIDEO_INTERPRET_DISPLAY_MEMORY,
333 NULL,
334 0,
335 NULL,
336 0,
337 &returnedDataLength);
338}
339
340#else /* VBOX_WITH_HGSMI */
341
342static void vboxHGSMIBufferSubmit (PPDEV ppdev, void *p)
343{
344 HGSMIOFFSET offBuffer = HGSMIHeapBufferOffset (&ppdev->hgsmiDisplayHeap, p);
345
346 ASMOutU16 (VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VBVA_GUEST);
347 ASMOutU32 (VBE_DISPI_IOPORT_DATA, offBuffer);
348}
349
350static BOOL vboxVBVAInformHost (PPDEV ppdev, BOOL bEnable)
351{
352 BOOL bRc = FALSE;
353
354 if (ppdev->bHGSMISupported)
355 {
356 void *p = HGSMIHeapAlloc (&ppdev->hgsmiDisplayHeap,
357 sizeof (VBVAENABLE),
358 HGSMI_CH_VBVA,
359 VBVA_ENABLE);
360 if (!p)
361 {
362 DISPDBG((0, "VBoxDISP::vboxVBVAInformHost: HGSMIHeapAlloc failed\n"));
363 }
364 else
365 {
366 VBVAENABLE *pEnable = (VBVAENABLE *)p;
367
368 pEnable->u32Flags = bEnable? VBVA_F_ENABLE: VBVA_F_DISABLE;
369 pEnable->u32Reserved = 0;
370
371 vboxHGSMIBufferSubmit (ppdev, p);
372
373 HGSMIHeapFree (&ppdev->hgsmiDisplayHeap, p);
374
375 bRc = TRUE;
376 }
377 }
378
379 return bRc;
380}
381
382/*
383 * Public hardware buffer methods.
384 */
385BOOL vboxVbvaEnable (PPDEV ppdev)
386{
387 BOOL bRc = FALSE;
388
389 DISPDBG((1, "VBoxDisp::vboxVbvaEnable called\n"));
390
391 if (ppdev->bHGSMISupported)
392 {
393 VBVABUFFER *pVBVA = (VBVABUFFER *)((uint8_t *)ppdev->pjScreen + ppdev->layout.offVBVABuffer);
394
395 pVBVA->u32HostEvents = 0;
396 pVBVA->u32SupportedOrders = 0;
397 pVBVA->off32Data = 0;
398 pVBVA->off32Free = 0;
399 RtlZeroMemory (pVBVA->aRecords, sizeof (pVBVA->aRecords));
400 pVBVA->indexRecordFirst = 0;
401 pVBVA->indexRecordFree = 0;
402 pVBVA->cbPartialWriteThreshold = 256;
403 pVBVA->cbData = ppdev->layout.cbVBVABuffer - sizeof (VBVABUFFER) + sizeof (pVBVA->au8Data);
404
405 ppdev->fHwBufferOverflow = FALSE;
406 ppdev->pRecord = NULL;
407 ppdev->pVBVA = pVBVA;
408
409 bRc = vboxVBVAInformHost (ppdev, TRUE);
410 }
411
412 if (!bRc)
413 {
414 vboxVbvaDisable (ppdev);
415 }
416
417 return bRc;
418}
419
420void vboxVbvaDisable (PPDEV ppdev)
421{
422 DISPDBG((1, "VBoxDisp::vbvaDisable called.\n"));
423
424 ppdev->fHwBufferOverflow = FALSE;
425 ppdev->pRecord = NULL;
426 ppdev->pVBVA = NULL;
427
428 vboxVBVAInformHost (ppdev, FALSE);
429
430 return;
431}
432
433BOOL vboxHwBufferBeginUpdate (PPDEV ppdev)
434{
435 BOOL bRc = FALSE;
436
437 DISPDBG((1, "VBoxDisp::vboxHwBufferBeginUpdate called flags = 0x%08X\n",
438 ppdev->pVBVA? ppdev->pVBVA->u32HostEvents: -1));
439
440 if ( ppdev->pVBVA
441 && (ppdev->pVBVA->u32HostEvents & VBVA_F_MODE_ENABLED))
442 {
443 uint32_t indexRecordNext;
444
445 VBVA_ASSERT (!ppdev->fHwBufferOverflow);
446 VBVA_ASSERT (ppdev->pRecord == NULL);
447
448 indexRecordNext = (ppdev->pVBVA->indexRecordFree + 1) % VBVA_MAX_RECORDS;
449
450 if (indexRecordNext == ppdev->pVBVA->indexRecordFirst)
451 {
452 /* All slots in the records queue are used. */
453 vboxHwBufferFlush (ppdev);
454 }
455
456 if (indexRecordNext == ppdev->pVBVA->indexRecordFirst)
457 {
458 /* Even after flush there is no place. Fail the request. */
459 DISPDBG((1, "VBoxDisp::vboxHwBufferBeginUpdate no space in the queue of records!!! first %d, last %d\n",
460 ppdev->pVBVA->indexRecordFirst, ppdev->pVBVA->indexRecordFree));
461 }
462 else
463 {
464 /* Initialize the record. */
465 VBVARECORD *pRecord = &ppdev->pVBVA->aRecords[ppdev->pVBVA->indexRecordFree];
466
467 pRecord->cbRecord = VBVA_F_RECORD_PARTIAL;
468
469 ppdev->pVBVA->indexRecordFree = indexRecordNext;
470
471 DISPDBG((1, "VBoxDisp::vboxHwBufferBeginUpdate indexRecordNext = %d\n", indexRecordNext));
472
473 /* Remember which record we are using. */
474 ppdev->pRecord = pRecord;
475
476 bRc = TRUE;
477 }
478 }
479
480 return bRc;
481}
482
483void vboxHwBufferEndUpdate (PPDEV ppdev)
484{
485 VBVARECORD *pRecord;
486
487 DISPDBG((1, "VBoxDisp::vboxHwBufferEndUpdate called\n"));
488
489 VBVA_ASSERT(ppdev->pVBVA);
490
491 pRecord = ppdev->pRecord;
492 VBVA_ASSERT (pRecord && (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL));
493
494 /* Mark the record completed. */
495 pRecord->cbRecord &= ~VBVA_F_RECORD_PARTIAL;
496
497 ppdev->fHwBufferOverflow = FALSE;
498 ppdev->pRecord = NULL;
499
500 return;
501}
502
503/*
504 * Private operations.
505 */
506static uint32_t vboxHwBufferAvail (const VBVABUFFER *pVBVA)
507{
508 int32_t i32Diff = pVBVA->off32Data - pVBVA->off32Free;
509
510 return i32Diff > 0? i32Diff: pVBVA->cbData + i32Diff;
511}
512
513static void vboxHwBufferFlush (PPDEV ppdev)
514{
515 /* Issue the flush command. */
516 void *p = HGSMIHeapAlloc (&ppdev->hgsmiDisplayHeap,
517 sizeof (VBVA_FLUSH),
518 HGSMI_CH_VBVA,
519 VBVA_FLUSH);
520 if (!p)
521 {
522 DISPDBG((0, "VBoxDISP::vboxHwBufferFlush: HGSMIHeapAlloc failed\n"));
523 }
524 else
525 {
526 VBVAFLUSH *pFlush = (VBVAFLUSH *)p;
527
528 pFlush->u32Reserved = 0;
529
530 vboxHGSMIBufferSubmit (ppdev, p);
531
532 HGSMIHeapFree (&ppdev->hgsmiDisplayHeap, p);
533 }
534
535 return;
536}
537
538static void vboxHwBufferPlaceDataAt (PPDEV ppdev, const void *p, uint32_t cb, uint32_t offset)
539{
540 VBVABUFFER *pVBVA = ppdev->pVBVA;
541 uint32_t u32BytesTillBoundary = pVBVA->cbData - offset;
542 uint8_t *dst = &pVBVA->au8Data[offset];
543 int32_t i32Diff = cb - u32BytesTillBoundary;
544
545 if (i32Diff <= 0)
546 {
547 /* Chunk will not cross buffer boundary. */
548 memcpy (dst, p, cb);
549 }
550 else
551 {
552 /* Chunk crosses buffer boundary. */
553 memcpy (dst, p, u32BytesTillBoundary);
554 memcpy (&pVBVA->au8Data[0], (uint8_t *)p + u32BytesTillBoundary, i32Diff);
555 }
556
557 return;
558}
559
560static BOOL vboxHwBufferWrite (PPDEV ppdev, const void *p, uint32_t cb)
561{
562 VBVARECORD *pRecord;
563 uint32_t cbHwBufferAvail;
564
565 uint32_t cbWritten = 0;
566
567 VBVABUFFER *pVBVA = ppdev->pVBVA;
568 VBVA_ASSERT(pVBVA);
569
570 if (!pVBVA || ppdev->fHwBufferOverflow)
571 {
572 return FALSE;
573 }
574
575 VBVA_ASSERT (pVBVA->indexRecordFirst != pVBVA->indexRecordFree);
576
577 pRecord = ppdev->pRecord;
578 VBVA_ASSERT (pRecord && (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL));
579
580 DISPDBG((1, "VW %d\n", cb));
581
582 cbHwBufferAvail = vboxHwBufferAvail (pVBVA);
583
584 while (cb > 0)
585 {
586 uint32_t cbChunk = cb;
587
588 DISPDBG((1, "VBoxDisp::vboxHwBufferWrite pVBVA->off32Free %d, pRecord->cbRecord 0x%08X, cbHwBufferAvail %d, cb %d, cbWritten %d\n",
589 pVBVA->off32Free, pRecord->cbRecord, cbHwBufferAvail, cb, cbWritten));
590
591 if (cbChunk >= cbHwBufferAvail)
592 {
593 DISPDBG((1, "VBoxDisp::vboxHwBufferWrite 1) avail %d, chunk %d\n", cbHwBufferAvail, cbChunk));
594
595 vboxHwBufferFlush (ppdev);
596
597 cbHwBufferAvail = vboxHwBufferAvail (pVBVA);
598
599 if (cbChunk >= cbHwBufferAvail)
600 {
601 DISPDBG((1, "VBoxDisp::vboxHwBufferWrite: no place for %d bytes. Only %d bytes available after flush. Going to partial writes.\n",
602 cb, cbHwBufferAvail));
603
604 if (cbHwBufferAvail <= pVBVA->cbPartialWriteThreshold)
605 {
606 DISPDBG((1, "VBoxDisp::vboxHwBufferWrite: Buffer overflow!!!\n"));
607 ppdev->fHwBufferOverflow = TRUE;
608 VBVA_ASSERT(FALSE);
609 return FALSE;
610 }
611
612 cbChunk = cbHwBufferAvail - pVBVA->cbPartialWriteThreshold;
613 }
614 }
615
616 VBVA_ASSERT(cbChunk <= cb);
617 VBVA_ASSERT(cbChunk <= vboxHwBufferAvail (pVBVA));
618
619 vboxHwBufferPlaceDataAt (ppdev, (uint8_t *)p + cbWritten, cbChunk, pVBVA->off32Free);
620
621 pVBVA->off32Free = (pVBVA->off32Free + cbChunk) % pVBVA->cbData;
622 pRecord->cbRecord += cbChunk;
623 cbHwBufferAvail -= cbChunk;
624
625 cb -= cbChunk;
626 cbWritten += cbChunk;
627 }
628
629 return TRUE;
630}
631
632/*
633 * Public writer to the hardware buffer.
634 */
635BOOL vboxWrite (PPDEV ppdev, const void *pv, uint32_t cb)
636{
637 return vboxHwBufferWrite (ppdev, pv, cb);
638}
639
640BOOL vboxOrderSupported (PPDEV ppdev, unsigned code)
641{
642 VBVABUFFER *pVBVA = ppdev->pVBVA;
643
644 if (!pVBVA)
645 {
646 return FALSE;
647 }
648
649 if (pVBVA->u32SupportedOrders & (1 << code))
650 {
651 return TRUE;
652 }
653
654 return FALSE;
655}
656
657void VBoxProcessDisplayInfo (PPDEV ppdev)
658{
659 if (ppdev->bHGSMISupported)
660 {
661 /* Issue the screen info command. */
662 void *p = HGSMIHeapAlloc (&ppdev->hgsmiDisplayHeap,
663 sizeof (VBVAINFOSCREEN),
664 HGSMI_CH_VBVA,
665 VBVA_INFO_SCREEN);
666 if (!p)
667 {
668 DISPDBG((0, "VBoxDISP::vboxHwBufferFlush: HGSMIHeapAlloc failed\n"));
669 }
670 else
671 {
672 VBVAINFOSCREEN *pScreen = (VBVAINFOSCREEN *)p;
673
674 pScreen->i32OriginX = ppdev->ptlDevOrg.x;
675 pScreen->i32OriginY = ppdev->ptlDevOrg.y;
676 pScreen->u32LineSize = ppdev->lDeltaScreen > 0?ppdev->lDeltaScreen: -ppdev->lDeltaScreen;
677 pScreen->u32Width = ppdev->cxScreen;
678 pScreen->u32Height = ppdev->cyScreen;
679 pScreen->u16BitsPerPixel = (uint16_t)ppdev->ulBitCount;
680 pScreen->u16Flags = VBVA_SCREEN_F_ACTIVE;
681
682 vboxHGSMIBufferSubmit (ppdev, p);
683
684 HGSMIHeapFree (&ppdev->hgsmiDisplayHeap, p);
685 }
686 }
687
688 return;
689}
690#endif /* VBOX_WITH_HGSMI */
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