aboutsummaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/svga/svga_resource_buffer.h
blob: 35ed35d61ddafaab62c79060416bdcbc4ebca78d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
/**********************************************************
 * Copyright 2008-2009 VMware, Inc.  All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 **********************************************************/

#ifndef SVGA_BUFFER_H
#define SVGA_BUFFER_H


#include "pipe/p_compiler.h"
#include "pipe/p_state.h"
#include "util/u_transfer.h"

#include "svga_screen_cache.h"
#include "svga_screen.h"
#include "svga_cmd.h"
#include "svga_context.h"


/**
 * Maximum number of discontiguous ranges
 */
#define SVGA_BUFFER_MAX_RANGES 32


struct svga_context;
struct svga_winsys_buffer;
struct svga_winsys_surface;


extern struct u_resource_vtbl svga_buffer_vtbl;

struct svga_buffer_range
{
   unsigned start;
   unsigned end;
};

struct svga_3d_update_gb_image;

/**
 * This structure describes the bind flags and cache key associated
 * with the host surface.
 */
struct svga_buffer_surface
{
   struct list_head list;
   unsigned bind_flags;
   struct svga_host_surface_cache_key key;
   struct svga_winsys_surface *handle;
};

/**
 * SVGA pipe buffer.
 */
struct svga_buffer
{
   struct u_resource b;

   /** This is a superset of b.b.bind */
   unsigned bind_flags;

   /**
    * Regular (non DMA'able) memory.
    *
    * Used for user buffers or for buffers which we know before hand that can
    * never be used by the virtual hardware directly, such as constant buffers.
    */
   void *swbuf;

   /**
    * Whether swbuf was created by the user or not.
    */
   boolean user;

   /**
    * Creation key for the host surface handle.
    *
    * This structure describes all the host surface characteristics so that it
    * can be looked up in cache, since creating a host surface is often a slow
    * operation.
    */
   struct svga_host_surface_cache_key key;

   /**
    * Host surface handle.
    *
    * This is a platform independent abstraction for host SID. We create when
    * trying to bind.
    *
    * Only set for non-user buffers.
    */
   struct svga_winsys_surface *handle;

   /**
    * List of surfaces created for this buffer resource to support
    * incompatible bind flags.
    */
   struct list_head surfaces;

   /**
    * Information about ongoing and past map operations.
    */
   struct {
      /**
       * Number of concurrent mappings.
       */
      unsigned count;

      /**
       * Dirty ranges.
       *
       * Ranges that were touched by the application and need to be uploaded to
       * the host.
       *
       * This information will be copied into dma.boxes, when emiting the
       * SVGA3dCmdSurfaceDMA command.
       */
      struct svga_buffer_range ranges[SVGA_BUFFER_MAX_RANGES];
      unsigned num_ranges;
   } map;

   /**
    * Information about uploaded version of user buffers.
    */
   struct {
      struct pipe_resource *buffer;

      /**
       * We combine multiple user buffers into the same hardware buffer. This
       * is the relative offset within that buffer.
       */
      unsigned offset;

      /**
       * Range of user buffer that is uploaded in @buffer at @offset.
       */
      unsigned start;
      unsigned end;
   } uploaded;

   /**
    * DMA'ble memory.
    *
    * A piece of GMR memory, with the same size of the buffer. It is created
    * when mapping the buffer, and will be used to upload vertex data to the
    * host.
    *
    * Only set for non-user buffers.
    */
   struct svga_winsys_buffer *hwbuf;

   /**
    * Information about pending DMA uploads.
    *
    */
   struct {
      /**
       * Whether this buffer has an unfinished DMA upload command.
       *
       * If not set then the rest of the information is null.
       */
      boolean pending;

      SVGA3dSurfaceDMAFlags flags;

      /**
       * Pointer to the DMA copy box *inside* the command buffer.
       */
      SVGA3dCopyBox *boxes;

      /**
       * Pointer to the sequence of update commands
       * *inside* the command buffer.
       */
      struct svga_3d_update_gb_image *updates;

      /**
       * Context that has the pending DMA to this buffer.
       */
      struct svga_context *svga;
   } dma;

   /**
    * Linked list head, used to gather all buffers with pending dma uploads on
    * a context. It is only valid if the dma.pending is set above.
    */
   struct list_head head;

   unsigned size;  /**< Approximate size in bytes */

   boolean dirty;  /**< Need to do a readback before mapping? */

