+static void vc4_bo_purgeable(struct vc4_bo *bo)
+{
+ struct drm_vc4_gem_madvise arg = {
+ .handle = bo->handle,
+ .madv = VC4_MADV_DONTNEED,
+ };
+
+ if (bo->screen->has_madvise)
+ vc4_ioctl(bo->screen->fd, DRM_IOCTL_VC4_GEM_MADVISE, &arg);
+}
+
+static bool vc4_bo_unpurgeable(struct vc4_bo *bo)
+{
+ struct drm_vc4_gem_madvise arg = {
+ .handle = bo->handle,
+ .madv = VC4_MADV_WILLNEED,
+ };
+
+ if (!bo->screen->has_madvise)
+ return true;
+
+ if (vc4_ioctl(bo->screen->fd, DRM_IOCTL_VC4_GEM_MADVISE, &arg))
+ return false;
+
+ return arg.retained;
+}
+
+static void
+vc4_bo_free(struct vc4_bo *bo)
+{
+ struct vc4_screen *screen = bo->screen;
+
+ if (bo->map) {
+ if (using_vc4_simulator && bo->name &&
+ strcmp(bo->name, "winsys") == 0) {
+ free(bo->map);
+ } else {
+ munmap(bo->map, bo->size);
+ VG(VALGRIND_FREELIKE_BLOCK(bo->map, 0));
+ }
+ }
+
+ struct drm_gem_close c;
+ memset(&c, 0, sizeof(c));
+ c.handle = bo->handle;
+ int ret = vc4_ioctl(screen->fd, DRM_IOCTL_GEM_CLOSE, &c);
+ if (ret != 0)
+ fprintf(stderr, "close object %d: %s\n", bo->handle, strerror(errno));
+
+ screen->bo_count--;
+ screen->bo_size -= bo->size;
+
+ if (dump_stats) {
+ fprintf(stderr, "Freed %s%s%dkb:\n",
+ bo->name ? bo->name : "",
+ bo->name ? " " : "",
+ bo->size / 1024);
+ vc4_bo_dump_stats(screen);
+ }
+
+ free(bo);
+}
+