VirtualBox

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

Last change on this file since 5999 was 5999, checked in by vboxsync, 17 years ago

The Giant CDDL Dual-License Header Change.

  • Property svn:eol-style set to native
File size: 5.6 KB
Line 
1/** @file
2 *
3 * VBoxGuest -- VirtualBox Win 2000/XP guest display driver
4 *
5 * VRDP bitmap cache.
6 *
7 */
8
9/*
10 * Copyright (C) 2006-2007 innotek GmbH
11 *
12 * This file is part of VirtualBox Open Source Edition (OSE), as
13 * available from http://www.virtualbox.org. This file is free software;
14 * you can redistribute it and/or modify it under the terms of the GNU
15 * General Public License (GPL) as published by the Free Software
16 * Foundation, in version 2 as it comes in the "COPYING" file of the
17 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
18 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
19 */
20
21#include "driver.h"
22#include "vrdpbmp.h"
23#include <iprt/crc64.h>
24#include <VBox/VRDPOrders.h>
25
26/*
27 * Cache has a fixed number of preallocated entries. Entries are linked in the MRU
28 * list. The list contains both used and free entries. Free entries are at the end.
29 * The most recently used entry is in the head.
30 *
31 * The purpose of the cache is to answer whether the bitmap was already encountered
32 * before.
33 *
34 * No serialization because the code is executed under vboxHwBuffer* semaphore.
35 */
36
37static uint64_t surfHash (const SURFOBJ *pso, uint32_t cbLine)
38{
39 uint64_t u64CRC = RTCrc64Start ();
40
41 uint32_t h = pso->sizlBitmap.cy;
42 uint8_t *pu8 = (uint8_t *)pso->pvScan0;
43
44 while (h > 0)
45 {
46 u64CRC = RTCrc64Process (u64CRC, pu8, cbLine);
47 pu8 += pso->lDelta;
48 h--;
49 }
50
51 u64CRC = RTCrc64Finish (u64CRC);
52
53 return u64CRC;
54} /* Hash function end. */
55
56
57static BOOL bcComputeHash (const SURFOBJ *pso, VRDPBCHASH *phash)
58{
59 uint32_t cbLine;
60
61 int bytesPerPixel = format2BytesPerPixel (pso);
62
63 if (bytesPerPixel == 0)
64 {
65 return FALSE;
66 }
67
68 phash->cx = (uint16_t)pso->sizlBitmap.cx;
69 phash->cy = (uint16_t)pso->sizlBitmap.cy;
70 phash->bytesPerPixel = bytesPerPixel;
71
72 cbLine = pso->sizlBitmap.cx * bytesPerPixel;
73 phash->hash64 = surfHash (pso, cbLine);
74
75 memset (phash->padding, 0, sizeof (phash->padding));
76
77 return TRUE;
78}
79
80/* Meves an entry to the head of MRU list. */
81static void bcMoveToHead (VRDPBC *pCache, VRDPBCENTRY *pEntry)
82{
83 if (pEntry->prev)
84 {
85 /* The entry is not yet in the head. Exclude from list. */
86 pEntry->prev->next = pEntry->next;
87
88 if (pEntry->next)
89 {
90 pEntry->next->prev = pEntry->prev;
91 }
92 else
93 {
94 pCache->tail = pEntry->prev;
95 }
96
97 /* Insert the entry at the head of MRU list. */
98 pEntry->prev = NULL;
99 pEntry->next = pCache->head;
100
101 VBVA_ASSERT(pCache->head);
102
103 pCache->head->prev = pEntry;
104 pCache->head = pEntry;
105 }
106}
107
108/* Returns TRUE if the hash already presents in the cache.
109 * Moves the found entry to the head of MRU list.
110 */
111static BOOL bcFindHash (VRDPBC *pCache, const VRDPBCHASH *phash)
112{
113 /* Search the MRU list. */
114 VRDPBCENTRY *pEntry = pCache->head;
115
116 while (pEntry && pEntry->fUsed)
117 {
118 if (memcmp (&pEntry->hash, phash, sizeof (VRDPBCHASH)) == 0)
119 {
120 /* Found the entry. Move it to the head of MRU list. */
121 bcMoveToHead (pCache, pEntry);
122
123 return TRUE;
124 }
125
126 pEntry = pEntry->next;
127 }
128
129 return FALSE;
130}
131
132/* Returns TRUE is a entry was also deleted to nake room for new entry. */
133static BOOL bcInsertHash (VRDPBC *pCache, const VRDPBCHASH *phash, VRDPBCHASH *phashDeleted)
134{
135 BOOL bRc = FALSE;
136 VRDPBCENTRY *pEntry;
137
138 DISPDBG((1, "insert hash cache %p, tail %p.\n", pCache, pCache->tail));
139
140 /* Get the free entry to be used. Try tail, that should be */
141 pEntry = pCache->tail;
142
143 if (pEntry == NULL)
144 {
145 return bRc;
146 }
147
148 if (pEntry->fUsed)
149 {
150 /* The cache is full. Remove the tail. */
151 memcpy (phashDeleted, &pEntry->hash, sizeof (VRDPBCHASH));
152 bRc = TRUE;
153 }
154
155 bcMoveToHead (pCache, pEntry);
156
157 memcpy (&pEntry->hash, phash, sizeof (VRDPBCHASH));
158 pEntry->fUsed = TRUE;
159
160 return bRc;
161}
162
163/*
164 * Public functions.
165 */
166
167/* Find out whether the surface already in the cache.
168 * Insert in the cache if not.
169 */
170int vrdpbmpCacheSurface (VRDPBC *pCache, const SURFOBJ *pso, VRDPBCHASH *phash, VRDPBCHASH *phashDeleted)
171{
172 int rc;
173
174 VRDPBCHASH hash;
175
176 BOOL bResult = bcComputeHash (pso, &hash);
177
178 DISPDBG((1, "vrdpbmpCacheSurface: compute hash %d.\n", bResult));
179 if (!bResult)
180 {
181 DISPDBG((1, "MEMBLT: vrdpbmpCacheSurface: could not compute hash.\n"));
182 return VRDPBMP_RC_NOT_CACHED;
183 }
184
185 bResult = bcFindHash (pCache, &hash);
186
187 DISPDBG((1, "vrdpbmpCacheSurface: find hash %d.\n", bResult));
188 *phash = hash;
189
190 if (bResult)
191 {
192 return VRDPBMP_RC_ALREADY_CACHED;
193 }
194
195 rc = VRDPBMP_RC_CACHED;
196
197 bResult = bcInsertHash (pCache, &hash, phashDeleted);
198
199 DISPDBG((1, "vrdpbmpCacheSurface: insert hash %d.\n", bResult));
200 if (bResult)
201 {
202 rc |= VRDPBMP_RC_F_DELETED;
203 }
204
205 return rc;
206}
207
208/* Setup the initial state of the cache. */
209void vrdpbmpReset (VRDPBC *pCache)
210{
211 int i;
212
213 VBVA_ASSERT(sizeof (VRDPBCHASH) == sizeof (VRDPBITMAPHASH));
214
215 /* Reinitialize the cache structure. */
216 memset (pCache, 0, sizeof (VRDPBC));
217
218 pCache->head = &pCache->aEntries[0];
219 pCache->tail = &pCache->aEntries[ELEMENTS(pCache->aEntries) - 1];
220
221 for (i = 0; i < ELEMENTS(pCache->aEntries); i++)
222 {
223 VRDPBCENTRY *pEntry = &pCache->aEntries[i];
224
225 if (pEntry != pCache->tail)
226 {
227 pEntry->next = &pCache->aEntries[i + 1];
228 }
229
230 if (pEntry != pCache->head)
231 {
232 pEntry->prev = &pCache->aEntries[i - 1];
233 }
234 }
235}
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