1
/* -*- c-basic-offset: 8 -*-
2
rdesktop: A Remote Desktop Protocol client.
3
Persistent Bitmap Cache routines
4
Copyright (C) Jeroen Meijer 2004-2008
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
GNU General Public License for more details.
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29
#define MAX_CELL_SIZE 0x1000 /* pixels */
31
#define IS_PERSISTENT(id) (id < 8 && pcache->pstcache_fd[id] > 0)
33
/* Update mru stamp/index for a bitmap */
35
pstcache_touch_bitmap(rdpPcache * pcache, uint8 cache_id, uint16 cache_idx, uint32 stamp)
39
if (!IS_PERSISTENT(cache_id) || cache_idx >= BMPCACHE2_NUM_PSTCELLS)
42
fd = pcache->pstcache_fd[cache_id];
43
rd_lseek_file(fd, 12 + cache_idx *
44
(pcache->pstcache_Bpp * MAX_CELL_SIZE + sizeof(CELLHEADER)));
45
rd_write_file(fd, &stamp, sizeof(stamp));
48
/* Load a bitmap from the persistent cache */
50
pstcache_load_bitmap(rdpPcache * pcache, uint8 cache_id, uint16 cache_idx)
57
if (!(pcache->rdp->settings->bitmap_cache_persist_enable))
60
if (!IS_PERSISTENT(cache_id) || cache_idx >= BMPCACHE2_NUM_PSTCELLS)
63
fd = pcache->pstcache_fd[cache_id];
64
rd_lseek_file(fd, cache_idx *
65
(pcache->pstcache_Bpp * MAX_CELL_SIZE + sizeof(CELLHEADER)));
66
rd_read_file(fd, &cellhdr, sizeof(CELLHEADER));
67
celldata = (uint8 *) xmalloc(cellhdr.length);
68
rd_read_file(fd, celldata, cellhdr.length);
70
bitmap = ui_create_bitmap(pcache->rdp->inst, cellhdr.width, cellhdr.height, celldata);
71
DEBUG("Load bitmap from disk: id=%d, idx=%d, bmp=0x%x)\n", cache_id, cache_idx,
72
(unsigned int) bitmap);
73
cache_put_bitmap(pcache->rdp->cache, cache_id, cache_idx, bitmap);
79
/* Store a bitmap in the persistent cache */
81
pstcache_save_bitmap(rdpPcache * pcache, uint8 cache_id, uint16 cache_idx, uint8 * key,
82
uint8 width, uint8 height, uint16 length, uint8 * data)
87
if (!IS_PERSISTENT(cache_id) || cache_idx >= BMPCACHE2_NUM_PSTCELLS)
90
memcpy(cellhdr.key, key, sizeof(HASH_KEY));
91
cellhdr.width = width;
92
cellhdr.height = height;
93
cellhdr.length = length;
96
fd = pcache->pstcache_fd[cache_id];
97
rd_lseek_file(fd, cache_idx *
98
(pcache->pstcache_Bpp * MAX_CELL_SIZE + sizeof(CELLHEADER)));
99
rd_write_file(fd, &cellhdr, sizeof(CELLHEADER));
100
rd_write_file(fd, data, length);
105
/* List the bitmap keys from the persistent cache file */
107
pstcache_enumerate(rdpPcache * pcache, uint8 id, HASH_KEY * keylist)
111
sint16 mru_idx[0xa00];
112
uint32 mru_stamp[0xa00];
115
if (!(pcache->rdp->settings->bitmap_cache &&
116
pcache->rdp->settings->bitmap_cache_persist_enable &&
120
/* The server disconnects if the bitmap cache content is sent more than once */
121
if (pcache->pstcache_enumerated)
124
DEBUG_RDP5("Persistent bitmap cache enumeration... ");
125
for (idx = 0; idx < BMPCACHE2_NUM_PSTCELLS; idx++)
127
fd = pcache->pstcache_fd[id];
128
rd_lseek_file(fd, idx *
129
(pcache->pstcache_Bpp * MAX_CELL_SIZE + sizeof(CELLHEADER)));
130
if (rd_read_file(fd, &cellhdr, sizeof(CELLHEADER)) <= 0)
133
if (memcmp(cellhdr.key, pcache->zero_key, sizeof(HASH_KEY)) != 0)
135
memcpy(keylist[idx], cellhdr.key, sizeof(HASH_KEY));
137
/* Pre-cache (not possible for 8 bit colour depth cause it needs a colourmap) */
138
if (pcache->rdp->settings->bitmap_cache_precache && cellhdr.stamp &&
139
pcache->rdp->settings->server_depth > 8)
140
pstcache_load_bitmap(pcache, id, idx);
143
for (n = idx; n > 0 && cellhdr.stamp < mru_stamp[n - 1]; n--)
145
mru_idx[n] = mru_idx[n - 1];
146
mru_stamp[n] = mru_stamp[n - 1];
150
mru_stamp[n] = cellhdr.stamp;
158
DEBUG_RDP5("%d cached bitmaps.\n", idx);
160
cache_rebuild_bmpcache_linked_list(pcache->rdp->cache, id, mru_idx, idx);
161
pcache->pstcache_enumerated = True;
165
/* initialise the persistent bitmap cache */
167
pstcache_init(rdpPcache * pcache, uint8 cache_id)
172
if (pcache->pstcache_enumerated)
175
pcache->pstcache_fd[cache_id] = 0;
177
if (!(pcache->rdp->settings->bitmap_cache &&
178
pcache->rdp->settings->bitmap_cache_persist_enable))
181
if (!rd_pstcache_mkdir())
183
DEBUG("failed to get/make cache directory!\n");
187
pcache->pstcache_Bpp = (pcache->rdp->settings->server_depth + 7) / 8;
188
sprintf(filename, "cache/pstcache_%d_%d", cache_id, pcache->pstcache_Bpp);
189
DEBUG("persistent bitmap cache file: %s\n", filename);
191
fd = rd_open_file(filename);
195
if (!rd_lock_file(fd, 0, 0))
197
ui_warning(pcache->rdp->inst, "Persistent bitmap caching is disabled. (The file is already in use)\n");
202
pcache->pstcache_fd[cache_id] = fd;
207
pcache_new(struct rdp_rdp * rdp)
211
self = (rdpPcache *) xmalloc(sizeof(rdpPcache));
214
memset(self, 0, sizeof(rdpPcache));
221
pcache_free(rdpPcache * pcache)