+static unsigned
+vmw_swc_get_command_buffer_size(struct svga_winsys_context *swc)
+{
+ const struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
+ return vswc->command.used;
+}
+
+static void
+vmw_swc_context_relocation(struct svga_winsys_context *swc,
+ uint32 *cid)
+{
+ *cid = swc->cid;
+}
+
+static boolean
+vmw_swc_add_validate_buffer(struct vmw_svga_winsys_context *vswc,
+ struct pb_buffer *pb_buf,
+ unsigned flags)
+{
+ ASSERTED enum pipe_error ret;
+ unsigned translated_flags;
+ boolean already_present;
+
+ translated_flags = vmw_translate_to_pb_flags(flags);
+ ret = pb_validate_add_buffer(vswc->validate, pb_buf, translated_flags,
+ vswc->hash, &already_present);
+ assert(ret == PIPE_OK);
+ return !already_present;
+}
+
+static void
+vmw_swc_region_relocation(struct svga_winsys_context *swc,
+ struct SVGAGuestPtr *where,
+ struct svga_winsys_buffer *buffer,
+ uint32 offset,
+ unsigned flags)
+{
+ struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
+ struct vmw_buffer_relocation *reloc;
+
+ assert(vswc->region.staged < vswc->region.reserved);
+
+ reloc = &vswc->region.relocs[vswc->region.used + vswc->region.staged];
+ reloc->region.where = where;
+
+ /*
+ * pb_validate holds a refcount to the buffer, so no need to
+ * refcount it again in the relocation.
+ */
+ reloc->buffer = vmw_pb_buffer(buffer);
+ reloc->offset = offset;
+ reloc->is_mob = FALSE;
+ ++vswc->region.staged;
+
+ if (vmw_swc_add_validate_buffer(vswc, reloc->buffer, flags)) {
+ vswc->seen_regions += reloc->buffer->size;
+ if ((swc->hints & SVGA_HINT_FLAG_CAN_PRE_FLUSH) &&
+ vswc->seen_regions >= VMW_GMR_POOL_SIZE/5)
+ vswc->preemptive_flush = TRUE;
+ }
+
+#ifdef DEBUG
+ if (!(flags & SVGA_RELOC_INTERNAL))
+ debug_flush_cb_reference(vswc->fctx, vmw_debug_flush_buf(buffer));
+#endif
+}
+
+static void
+vmw_swc_mob_relocation(struct svga_winsys_context *swc,
+ SVGAMobId *id,
+ uint32 *offset_into_mob,
+ struct svga_winsys_buffer *buffer,
+ uint32 offset,
+ unsigned flags)
+{
+ struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
+ struct vmw_buffer_relocation *reloc;
+ struct pb_buffer *pb_buffer = vmw_pb_buffer(buffer);
+
+ if (id) {
+ assert(vswc->region.staged < vswc->region.reserved);
+
+ reloc = &vswc->region.relocs[vswc->region.used + vswc->region.staged];
+ reloc->mob.id = id;
+ reloc->mob.offset_into_mob = offset_into_mob;
+
+ /*
+ * pb_validate holds a refcount to the buffer, so no need to
+ * refcount it again in the relocation.
+ */
+ reloc->buffer = pb_buffer;
+ reloc->offset = offset;
+ reloc->is_mob = TRUE;
+ ++vswc->region.staged;
+ }
+
+ if (vmw_swc_add_validate_buffer(vswc, pb_buffer, flags)) {
+ vswc->seen_mobs += pb_buffer->size;
+
+ if ((swc->hints & SVGA_HINT_FLAG_CAN_PRE_FLUSH) &&
+ vswc->seen_mobs >=
+ vswc->vws->ioctl.max_mob_memory / VMW_MAX_MOB_MEM_FACTOR)
+ vswc->preemptive_flush = TRUE;
+ }
+
+#ifdef DEBUG
+ if (!(flags & SVGA_RELOC_INTERNAL))
+ debug_flush_cb_reference(vswc->fctx, vmw_debug_flush_buf(buffer));
+#endif
+}
+
+
+/**
+ * vmw_swc_surface_clear_reference - Clear referenced info for a surface
+ *
+ * @swc: Pointer to an svga_winsys_context
+ * @vsurf: Pointer to a vmw_svga_winsys_surface, the referenced info of which
+ * we want to clear
+ *
+ * This is primarily used by a discard surface map to indicate that the
+ * surface data is no longer referenced by a draw call, and mapping it
+ * should therefore no longer cause a flush.
+ */
+void
+vmw_swc_surface_clear_reference(struct svga_winsys_context *swc,
+ struct vmw_svga_winsys_surface *vsurf)
+{
+ struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
+ struct vmw_ctx_validate_item *isrf =
+ util_hash_table_get(vswc->hash, vsurf);
+
+ if (isrf && isrf->referenced) {
+ isrf->referenced = FALSE;
+ p_atomic_dec(&vsurf->validated);
+ }
+}
+
+static void
+vmw_swc_surface_only_relocation(struct svga_winsys_context *swc,
+ uint32 *where,
+ struct vmw_svga_winsys_surface *vsurf,
+ unsigned flags)
+{
+ struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
+ struct vmw_ctx_validate_item *isrf;
+
+ assert(vswc->surface.staged < vswc->surface.reserved);
+ isrf = util_hash_table_get(vswc->hash, vsurf);
+
+ if (isrf == NULL) {
+ isrf = &vswc->surface.items[vswc->surface.used + vswc->surface.staged];
+ vmw_svga_winsys_surface_reference(&isrf->vsurf, vsurf);
+ isrf->referenced = FALSE;
+
+ _mesa_hash_table_insert(vswc->hash, vsurf, isrf);
+ ++vswc->surface.staged;
+
+ vswc->seen_surfaces += vsurf->size;
+ if ((swc->hints & SVGA_HINT_FLAG_CAN_PRE_FLUSH) &&
+ vswc->seen_surfaces >=
+ vswc->vws->ioctl.max_surface_memory / VMW_MAX_SURF_MEM_FACTOR)
+ vswc->preemptive_flush = TRUE;
+ }
+
+ if (!(flags & SVGA_RELOC_INTERNAL) && !isrf->referenced) {
+ isrf->referenced = TRUE;
+ p_atomic_inc(&vsurf->validated);
+ }
+
+ if (where)
+ *where = vsurf->sid;
+}