+ if (usage & PIPE_TRANSFER_WRITE) {
+ if ((usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) &&
+ !(resource->flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT)) {
+ /*
+ * Flush any pending primitives, finish writing any pending DMA
+ * commands, and tell the host to discard the buffer contents on
+ * the next DMA operation.
+ */
+
+ svga_hwtnl_flush_buffer(svga, resource);
+
+ if (sbuf->dma.pending) {
+ svga_buffer_upload_flush(svga, sbuf);
+
+ /*
+ * Instead of flushing the context command buffer, simply discard
+ * the current hwbuf, and start a new one.
+ * With GB objects, the map operation takes care of this
+ * if passed the PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE flag,
+ * and the old backing store is busy.
+ */
+
+ if (!svga_have_gb_objects(svga))
+ svga_buffer_destroy_hw_storage(ss, sbuf);
+ }
+
+ sbuf->map.num_ranges = 0;
+ sbuf->dma.flags.discard = TRUE;
+ }
+
+ if (usage & PIPE_TRANSFER_UNSYNCHRONIZED) {
+ if (!sbuf->map.num_ranges) {
+ /*
+ * No pending ranges to upload so far, so we can tell the host to
+ * not synchronize on the next DMA command.
+ */
+
+ sbuf->dma.flags.unsynchronized = TRUE;
+ }
+ } else {
+ /*
+ * Synchronizing, so flush any pending primitives, finish writing any
+ * pending DMA command, and ensure the next DMA will be done in order.
+ */
+
+ svga_hwtnl_flush_buffer(svga, resource);
+
+ if (sbuf->dma.pending) {
+ svga_buffer_upload_flush(svga, sbuf);
+
+ if (svga_buffer_has_hw_storage(sbuf)) {
+ /*
+ * We have a pending DMA upload from a hardware buffer, therefore
+ * we need to ensure that the host finishes processing that DMA
+ * command before the state tracker can start overwriting the
+ * hardware buffer.
+ *
+ * XXX: This could be avoided by tying the hardware buffer to
+ * the transfer (just as done with textures), which would allow
+ * overlapping DMAs commands to be queued on the same context
+ * buffer. However, due to the likelihood of software vertex
+ * processing, it is more convenient to hold on to the hardware
+ * buffer, allowing to quickly access the contents from the CPU
+ * without having to do a DMA download from the host.
+ */
+
+ if (usage & PIPE_TRANSFER_DONTBLOCK) {
+ /*
+ * Flushing the command buffer here will most likely cause
+ * the map of the hwbuf below to block, so preemptively
+ * return NULL here if DONTBLOCK is set to prevent unnecessary
+ * command buffer flushes.
+ */
+
+ FREE(transfer);
+ goto done;
+ }
+
+ svga_context_flush(svga, NULL);
+ }
+ }
+
+ sbuf->dma.flags.unsynchronized = FALSE;
+ }
+ }
+
+ if (!sbuf->swbuf && !svga_buffer_has_hw_storage(sbuf)) {
+ if (svga_buffer_create_hw_storage(ss, sbuf, sbuf->bind_flags) != PIPE_OK) {