   /** In some cases we try to keep the results of the translate_indices()
    * function from svga_draw_elements.c
    */
   struct {
      enum pipe_prim_type orig_prim, new_prim;
      struct pipe_resource *buffer;
      unsigned index_size;
      unsigned offset;  /**< first index */
      unsigned count;   /**< num indices */
   } translated_indices;
};


static inline struct svga_buffer *
svga_buffer(struct pipe_resource *resource)
{
   struct svga_buffer *buf = (struct svga_buffer *) resource;
   assert(buf == NULL || buf->b.vtbl == &svga_buffer_vtbl);
   return buf;
}


/**
 * Returns TRUE for user buffers.  We may
 * decide to use an alternate upload path for these buffers.
 */
static inline boolean
svga_buffer_is_user_buffer(struct pipe_resource *buffer)
{
   if (buffer) {
      return svga_buffer(buffer)->user;
   } else {
      return FALSE;
   }
}

/**
 * Returns a pointer to a struct svga_winsys_screen given a
 * struct svga_buffer.
 */
static inline struct svga_winsys_screen *
svga_buffer_winsys_screen(struct svga_buffer *sbuf)
{
   return svga_screen(sbuf->b.b.screen)->sws;
}


/**
 * Returns whether a buffer has hardware storage that is
 * visible to the GPU.
 */
static inline boolean
svga_buffer_has_hw_storage(struct svga_buffer *sbuf)
{
   if (svga_buffer_winsys_screen(sbuf)->have_gb_objects)
      return (sbuf->handle ? TRUE : FALSE);
   else
      return (sbuf->hwbuf ? TRUE : FALSE);
}

/**
 * Map the hardware storage of a buffer.
 * \param flags  bitmask of PIPE_TRANSFER_* flags
 */
static inline void *
svga_buffer_hw_storage_map(struct svga_context *svga,
                           struct svga_buffer *sbuf,
                           unsigned flags, boolean *retry)
{
   struct svga_winsys_screen *sws = svga_buffer_winsys_screen(sbuf);

   svga->hud.num_buffers_mapped++;

   if (sws->have_gb_objects) {
      return svga->swc->surface_map(svga->swc, sbuf->handle, flags, retry);
   } else {
      *retry = FALSE;
      return sws->buffer_map(sws, sbuf->hwbuf, flags);
   }
}

/**
 * Unmap the hardware storage of a buffer.
 */
static inline void
svga_buffer_hw_storage_unmap(struct svga_context *svga,
                             struct svga_buffer *sbuf)
{
   struct svga_winsys_screen *sws = svga_buffer_winsys_screen(sbuf);

   if (sws->have_gb_objects) {
      struct svga_winsys_context *swc = svga->swc;
      boolean rebind;
      swc->surface_unmap(swc, sbuf->handle, &rebind);
      if (rebind) {
         enum pipe_error ret;
         ret = SVGA3D_BindGBSurface(swc, sbuf->handle);
         if (ret != PIPE_OK) {
            /* flush and retry */
            svga_context_flush(svga, NULL);
            ret = SVGA3D_BindGBSurface(swc, sbuf->handle);
            assert(ret == PIPE_OK);
         }
         if (swc->force_coherent) {
            ret = SVGA3D_UpdateGBSurface(swc, sbuf->handle);
            if (ret != PIPE_OK) {
               /* flush and retry */
               svga_context_flush(svga, NULL);
               ret = SVGA3D_UpdateGBSurface(swc, sbuf->handle);
               assert(ret == PIPE_OK);
            }
         }
      }
   } else
      sws->buffer_unmap(sws, sbuf->hwbuf);
}


struct pipe_resource *
svga_user_buffer_create(struct pipe_screen *screen,
                        void *ptr,
                        unsigned bytes,
                        unsigned usage);

struct pipe_resource *
svga_buffer_create(struct pipe_screen *screen,
                   const struct pipe_resource *template);



/**
 * Get the host surface handle for this buffer.
 *
 * This will ensure the host surface is updated, issuing DMAs as needed.
 *
 * NOTE: This may insert new commands in the context, so it *must* be called
 * before reserving command buffer space. And, in order to insert commands
 * it may need to call svga_context_flush().
 */
struct svga_winsys_surface *
svga_buffer_handle(struct svga_context *svga,
                   struct pipe_resource *buf,
                   unsigned tobind_flags);

void
svga_context_flush_buffers(struct svga_context *svga);

struct svga_winsys_buffer *
svga_winsys_buffer_create(struct svga_context *svga,
                          unsigned alignment,
                          unsigned usage,
                          unsigned size);

#endif /* SVGA_BUFFER_H */