1bb7431abf4e995d838bf1d58e75044cb8c31938
[mesa.git] / src / gallium / drivers / svga / svga_resource_buffer_upload.c
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 */
46 struct svga_3d_update_gb_image {
47 SVGA3dCmdHeader header;
48 SVGA3dCmdUpdateGBImage body;
49 };
50
51 struct 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 */
64 struct svga_winsys_buffer *
65 svga_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 */
94 void
95 svga_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 */
114 enum pipe_error
115 svga_buffer_create_hw_storage(struct svga_screen *ss,
116 struct svga_buffer *sbuf,
117 unsigned bind_flags)
118 {
119 assert(!sbuf->user);
120
121 if (ss->sws->have_gb_objects) {
122 assert(sbuf->handle || !sbuf->dma.pending);
123 return svga_buffer_create_host_surface(ss, sbuf, bind_flags);
124 }
125 if (!sbuf->hwbuf) {
126 struct svga_winsys_screen *sws = ss->sws;
127 unsigned alignment = 16;
128 unsigned usage = 0;
129 unsigned size = sbuf->b.b.width0;
130
131 sbuf->hwbuf = sws->buffer_create(sws, alignment, usage, size);
132 if (!sbuf->hwbuf)
133 return PIPE_ERROR_OUT_OF_MEMORY;
134
135 assert(!sbuf->dma.pending);
136 }
137
138 return PIPE_OK;
139 }
140
141
142 /**
143 * Allocate graphics memory for vertex/index/constant/etc buffer (not
144 * textures).
145 */
146 enum pipe_error
147 svga_buffer_create_host_surface(struct svga_screen *ss,
148 struct svga_buffer *sbuf,
149 unsigned bind_flags)
150 {
151 enum pipe_error ret = PIPE_OK;
152
153 assert(!sbuf->user);
154
155 if (!sbuf->handle) {
156 boolean validated;
157
158 sbuf->key.flags = 0;
159
160 sbuf->key.format = SVGA3D_BUFFER;
161 if (bind_flags & PIPE_BIND_VERTEX_BUFFER) {
162 sbuf->key.flags |= SVGA3D_SURFACE_HINT_VERTEXBUFFER;
163 sbuf->key.flags |= SVGA3D_SURFACE_BIND_VERTEX_BUFFER;
164 }
165 if (bind_flags & PIPE_BIND_INDEX_BUFFER) {
166 sbuf->key.flags |= SVGA3D_SURFACE_HINT_INDEXBUFFER;
167 sbuf->key.flags |= SVGA3D_SURFACE_BIND_INDEX_BUFFER;
168 }
169 if (bind_flags & PIPE_BIND_CONSTANT_BUFFER)
170 sbuf->key.flags |= SVGA3D_SURFACE_BIND_CONSTANT_BUFFER;
171
172 if (bind_flags & PIPE_BIND_STREAM_OUTPUT)
173 sbuf->key.flags |= SVGA3D_SURFACE_BIND_STREAM_OUTPUT;
174
175 if (bind_flags & PIPE_BIND_SAMPLER_VIEW)
176 sbuf->key.flags |= SVGA3D_SURFACE_BIND_SHADER_RESOURCE;
177
178 if (!bind_flags && sbuf->b.b.usage == PIPE_USAGE_STAGING) {
179 /* This surface is to be used with the
180 * SVGA3D_CMD_DX_TRANSFER_FROM_BUFFER command, and no other
181 * bind flags are allowed to be set for this surface.
182 */
183 sbuf->key.flags = SVGA3D_SURFACE_TRANSFER_FROM_BUFFER;
184 }
185
186 if (sbuf->b.b.flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT) {
187 /* This surface can be mapped persistently. We use
188 * coherent memory to avoid implementing memory barriers for
189 * persistent non-coherent memory for now.
190 */
191 sbuf->key.coherent = 1;
192 }
193
194 sbuf->key.size.width = sbuf->b.b.width0;
195 sbuf->key.size.height = 1;
196 sbuf->key.size.depth = 1;
197
198 sbuf->key.numFaces = 1;
199 sbuf->key.numMipLevels = 1;
200 sbuf->key.cachable = 1;
201 sbuf->key.arraySize = 1;
202 sbuf->key.sampleCount = 0;
203
204 SVGA_DBG(DEBUG_DMA, "surface_create for buffer sz %d\n",
205 sbuf->b.b.width0);
206
207 sbuf->handle = svga_screen_surface_create(ss, bind_flags,
208 sbuf->b.b.usage,
209 &validated, &sbuf->key);
210 if (!sbuf->handle)
211 return PIPE_ERROR_OUT_OF_MEMORY;
212
213 /* Always set the discard flag on the first time the buffer is written
214 * as svga_screen_surface_create might have passed a recycled host
215 * buffer.
216 */
217 sbuf->dma.flags.discard = TRUE;
218
219 SVGA_DBG(DEBUG_DMA, " --> got sid %p sz %d (buffer)\n",
220 sbuf->handle, sbuf->b.b.width0);
221
222 /* Add the new surface to the buffer surface list */
223 ret = svga_buffer_add_host_surface(sbuf, sbuf->handle, &sbuf->key,
224 bind_flags);
225 }
226
227 return ret;
228 }
229
230
231 /**
232 * Recreates a host surface with the new bind flags.
233 */
234 enum pipe_error
235 svga_buffer_recreate_host_surface(struct svga_context *svga,
236 struct svga_buffer *sbuf,
237 unsigned bind_flags)
238 {
239 enum pipe_error ret = PIPE_OK;
240 struct svga_winsys_surface *old_handle = sbuf->handle;
241
242 assert(sbuf->bind_flags != bind_flags);
243 assert(old_handle);
244
245 sbuf->handle = NULL;
246
247 /* Create a new resource with the requested bind_flags */
248 ret = svga_buffer_create_host_surface(svga_screen(svga->pipe.screen),
249 sbuf, bind_flags);
250 if (ret == PIPE_OK) {
251 /* Copy the surface data */
252 assert(sbuf->handle);
253 ret = SVGA3D_vgpu10_BufferCopy(svga->swc, old_handle, sbuf->handle,
254 0, 0, sbuf->b.b.width0);
255 if (ret != PIPE_OK) {
256 svga_context_flush(svga, NULL);
257 ret = SVGA3D_vgpu10_BufferCopy(svga->swc, old_handle, sbuf->handle,
258 0, 0, sbuf->b.b.width0);
259 assert(ret == PIPE_OK);
260 }
261 }
262
263 /* Set the new bind flags for this buffer resource */
264 sbuf->bind_flags = bind_flags;
265
266 return ret;
267 }
268
269
270 /**
271 * Returns TRUE if the surface bind flags is compatible with the new bind flags.
272 */
273 static boolean
274 compatible_bind_flags(unsigned bind_flags,
275 unsigned tobind_flags)
276 {
277 if ((bind_flags & tobind_flags) == tobind_flags)
278 return TRUE;
279 else if ((bind_flags|tobind_flags) & PIPE_BIND_CONSTANT_BUFFER)
280 return FALSE;
281 else
282 return TRUE;
283 }
284
285
286 /**
287 * Returns a buffer surface from the surface list
288 * that has the requested bind flags or its existing bind flags
289 * can be promoted to include the new bind flags.
290 */
291 static struct svga_buffer_surface *
292 svga_buffer_get_host_surface(struct svga_buffer *sbuf,
293 unsigned bind_flags)
294 {
295 struct svga_buffer_surface *bufsurf;
296
297 LIST_FOR_EACH_ENTRY(bufsurf, &sbuf->surfaces, list) {
298 if (compatible_bind_flags(bufsurf->bind_flags, bind_flags))
299 return bufsurf;
300 }
301 return NULL;
302 }
303
304
305 /**
306 * Adds the host surface to the buffer surface list.
307 */
308 enum pipe_error
309 svga_buffer_add_host_surface(struct svga_buffer *sbuf,
310 struct svga_winsys_surface *handle,
311 struct svga_host_surface_cache_key *key,
312 unsigned bind_flags)
313 {
314 struct svga_buffer_surface *bufsurf;
315
316 bufsurf = CALLOC_STRUCT(svga_buffer_surface);
317 if (!bufsurf)
318 return PIPE_ERROR_OUT_OF_MEMORY;
319
320 bufsurf->bind_flags = bind_flags;
321 bufsurf->handle = handle;
322 bufsurf->key = *key;
323
324 /* add the surface to the surface list */
325 LIST_ADD(&bufsurf->list, &sbuf->surfaces);
326
327 /* Set the new bind flags for this buffer resource */
328 sbuf->bind_flags = bind_flags;
329
330 return PIPE_OK;
331 }
332
333
334 /**
335 * Start using the specified surface for this buffer resource.
336 */
337 void
338 svga_buffer_bind_host_surface(struct svga_context *svga,
339 struct svga_buffer *sbuf,
340 struct svga_buffer_surface *bufsurf)
341 {
342 enum pipe_error ret;
343
344 /* Update the to-bind surface */
345 assert(bufsurf->handle);
346 assert(sbuf->handle);
347
348 /* If we are switching from stream output to other buffer,
349 * make sure to copy the buffer content.
350 */
351 if (sbuf->bind_flags & PIPE_BIND_STREAM_OUTPUT) {
352 ret = SVGA3D_vgpu10_BufferCopy(svga->swc, sbuf->handle, bufsurf->handle,
353 0, 0, sbuf->b.b.width0);
354 if (ret != PIPE_OK) {
355 svga_context_flush(svga, NULL);
356 ret = SVGA3D_vgpu10_BufferCopy(svga->swc, sbuf->handle, bufsurf->handle,
357 0, 0, sbuf->b.b.width0);
358 assert(ret == PIPE_OK);
359 }
360 }
361
362 /* Set this surface as the current one */
363 sbuf->handle = bufsurf->handle;
364 sbuf->key = bufsurf->key;
365 sbuf->bind_flags = bufsurf->bind_flags;
366 }
367
368
369 /**
370 * Prepare a host surface that can be used as indicated in the
371 * tobind_flags. If the existing host surface is not created
372 * with the necessary binding flags and if the new bind flags can be
373 * combined with the existing bind flags, then we will recreate a
374 * new surface with the combined bind flags. Otherwise, we will create
375 * a surface for that incompatible bind flags.
376 * For example, if a stream output buffer is reused as a constant buffer,
377 * since constant buffer surface cannot be bound as a stream output surface,
378 * two surfaces will be created, one for stream output,
379 * and another one for constant buffer.
380 */
381 enum pipe_error
382 svga_buffer_validate_host_surface(struct svga_context *svga,
383 struct svga_buffer *sbuf,
384 unsigned tobind_flags)
385 {
386 struct svga_buffer_surface *bufsurf;
387 enum pipe_error ret = PIPE_OK;
388
389 /* Flush any pending upload first */
390 svga_buffer_upload_flush(svga, sbuf);
391
392 /* First check from the cached buffer surface list to see if there is
393 * already a buffer surface that has the requested bind flags, or
394 * surface with compatible bind flags that can be promoted.
395 */
396 bufsurf = svga_buffer_get_host_surface(sbuf, tobind_flags);
397
398 if (bufsurf) {
399 if ((bufsurf->bind_flags & tobind_flags) == tobind_flags) {
400 /* there is a surface with the requested bind flags */
401 svga_buffer_bind_host_surface(svga, sbuf, bufsurf);
402 } else {
403
404 /* Recreate a host surface with the combined bind flags */
405 ret = svga_buffer_recreate_host_surface(svga, sbuf,
406 bufsurf->bind_flags |
407 tobind_flags);
408
409 /* Destroy the old surface */
410 svga_screen_surface_destroy(svga_screen(sbuf->b.b.screen),
411 &bufsurf->key, &bufsurf->handle);
412
413 LIST_DEL(&bufsurf->list);
414 FREE(bufsurf);
415 }
416 } else {
417 /* Need to create a new surface if the bind flags are incompatible,
418 * such as constant buffer surface & stream output surface.
419 */
420 ret = svga_buffer_recreate_host_surface(svga, sbuf,
421 tobind_flags);
422 }
423 return ret;
424 }
425
426
427 void
428 svga_buffer_destroy_host_surface(struct svga_screen *ss,
429 struct svga_buffer *sbuf)
430 {
431 struct svga_buffer_surface *bufsurf, *next;
432
433 LIST_FOR_EACH_ENTRY_SAFE(bufsurf, next, &sbuf->surfaces, list) {
434 SVGA_DBG(DEBUG_DMA, " ungrab sid %p sz %d\n",
435 bufsurf->handle, sbuf->b.b.width0);
436 svga_screen_surface_destroy(ss, &bufsurf->key, &bufsurf->handle);
437 FREE(bufsurf);
438 }
439 }
440
441
442 /**
443 * Insert a number of preliminary UPDATE_GB_IMAGE commands in the
444 * command buffer, equal to the current number of mapped ranges.
445 * The UPDATE_GB_IMAGE commands will be patched with the
446 * actual ranges just before flush.
447 */
448 static enum pipe_error
449 svga_buffer_upload_gb_command(struct svga_context *svga,
450 struct svga_buffer *sbuf)
451 {
452 struct svga_winsys_context *swc = svga->swc;
453 SVGA3dCmdUpdateGBImage *update_cmd;
454 struct svga_3d_update_gb_image *whole_update_cmd = NULL;
455 const uint32 numBoxes = sbuf->map.num_ranges;
456 struct pipe_resource *dummy;
457 unsigned i;
458
459 if (swc->force_coherent || sbuf->key.coherent)
460 return PIPE_OK;
461
462 assert(svga_have_gb_objects(svga));
463 assert(numBoxes);
464 assert(sbuf->dma.updates == NULL);
465
466 if (sbuf->dma.flags.discard) {
467 struct svga_3d_invalidate_gb_image *cicmd = NULL;
468 SVGA3dCmdInvalidateGBImage *invalidate_cmd;
469 const unsigned total_commands_size =
470 sizeof(*invalidate_cmd) + numBoxes * sizeof(*whole_update_cmd);
471
472 /* Allocate FIFO space for one INVALIDATE_GB_IMAGE command followed by
473 * 'numBoxes' UPDATE_GB_IMAGE commands. Allocate all at once rather
474 * than with separate commands because we need to properly deal with
475 * filling the command buffer.
476 */
477 invalidate_cmd = SVGA3D_FIFOReserve(swc,
478 SVGA_3D_CMD_INVALIDATE_GB_IMAGE,
479 total_commands_size, 1 + numBoxes);
480 if (!invalidate_cmd)
481 return PIPE_ERROR_OUT_OF_MEMORY;
482
483 cicmd = container_of(invalidate_cmd, cicmd, body);
484 cicmd->header.size = sizeof(*invalidate_cmd);
485 swc->surface_relocation(swc, &invalidate_cmd->image.sid, NULL,
486 sbuf->handle,
487 (SVGA_RELOC_WRITE |
488 SVGA_RELOC_INTERNAL |
489 SVGA_RELOC_DMA));
490 invalidate_cmd->image.face = 0;
491 invalidate_cmd->image.mipmap = 0;
492
493 /* The whole_update_command is a SVGA3dCmdHeader plus the
494 * SVGA3dCmdUpdateGBImage command.
495 */
496 whole_update_cmd = (struct svga_3d_update_gb_image *) &invalidate_cmd[1];
497 /* initialize the first UPDATE_GB_IMAGE command */
498 whole_update_cmd->header.id = SVGA_3D_CMD_UPDATE_GB_IMAGE;
499 update_cmd = &whole_update_cmd->body;
500
501 } else {
502 /* Allocate FIFO space for 'numBoxes' UPDATE_GB_IMAGE commands */
503 const unsigned total_commands_size =
504 sizeof(*update_cmd) + (numBoxes - 1) * sizeof(*whole_update_cmd);
505
506 update_cmd = SVGA3D_FIFOReserve(swc,
507 SVGA_3D_CMD_UPDATE_GB_IMAGE,
508 total_commands_size, numBoxes);
509 if (!update_cmd)
510 return PIPE_ERROR_OUT_OF_MEMORY;
511
512 /* The whole_update_command is a SVGA3dCmdHeader plus the
513 * SVGA3dCmdUpdateGBImage command.
514 */
515 whole_update_cmd = container_of(update_cmd, whole_update_cmd, body);
516 }
517
518 /* Init the first UPDATE_GB_IMAGE command */
519 whole_update_cmd->header.size = sizeof(*update_cmd);
520 swc->surface_relocation(swc, &update_cmd->image.sid, NULL, sbuf->handle,
521 SVGA_RELOC_WRITE | SVGA_RELOC_INTERNAL);
522 update_cmd->image.face = 0;
523 update_cmd->image.mipmap = 0;
524
525 /* Save pointer to the first UPDATE_GB_IMAGE command so that we can
526 * fill in the box info below.
527 */
528 sbuf->dma.updates = whole_update_cmd;
529
530 /*
531 * Copy the face, mipmap, etc. info to all subsequent commands.
532 * Also do the surface relocation for each subsequent command.
533 */
534 for (i = 1; i < numBoxes; ++i) {
535 whole_update_cmd++;
536 memcpy(whole_update_cmd, sbuf->dma.updates, sizeof(*whole_update_cmd));
537
538 swc->surface_relocation(swc, &whole_update_cmd->body.image.sid, NULL,
539 sbuf->handle,
540 SVGA_RELOC_WRITE | SVGA_RELOC_INTERNAL);
541 }
542
543 /* Increment reference count */
544 sbuf->dma.svga = svga;
545 dummy = NULL;
546 pipe_resource_reference(&dummy, &sbuf->b.b);
547 SVGA_FIFOCommitAll(swc);
548
549 swc->hints |= SVGA_HINT_FLAG_CAN_PRE_FLUSH;
550 sbuf->dma.flags.discard = FALSE;
551
552 svga->hud.num_resource_updates++;
553
554 return PIPE_OK;
555 }
556
557
558 /**
559 * Issue DMA commands to transfer guest memory to the host.
560 * Note that the memory segments (offset, size) will be patched in
561 * later in the svga_buffer_upload_flush() function.
562 */
563 static enum pipe_error
564 svga_buffer_upload_hb_command(struct svga_context *svga,
565 struct svga_buffer *sbuf)
566 {
567 struct svga_winsys_context *swc = svga->swc;
568 struct svga_winsys_buffer *guest = sbuf->hwbuf;
569 struct svga_winsys_surface *host = sbuf->handle;
570 const SVGA3dTransferType transfer = SVGA3D_WRITE_HOST_VRAM;
571 SVGA3dCmdSurfaceDMA *cmd;
572 const uint32 numBoxes = sbuf->map.num_ranges;
573 SVGA3dCopyBox *boxes;
574 SVGA3dCmdSurfaceDMASuffix *pSuffix;
575 unsigned region_flags;
576 unsigned surface_flags;
577 struct pipe_resource *dummy;
578
579 assert(!svga_have_gb_objects(svga));
580
581 if (transfer == SVGA3D_WRITE_HOST_VRAM) {
582 region_flags = SVGA_RELOC_READ;
583 surface_flags = SVGA_RELOC_WRITE;
584 }
585 else if (transfer == SVGA3D_READ_HOST_VRAM) {
586 region_flags = SVGA_RELOC_WRITE;
587 surface_flags = SVGA_RELOC_READ;
588 }
589 else {
590 assert(0);
591 return PIPE_ERROR_BAD_INPUT;
592 }
593
594 assert(numBoxes);
595
596 cmd = SVGA3D_FIFOReserve(swc,
597 SVGA_3D_CMD_SURFACE_DMA,
598 sizeof *cmd + numBoxes * sizeof *boxes + sizeof *pSuffix,
599 2);
600 if (!cmd)
601 return PIPE_ERROR_OUT_OF_MEMORY;
602
603 swc->region_relocation(swc, &cmd->guest.ptr, guest, 0, region_flags);
604 cmd->guest.pitch = 0;
605
606 swc->surface_relocation(swc, &cmd->host.sid, NULL, host, surface_flags);
607 cmd->host.face = 0;
608 cmd->host.mipmap = 0;
609
610 cmd->transfer = transfer;
611
612 sbuf->dma.boxes = (SVGA3dCopyBox *)&cmd[1];
613 sbuf->dma.svga = svga;
614
615 /* Increment reference count */
616 dummy = NULL;
617 pipe_resource_reference(&dummy, &sbuf->b.b);
618
619 pSuffix = (SVGA3dCmdSurfaceDMASuffix *)((uint8_t*)cmd + sizeof *cmd + numBoxes * sizeof *boxes);
620 pSuffix->suffixSize = sizeof *pSuffix;
621 pSuffix->maximumOffset = sbuf->b.b.width0;
622 pSuffix->flags = sbuf->dma.flags;
623
624 SVGA_FIFOCommitAll(swc);
625
626 swc->hints |= SVGA_HINT_FLAG_CAN_PRE_FLUSH;
627 sbuf->dma.flags.discard = FALSE;
628
629 svga->hud.num_buffer_uploads++;
630
631 return PIPE_OK;
632 }
633
634
635 /**
636 * Issue commands to transfer guest memory to the host.
637 */
638 static enum pipe_error
639 svga_buffer_upload_command(struct svga_context *svga, struct svga_buffer *sbuf)
640 {
641 if (svga_have_gb_objects(svga)) {
642 return svga_buffer_upload_gb_command(svga, sbuf);
643 } else {
644 return svga_buffer_upload_hb_command(svga, sbuf);
645 }
646 }
647
648
649 /**
650 * Patch up the upload DMA command reserved by svga_buffer_upload_command
651 * with the final ranges.
652 */
653 void
654 svga_buffer_upload_flush(struct svga_context *svga, struct svga_buffer *sbuf)
655 {
656 unsigned i;
657 struct pipe_resource *dummy;
658
659 if (!sbuf->dma.pending || svga->swc->force_coherent ||
660 sbuf->key.coherent) {
661 //debug_printf("no dma pending on buffer\n");
662 return;
663 }
664
665 assert(sbuf->handle);
666 assert(sbuf->map.num_ranges);
667 assert(sbuf->dma.svga == svga);
668
669 /*
670 * Patch the DMA/update command with the final copy box.
671 */
672 if (svga_have_gb_objects(svga)) {
673 struct svga_3d_update_gb_image *update = sbuf->dma.updates;
674
675 assert(update);
676
677 for (i = 0; i < sbuf->map.num_ranges; ++i, ++update) {
678 SVGA3dBox *box = &update->body.box;
679
680 SVGA_DBG(DEBUG_DMA, " bytes %u - %u\n",
681 sbuf->map.ranges[i].start, sbuf->map.ranges[i].end);
682
683 box->x = sbuf->map.ranges[i].start;
684 box->y = 0;
685 box->z = 0;
686 box->w = sbuf->map.ranges[i].end - sbuf->map.ranges[i].start;
687 box->h = 1;
688 box->d = 1;
689
690 assert(box->x <= sbuf->b.b.width0);
691 assert(box->x + box->w <= sbuf->b.b.width0);
692
693 svga->hud.num_bytes_uploaded += box->w;
694 svga->hud.num_buffer_uploads++;
695 }
696 }
697 else {
698 assert(sbuf->hwbuf);
699 assert(sbuf->dma.boxes);
700 SVGA_DBG(DEBUG_DMA, "dma to sid %p\n", sbuf->handle);
701
702 for (i = 0; i < sbuf->map.num_ranges; ++i) {
703 SVGA3dCopyBox *box = sbuf->dma.boxes + i;
704
705 SVGA_DBG(DEBUG_DMA, " bytes %u - %u\n",
706 sbuf->map.ranges[i].start, sbuf->map.ranges[i].end);
707
708 box->x = sbuf->map.ranges[i].start;
709 box->y = 0;
710 box->z = 0;
711 box->w = sbuf->map.ranges[i].end - sbuf->map.ranges[i].start;
712 box->h = 1;
713 box->d = 1;
714 box->srcx = sbuf->map.ranges[i].start;
715 box->srcy = 0;
716 box->srcz = 0;
717
718 assert(box->x <= sbuf->b.b.width0);
719 assert(box->x + box->w <= sbuf->b.b.width0);
720
721 svga->hud.num_bytes_uploaded += box->w;
722 svga->hud.num_buffer_uploads++;
723 }
724 }
725
726 /* Reset sbuf for next use/upload */
727
728 sbuf->map.num_ranges = 0;
729
730 assert(sbuf->head.prev && sbuf->head.next);
731 LIST_DEL(&sbuf->head); /* remove from svga->dirty_buffers list */
732 #ifdef DEBUG
733 sbuf->head.next = sbuf->head.prev = NULL;
734 #endif
735 sbuf->dma.pending = FALSE;
736 sbuf->dma.flags.discard = FALSE;
737 sbuf->dma.flags.unsynchronized = FALSE;
738
739 sbuf->dma.svga = NULL;
740 sbuf->dma.boxes = NULL;
741 sbuf->dma.updates = NULL;
742
743 /* Decrement reference count (and potentially destroy) */
744 dummy = &sbuf->b.b;
745 pipe_resource_reference(&dummy, NULL);
746 }
747
748
749 /**
750 * Note a dirty range.
751 *
752 * This function only notes the range down. It doesn't actually emit a DMA
753 * upload command. That only happens when a context tries to refer to this
754 * buffer, and the DMA upload command is added to that context's command
755 * buffer.
756 *
757 * We try to lump as many contiguous DMA transfers together as possible.
758 */
759 void
760 svga_buffer_add_range(struct svga_buffer *sbuf, unsigned start, unsigned end)
761 {
762 unsigned i;
763 unsigned nearest_range;
764 unsigned nearest_dist;
765
766 assert(end > start);
767
768 if (sbuf->map.num_ranges < SVGA_BUFFER_MAX_RANGES) {
769 nearest_range = sbuf->map.num_ranges;
770 nearest_dist = ~0;
771 } else {
772 nearest_range = SVGA_BUFFER_MAX_RANGES - 1;
773 nearest_dist = 0;
774 }
775
776 /*
777 * Try to grow one of the ranges.
778 */
779 for (i = 0; i < sbuf->map.num_ranges; ++i) {
780 const int left_dist = start - sbuf->map.ranges[i].end;
781 const int right_dist = sbuf->map.ranges[i].start - end;
782 const int dist = MAX2(left_dist, right_dist);
783
784 if (dist <= 0) {
785 /*
786 * Ranges are contiguous or overlapping -- extend this one and return.
787 *
788 * Note that it is not this function's task to prevent overlapping
789 * ranges, as the GMR was already given so it is too late to do
790 * anything. If the ranges overlap here it must surely be because
791 * PIPE_TRANSFER_UNSYNCHRONIZED was set.
792 */
793 sbuf->map.ranges[i].start = MIN2(sbuf->map.ranges[i].start, start);
794 sbuf->map.ranges[i].end = MAX2(sbuf->map.ranges[i].end, end);
795 return;
796 }
797 else {
798 /*
799 * Discontiguous ranges -- keep track of the nearest range.
800 */
801 if (dist < nearest_dist) {
802 nearest_range = i;
803 nearest_dist = dist;
804 }
805 }
806 }
807
808 /*
809 * We cannot add a new range to an existing DMA command, so patch-up the
810 * pending DMA upload and start clean.
811 */
812
813 svga_buffer_upload_flush(sbuf->dma.svga, sbuf);
814
815 assert(!sbuf->dma.pending);
816 assert(!sbuf->dma.svga);
817 assert(!sbuf->dma.boxes);
818
819 if (sbuf->map.num_ranges < SVGA_BUFFER_MAX_RANGES) {
820 /*
821 * Add a new range.
822 */
823
824 sbuf->map.ranges[sbuf->map.num_ranges].start = start;
825 sbuf->map.ranges[sbuf->map.num_ranges].end = end;
826 ++sbuf->map.num_ranges;
827 } else {
828 /*
829 * Everything else failed, so just extend the nearest range.
830 *
831 * It is OK to do this because we always keep a local copy of the
832 * host buffer data, for SW TNL, and the host never modifies the buffer.
833 */
834
835 assert(nearest_range < SVGA_BUFFER_MAX_RANGES);
836 assert(nearest_range < sbuf->map.num_ranges);
837 sbuf->map.ranges[nearest_range].start =
838 MIN2(sbuf->map.ranges[nearest_range].start, start);
839 sbuf->map.ranges[nearest_range].end =
840 MAX2(sbuf->map.ranges[nearest_range].end, end);
841 }
842 }
843
844
845
846 /**
847 * Copy the contents of the malloc buffer to a hardware buffer.
848 */
849 static enum pipe_error
850 svga_buffer_update_hw(struct svga_context *svga, struct svga_buffer *sbuf,
851 unsigned bind_flags)
852 {
853 assert(!sbuf->user);
854 if (!svga_buffer_has_hw_storage(sbuf)) {
855 struct svga_screen *ss = svga_screen(sbuf->b.b.screen);
856 enum pipe_error ret;
857 boolean retry;
858 void *map;
859 unsigned i;
860
861 assert(sbuf->swbuf);
862 if (!sbuf->swbuf)
863 return PIPE_ERROR;
864
865 ret = svga_buffer_create_hw_storage(svga_screen(sbuf->b.b.screen), sbuf,
866 bind_flags);
867 if (ret != PIPE_OK)
868 return ret;
869
870 mtx_lock(&ss->swc_mutex);
871 map = svga_buffer_hw_storage_map(svga, sbuf, PIPE_TRANSFER_WRITE, &retry);
872 assert(map);
873 assert(!retry);
874 if (!map) {
875 mtx_unlock(&ss->swc_mutex);
876 svga_buffer_destroy_hw_storage(ss, sbuf);
877 return PIPE_ERROR;
878 }
879
880 /* Copy data from malloc'd swbuf to the new hardware buffer */
881 for (i = 0; i < sbuf->map.num_ranges; i++) {
882 unsigned start = sbuf->map.ranges[i].start;
883 unsigned len = sbuf->map.ranges[i].end - start;
884 memcpy((uint8_t *) map + start, (uint8_t *) sbuf->swbuf + start, len);
885 }
886
887 if (svga->swc->force_coherent || sbuf->key.coherent)
888 sbuf->map.num_ranges = 0;
889
890 svga_buffer_hw_storage_unmap(svga, sbuf);
891
892 /* This user/malloc buffer is now indistinguishable from a gpu buffer */
893 assert(sbuf->map.count == 0);
894 if (sbuf->map.count == 0) {
895 if (sbuf->user)
896 sbuf->user = FALSE;
897 else
898 align_free(sbuf->swbuf);
899 sbuf->swbuf = NULL;
900 }
901
902 mtx_unlock(&ss->swc_mutex);
903 }
904
905 return PIPE_OK;
906 }
907
908
909 /**
910 * Upload the buffer to the host in a piecewise fashion.
911 *
912 * Used when the buffer is too big to fit in the GMR aperture.
913 * This function should never get called in the guest-backed case
914 * since we always have a full-sized hardware storage backing the
915 * host surface.
916 */
917 static enum pipe_error
918 svga_buffer_upload_piecewise(struct svga_screen *ss,
919 struct svga_context *svga,
920 struct svga_buffer *sbuf)
921 {
922 struct svga_winsys_screen *sws = ss->sws;
923 const unsigned alignment = sizeof(void *);
924 const unsigned usage = 0;
925 unsigned i;
926
927 assert(sbuf->map.num_ranges);
928 assert(!sbuf->dma.pending);
929 assert(!svga_have_gb_objects(svga));
930
931 SVGA_DBG(DEBUG_DMA, "dma to sid %p\n", sbuf->handle);
932
933 for (i = 0; i < sbuf->map.num_ranges; ++i) {
934 const struct svga_buffer_range *range = &sbuf->map.ranges[i];
935 unsigned offset = range->start;
936 unsigned size = range->end - range->start;
937
938 while (offset < range->end) {
939 struct svga_winsys_buffer *hwbuf;
940 uint8_t *map;
941 enum pipe_error ret;
942
943 if (offset + size > range->end)
944 size = range->end - offset;
945
946 hwbuf = sws->buffer_create(sws, alignment, usage, size);
947 while (!hwbuf) {
948 size /= 2;
949 if (!size)
950 return PIPE_ERROR_OUT_OF_MEMORY;
951 hwbuf = sws->buffer_create(sws, alignment, usage, size);
952 }
953
954 SVGA_DBG(DEBUG_DMA, " bytes %u - %u\n",
955 offset, offset + size);
956
957 map = sws->buffer_map(sws, hwbuf,
958 PIPE_TRANSFER_WRITE |
959 PIPE_TRANSFER_DISCARD_RANGE);
960 assert(map);
961 if (map) {
962 memcpy(map, (const char *) sbuf->swbuf + offset, size);
963 sws->buffer_unmap(sws, hwbuf);
964 }
965
966 ret = SVGA3D_BufferDMA(svga->swc,
967 hwbuf, sbuf->handle,
968 SVGA3D_WRITE_HOST_VRAM,
969 size, 0, offset, sbuf->dma.flags);
970 if (ret != PIPE_OK) {
971 svga_context_flush(svga, NULL);
972 ret = SVGA3D_BufferDMA(svga->swc,
973 hwbuf, sbuf->handle,
974 SVGA3D_WRITE_HOST_VRAM,
975 size, 0, offset, sbuf->dma.flags);
976 assert(ret == PIPE_OK);
977 }
978
979 sbuf->dma.flags.discard = FALSE;
980
981 sws->buffer_destroy(sws, hwbuf);
982
983 offset += size;
984 }
985 }
986
987 sbuf->map.num_ranges = 0;
988
989 return PIPE_OK;
990 }
991
992
993 /**
994 * Get (or create/upload) the winsys surface handle so that we can
995 * refer to this buffer in fifo commands.
996 * This function will create the host surface, and in the GB case also the
997 * hardware storage. In the non-GB case, the hardware storage will be created
998 * if there are mapped ranges and the data is currently in a malloc'ed buffer.
999 */
1000 struct svga_winsys_surface *
1001 svga_buffer_handle(struct svga_context *svga, struct pipe_resource *buf,
1002 unsigned tobind_flags)
1003 {
1004 struct pipe_screen *screen = svga->pipe.screen;
1005 struct svga_screen *ss = svga_screen(screen);
1006 struct svga_buffer *sbuf;
1007 enum pipe_error ret;
1008
1009 if (!buf)
1010 return NULL;
1011
1012 sbuf = svga_buffer(buf);
1013
1014 assert(!sbuf->user);
1015
1016 if (sbuf->handle) {
1017 if ((sbuf->bind_flags & tobind_flags) != tobind_flags) {
1018 /* If the allocated resource's bind flags do not include the
1019 * requested bind flags, validate the host surface.
1020 */
1021 ret = svga_buffer_validate_host_surface(svga, sbuf, tobind_flags);
1022 if (ret != PIPE_OK)
1023 return NULL;
1024 }
1025 } else {
1026 /* If there is no resource handle yet, then combine the buffer bind
1027 * flags and the tobind_flags if they are compatible.
1028 * If not, just use the tobind_flags for creating the resource handle.
1029 */
1030 if (compatible_bind_flags(sbuf->bind_flags, tobind_flags))
1031 sbuf->bind_flags = sbuf->bind_flags | tobind_flags;
1032 else
1033 sbuf->bind_flags = tobind_flags;
1034
1035 assert((sbuf->bind_flags & tobind_flags) == tobind_flags);
1036
1037 /* This call will set sbuf->handle */
1038 if (svga_have_gb_objects(svga)) {
1039 ret = svga_buffer_update_hw(svga, sbuf, sbuf->bind_flags);
1040 } else {
1041 ret = svga_buffer_create_host_surface(ss, sbuf, sbuf->bind_flags);
1042 }
1043 if (ret != PIPE_OK)
1044 return NULL;
1045 }
1046
1047 assert(sbuf->handle);
1048 if (svga->swc->force_coherent || sbuf->key.coherent)
1049 return sbuf->handle;
1050
1051 if (sbuf->map.num_ranges) {
1052 if (!sbuf->dma.pending) {
1053 /* No pending DMA/update commands yet. */
1054
1055 /* Migrate the data from swbuf -> hwbuf if necessary */
1056 ret = svga_buffer_update_hw(svga, sbuf, sbuf->bind_flags);
1057 if (ret == PIPE_OK) {
1058 /* Emit DMA or UpdateGBImage commands */
1059 ret = svga_buffer_upload_command(svga, sbuf);
1060 if (ret == PIPE_ERROR_OUT_OF_MEMORY) {
1061 svga_context_flush(svga, NULL);
1062 ret = svga_buffer_upload_command(svga, sbuf);
1063 assert(ret == PIPE_OK);
1064 }
1065 if (ret == PIPE_OK) {
1066 sbuf->dma.pending = TRUE;
1067 assert(!sbuf->head.prev && !sbuf->head.next);
1068 LIST_ADDTAIL(&sbuf->head, &svga->dirty_buffers);
1069 }
1070 }
1071 else if (ret == PIPE_ERROR_OUT_OF_MEMORY) {
1072 /*
1073 * The buffer is too big to fit in the GMR aperture, so break it in
1074 * smaller pieces.
1075 */
1076 ret = svga_buffer_upload_piecewise(ss, svga, sbuf);
1077 }
1078
1079 if (ret != PIPE_OK) {
1080 /*
1081 * Something unexpected happened above. There is very little that
1082 * we can do other than proceeding while ignoring the dirty ranges.
1083 */
1084 assert(0);
1085 sbuf->map.num_ranges = 0;
1086 }
1087 }
1088 else {
1089 /*
1090 * There a pending dma already. Make sure it is from this context.
1091 */
1092 assert(sbuf->dma.svga == svga);
1093 }
1094 }
1095
1096 assert(sbuf->map.num_ranges == 0 || sbuf->dma.pending);
1097
1098 return sbuf->handle;
1099 }
1100
1101
1102 void
1103 svga_context_flush_buffers(struct svga_context *svga)
1104 {
1105 struct list_head *curr, *next;
1106
1107 SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_BUFFERSFLUSH);
1108
1109 curr = svga->dirty_buffers.next;
1110 next = curr->next;
1111 while (curr != &svga->dirty_buffers) {
1112 struct svga_buffer *sbuf = LIST_ENTRY(struct svga_buffer, curr, head);
1113
1114 assert(p_atomic_read(&sbuf->b.b.reference.count) != 0);
1115 assert(sbuf->dma.pending);
1116
1117 svga_buffer_upload_flush(svga, sbuf);
1118
1119 curr = next;
1120 next = curr->next;
1121 }
1122
1123 SVGA_STATS_TIME_POP(svga_sws(svga));
1124 }