Home | History | Annotate | Download | only in svga
      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 {
    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 
    142 enum pipe_error
    143 svga_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 
    211 void
    212 svga_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  */
    229 static enum pipe_error
    230 svga_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  */
    340 static enum pipe_error
    341 svga_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  */
    415 static enum pipe_error
    416 svga_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  */
    430 void
    431 svga_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  */
    535 void
    536 svga_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  */
    625 static enum pipe_error
    626 svga_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  */
    688 static enum pipe_error
    689 svga_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  */
    771 struct svga_winsys_surface *
    772 svga_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 
    851 void
    852 svga_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