13192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz/**********************************************************
23192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * Copyright 2008-2009 VMware, Inc.  All rights reserved.
33192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz *
43192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * Permission is hereby granted, free of charge, to any person
53192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * obtaining a copy of this software and associated documentation
63192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * files (the "Software"), to deal in the Software without
73192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * restriction, including without limitation the rights to use, copy,
83192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * modify, merge, publish, distribute, sublicense, and/or sell copies
93192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * of the Software, and to permit persons to whom the Software is
103192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * furnished to do so, subject to the following conditions:
113192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz *
123192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * The above copyright notice and this permission notice shall be
133192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * included in all copies or substantial portions of the Software.
143192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz *
153192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
163192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
173192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
183192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
193192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
203192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
213192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
223192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * SOFTWARE.
233192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz *
243192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz **********************************************************/
253192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
263192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
27421f134028ea2930cb80c7189e552320a8a6e49fBrian Paul#include "os/os_thread.h"
283192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz#include "pipe/p_state.h"
293192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz#include "pipe/p_defines.h"
3028486880ca3ec39419ccee0cb1a3bedc9ef7117cJosé Fonseca#include "util/u_inlines.h"
313192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz#include "util/u_math.h"
323192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz#include "util/u_memory.h"
333192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
34421f134028ea2930cb80c7189e552320a8a6e49fBrian Paul#include "svga_cmd.h"
353192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz#include "svga_context.h"
36421f134028ea2930cb80c7189e552320a8a6e49fBrian Paul#include "svga_debug.h"
37287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell#include "svga_resource_buffer.h"
38287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell#include "svga_resource_buffer_upload.h"
39421f134028ea2930cb80c7189e552320a8a6e49fBrian Paul#include "svga_screen.h"
403192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz#include "svga_winsys.h"
413192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
423192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
43b84590994c4261d85485357263146d5e3d8827ebJosé Fonseca/**
44b84590994c4261d85485357263146d5e3d8827ebJosé Fonseca * Allocate a winsys_buffer (ie. DMA, aka GMR memory).
45b84590994c4261d85485357263146d5e3d8827ebJosé Fonseca *
46b84590994c4261d85485357263146d5e3d8827ebJosé Fonseca * It will flush and retry in case the first attempt to create a DMA buffer
47b84590994c4261d85485357263146d5e3d8827ebJosé Fonseca * fails, so it should not be called from any function involved in flushing
48b84590994c4261d85485357263146d5e3d8827ebJosé Fonseca * to avoid recursion.
493192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz */
503192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantzstruct svga_winsys_buffer *
51b84590994c4261d85485357263146d5e3d8827ebJosé Fonsecasvga_winsys_buffer_create( struct svga_context *svga,
5259d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul                           unsigned alignment,
533192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz                           unsigned usage,
543192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz                           unsigned size )
553192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz{
56b84590994c4261d85485357263146d5e3d8827ebJosé Fonseca   struct svga_screen *svgascreen = svga_screen(svga->pipe.screen);
57b84590994c4261d85485357263146d5e3d8827ebJosé Fonseca   struct svga_winsys_screen *sws = svgascreen->sws;
583192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   struct svga_winsys_buffer *buf;
5959d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul
603192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   /* Just try */
613192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   buf = sws->buffer_create(sws, alignment, usage, size);
6229288249e35693a33b7873ed11b09c313b2e49f0José Fonseca   if (!buf) {
6329288249e35693a33b7873ed11b09c313b2e49f0José Fonseca      SVGA_DBG(DEBUG_DMA|DEBUG_PERF, "flushing context to find %d bytes GMR\n",
6459d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul               size);
6559d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul
663192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      /* Try flushing all pending DMAs */
67b84590994c4261d85485357263146d5e3d8827ebJosé Fonseca      svga_context_flush(svga, NULL);
683192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      buf = sws->buffer_create(sws, alignment, usage, size);
693192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   }
7059d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul
713192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   return buf;
723192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz}
733192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
743192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
75287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwellvoid
76287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwellsvga_buffer_destroy_hw_storage(struct svga_screen *ss, struct svga_buffer *sbuf)
77287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell{
78287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell   struct svga_winsys_screen *sws = ss->sws;
79287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell
80287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell   assert(!sbuf->map.count);
81287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell   assert(sbuf->hwbuf);
8259d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul   if (sbuf->hwbuf) {
83287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell      sws->buffer_destroy(sws, sbuf->hwbuf);
84287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell      sbuf->hwbuf = NULL;
85287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell   }
86287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell}
87287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell
88287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell
89287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell
903192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz/**
9159d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul * Allocate DMA'ble storage for the buffer.
9259d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul *
933192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * Called before mapping a buffer.
943192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz */
95287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwellenum pipe_error
963192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantzsvga_buffer_create_hw_storage(struct svga_screen *ss,
973192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz                              struct svga_buffer *sbuf)
983192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz{
99b330928549b39e97e16aee636c335865504ffab9José Fonseca   assert(!sbuf->user);
100b330928549b39e97e16aee636c335865504ffab9José Fonseca
10159d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul   if (!sbuf->hwbuf) {
102b84590994c4261d85485357263146d5e3d8827ebJosé Fonseca      struct svga_winsys_screen *sws = ss->sws;
103287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell      unsigned alignment = 16;
1043192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      unsigned usage = 0;
105287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell      unsigned size = sbuf->b.b.width0;
10659d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul
107b84590994c4261d85485357263146d5e3d8827ebJosé Fonseca      sbuf->hwbuf = sws->buffer_create(sws, alignment, usage, size);
10859d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul      if (!sbuf->hwbuf)
1093192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz         return PIPE_ERROR_OUT_OF_MEMORY;
11059d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul
111cf861335a44376609258a2ec399c215e35f9f075José Fonseca      assert(!sbuf->dma.pending);
1123192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   }
11359d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul
1143192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   return PIPE_OK;
1153192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz}
1163192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
1173192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
118287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell
119287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwellenum pipe_error
120287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwellsvga_buffer_create_host_surface(struct svga_screen *ss,
121287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell                                struct svga_buffer *sbuf)
122287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell{
12374651f5738032466fceede8b8f0c3ce29a770551José Fonseca   assert(!sbuf->user);
12474651f5738032466fceede8b8f0c3ce29a770551José Fonseca
12559d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul   if (!sbuf->handle) {
126287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell      sbuf->key.flags = 0;
12759d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul
128287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell      sbuf->key.format = SVGA3D_BUFFER;
12959d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul      if (sbuf->b.b.bind & PIPE_BIND_VERTEX_BUFFER)
130287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell         sbuf->key.flags |= SVGA3D_SURFACE_HINT_VERTEXBUFFER;
13159d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul      if (sbuf->b.b.bind & PIPE_BIND_INDEX_BUFFER)
132287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell         sbuf->key.flags |= SVGA3D_SURFACE_HINT_INDEXBUFFER;
13359d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul
134287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell      sbuf->key.size.width = sbuf->b.b.width0;
135287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell      sbuf->key.size.height = 1;
136287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell      sbuf->key.size.depth = 1;
13759d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul
138287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell      sbuf->key.numFaces = 1;
139287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell      sbuf->key.numMipLevels = 1;
140287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell      sbuf->key.cachable = 1;
14159d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul
142287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell      SVGA_DBG(DEBUG_DMA, "surface_create for buffer sz %d\n", sbuf->b.b.width0);
143287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell
144287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell      sbuf->handle = svga_screen_surface_create(ss, &sbuf->key);
14559d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul      if (!sbuf->handle)
146287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell         return PIPE_ERROR_OUT_OF_MEMORY;
14759d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul
148287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell      /* Always set the discard flag on the first time the buffer is written
149287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell       * as svga_screen_surface_create might have passed a recycled host
150287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell       * buffer.
151287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell       */
152287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell      sbuf->dma.flags.discard = TRUE;
153287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell
154287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell      SVGA_DBG(DEBUG_DMA, "   --> got sid %p sz %d (buffer)\n", sbuf->handle, sbuf->b.b.width0);
155287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell   }
15659d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul
157287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell   return PIPE_OK;
15859d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul}
159287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell
160287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell
161287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwellvoid
162287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwellsvga_buffer_destroy_host_surface(struct svga_screen *ss,
163287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell                                 struct svga_buffer *sbuf)
164287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell{
16559d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul   if (sbuf->handle) {
166287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell      SVGA_DBG(DEBUG_DMA, " ungrab sid %p sz %d\n", sbuf->handle, sbuf->b.b.width0);
167287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell      svga_screen_surface_destroy(ss, &sbuf->key, &sbuf->handle);
168287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell   }
16959d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul}
170287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell
171287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell
1723192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz/**
1733192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * Variant of SVGA3D_BufferDMA which leaves the copy box temporarily in blank.
1743192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz */
1753192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantzstatic enum pipe_error
1763192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantzsvga_buffer_upload_command(struct svga_context *svga,
1773192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz                           struct svga_buffer *sbuf)
1783192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz{
1793192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   struct svga_winsys_context *swc = svga->swc;
180cf861335a44376609258a2ec399c215e35f9f075José Fonseca   struct svga_winsys_buffer *guest = sbuf->hwbuf;
1813192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   struct svga_winsys_surface *host = sbuf->handle;
1823192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   SVGA3dTransferType transfer = SVGA3D_WRITE_HOST_VRAM;
1833192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   SVGA3dCmdSurfaceDMA *cmd;
184cf861335a44376609258a2ec399c215e35f9f075José Fonseca   uint32 numBoxes = sbuf->map.num_ranges;
1853192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   SVGA3dCopyBox *boxes;
1863192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   SVGA3dCmdSurfaceDMASuffix *pSuffix;
1873192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   unsigned region_flags;
1883192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   unsigned surface_flags;
189287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell   struct pipe_resource *dummy;
1903192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
19159d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul   if (transfer == SVGA3D_WRITE_HOST_VRAM) {
192287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell      region_flags = SVGA_RELOC_READ;
193287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell      surface_flags = SVGA_RELOC_WRITE;
1943192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   }
19559d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul   else if (transfer == SVGA3D_READ_HOST_VRAM) {
196287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell      region_flags = SVGA_RELOC_WRITE;
197287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell      surface_flags = SVGA_RELOC_READ;
1983192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   }
1993192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   else {
2003192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      assert(0);
2013192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      return PIPE_ERROR_BAD_INPUT;
2023192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   }
2033192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
2043192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   assert(numBoxes);
2053192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
2063192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   cmd = SVGA3D_FIFOReserve(swc,
2073192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz                            SVGA_3D_CMD_SURFACE_DMA,
2083192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz                            sizeof *cmd + numBoxes * sizeof *boxes + sizeof *pSuffix,
2093192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz                            2);
21059d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul   if (!cmd)
2113192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      return PIPE_ERROR_OUT_OF_MEMORY;
2123192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
2133192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   swc->region_relocation(swc, &cmd->guest.ptr, guest, 0, region_flags);
2143192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   cmd->guest.pitch = 0;
2153192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
2163192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   swc->surface_relocation(swc, &cmd->host.sid, host, surface_flags);
2173192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   cmd->host.face = 0;
2183192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   cmd->host.mipmap = 0;
2193192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
2203192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   cmd->transfer = transfer;
2213192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
222cf861335a44376609258a2ec399c215e35f9f075José Fonseca   sbuf->dma.boxes = (SVGA3dCopyBox *)&cmd[1];
223cf861335a44376609258a2ec399c215e35f9f075José Fonseca   sbuf->dma.svga = svga;
2243192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
2253192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   /* Increment reference count */
2263192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   dummy = NULL;
227287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell   pipe_resource_reference(&dummy, &sbuf->b.b);
2283192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
2293192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   pSuffix = (SVGA3dCmdSurfaceDMASuffix *)((uint8_t*)cmd + sizeof *cmd + numBoxes * sizeof *boxes);
2303192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   pSuffix->suffixSize = sizeof *pSuffix;
231287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell   pSuffix->maximumOffset = sbuf->b.b.width0;
2322452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca   pSuffix->flags = sbuf->dma.flags;
2333192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
2342452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca   SVGA_FIFOCommitAll(swc);
2352452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca
2362452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca   sbuf->dma.flags.discard = FALSE;
2373192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
2383192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   return PIPE_OK;
2393192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz}
2403192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
2413192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
2423192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz/**
2433192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * Patch up the upload DMA command reserved by svga_buffer_upload_command
2443192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * with the final ranges.
2453192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz */
246ef33c82bfde788733aabc5dcc9647416c31ae254José Fonsecavoid
2473192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantzsvga_buffer_upload_flush(struct svga_context *svga,
2483192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz                         struct svga_buffer *sbuf)
2493192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz{
2503192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   SVGA3dCopyBox *boxes;
2513192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   unsigned i;
252610c24b19d21f3d147fde4d96a3afaa107670f1eJosé Fonseca   struct pipe_resource *dummy;
2533192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
254ef33c82bfde788733aabc5dcc9647416c31ae254José Fonseca   if (!sbuf->dma.pending) {
255ef33c82bfde788733aabc5dcc9647416c31ae254José Fonseca      return;
256ef33c82bfde788733aabc5dcc9647416c31ae254José Fonseca   }
257ef33c82bfde788733aabc5dcc9647416c31ae254José Fonseca
25859d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul   assert(sbuf->handle);
259cf861335a44376609258a2ec399c215e35f9f075José Fonseca   assert(sbuf->hwbuf);
260cf861335a44376609258a2ec399c215e35f9f075José Fonseca   assert(sbuf->map.num_ranges);
261cf861335a44376609258a2ec399c215e35f9f075José Fonseca   assert(sbuf->dma.svga == svga);
262cf861335a44376609258a2ec399c215e35f9f075José Fonseca   assert(sbuf->dma.boxes);
26359d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul
2643192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   /*
2653192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz    * Patch the DMA command with the final copy box.
2663192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz    */
2673192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
2683192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   SVGA_DBG(DEBUG_DMA, "dma to sid %p\n", sbuf->handle);
2693192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
270cf861335a44376609258a2ec399c215e35f9f075José Fonseca   boxes = sbuf->dma.boxes;
27159d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul   for (i = 0; i < sbuf->map.num_ranges; ++i) {
2723192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      SVGA_DBG(DEBUG_DMA, "  bytes %u - %u\n",
273cf861335a44376609258a2ec399c215e35f9f075José Fonseca               sbuf->map.ranges[i].start, sbuf->map.ranges[i].end);
2743192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
275cf861335a44376609258a2ec399c215e35f9f075José Fonseca      boxes[i].x = sbuf->map.ranges[i].start;
2763192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      boxes[i].y = 0;
2773192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      boxes[i].z = 0;
278cf861335a44376609258a2ec399c215e35f9f075José Fonseca      boxes[i].w = sbuf->map.ranges[i].end - sbuf->map.ranges[i].start;
2793192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      boxes[i].h = 1;
2803192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      boxes[i].d = 1;
281cf861335a44376609258a2ec399c215e35f9f075José Fonseca      boxes[i].srcx = sbuf->map.ranges[i].start;
2823192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      boxes[i].srcy = 0;
2833192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      boxes[i].srcz = 0;
2843192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   }
2853192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
286cf861335a44376609258a2ec399c215e35f9f075José Fonseca   sbuf->map.num_ranges = 0;
2873192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
2883192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   assert(sbuf->head.prev && sbuf->head.next);
2893192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   LIST_DEL(&sbuf->head);
29050edefec2dd5ec2990ab2cd699478139173d5fd2José Fonseca#ifdef DEBUG
29159d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul   sbuf->head.next = sbuf->head.prev = NULL;
29250edefec2dd5ec2990ab2cd699478139173d5fd2José Fonseca#endif
293cf861335a44376609258a2ec399c215e35f9f075José Fonseca   sbuf->dma.pending = FALSE;
294ef33c82bfde788733aabc5dcc9647416c31ae254José Fonseca   sbuf->dma.flags.discard = FALSE;
295ef33c82bfde788733aabc5dcc9647416c31ae254José Fonseca   sbuf->dma.flags.unsynchronized = FALSE;
2963192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
297cf861335a44376609258a2ec399c215e35f9f075José Fonseca   sbuf->dma.svga = NULL;
298cf861335a44376609258a2ec399c215e35f9f075José Fonseca   sbuf->dma.boxes = NULL;
2993192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
300610c24b19d21f3d147fde4d96a3afaa107670f1eJosé Fonseca   /* Decrement reference count (and potentially destroy) */
301610c24b19d21f3d147fde4d96a3afaa107670f1eJosé Fonseca   dummy = &sbuf->b.b;
302610c24b19d21f3d147fde4d96a3afaa107670f1eJosé Fonseca   pipe_resource_reference(&dummy, NULL);
3033192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz}
3043192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
3053192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
3063192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz/**
307cf861335a44376609258a2ec399c215e35f9f075José Fonseca * Note a dirty range.
3083192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz *
3093192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * This function only notes the range down. It doesn't actually emit a DMA
3103192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * upload command. That only happens when a context tries to refer to this
31159d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul * buffer, and the DMA upload command is added to that context's command
31259d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul * buffer.
31359d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul *
3143192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz * We try to lump as many contiguous DMA transfers together as possible.
3153192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz */
316287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwellvoid
317cf861335a44376609258a2ec399c215e35f9f075José Fonsecasvga_buffer_add_range(struct svga_buffer *sbuf,
318cf861335a44376609258a2ec399c215e35f9f075José Fonseca                      unsigned start,
319cf861335a44376609258a2ec399c215e35f9f075José Fonseca                      unsigned end)
3203192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz{
3213192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   unsigned i;
322422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca   unsigned nearest_range;
323422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca   unsigned nearest_dist;
3243192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
3253192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   assert(end > start);
32659d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul
327cf861335a44376609258a2ec399c215e35f9f075José Fonseca   if (sbuf->map.num_ranges < SVGA_BUFFER_MAX_RANGES) {
328cf861335a44376609258a2ec399c215e35f9f075José Fonseca      nearest_range = sbuf->map.num_ranges;
329422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca      nearest_dist = ~0;
330422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca   } else {
331422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca      nearest_range = SVGA_BUFFER_MAX_RANGES - 1;
332422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca      nearest_dist = 0;
333422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca   }
334422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca
3353192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   /*
3363192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz    * Try to grow one of the ranges.
3373192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz    */
3383192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
33959d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul   for (i = 0; i < sbuf->map.num_ranges; ++i) {
340422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca      int left_dist;
341422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca      int right_dist;
342422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca      int dist;
343422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca
344cf861335a44376609258a2ec399c215e35f9f075José Fonseca      left_dist = start - sbuf->map.ranges[i].end;
345cf861335a44376609258a2ec399c215e35f9f075José Fonseca      right_dist = sbuf->map.ranges[i].start - end;
346422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca      dist = MAX2(left_dist, right_dist);
347422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca
348422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca      if (dist <= 0) {
349422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca         /*
350422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca          * Ranges are contiguous or overlapping -- extend this one and return.
351ef33c82bfde788733aabc5dcc9647416c31ae254José Fonseca          *
352ef33c82bfde788733aabc5dcc9647416c31ae254José Fonseca          * Note that it is not this function's task to prevent overlapping
353ef33c82bfde788733aabc5dcc9647416c31ae254José Fonseca          * ranges, as the GMR was already given so it is too late to do
354ef33c82bfde788733aabc5dcc9647416c31ae254José Fonseca          * anything.  If the ranges overlap here it must surely be because
355ef33c82bfde788733aabc5dcc9647416c31ae254José Fonseca          * PIPE_TRANSFER_UNSYNCHRONIZED was set.
356422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca          */
357422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca
358cf861335a44376609258a2ec399c215e35f9f075José Fonseca         sbuf->map.ranges[i].start = MIN2(sbuf->map.ranges[i].start, start);
359cf861335a44376609258a2ec399c215e35f9f075José Fonseca         sbuf->map.ranges[i].end   = MAX2(sbuf->map.ranges[i].end,   end);
3603192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz         return;
3613192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      }
362422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca      else {
363422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca         /*
364422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca          * Discontiguous ranges -- keep track of the nearest range.
365422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca          */
366422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca
367422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca         if (dist < nearest_dist) {
368422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca            nearest_range = i;
369422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca            nearest_dist = dist;
370422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca         }
371422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca      }
3723192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   }
3733192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
3743192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   /*
3753192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz    * We cannot add a new range to an existing DMA command, so patch-up the
3763192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz    * pending DMA upload and start clean.
3773192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz    */
3783192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
379ef33c82bfde788733aabc5dcc9647416c31ae254José Fonseca   svga_buffer_upload_flush(sbuf->dma.svga, sbuf);
3803192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
381cf861335a44376609258a2ec399c215e35f9f075José Fonseca   assert(!sbuf->dma.pending);
382cf861335a44376609258a2ec399c215e35f9f075José Fonseca   assert(!sbuf->dma.svga);
383cf861335a44376609258a2ec399c215e35f9f075José Fonseca   assert(!sbuf->dma.boxes);
3843192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
385cf861335a44376609258a2ec399c215e35f9f075José Fonseca   if (sbuf->map.num_ranges < SVGA_BUFFER_MAX_RANGES) {
386422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca      /*
387422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca       * Add a new range.
388422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca       */
3893192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
390cf861335a44376609258a2ec399c215e35f9f075José Fonseca      sbuf->map.ranges[sbuf->map.num_ranges].start = start;
391cf861335a44376609258a2ec399c215e35f9f075José Fonseca      sbuf->map.ranges[sbuf->map.num_ranges].end = end;
392cf861335a44376609258a2ec399c215e35f9f075José Fonseca      ++sbuf->map.num_ranges;
393422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca   } else {
394422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca      /*
395422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca       * Everything else failed, so just extend the nearest range.
396422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca       *
397422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca       * It is OK to do this because we always keep a local copy of the
398422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca       * host buffer data, for SW TNL, and the host never modifies the buffer.
399422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca       */
400422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca
401422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca      assert(nearest_range < SVGA_BUFFER_MAX_RANGES);
402cf861335a44376609258a2ec399c215e35f9f075José Fonseca      assert(nearest_range < sbuf->map.num_ranges);
403cf861335a44376609258a2ec399c215e35f9f075José Fonseca      sbuf->map.ranges[nearest_range].start = MIN2(sbuf->map.ranges[nearest_range].start, start);
404cf861335a44376609258a2ec399c215e35f9f075José Fonseca      sbuf->map.ranges[nearest_range].end   = MAX2(sbuf->map.ranges[nearest_range].end,   end);
405422167a9b0dc5b6da7bc7c47621b5da1bc6d315bJosé Fonseca   }
4063192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz}
4073192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
4083192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
4093192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
410d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca/**
411b330928549b39e97e16aee636c335865504ffab9José Fonseca * Copy the contents of the malloc buffer to a hardware buffer.
4123192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz */
413daf4254d07328381ed013aac25e25d6021fbfd14Brian Paulstatic enum pipe_error
4143192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantzsvga_buffer_update_hw(struct svga_screen *ss, struct svga_buffer *sbuf)
4153192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz{
416b330928549b39e97e16aee636c335865504ffab9José Fonseca   assert(!sbuf->user);
41759d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul   if (!sbuf->hwbuf) {
4183192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      enum pipe_error ret;
4193192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      void *map;
42059d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul
4213192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      assert(sbuf->swbuf);
42259d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul      if (!sbuf->swbuf)
4233192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz         return PIPE_ERROR;
42459d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul
4253192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      ret = svga_buffer_create_hw_storage(ss, sbuf);
42659d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul      if (ret != PIPE_OK)
4273192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz         return ret;
4283192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
4293192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      pipe_mutex_lock(ss->swc_mutex);
430287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell      map = ss->sws->buffer_map(ss->sws, sbuf->hwbuf, PIPE_TRANSFER_WRITE);
4313192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      assert(map);
43259d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul      if (!map) {
4333192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz	 pipe_mutex_unlock(ss->swc_mutex);
4342452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca         svga_buffer_destroy_hw_storage(ss, sbuf);
4352452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca         return PIPE_ERROR;
4363192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      }
4373192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
438287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell      memcpy(map, sbuf->swbuf, sbuf->b.b.width0);
439cf861335a44376609258a2ec399c215e35f9f075José Fonseca      ss->sws->buffer_unmap(ss->sws, sbuf->hwbuf);
4403192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
4413192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      /* This user/malloc buffer is now indistinguishable from a gpu buffer */
4423192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      assert(!sbuf->map.count);
44359d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul      if (!sbuf->map.count) {
44459d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul         if (sbuf->user)
4453192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz            sbuf->user = FALSE;
4463192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz         else
4473192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz            align_free(sbuf->swbuf);
4483192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz         sbuf->swbuf = NULL;
4493192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      }
45059d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul
4512452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca      pipe_mutex_unlock(ss->swc_mutex);
4523192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   }
45359d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul
4542452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca   return PIPE_OK;
4552452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca}
4562452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca
4572452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca
4582452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca/**
4592452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca * Upload the buffer to the host in a piecewise fashion.
4602452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca *
4612452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca * Used when the buffer is too big to fit in the GMR aperture.
4622452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca */
463daf4254d07328381ed013aac25e25d6021fbfd14Brian Paulstatic enum pipe_error
4642452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonsecasvga_buffer_upload_piecewise(struct svga_screen *ss,
4652452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca                             struct svga_context *svga,
4662452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca                             struct svga_buffer *sbuf)
4672452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca{
4682452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca   struct svga_winsys_screen *sws = ss->sws;
469d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca   const unsigned alignment = sizeof(void *);
4702452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca   const unsigned usage = 0;
471d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca   unsigned i;
472d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca
473d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca   assert(sbuf->map.num_ranges);
474d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca   assert(!sbuf->dma.pending);
4752452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca
4762452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca   SVGA_DBG(DEBUG_DMA, "dma to sid %p\n", sbuf->handle);
4772452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca
478d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca   for (i = 0; i < sbuf->map.num_ranges; ++i) {
479d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca      struct svga_buffer_range *range = &sbuf->map.ranges[i];
480d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca      unsigned offset = range->start;
481d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca      unsigned size = range->end - range->start;
4822452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca
483d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca      while (offset < range->end) {
484d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca         struct svga_winsys_buffer *hwbuf;
485d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca         uint8_t *map;
486d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca         enum pipe_error ret;
4872452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca
488d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca         if (offset + size > range->end)
489d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca            size = range->end - offset;
4902452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca
491b84590994c4261d85485357263146d5e3d8827ebJosé Fonseca         hwbuf = sws->buffer_create(sws, alignment, usage, size);
492d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca         while (!hwbuf) {
493d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca            size /= 2;
494d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca            if (!size)
495d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca               return PIPE_ERROR_OUT_OF_MEMORY;
496b84590994c4261d85485357263146d5e3d8827ebJosé Fonseca            hwbuf = sws->buffer_create(sws, alignment, usage, size);
497d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca         }
4982452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca
499d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca         SVGA_DBG(DEBUG_DMA, "  bytes %u - %u\n",
500d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca                  offset, offset + size);
5012452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca
502d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca         map = sws->buffer_map(sws, hwbuf,
503287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell                               PIPE_TRANSFER_WRITE |
5047cd1c62b6be88072e3d937b67c499592490927f1Marek Olšák                               PIPE_TRANSFER_DISCARD_RANGE);
505d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca         assert(map);
506d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca         if (map) {
507d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca            memcpy(map, sbuf->swbuf, size);
508d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca            sws->buffer_unmap(sws, hwbuf);
509d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca         }
5102452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca
511d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca         ret = SVGA3D_BufferDMA(svga->swc,
512d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca                                hwbuf, sbuf->handle,
513d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca                                SVGA3D_WRITE_HOST_VRAM,
5148ea7d8412c5c002b43824a5df5356cbe1a05ce20José Fonseca                                size, 0, offset, sbuf->dma.flags);
51559d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul         if (ret != PIPE_OK) {
516d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca            svga_context_flush(svga, NULL);
517d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca            ret =  SVGA3D_BufferDMA(svga->swc,
518d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca                                    hwbuf, sbuf->handle,
519d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca                                    SVGA3D_WRITE_HOST_VRAM,
5208ea7d8412c5c002b43824a5df5356cbe1a05ce20José Fonseca                                    size, 0, offset, sbuf->dma.flags);
521d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca            assert(ret == PIPE_OK);
522d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca         }
5232452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca
524d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca         sbuf->dma.flags.discard = FALSE;
5252452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca
526d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca         sws->buffer_destroy(sws, hwbuf);
5272452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca
528d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca         offset += size;
529d1a022537195dc9afca7b487af70b188fbcfcd99José Fonseca      }
5302452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca   }
5312452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca
5322452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca   sbuf->map.num_ranges = 0;
5332452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca
5343192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   return PIPE_OK;
5353192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz}
5363192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
5373192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
538287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell
539287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell
540287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell/* Get (or create/upload) the winsys surface handle so that we can
541287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell * refer to this buffer in fifo commands.
542287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell */
5433192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantzstruct svga_winsys_surface *
5443192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantzsvga_buffer_handle(struct svga_context *svga,
545287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell                   struct pipe_resource *buf)
5463192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz{
5473192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   struct pipe_screen *screen = svga->pipe.screen;
5483192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   struct svga_screen *ss = svga_screen(screen);
5493192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   struct svga_buffer *sbuf;
5503192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   enum pipe_error ret;
5513192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
55259d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul   if (!buf)
5533192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      return NULL;
5543192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
5553192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   sbuf = svga_buffer(buf);
55659d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul
5573192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   assert(!sbuf->map.count);
558b330928549b39e97e16aee636c335865504ffab9José Fonseca   assert(!sbuf->user);
55959d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul
56059d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul   if (!sbuf->handle) {
5613192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      ret = svga_buffer_create_host_surface(ss, sbuf);
56259d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul      if (ret != PIPE_OK)
5633192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz	 return NULL;
5643192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   }
5653192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
5662452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca   assert(sbuf->handle);
5673192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
5682452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca   if (sbuf->map.num_ranges) {
5692452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca      if (!sbuf->dma.pending) {
5702452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca         /*
5712452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca          * No pending DMA upload yet, so insert a DMA upload command now.
5722452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca          */
5733192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
5742452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca         /*
5752452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca          * Migrate the data from swbuf -> hwbuf if necessary.
5762452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca          */
5772452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca         ret = svga_buffer_update_hw(ss, sbuf);
5782452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca         if (ret == PIPE_OK) {
5792452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca            /*
5802452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca             * Queue a dma command.
5812452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca             */
5822452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca
5832452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca            ret = svga_buffer_upload_command(svga, sbuf);
5842452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca            if (ret == PIPE_ERROR_OUT_OF_MEMORY) {
5852452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca               svga_context_flush(svga, NULL);
5862452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca               ret = svga_buffer_upload_command(svga, sbuf);
5872452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca               assert(ret == PIPE_OK);
5882452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca            }
5892452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca            if (ret == PIPE_OK) {
5902452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca               sbuf->dma.pending = TRUE;
5912452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca               assert(!sbuf->head.prev && !sbuf->head.next);
5922452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca               LIST_ADDTAIL(&sbuf->head, &svga->dirty_buffers);
5932452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca            }
5942452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca         }
5952452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca         else if (ret == PIPE_ERROR_OUT_OF_MEMORY) {
5962452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca            /*
5972452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca             * The buffer is too big to fit in the GMR aperture, so break it in
5982452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca             * smaller pieces.
5992452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca             */
6002452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca            ret = svga_buffer_upload_piecewise(ss, svga, sbuf);
6012452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca         }
6022452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca
6032452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca         if (ret != PIPE_OK) {
6042452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca            /*
6052452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca             * Something unexpected happened above. There is very little that
6062452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca             * we can do other than proceeding while ignoring the dirty ranges.
6072452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca             */
6082452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca            assert(0);
6092452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca            sbuf->map.num_ranges = 0;
6102452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca         }
6112452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca      }
6122452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca      else {
6132452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca         /*
6142452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca          * There a pending dma already. Make sure it is from this context.
6152452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca          */
6162452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca         assert(sbuf->dma.svga == svga);
6172452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca      }
6183192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   }
6193192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
6202452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca   assert(!sbuf->map.num_ranges || sbuf->dma.pending);
6212452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca
6223192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   return sbuf->handle;
6233192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz}
6243192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
6252452921e5adb56a3d99e52fb2b963fcd2a0b75e9José Fonseca
6263192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
6273192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantzvoid
6283192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantzsvga_context_flush_buffers(struct svga_context *svga)
6293192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz{
6303192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   struct list_head *curr, *next;
6313192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   struct svga_buffer *sbuf;
6323192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
6333192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   curr = svga->dirty_buffers.next;
6343192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   next = curr->next;
6353192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   while(curr != &svga->dirty_buffers) {
6363192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      sbuf = LIST_ENTRY(struct svga_buffer, curr, head);
6373192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
638287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell      assert(p_atomic_read(&sbuf->b.b.reference.count) != 0);
639cf861335a44376609258a2ec399c215e35f9f075José Fonseca      assert(sbuf->dma.pending);
64059d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul
6413192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      svga_buffer_upload_flush(svga, sbuf);
6423192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz
64359d2c4f8e5a00133c093137b2f4836313f633d60Brian Paul      curr = next;
6443192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz      next = curr->next;
6453192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz   }
6463192633d4abe262d413e41feb871fe8deed409d8Jakob Bornecrantz}
647