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 along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #define MAX_CELL_SIZE 0x1000 /* pixels */
25 #define IS_PERSISTENT(id) (id < 8 && This->pstcache_fd[id] > 0)
27 const uint8 zero_key
[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
30 /* Update mru stamp/index for a bitmap */
32 pstcache_touch_bitmap(RDPCLIENT
* This
, uint8 cache_id
, uint16 cache_idx
, uint32 stamp
)
36 if (!IS_PERSISTENT(cache_id
) || cache_idx
>= BMPCACHE2_NUM_PSTCELLS
)
39 fd
= This
->pstcache_fd
[cache_id
];
40 rd_lseek_file(fd
, 12 + cache_idx
* (This
->pstcache_Bpp
* MAX_CELL_SIZE
+ sizeof(CELLHEADER
)));
41 rd_write_file(fd
, &stamp
, sizeof(stamp
));
44 /* Load a bitmap from the persistent cache */
46 pstcache_load_bitmap(RDPCLIENT
* This
, uint8 cache_id
, uint16 cache_idx
)
53 if (!This
->bitmap_cache_persist_enable
)
56 if (!IS_PERSISTENT(cache_id
) || cache_idx
>= BMPCACHE2_NUM_PSTCELLS
)
59 fd
= This
->pstcache_fd
[cache_id
];
60 rd_lseek_file(fd
, cache_idx
* (This
->pstcache_Bpp
* MAX_CELL_SIZE
+ sizeof(CELLHEADER
)));
61 rd_read_file(fd
, &cellhdr
, sizeof(CELLHEADER
));
62 celldata
= (uint8
*) malloc(cellhdr
.length
);
67 rd_read_file(fd
, celldata
, cellhdr
.length
);
69 bitmap
= ui_create_bitmap(This
, cellhdr
.width
, cellhdr
.height
, celldata
);
70 DEBUG(("Load bitmap from disk: id=%d, idx=%d, bmp=0x%x)\n", cache_id
, cache_idx
, bitmap
));
71 cache_put_bitmap(This
, cache_id
, cache_idx
, bitmap
);
77 /* Store a bitmap in the persistent cache */
79 pstcache_save_bitmap(RDPCLIENT
* This
, uint8 cache_id
, uint16 cache_idx
, uint8
* key
,
80 uint8 width
, uint8 height
, uint16 length
, uint8
* data
)
85 if (!IS_PERSISTENT(cache_id
) || cache_idx
>= BMPCACHE2_NUM_PSTCELLS
)
88 memcpy(cellhdr
.key
, key
, sizeof(HASH_KEY
));
89 cellhdr
.width
= width
;
90 cellhdr
.height
= height
;
91 cellhdr
.length
= length
;
94 fd
= This
->pstcache_fd
[cache_id
];
95 rd_lseek_file(fd
, cache_idx
* (This
->pstcache_Bpp
* MAX_CELL_SIZE
+ sizeof(CELLHEADER
)));
96 rd_write_file(fd
, &cellhdr
, sizeof(CELLHEADER
));
97 rd_write_file(fd
, data
, length
);
102 /* List the bitmap keys from the persistent cache file */
104 pstcache_enumerate(RDPCLIENT
* This
, uint8 id
, HASH_KEY
* keylist
)
108 sint16 mru_idx
[0xa00];
109 uint32 mru_stamp
[0xa00];
112 if (!(This
->bitmap_cache
&& This
->bitmap_cache_persist_enable
&& IS_PERSISTENT(id
)))
115 /* The server disconnects if the bitmap cache content is sent more than once */
116 if (This
->pstcache_enumerated
)
119 DEBUG_RDP5(("Persistent bitmap cache enumeration... "));
120 for (idx
= 0; idx
< BMPCACHE2_NUM_PSTCELLS
; idx
++)
122 fd
= This
->pstcache_fd
[id
];
123 rd_lseek_file(fd
, idx
* (This
->pstcache_Bpp
* MAX_CELL_SIZE
+ sizeof(CELLHEADER
)));
124 if (rd_read_file(fd
, &cellhdr
, sizeof(CELLHEADER
)) <= 0)
127 if (memcmp(cellhdr
.key
, zero_key
, sizeof(HASH_KEY
)) != 0)
129 memcpy(keylist
[idx
], cellhdr
.key
, sizeof(HASH_KEY
));
131 /* Pre-cache (not possible for 8 bit colour depth cause it needs a colourmap) */
132 if (This
->bitmap_cache_precache
&& cellhdr
.stamp
&& This
->server_depth
> 8)
133 pstcache_load_bitmap(This
, id
, idx
);
136 for (n
= idx
; n
> 0 && cellhdr
.stamp
< mru_stamp
[n
- 1]; n
--)
138 mru_idx
[n
] = mru_idx
[n
- 1];
139 mru_stamp
[n
] = mru_stamp
[n
- 1];
143 mru_stamp
[n
] = cellhdr
.stamp
;
151 DEBUG_RDP5(("%d cached bitmaps.\n", idx
));
153 cache_rebuild_bmpcache_linked_list(This
, id
, mru_idx
, idx
);
154 This
->pstcache_enumerated
= True
;
158 /* initialise the persistent bitmap cache */
160 pstcache_init(RDPCLIENT
* This
, uint8 cache_id
)
165 if (This
->pstcache_enumerated
)
168 This
->pstcache_fd
[cache_id
] = 0;
170 if (!(This
->bitmap_cache
&& This
->bitmap_cache_persist_enable
))
173 if (!rd_pstcache_mkdir())
175 DEBUG(("failed to get/make cache directory!\n"));
179 This
->pstcache_Bpp
= (This
->server_depth
+ 7) / 8;
180 sprintf(filename
, "cache/pstcache_%d_%d", cache_id
, This
->pstcache_Bpp
);
181 DEBUG(("persistent bitmap cache file: %s\n", filename
));
183 fd
= rd_open_file(filename
);
187 if (!rd_lock_file(fd
, 0, 0))
189 warning("Persistent bitmap caching is disabled. (The file is already in use)\n");
194 This
->pstcache_fd
[cache_id
] = fd
;