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#ifndef SVGA_BUFFER_H
27#define SVGA_BUFFER_H
28
29
30#include "pipe/p_compiler.h"
31#include "pipe/p_state.h"
32#include "util/u_transfer.h"
33
34#include "svga_screen_cache.h"
35#include "svga_screen.h"
36#include "svga_cmd.h"
37#include "svga_context.h"
38
39
40/**
41 * Maximum number of discontiguous ranges
42 */
43#define SVGA_BUFFER_MAX_RANGES 32
44
45
46struct svga_context;
47struct svga_winsys_buffer;
48struct svga_winsys_surface;
49
50struct svga_buffer_range
51{
52   unsigned start;
53   unsigned end;
54};
55
56struct svga_3d_update_gb_image;
57
58/**
59 * This structure describes the bind flags and cache key associated
60 * with the host surface.
61 */
62struct svga_buffer_surface
63{
64   struct list_head list;
65   unsigned bind_flags;
66   struct svga_host_surface_cache_key key;
67   struct svga_winsys_surface *handle;
68   enum svga_surface_state surface_state;
69};
70
71/**
72 * SVGA pipe buffer.
73 */
74struct svga_buffer
75{
76   struct pipe_resource b;
77
78   /** This is a superset of b.b.bind */
79   unsigned bind_flags;
80
81   /**
82    * Regular (non DMA'able) memory.
83    *
84    * Used for user buffers or for buffers which we know before hand that can
85    * never be used by the virtual hardware directly, such as constant buffers.
86    */
87   void *swbuf;
88
89   /**
90    * Whether swbuf was created by the user or not.
91    */
92   boolean user;
93
94   /**
95    * Whether swbuf is used for this buffer.
96    */
97   boolean use_swbuf;
98
99   /**
100    * Creation key for the host surface handle.
101    *
102    * This structure describes all the host surface characteristics so that it
103    * can be looked up in cache, since creating a host surface is often a slow
104    * operation.
105    */
106   struct svga_host_surface_cache_key key;
107
108   /**
109    * Host surface handle.
110    *
111    * This is a platform independent abstraction for host SID. We create when
112    * trying to bind.
113    *
114    * Only set for non-user buffers.
115    */
116   struct svga_winsys_surface *handle;
117
118   /**
119    * List of surfaces created for this buffer resource to support
120    * incompatible bind flags.
121    */
122   struct list_head surfaces;
123
124   /* Current surface structure */
125   struct svga_buffer_surface *bufsurf;
126
127   /**
128    * Information about ongoing and past map operations.
129    */
130   struct {
131      /**
132       * Number of concurrent mappings.
133       */
134      unsigned count;
135
136      /**
137       * Dirty ranges.
138       *
139       * Ranges that were touched by the application and need to be uploaded to
140       * the host.
141       *
142       * This information will be copied into dma.boxes, when emiting the
143       * SVGA3dCmdSurfaceDMA command.
144       */
145      struct svga_buffer_range ranges[SVGA_BUFFER_MAX_RANGES];
146      unsigned num_ranges;
147   } map;
148
149   /**
150    * Information about uploaded version of user buffers.
151    */
152   struct {
153      struct pipe_resource *buffer;
154
155      /**
156       * We combine multiple user buffers into the same hardware buffer. This
157       * is the relative offset within that buffer.
158       */
159      unsigned offset;
160
161      /**
162       * Range of user buffer that is uploaded in @buffer at @offset.
163       */
164      unsigned start;
165      unsigned end;
166   } uploaded;
167
168   /**
169    * DMA'ble memory.
170    *
171    * A piece of GMR memory, with the same size of the buffer. It is created
172    * when mapping the buffer, and will be used to upload vertex data to the
173    * host.
174    *
175    * Only set for non-user buffers.
176    */
177   struct svga_winsys_buffer *hwbuf;
178
179   /**
180    * Information about pending DMA uploads.
181    *
182    */
183   struct {
184      /**
185       * Whether this buffer has an unfinished DMA upload command.
186       *
187       * If not set then the rest of the information is null.
188       */
189      boolean pending;
190
191      SVGA3dSurfaceDMAFlags flags;
192
193      /**
194       * Pointer to the DMA copy box *inside* the command buffer.
195       */
196      SVGA3dCopyBox *boxes;
197
198      /**
199       * Pointer to the sequence of update commands
200       * *inside* the command buffer.
201       */
202      struct svga_3d_update_gb_image *updates;
203
204      /**
205       * Context that has the pending DMA to this buffer.
206       */
207      struct svga_context *svga;
208   } dma;
209
210   /**
211    * Linked list head, used to gather all buffers with pending dma uploads on
212    * a context. It is only valid if the dma.pending is set above.
213    */
214   struct list_head head;
215
216   unsigned size;  /**< Approximate size in bytes */
217
218   boolean dirty;  /**< Need to do a readback before mapping? */
219   boolean uav;    /* Set if the buffer is bound to a uav */
220
221   /** In some cases we try to keep the results of the translate_indices()
222    * function from svga_draw_elements.c
223    */
224   struct {
225      enum pipe_prim_type orig_prim, new_prim;
226      struct pipe_resource *buffer;
227      unsigned index_size;
228      unsigned offset;  /**< first index */
229      unsigned count;   /**< num indices */
230   } translated_indices;
231};
232
233
234static inline struct svga_buffer *
235svga_buffer(struct pipe_resource *resource)
236{
237   struct svga_buffer *buf = (struct svga_buffer *) resource;
238   assert(buf == NULL || buf->b.target == PIPE_BUFFER);
239   return buf;
240}
241
242
243/**
244 * Returns TRUE for user buffers.  We may
245 * decide to use an alternate upload path for these buffers.
246 */
247static inline boolean
248svga_buffer_is_user_buffer(struct pipe_resource *buffer)
249{
250   if (buffer) {
251      return svga_buffer(buffer)->user;
252   } else {
253      return FALSE;
254   }
255}
256
257/**
258 * Returns a pointer to a struct svga_winsys_screen given a
259 * struct svga_buffer.
260 */
261static inline struct svga_winsys_screen *
262svga_buffer_winsys_screen(struct svga_buffer *sbuf)
263{
264   return svga_screen(sbuf->b.screen)->sws;
265}
266
267
268/**
269 * Returns whether a buffer has hardware storage that is
270 * visible to the GPU.
271 */
272static inline boolean
273svga_buffer_has_hw_storage(struct svga_buffer *sbuf)
274{
275   if (svga_buffer_winsys_screen(sbuf)->have_gb_objects)
276      return (sbuf->handle ? TRUE : FALSE);
277   else
278      return (sbuf->hwbuf ? TRUE : FALSE);
279}
280
281/**
282 * Map the hardware storage of a buffer.
283 * \param flags  bitmask of PIPE_MAP_* flags
284 */
285static inline void *
286svga_buffer_hw_storage_map(struct svga_context *svga,
287                           struct svga_buffer *sbuf,
288                           unsigned flags, boolean *retry)
289{
290   struct svga_winsys_screen *sws = svga_buffer_winsys_screen(sbuf);
291
292   svga->hud.num_buffers_mapped++;
293
294   if (sws->have_gb_objects) {
295      struct svga_winsys_context *swc = svga->swc;
296      boolean rebind;
297      void *map;
298
299      if (swc->force_coherent) {
300         flags |= PIPE_MAP_PERSISTENT | PIPE_MAP_COHERENT;
301      }
302      map = swc->surface_map(swc, sbuf->handle, flags, retry, &rebind);
303      if (map && rebind) {
304         enum pipe_error ret;
305
306         ret = SVGA3D_BindGBSurface(swc, sbuf->handle);
307         if (ret != PIPE_OK) {
308            svga_context_flush(svga, NULL);
309            ret = SVGA3D_BindGBSurface(swc, sbuf->handle);
310            assert(ret == PIPE_OK);
311         }
312         svga_context_flush(svga, NULL);
313      }
314      return map;
315   } else {
316      *retry = FALSE;
317      return sws->buffer_map(sws, sbuf->hwbuf, flags);
318   }
319}
320
321/**
322 * Unmap the hardware storage of a buffer.
323 */
324static inline void
325svga_buffer_hw_storage_unmap(struct svga_context *svga,
326                             struct svga_buffer *sbuf)
327{
328   struct svga_winsys_screen *sws = svga_buffer_winsys_screen(sbuf);
329
330   if (sws->have_gb_objects) {
331      struct svga_winsys_context *swc = svga->swc;
332      boolean rebind;
333
334      swc->surface_unmap(swc, sbuf->handle, &rebind);
335      if (rebind) {
336         SVGA_RETRY(svga, SVGA3D_BindGBSurface(swc, sbuf->handle));
337      }
338   } else
339      sws->buffer_unmap(sws, sbuf->hwbuf);
340
341   /* Mark the buffer surface as UPDATED */
342   assert(sbuf->bufsurf);
343   sbuf->bufsurf->surface_state = SVGA_SURFACE_STATE_UPDATED;
344}
345
346
347static inline void
348svga_set_buffer_rendered_to(struct svga_buffer_surface *bufsurf)
349{
350   bufsurf->surface_state = SVGA_SURFACE_STATE_RENDERED;
351}
352
353
354static inline boolean
355svga_was_buffer_rendered_to(const struct svga_buffer_surface *bufsurf)
356{
357   return (bufsurf->surface_state == SVGA_SURFACE_STATE_RENDERED);
358}
359
360
361struct pipe_resource *
362svga_user_buffer_create(struct pipe_screen *screen,
363                        void *ptr,
364                        unsigned bytes,
365                        unsigned usage);
366
367struct pipe_resource *
368svga_buffer_create(struct pipe_screen *screen,
369                   const struct pipe_resource *template);
370
371
372
373/**
374 * Get the host surface handle for this buffer.
375 *
376 * This will ensure the host surface is updated, issuing DMAs as needed.
377 *
378 * NOTE: This may insert new commands in the context, so it *must* be called
379 * before reserving command buffer space. And, in order to insert commands
380 * it may need to call svga_context_flush().
381 */
382struct svga_winsys_surface *
383svga_buffer_handle(struct svga_context *svga,
384                   struct pipe_resource *buf,
385                   unsigned tobind_flags);
386
387void
388svga_context_flush_buffers(struct svga_context *svga);
389
390struct svga_winsys_buffer *
391svga_winsys_buffer_create(struct svga_context *svga,
392                          unsigned alignment,
393                          unsigned usage,
394                          unsigned size);
395
396void
397svga_buffer_transfer_flush_region(struct pipe_context *pipe,
398                                  struct pipe_transfer *transfer,
399                                  const struct pipe_box *box);
400
401void
402svga_resource_destroy(struct pipe_screen *screen,
403                      struct pipe_resource *buf);
404
405void *
406svga_buffer_transfer_map(struct pipe_context *pipe,
407                         struct pipe_resource *resource,
408                         unsigned level,
409                         unsigned usage,
410                         const struct pipe_box *box,
411                         struct pipe_transfer **ptransfer);
412
413void
414svga_buffer_transfer_unmap(struct pipe_context *pipe,
415                           struct pipe_transfer *transfer);
416
417#endif /* SVGA_BUFFER_H */
418