1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Persistent Bitmap Cache routines
4 Copyright (C) Jeroen Meijer 2004-2005
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.
23 #define MAX_CELL_SIZE 0x1000 /* pixels */
25 extern int g_server_depth
;
26 extern BOOL g_bitmap_cache
;
27 extern BOOL g_bitmap_cache_persist_enable
;
28 extern BOOL g_bitmap_cache_precache
;
32 BOOL g_pstcache_enumerated
= False
;
33 uint8 zero_key
[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
36 /* Update mru stamp/index for a bitmap */
38 pstcache_touch_bitmap(uint8 cache_id
, uint16 cache_idx
, uint32 stamp
)
42 if (!IS_PERSISTENT(cache_id
) || cache_idx
>= BMPCACHE2_NUM_PSTCELLS
)
45 fd
= g_pstcache_fd
[cache_id
];
46 rd_lseek_file(fd
, 12 + cache_idx
* (g_pstcache_Bpp
* MAX_CELL_SIZE
+ sizeof(CELLHEADER
)));
47 rd_write_file(fd
, &stamp
, sizeof(stamp
));
50 /* Load a bitmap from the persistent cache */
52 pstcache_load_bitmap(uint8 cache_id
, uint16 cache_idx
)
59 if (!g_bitmap_cache_persist_enable
)
62 if (!IS_PERSISTENT(cache_id
) || cache_idx
>= BMPCACHE2_NUM_PSTCELLS
)
65 memset(&cellhdr
, 0, sizeof(CELLHEADER
));
67 fd
= g_pstcache_fd
[cache_id
];
68 rd_lseek_file(fd
, cache_idx
* (g_pstcache_Bpp
* MAX_CELL_SIZE
+ sizeof(CELLHEADER
)));
69 rd_read_file(fd
, &cellhdr
, sizeof(CELLHEADER
));
70 celldata
= (uint8
*) xmalloc(cellhdr
.length
);
71 rd_read_file(fd
, celldata
, cellhdr
.length
);
73 bitmap
= ui_create_bitmap(cellhdr
.width
, cellhdr
.height
, celldata
);
74 DEBUG(("Load bitmap from disk: id=%d, idx=%d, bmp=0x%x)\n", cache_id
, cache_idx
, bitmap
));
75 cache_put_bitmap(cache_id
, cache_idx
, bitmap
);
81 /* Store a bitmap in the persistent cache */
83 pstcache_save_bitmap(uint8 cache_id
, uint16 cache_idx
, uint8
* key
,
84 uint8 width
, uint8 height
, uint16 length
, uint8
* data
)
89 if (!IS_PERSISTENT(cache_id
) || cache_idx
>= BMPCACHE2_NUM_PSTCELLS
)
92 memcpy(cellhdr
.key
, key
, sizeof(HASH_KEY
));
93 cellhdr
.width
= width
;
94 cellhdr
.height
= height
;
95 cellhdr
.length
= length
;
98 fd
= g_pstcache_fd
[cache_id
];
99 rd_lseek_file(fd
, cache_idx
* (g_pstcache_Bpp
* MAX_CELL_SIZE
+ sizeof(CELLHEADER
)));
100 rd_write_file(fd
, &cellhdr
, sizeof(CELLHEADER
));
101 rd_write_file(fd
, data
, length
);
106 /* List the bitmap keys from the persistent cache file */
108 pstcache_enumerate(uint8 id
, HASH_KEY
* keylist
)
112 sint16 mru_idx
[0xa00];
113 uint32 mru_stamp
[0xa00];
116 if (!(g_bitmap_cache
&& g_bitmap_cache_persist_enable
&& IS_PERSISTENT(id
)))
119 /* The server disconnects if the bitmap cache content is sent more than once */
120 if (g_pstcache_enumerated
)
123 DEBUG_RDP5(("Persistent bitmap cache enumeration... "));
124 for (idx
= 0; idx
< BMPCACHE2_NUM_PSTCELLS
; idx
++)
126 fd
= g_pstcache_fd
[id
];
127 rd_lseek_file(fd
, idx
* (g_pstcache_Bpp
* MAX_CELL_SIZE
+ sizeof(CELLHEADER
)));
128 if (rd_read_file(fd
, &cellhdr
, sizeof(CELLHEADER
)) <= 0)
131 if (memcmp(cellhdr
.key
, zero_key
, sizeof(HASH_KEY
)) != 0)
133 memcpy(keylist
[idx
], cellhdr
.key
, sizeof(HASH_KEY
));
135 /* Pre-cache (not possible for 8 bit colour depth cause it needs a colourmap) */
136 if (g_bitmap_cache_precache
&& cellhdr
.stamp
&& g_server_depth
> 8)
137 pstcache_load_bitmap(id
, idx
);
140 for (n
= idx
; n
> 0 && cellhdr
.stamp
< mru_stamp
[n
- 1]; n
--)
142 mru_idx
[n
] = mru_idx
[n
- 1];
143 mru_stamp
[n
] = mru_stamp
[n
- 1];
147 mru_stamp
[n
] = cellhdr
.stamp
;
155 DEBUG_RDP5(("%d cached bitmaps.\n", idx
));
157 cache_rebuild_bmpcache_linked_list(id
, mru_idx
, idx
);
158 g_pstcache_enumerated
= True
;
162 /* initialise the persistent bitmap cache */
164 pstcache_init(uint8 cache_id
)
169 if (g_pstcache_enumerated
)
172 g_pstcache_fd
[cache_id
] = 0;
174 if (!(g_bitmap_cache
&& g_bitmap_cache_persist_enable
))
177 if (!rd_pstcache_mkdir())
179 DEBUG(("failed to get/make cache directory!\n"));
183 g_pstcache_Bpp
= (g_server_depth
+ 7) / 8;
184 sprintf(filename
, "cache/pstcache_%d_%d", cache_id
, g_pstcache_Bpp
);
185 DEBUG(("persistent bitmap cache file: %s\n", filename
));
187 fd
= rd_open_file(filename
);
191 if (!rd_lock_file(fd
, 0, 0))
193 warning("Persistent bitmap caching is disabled. (The file is already in use)\n");
198 g_pstcache_fd
[cache_id
] = fd
;