VirtualBox

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

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

Biggest check-in ever. New source code headers for all (C) innotek files.

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