- pipe_mutex_lock(cache->mutex);
-
- if(!LIST_IS_EMPTY(&cache->empty)) {
- /* use the first empty entry */
- entry = LIST_ENTRY(struct svga_host_surface_cache_entry, cache->empty.next, head);
-
+ mtx_lock(&cache->mutex);
+
+ if (surf_size >= SVGA_HOST_SURFACE_CACHE_BYTES) {
+ /* this surface is too large to cache, just free it */
+ sws->surface_reference(sws, &handle, NULL);
+ mtx_unlock(&cache->mutex);
+ return;
+ }
+
+ if (cache->total_size + surf_size > SVGA_HOST_SURFACE_CACHE_BYTES) {
+ /* Adding this surface would exceed the cache size.
+ * Try to discard least recently used entries until we hit the
+ * new target cache size.
+ */
+ unsigned target_size = SVGA_HOST_SURFACE_CACHE_BYTES - surf_size;
+
+ svga_screen_cache_shrink(svgascreen, target_size);
+
+ if (cache->total_size > target_size) {
+ /* we weren't able to shrink the cache as much as we wanted so
+ * just discard this surface.
+ */
+ sws->surface_reference(sws, &handle, NULL);
+ mtx_unlock(&cache->mutex);
+ return;
+ }
+ }
+
+ if (!LIST_IS_EMPTY(&cache->empty)) {
+ /* An empty entry has no surface associated with it.
+ * Use the first empty entry.
+ */
+ entry = LIST_ENTRY(struct svga_host_surface_cache_entry,
+ cache->empty.next, head);
+
+ /* Remove from LRU list */