1/**********************************************************
2 * Copyright 2008-2009 VMware, Inc.  All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 **********************************************************/
25
26
27#include "os/os_thread.h"
28#include "pipe/p_state.h"
29#include "pipe/p_defines.h"
30#include "util/u_inlines.h"
31#include "util/u_math.h"
32#include "util/u_memory.h"
33
34#include "svga_cmd.h"
35#include "svga_context.h"
36#include "svga_debug.h"
37#include "svga_resource_buffer.h"
38#include "svga_resource_buffer_upload.h"
39#include "svga_screen.h"
40#include "svga_winsys.h"
41
42/**
43 * Describes a complete SVGA_3D_CMD_UPDATE_GB_IMAGE command
44 *
45 */
46struct svga_3d_update_gb_image {
47   SVGA3dCmdHeader header;
48   SVGA3dCmdUpdateGBImage body;
49};
50
51struct svga_3d_invalidate_gb_image {
52   SVGA3dCmdHeader header;
53   SVGA3dCmdInvalidateGBImage body;
54};
55
56
57/**
58 * Allocate a winsys_buffer (ie. DMA, aka GMR memory).
59 *
60 * It will flush and retry in case the first attempt to create a DMA buffer
61 * fails, so it should not be called from any function involved in flushing
62 * to avoid recursion.
63 */
64struct svga_winsys_buffer *
65svga_winsys_buffer_create( struct svga_context *svga,
66                           unsigned alignment,
67                           unsigned usage,
68                           unsigned size )
69{
70   struct svga_screen *svgascreen = svga_screen(svga->pipe.screen);
71   struct svga_winsys_screen *sws = svgascreen->sws;
72   struct svga_winsys_buffer *buf;
73
74   /* Just try */
75   buf = sws->buffer_create(sws, alignment, usage, size);
76   if (!buf) {
77      SVGA_DBG(DEBUG_DMA|DEBUG_PERF, "flushing context to find %d bytes GMR\n",
78               size);
79
80      /* Try flushing all pending DMAs */
81      svga_context_flush(svga, NULL);
82      buf = sws->buffer_create(sws, alignment, usage, size);
83   }
84
85   return buf;
86}
87
88
89/**
90 * Destroy HW storage if separate from the host surface.
91 * In the GB case, the HW storage is associated with the host surface
92 * and is therefore a No-op.
93 */
94void
95svga_buffer_destroy_hw_storage(struct svga_screen *ss, struct svga_buffer *sbuf)
96{
97   struct svga_winsys_screen *sws = ss->sws;
98
99   assert(sbuf->map.count == 0);
100   assert(sbuf->hwbuf);
101   if (sbuf->hwbuf) {
102      sws->buffer_destroy(sws, sbuf->hwbuf);
103      sbuf->hwbuf = NULL;
104   }
105}
106
107
108
109/**
110 * Allocate DMA'ble or Updatable storage for the buffer.
111 *
112 * Called before mapping a buffer.
113 */
114enum pipe_error
115svga_buffer_create_hw_storage(struct svga_screen *ss,
116                              struct svga_buffer *sbuf)
117{
118   assert(!sbuf->user);
119
120   if (ss->sws->have_gb_objects) {
121      assert(sbuf->handle || !sbuf->dma.pending);
122      return svga_buffer_create_host_surface(ss, sbuf);
123   }
124   if (!sbuf->hwbuf) {
125      struct svga_winsys_screen *sws = ss->sws;
126      unsigned alignment = 16;
127      unsigned usage = 0;
128      unsigned size = sbuf->b.b.width0;
129
130      sbuf->hwbuf = sws->buffer_create(sws, alignment, usage, size);
131      if (!sbuf->hwbuf)
132         return PIPE_ERROR_OUT_OF_MEMORY;
133
134      assert(!sbuf->dma.pending);
135   }
136
137   return PIPE_OK;
138}
139
140
141
142enum pipe_error
143svga_buffer_create_host_surface(struct svga_screen *ss,
144                                struct svga_buffer *sbuf)
145{
146   assert(!sbuf->user);
147
148   if (!sbuf->handle) {
149      boolean validated;
150
151      sbuf->key.flags = 0;
152
153      sbuf->key.format = SVGA3D_BUFFER;
154      if (sbuf->bind_flags & PIPE_BIND_VERTEX_BUFFER) {
155         sbuf->key.flags |= SVGA3D_SURFACE_HINT_VERTEXBUFFER;
156         sbuf->key.flags |= SVGA3D_SURFACE_BIND_VERTEX_BUFFER;
157      }
158      if (sbuf->bind_flags & PIPE_BIND_INDEX_BUFFER) {
159         sbuf->key.flags |= SVGA3D_SURFACE_HINT_INDEXBUFFER;
160         sbuf->key.flags |= SVGA3D_SURFACE_BIND_INDEX_BUFFER;
161      }
162      if (sbuf->bind_flags & PIPE_BIND_CONSTANT_BUFFER)
163         sbuf->key.flags |= SVGA3D_SURFACE_BIND_CONSTANT_BUFFER;
164
165      if (sbuf->bind_flags & PIPE_BIND_STREAM_OUTPUT)
166         sbuf->key.flags |= SVGA3D_SURFACE_BIND_STREAM_OUTPUT;
167
168      if (sbuf->bind_flags & PIPE_BIND_SAMPLER_VIEW)
169         sbuf->key.flags |= SVGA3D_SURFACE_BIND_SHADER_RESOURCE;
170
171      if (!sbuf->bind_flags && sbuf->b.b.usage == PIPE_USAGE_STAGING) {
172         /* This surface is to be used with the
173          * SVGA3D_CMD_DX_TRANSFER_FROM_BUFFER command, and no other
174          * bind flags are allowed to be set for this surface.
175          */
176         sbuf->key.flags = SVGA3D_SURFACE_TRANSFER_FROM_BUFFER;
177      }
178
179      sbuf->key.size.width = sbuf->b.b.width0;
180      sbuf->key.size.height = 1;
181      sbuf->key.size.depth = 1;
182
183      sbuf->key.numFaces = 1;
184      sbuf->key.numMipLevels = 1;
185      sbuf->key.cachable = 1;
186      sbuf->key.arraySize = 1;
187
188      SVGA_DBG(DEBUG_DMA, "surface_create for buffer sz %d\n",
189               sbuf->b.b.width0);
190
191      sbuf->handle = svga_screen_surface_create(ss, sbuf->b.b.bind,
192                                                sbuf->b.b.usage,
193                                                &validated, &sbuf->key);
194      if (!sbuf->handle)
195         return PIPE_ERROR_OUT_OF_MEMORY;
196
197      /* Always set the discard flag on the first time the buffer is written
198       * as svga_screen_surface_create might have passed a recycled host
199       * buffer.
200       */
201      sbuf->dma.flags.discard = TRUE;
202
203      SVGA_DBG(DEBUG_DMA, "   --> got sid %p sz %d (buffer)\n",
204               sbuf->handle, sbuf->b.b.width0);
205   }
206
207   return PIPE_OK;
208}
209
210
211void
212svga_buffer_destroy_host_surface(struct svga_screen *ss,
213                                 struct svga_buffer *sbuf)
214{
215   if (sbuf->handle) {
216      SVGA_DBG(DEBUG_DMA, " ungrab sid %p sz %d\n",
217               sbuf->handle, sbuf->b.b.width0);
218      svga_screen_surface_destroy(ss, &sbuf->key, &sbuf->handle);
219   }
220}
221
222
223/**
224 * Insert a number of preliminary UPDATE_GB_IMAGE commands in the
225 * command buffer, equal to the current number of mapped ranges.
226 * The UPDATE_GB_IMAGE commands will be patched with the
227 * actual ranges just before flush.
228 */
229static enum pipe_error
230svga_buffer_upload_gb_command(struct svga_context *svga,
231			      struct svga_buffer *sbuf)
232{
233   struct svga_winsys_context *swc = svga->swc;
234   SVGA3dCmdUpdateGBImage *update_cmd;
235   struct svga_3d_update_gb_image *whole_update_cmd = NULL;
236   const uint32 numBoxes = sbuf->map.num_ranges;
237   struct pipe_resource *dummy;
238   unsigned i;
239
240   assert(svga_have_gb_objects(svga));
241   assert(numBoxes);
242   assert(sbuf->dma.updates == NULL);
243
244   if (sbuf->dma.flags.discard) {
245      struct svga_3d_invalidate_gb_image *cicmd = NULL;
246      SVGA3dCmdInvalidateGBImage *invalidate_cmd;
247      const unsigned total_commands_size =
248         sizeof(*invalidate_cmd) + numBoxes * sizeof(*whole_update_cmd);
249
250      /* Allocate FIFO space for one INVALIDATE_GB_IMAGE command followed by
251       * 'numBoxes' UPDATE_GB_IMAGE commands.  Allocate all at once rather
252       * than with separate commands because we need to properly deal with
253       * filling the command buffer.
254       */
255      invalidate_cmd = SVGA3D_FIFOReserve(swc,
256                                          SVGA_3D_CMD_INVALIDATE_GB_IMAGE,
257                                          total_commands_size, 1 + numBoxes);
258      if (!invalidate_cmd)
259	 return PIPE_ERROR_OUT_OF_MEMORY;
260
261      cicmd = container_of(invalidate_cmd, cicmd, body);
262      cicmd->header.size = sizeof(*invalidate_cmd);
263      swc->surface_relocation(swc, &invalidate_cmd->image.sid, NULL, sbuf->handle,
264                              (SVGA_RELOC_WRITE |
265                               SVGA_RELOC_INTERNAL |
266                               SVGA_RELOC_DMA));
267      invalidate_cmd->image.face = 0;
268      invalidate_cmd->image.mipmap = 0;
269
270      /* The whole_update_command is a SVGA3dCmdHeader plus the
271       * SVGA3dCmdUpdateGBImage command.
272       */
273      whole_update_cmd = (struct svga_3d_update_gb_image *) &invalidate_cmd[1];
274      /* initialize the first UPDATE_GB_IMAGE command */
275      whole_update_cmd->header.id = SVGA_3D_CMD_UPDATE_GB_IMAGE;
276      update_cmd = &whole_update_cmd->body;
277
278   } else {
279      /* Allocate FIFO space for 'numBoxes' UPDATE_GB_IMAGE commands */
280      const unsigned total_commands_size =
281         sizeof(*update_cmd) + (numBoxes - 1) * sizeof(*whole_update_cmd);
282
283      update_cmd = SVGA3D_FIFOReserve(swc,
284                                      SVGA_3D_CMD_UPDATE_GB_IMAGE,
285                                      total_commands_size, numBoxes);
286      if (!update_cmd)
287	 return PIPE_ERROR_OUT_OF_MEMORY;
288
289      /* The whole_update_command is a SVGA3dCmdHeader plus the
290       * SVGA3dCmdUpdateGBImage command.
291       */
292      whole_update_cmd = container_of(update_cmd, whole_update_cmd, body);
293   }
294
295   /* Init the first UPDATE_GB_IMAGE command */
296   whole_update_cmd->header.size = sizeof(*update_cmd);
297   swc->surface_relocation(swc, &update_cmd->image.sid, NULL, sbuf->handle,
298			   SVGA_RELOC_WRITE | SVGA_RELOC_INTERNAL);
299   update_cmd->image.face = 0;
300   update_cmd->image.mipmap = 0;
301
302   /* Save pointer to the first UPDATE_GB_IMAGE command so that we can
303    * fill in the box info below.
304    */
305   sbuf->dma.updates = whole_update_cmd;
306
307   /*
308    * Copy the face, mipmap, etc. info to all subsequent commands.
309    * Also do the surface relocation for each subsequent command.
310    */
311   for (i = 1; i < numBoxes; ++i) {
312      whole_update_cmd++;
313      memcpy(whole_update_cmd, sbuf->dma.updates, sizeof(*whole_update_cmd));
314
315      swc->surface_relocation(swc, &whole_update_cmd->body.image.sid, NULL,
316                              sbuf->handle,
317                              SVGA_RELOC_WRITE | SVGA_RELOC_INTERNAL);
318   }
319
320   /* Increment reference count */
321   sbuf->dma.svga = svga;
322   dummy = NULL;
323   pipe_resource_reference(&dummy, &sbuf->b.b);
324   SVGA_FIFOCommitAll(swc);
325
326   swc->hints |= SVGA_HINT_FLAG_CAN_PRE_FLUSH;
327   sbuf->dma.flags.discard = FALSE;
328
329   svga->hud.num_resource_updates++;
330
331   return PIPE_OK;
332}
333
334
335/**
336 * Issue DMA commands to transfer guest memory to the host.
337 * Note that the memory segments (offset, size) will be patched in
338 * later in the svga_buffer_upload_flush() function.
339 */
340static enum pipe_error
341svga_buffer_upload_hb_command(struct svga_context *svga,
342                              struct svga_buffer *sbuf)
343{
344   struct svga_winsys_context *swc = svga->swc;
345   struct svga_winsys_buffer *guest = sbuf->hwbuf;
346   struct svga_winsys_surface *host = sbuf->handle;
347   const SVGA3dTransferType transfer = SVGA3D_WRITE_HOST_VRAM;
348   SVGA3dCmdSurfaceDMA *cmd;
349   const uint32 numBoxes = sbuf->map.num_ranges;
350   SVGA3dCopyBox *boxes;
351   SVGA3dCmdSurfaceDMASuffix *pSuffix;
352   unsigned region_flags;
353   unsigned surface_flags;
354   struct pipe_resource *dummy;
355
356   assert(!svga_have_gb_objects(svga));
357
358   if (transfer == SVGA3D_WRITE_HOST_VRAM) {
359      region_flags = SVGA_RELOC_READ;
360      surface_flags = SVGA_RELOC_WRITE;
361   }
362   else if (transfer == SVGA3D_READ_HOST_VRAM) {
363      region_flags = SVGA_RELOC_WRITE;
364      surface_flags = SVGA_RELOC_READ;
365   }
366   else {
367      assert(0);
368      return PIPE_ERROR_BAD_INPUT;
369   }
370
371   assert(numBoxes);
372
373   cmd = SVGA3D_FIFOReserve(swc,
374                            SVGA_3D_CMD_SURFACE_DMA,
375                            sizeof *cmd + numBoxes * sizeof *boxes + sizeof *pSuffix,
376                            2);
377   if (!cmd)
378      return PIPE_ERROR_OUT_OF_MEMORY;
379
380   swc->region_relocation(swc, &cmd->guest.ptr, guest, 0, region_flags);
381   cmd->guest.pitch = 0;
382
383   swc->surface_relocation(swc, &cmd->host.sid, NULL, host, surface_flags);
384   cmd->host.face = 0;
385   cmd->host.mipmap = 0;
386
387   cmd->transfer = transfer;
388
389   sbuf->dma.boxes = (SVGA3dCopyBox *)&cmd[1];
390   sbuf->dma.svga = svga;
391
392   /* Increment reference count */
393   dummy = NULL;
394   pipe_resource_reference(&dummy, &sbuf->b.b);
395
396   pSuffix = (SVGA3dCmdSurfaceDMASuffix *)((uint8_t*)cmd + sizeof *cmd + numBoxes * sizeof *boxes);
397   pSuffix->suffixSize = sizeof *pSuffix;
398   pSuffix->maximumOffset = sbuf->b.b.width0;
399   pSuffix->flags = sbuf->dma.flags;
400
401   SVGA_FIFOCommitAll(swc);
402
403   swc->hints |= SVGA_HINT_FLAG_CAN_PRE_FLUSH;
404   sbuf->dma.flags.discard = FALSE;
405
406   svga->hud.num_buffer_uploads++;
407
408   return PIPE_OK;
409}
410
411
412/**
413 * Issue commands to transfer guest memory to the host.
414 */
415static enum pipe_error
416svga_buffer_upload_command(struct svga_context *svga, struct svga_buffer *sbuf)
417{
418   if (svga_have_gb_objects(svga)) {
419      return svga_buffer_upload_gb_command(svga, sbuf);
420   } else {
421      return svga_buffer_upload_hb_command(svga, sbuf);
422   }
423}
424
425
426/**
427 * Patch up the upload DMA command reserved by svga_buffer_upload_command
428 * with the final ranges.
429 */
430void
431svga_buffer_upload_flush(struct svga_context *svga,
432			 struct svga_buffer *sbuf)
433{
434   unsigned i;
435   struct pipe_resource *dummy;
436
437   if (!sbuf->dma.pending) {
438      //debug_printf("no dma pending on buffer\n");
439      return;
440   }
441
442   assert(sbuf->handle);
443   assert(sbuf->map.num_ranges);
444   assert(sbuf->dma.svga == svga);
445
446   /*
447    * Patch the DMA/update command with the final copy box.
448    */
449   if (svga_have_gb_objects(svga)) {
450      struct svga_3d_update_gb_image *update = sbuf->dma.updates;
451      assert(update);
452
453      for (i = 0; i < sbuf->map.num_ranges; ++i, ++update) {
454         SVGA3dBox *box = &update->body.box;
455
456         SVGA_DBG(DEBUG_DMA, "  bytes %u - %u\n",
457                  sbuf->map.ranges[i].start, sbuf->map.ranges[i].end);
458
459         box->x = sbuf->map.ranges[i].start;
460         box->y = 0;
461         box->z = 0;
462         box->w = sbuf->map.ranges[i].end - sbuf->map.ranges[i].start;
463         box->h = 1;
464         box->d = 1;
465
466         assert(box->x <= sbuf->b.b.width0);
467         assert(box->x + box->w <= sbuf->b.b.width0);
468
469         svga->hud.num_bytes_uploaded += box->w;
470         svga->hud.num_buffer_uploads++;
471      }
472   }
473   else {
474      assert(sbuf->hwbuf);
475      assert(sbuf->dma.boxes);
476      SVGA_DBG(DEBUG_DMA, "dma to sid %p\n", sbuf->handle);
477
478      for (i = 0; i < sbuf->map.num_ranges; ++i) {
479         SVGA3dCopyBox *box = sbuf->dma.boxes + i;
480
481         SVGA_DBG(DEBUG_DMA, "  bytes %u - %u\n",
482               sbuf->map.ranges[i].start, sbuf->map.ranges[i].end);
483
484         box->x = sbuf->map.ranges[i].start;
485         box->y = 0;
486         box->z = 0;
487         box->w = sbuf->map.ranges[i].end - sbuf->map.ranges[i].start;
488         box->h = 1;
489         box->d = 1;
490         box->srcx = sbuf->map.ranges[i].start;
491         box->srcy = 0;
492         box->srcz = 0;
493
494         assert(box->x <= sbuf->b.b.width0);
495         assert(box->x + box->w <= sbuf->b.b.width0);
496
497         svga->hud.num_bytes_uploaded += box->w;
498         svga->hud.num_buffer_uploads++;
499      }
500   }
501
502   /* Reset sbuf for next use/upload */
503
504   sbuf->map.num_ranges = 0;
505
506   assert(sbuf->head.prev && sbuf->head.next);
507   LIST_DEL(&sbuf->head);  /* remove from svga->dirty_buffers list */
508#ifdef DEBUG
509   sbuf->head.next = sbuf->head.prev = NULL;
510#endif
511   sbuf->dma.pending = FALSE;
512   sbuf->dma.flags.discard = FALSE;
513   sbuf->dma.flags.unsynchronized = FALSE;
514
515   sbuf->dma.svga = NULL;
516   sbuf->dma.boxes = NULL;
517   sbuf->dma.updates = NULL;
518
519   /* Decrement reference count (and potentially destroy) */
520   dummy = &sbuf->b.b;
521   pipe_resource_reference(&dummy, NULL);
522}
523
524
525/**
526 * Note a dirty range.
527 *
528 * This function only notes the range down. It doesn't actually emit a DMA
529 * upload command. That only happens when a context tries to refer to this
530 * buffer, and the DMA upload command is added to that context's command
531 * buffer.
532 *
533 * We try to lump as many contiguous DMA transfers together as possible.
534 */
535void
536svga_buffer_add_range(struct svga_buffer *sbuf, unsigned start, unsigned end)
537{
538   unsigned i;
539   unsigned nearest_range;
540   unsigned nearest_dist;
541
542   assert(end > start);
543
544   if (sbuf->map.num_ranges < SVGA_BUFFER_MAX_RANGES) {
545      nearest_range = sbuf->map.num_ranges;
546      nearest_dist = ~0;
547   } else {
548      nearest_range = SVGA_BUFFER_MAX_RANGES - 1;
549      nearest_dist = 0;
550   }
551
552   /*
553    * Try to grow one of the ranges.
554    */
555   for (i = 0; i < sbuf->map.num_ranges; ++i) {
556      const int left_dist = start - sbuf->map.ranges[i].end;
557      const int right_dist = sbuf->map.ranges[i].start - end;
558      const int dist = MAX2(left_dist, right_dist);
559
560      if (dist <= 0) {
561         /*
562          * Ranges are contiguous or overlapping -- extend this one and return.
563          *
564          * Note that it is not this function's task to prevent overlapping
565          * ranges, as the GMR was already given so it is too late to do
566          * anything.  If the ranges overlap here it must surely be because
567          * PIPE_TRANSFER_UNSYNCHRONIZED was set.
568          */
569         sbuf->map.ranges[i].start = MIN2(sbuf->map.ranges[i].start, start);
570         sbuf->map.ranges[i].end   = MAX2(sbuf->map.ranges[i].end,   end);
571         return;
572      }
573      else {
574         /*
575          * Discontiguous ranges -- keep track of the nearest range.
576          */
577         if (dist < nearest_dist) {
578            nearest_range = i;
579            nearest_dist = dist;
580         }
581      }
582   }
583
584   /*
585    * We cannot add a new range to an existing DMA command, so patch-up the
586    * pending DMA upload and start clean.
587    */
588
589   svga_buffer_upload_flush(sbuf->dma.svga, sbuf);
590
591   assert(!sbuf->dma.pending);
592   assert(!sbuf->dma.svga);
593   assert(!sbuf->dma.boxes);
594
595   if (sbuf->map.num_ranges < SVGA_BUFFER_MAX_RANGES) {
596      /*
597       * Add a new range.
598       */
599
600      sbuf->map.ranges[sbuf->map.num_ranges].start = start;
601      sbuf->map.ranges[sbuf->map.num_ranges].end = end;
602      ++sbuf->map.num_ranges;
603   } else {
604      /*
605       * Everything else failed, so just extend the nearest range.
606       *
607       * It is OK to do this because we always keep a local copy of the
608       * host buffer data, for SW TNL, and the host never modifies the buffer.
609       */
610
611      assert(nearest_range < SVGA_BUFFER_MAX_RANGES);
612      assert(nearest_range < sbuf->map.num_ranges);
613      sbuf->map.ranges[nearest_range].start =
614         MIN2(sbuf->map.ranges[nearest_range].start, start);
615      sbuf->map.ranges[nearest_range].end =
616         MAX2(sbuf->map.ranges[nearest_range].end, end);
617   }
618}
619
620
621
622/**
623 * Copy the contents of the malloc buffer to a hardware buffer.
624 */
625static enum pipe_error
626svga_buffer_update_hw(struct svga_context *svga, struct svga_buffer *sbuf)
627{
628   assert(!sbuf->user);
629   if (!svga_buffer_has_hw_storage(sbuf)) {
630      struct svga_screen *ss = svga_screen(sbuf->b.b.screen);
631      enum pipe_error ret;
632      boolean retry;
633      void *map;
634      unsigned i;
635
636      assert(sbuf->swbuf);
637      if (!sbuf->swbuf)
638         return PIPE_ERROR;
639
640      ret = svga_buffer_create_hw_storage(svga_screen(sbuf->b.b.screen), sbuf);
641      if (ret != PIPE_OK)
642         return ret;
643
644      pipe_mutex_lock(ss->swc_mutex);
645      map = svga_buffer_hw_storage_map(svga, sbuf, PIPE_TRANSFER_WRITE, &retry);
646      assert(map);
647      assert(!retry);
648      if (!map) {
649	 pipe_mutex_unlock(ss->swc_mutex);
650         svga_buffer_destroy_hw_storage(ss, sbuf);
651         return PIPE_ERROR;
652      }
653
654      /* Copy data from malloc'd swbuf to the new hardware buffer */
655      for (i = 0; i < sbuf->map.num_ranges; i++) {
656         unsigned start = sbuf->map.ranges[i].start;
657         unsigned len = sbuf->map.ranges[i].end - start;
658         memcpy((uint8_t *) map + start, (uint8_t *) sbuf->swbuf + start, len);
659      }
660
661      svga_buffer_hw_storage_unmap(svga, sbuf);
662
663      /* This user/malloc buffer is now indistinguishable from a gpu buffer */
664      assert(sbuf->map.count == 0);
665      if (sbuf->map.count == 0) {
666         if (sbuf->user)
667            sbuf->user = FALSE;
668         else
669            align_free(sbuf->swbuf);
670         sbuf->swbuf = NULL;
671      }
672
673      pipe_mutex_unlock(ss->swc_mutex);
674   }
675
676   return PIPE_OK;
677}
678
679
680/**
681 * Upload the buffer to the host in a piecewise fashion.
682 *
683 * Used when the buffer is too big to fit in the GMR aperture.
684 * This function should never get called in the guest-backed case
685 * since we always have a full-sized hardware storage backing the
686 * host surface.
687 */
688static enum pipe_error
689svga_buffer_upload_piecewise(struct svga_screen *ss,
690                             struct svga_context *svga,
691                             struct svga_buffer *sbuf)
692{
693   struct svga_winsys_screen *sws = ss->sws;
694   const unsigned alignment = sizeof(void *);
695   const unsigned usage = 0;
696   unsigned i;
697
698   assert(sbuf->map.num_ranges);
699   assert(!sbuf->dma.pending);
700   assert(!svga_have_gb_objects(svga));
701
702   SVGA_DBG(DEBUG_DMA, "dma to sid %p\n", sbuf->handle);
703
704   for (i = 0; i < sbuf->map.num_ranges; ++i) {
705      const struct svga_buffer_range *range = &sbuf->map.ranges[i];
706      unsigned offset = range->start;
707      unsigned size = range->end - range->start;
708
709      while (offset < range->end) {
710         struct svga_winsys_buffer *hwbuf;
711         uint8_t *map;
712         enum pipe_error ret;
713
714         if (offset + size > range->end)
715            size = range->end - offset;
716
717         hwbuf = sws->buffer_create(sws, alignment, usage, size);
718         while (!hwbuf) {
719            size /= 2;
720            if (!size)
721               return PIPE_ERROR_OUT_OF_MEMORY;
722            hwbuf = sws->buffer_create(sws, alignment, usage, size);
723         }
724
725         SVGA_DBG(DEBUG_DMA, "  bytes %u - %u\n",
726                  offset, offset + size);
727
728         map = sws->buffer_map(sws, hwbuf,
729                               PIPE_TRANSFER_WRITE |
730                               PIPE_TRANSFER_DISCARD_RANGE);
731         assert(map);
732         if (map) {
733            memcpy(map, (const char *) sbuf->swbuf + offset, size);
734            sws->buffer_unmap(sws, hwbuf);
735         }
736
737         ret = SVGA3D_BufferDMA(svga->swc,
738                                hwbuf, sbuf->handle,
739                                SVGA3D_WRITE_HOST_VRAM,
740                                size, 0, offset, sbuf->dma.flags);
741         if (ret != PIPE_OK) {
742            svga_context_flush(svga, NULL);
743            ret =  SVGA3D_BufferDMA(svga->swc,
744                                    hwbuf, sbuf->handle,
745                                    SVGA3D_WRITE_HOST_VRAM,
746                                    size, 0, offset, sbuf->dma.flags);
747            assert(ret == PIPE_OK);
748         }
749
750         sbuf->dma.flags.discard = FALSE;
751
752         sws->buffer_destroy(sws, hwbuf);
753
754         offset += size;
755      }
756   }
757
758   sbuf->map.num_ranges = 0;
759
760   return PIPE_OK;
761}
762
763
764/**
765 * Get (or create/upload) the winsys surface handle so that we can
766 * refer to this buffer in fifo commands.
767 * This function will create the host surface, and in the GB case also the
768 * hardware storage. In the non-GB case, the hardware storage will be created
769 * if there are mapped ranges and the data is currently in a malloc'ed buffer.
770 */
771struct svga_winsys_surface *
772svga_buffer_handle(struct svga_context *svga, struct pipe_resource *buf)
773{
774   struct pipe_screen *screen = svga->pipe.screen;
775   struct svga_screen *ss = svga_screen(screen);
776   struct svga_buffer *sbuf;
777   enum pipe_error ret;
778
779   if (!buf)
780      return NULL;
781
782   sbuf = svga_buffer(buf);
783
784   assert(!sbuf->user);
785
786   if (!sbuf->handle) {
787      /* This call will set sbuf->handle */
788      if (svga_have_gb_objects(svga)) {
789	 ret = svga_buffer_update_hw(svga, sbuf);
790      } else {
791	 ret = svga_buffer_create_host_surface(ss, sbuf);
792      }
793      if (ret != PIPE_OK)
794	 return NULL;
795   }
796
797   assert(sbuf->handle);
798
799   if (sbuf->map.num_ranges) {
800      if (!sbuf->dma.pending) {
801         /* No pending DMA/update commands yet. */
802
803         /* Migrate the data from swbuf -> hwbuf if necessary */
804         ret = svga_buffer_update_hw(svga, sbuf);
805         if (ret == PIPE_OK) {
806            /* Emit DMA or UpdateGBImage commands */
807            ret = svga_buffer_upload_command(svga, sbuf);
808            if (ret == PIPE_ERROR_OUT_OF_MEMORY) {
809               svga_context_flush(svga, NULL);
810               ret = svga_buffer_upload_command(svga, sbuf);
811               assert(ret == PIPE_OK);
812            }
813            if (ret == PIPE_OK) {
814               sbuf->dma.pending = TRUE;
815               assert(!sbuf->head.prev && !sbuf->head.next);
816               LIST_ADDTAIL(&sbuf->head, &svga->dirty_buffers);
817            }
818         }
819         else if (ret == PIPE_ERROR_OUT_OF_MEMORY) {
820            /*
821             * The buffer is too big to fit in the GMR aperture, so break it in
822             * smaller pieces.
823             */
824            ret = svga_buffer_upload_piecewise(ss, svga, sbuf);
825         }
826
827         if (ret != PIPE_OK) {
828            /*
829             * Something unexpected happened above. There is very little that
830             * we can do other than proceeding while ignoring the dirty ranges.
831             */
832            assert(0);
833            sbuf->map.num_ranges = 0;
834         }
835      }
836      else {
837         /*
838          * There a pending dma already. Make sure it is from this context.
839          */
840         assert(sbuf->dma.svga == svga);
841      }
842   }
843
844   assert(sbuf->map.num_ranges == 0 || sbuf->dma.pending);
845
846   return sbuf->handle;
847}
848
849
850
851void
852svga_context_flush_buffers(struct svga_context *svga)
853{
854   struct list_head *curr, *next;
855
856   SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_BUFFERSFLUSH);
857
858   curr = svga->dirty_buffers.next;
859   next = curr->next;
860   while (curr != &svga->dirty_buffers) {
861      struct svga_buffer *sbuf = LIST_ENTRY(struct svga_buffer, curr, head);
862
863      assert(p_atomic_read(&sbuf->b.b.reference.count) != 0);
864      assert(sbuf->dma.pending);
865
866      svga_buffer_upload_flush(svga, sbuf);
867
868      curr = next;
869      next = curr->next;
870   }
871
872   SVGA_STATS_TIME_POP(svga_sws(svga));
873}
874