1bf215546Sopenharmony_ci/**********************************************************
2bf215546Sopenharmony_ci * Copyright 2009-2015 VMware, Inc.  All rights reserved.
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person
5bf215546Sopenharmony_ci * obtaining a copy of this software and associated documentation
6bf215546Sopenharmony_ci * files (the "Software"), to deal in the Software without
7bf215546Sopenharmony_ci * restriction, including without limitation the rights to use, copy,
8bf215546Sopenharmony_ci * modify, merge, publish, distribute, sublicense, and/or sell copies
9bf215546Sopenharmony_ci * of the Software, and to permit persons to whom the Software is
10bf215546Sopenharmony_ci * furnished to do so, subject to the following conditions:
11bf215546Sopenharmony_ci *
12bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be
13bf215546Sopenharmony_ci * included in all copies or substantial portions of the Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16bf215546Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18bf215546Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19bf215546Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20bf215546Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21bf215546Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22bf215546Sopenharmony_ci * SOFTWARE.
23bf215546Sopenharmony_ci *
24bf215546Sopenharmony_ci **********************************************************/
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#include "svga_cmd.h"
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ci#include "util/u_debug.h"
30bf215546Sopenharmony_ci#include "util/u_memory.h"
31bf215546Sopenharmony_ci#include "util/u_debug_stack.h"
32bf215546Sopenharmony_ci#include "util/u_debug_flush.h"
33bf215546Sopenharmony_ci#include "util/u_hash_table.h"
34bf215546Sopenharmony_ci#include "pipebuffer/pb_buffer.h"
35bf215546Sopenharmony_ci#include "pipebuffer/pb_validate.h"
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci#include "svga_winsys.h"
38bf215546Sopenharmony_ci#include "vmw_context.h"
39bf215546Sopenharmony_ci#include "vmw_screen.h"
40bf215546Sopenharmony_ci#include "vmw_buffer.h"
41bf215546Sopenharmony_ci#include "vmw_surface.h"
42bf215546Sopenharmony_ci#include "vmw_fence.h"
43bf215546Sopenharmony_ci#include "vmw_shader.h"
44bf215546Sopenharmony_ci#include "vmw_query.h"
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_ci#define VMW_COMMAND_SIZE (64*1024)
47bf215546Sopenharmony_ci#define VMW_SURFACE_RELOCS (1024)
48bf215546Sopenharmony_ci#define VMW_SHADER_RELOCS (1024)
49bf215546Sopenharmony_ci#define VMW_REGION_RELOCS (512)
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_ci#define VMW_MUST_FLUSH_STACK 8
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_ci/*
54bf215546Sopenharmony_ci * A factor applied to the maximum mob memory size to determine
55bf215546Sopenharmony_ci * the optimial time to preemptively flush the command buffer.
56bf215546Sopenharmony_ci * The constant is based on some performance trials with SpecViewperf.
57bf215546Sopenharmony_ci */
58bf215546Sopenharmony_ci#define VMW_MAX_MOB_MEM_FACTOR  2
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_ci/*
61bf215546Sopenharmony_ci * A factor applied to the maximum surface memory size to determine
62bf215546Sopenharmony_ci * the optimial time to preemptively flush the command buffer.
63bf215546Sopenharmony_ci * The constant is based on some performance trials with SpecViewperf.
64bf215546Sopenharmony_ci */
65bf215546Sopenharmony_ci#define VMW_MAX_SURF_MEM_FACTOR 2
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_ci
68bf215546Sopenharmony_ci
69bf215546Sopenharmony_cistruct vmw_buffer_relocation
70bf215546Sopenharmony_ci{
71bf215546Sopenharmony_ci   struct pb_buffer *buffer;
72bf215546Sopenharmony_ci   boolean is_mob;
73bf215546Sopenharmony_ci   uint32 offset;
74bf215546Sopenharmony_ci
75bf215546Sopenharmony_ci   union {
76bf215546Sopenharmony_ci      struct {
77bf215546Sopenharmony_ci	 struct SVGAGuestPtr *where;
78bf215546Sopenharmony_ci      } region;
79bf215546Sopenharmony_ci      struct {
80bf215546Sopenharmony_ci	 SVGAMobId *id;
81bf215546Sopenharmony_ci	 uint32 *offset_into_mob;
82bf215546Sopenharmony_ci      } mob;
83bf215546Sopenharmony_ci   };
84bf215546Sopenharmony_ci};
85bf215546Sopenharmony_ci
86bf215546Sopenharmony_cistruct vmw_ctx_validate_item {
87bf215546Sopenharmony_ci   union {
88bf215546Sopenharmony_ci      struct vmw_svga_winsys_surface *vsurf;
89bf215546Sopenharmony_ci      struct vmw_svga_winsys_shader *vshader;
90bf215546Sopenharmony_ci   };
91bf215546Sopenharmony_ci   boolean referenced;
92bf215546Sopenharmony_ci};
93bf215546Sopenharmony_ci
94bf215546Sopenharmony_cistruct vmw_svga_winsys_context
95bf215546Sopenharmony_ci{
96bf215546Sopenharmony_ci   struct svga_winsys_context base;
97bf215546Sopenharmony_ci
98bf215546Sopenharmony_ci   struct vmw_winsys_screen *vws;
99bf215546Sopenharmony_ci   struct hash_table *hash;
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_ci#ifdef DEBUG
102bf215546Sopenharmony_ci   boolean must_flush;
103bf215546Sopenharmony_ci   struct debug_stack_frame must_flush_stack[VMW_MUST_FLUSH_STACK];
104bf215546Sopenharmony_ci   struct debug_flush_ctx *fctx;
105bf215546Sopenharmony_ci#endif
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_ci   struct {
108bf215546Sopenharmony_ci      uint8_t buffer[VMW_COMMAND_SIZE];
109bf215546Sopenharmony_ci      uint32_t size;
110bf215546Sopenharmony_ci      uint32_t used;
111bf215546Sopenharmony_ci      uint32_t reserved;
112bf215546Sopenharmony_ci   } command;
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_ci   struct {
115bf215546Sopenharmony_ci      struct vmw_ctx_validate_item items[VMW_SURFACE_RELOCS];
116bf215546Sopenharmony_ci      uint32_t size;
117bf215546Sopenharmony_ci      uint32_t used;
118bf215546Sopenharmony_ci      uint32_t staged;
119bf215546Sopenharmony_ci      uint32_t reserved;
120bf215546Sopenharmony_ci   } surface;
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci   struct {
123bf215546Sopenharmony_ci      struct vmw_buffer_relocation relocs[VMW_REGION_RELOCS];
124bf215546Sopenharmony_ci      uint32_t size;
125bf215546Sopenharmony_ci      uint32_t used;
126bf215546Sopenharmony_ci      uint32_t staged;
127bf215546Sopenharmony_ci      uint32_t reserved;
128bf215546Sopenharmony_ci   } region;
129bf215546Sopenharmony_ci
130bf215546Sopenharmony_ci   struct {
131bf215546Sopenharmony_ci      struct vmw_ctx_validate_item items[VMW_SHADER_RELOCS];
132bf215546Sopenharmony_ci      uint32_t size;
133bf215546Sopenharmony_ci      uint32_t used;
134bf215546Sopenharmony_ci      uint32_t staged;
135bf215546Sopenharmony_ci      uint32_t reserved;
136bf215546Sopenharmony_ci   } shader;
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_ci   struct pb_validate *validate;
139bf215546Sopenharmony_ci
140bf215546Sopenharmony_ci   /**
141bf215546Sopenharmony_ci    * The amount of surface, GMR or MOB memory that is referred by the commands
142bf215546Sopenharmony_ci    * currently batched in the context command buffer.
143bf215546Sopenharmony_ci    */
144bf215546Sopenharmony_ci   uint64_t seen_surfaces;
145bf215546Sopenharmony_ci   uint64_t seen_regions;
146bf215546Sopenharmony_ci   uint64_t seen_mobs;
147bf215546Sopenharmony_ci
148bf215546Sopenharmony_ci   /**
149bf215546Sopenharmony_ci    * Whether this context should fail to reserve more commands, not because it
150bf215546Sopenharmony_ci    * ran out of command space, but because a substantial ammount of GMR was
151bf215546Sopenharmony_ci    * referred.
152bf215546Sopenharmony_ci    */
153bf215546Sopenharmony_ci   boolean preemptive_flush;
154bf215546Sopenharmony_ci};
155bf215546Sopenharmony_ci
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_cistatic inline struct vmw_svga_winsys_context *
158bf215546Sopenharmony_civmw_svga_winsys_context(struct svga_winsys_context *swc)
159bf215546Sopenharmony_ci{
160bf215546Sopenharmony_ci   assert(swc);
161bf215546Sopenharmony_ci   return (struct vmw_svga_winsys_context *)swc;
162bf215546Sopenharmony_ci}
163bf215546Sopenharmony_ci
164bf215546Sopenharmony_ci
165bf215546Sopenharmony_cistatic inline enum pb_usage_flags
166bf215546Sopenharmony_civmw_translate_to_pb_flags(unsigned flags)
167bf215546Sopenharmony_ci{
168bf215546Sopenharmony_ci   enum pb_usage_flags f = 0;
169bf215546Sopenharmony_ci   if (flags & SVGA_RELOC_READ)
170bf215546Sopenharmony_ci      f |= PB_USAGE_GPU_READ;
171bf215546Sopenharmony_ci
172bf215546Sopenharmony_ci   if (flags & SVGA_RELOC_WRITE)
173bf215546Sopenharmony_ci      f |= PB_USAGE_GPU_WRITE;
174bf215546Sopenharmony_ci
175bf215546Sopenharmony_ci   return f;
176bf215546Sopenharmony_ci}
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_cistatic enum pipe_error
179bf215546Sopenharmony_civmw_swc_flush(struct svga_winsys_context *swc,
180bf215546Sopenharmony_ci              struct pipe_fence_handle **pfence)
181bf215546Sopenharmony_ci{
182bf215546Sopenharmony_ci   struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
183bf215546Sopenharmony_ci   struct vmw_winsys_screen *vws = vswc->vws;
184bf215546Sopenharmony_ci   struct pipe_fence_handle *fence = NULL;
185bf215546Sopenharmony_ci   unsigned i;
186bf215546Sopenharmony_ci   enum pipe_error ret;
187bf215546Sopenharmony_ci
188bf215546Sopenharmony_ci   /*
189bf215546Sopenharmony_ci    * If we hit a retry, lock the mutex and retry immediately.
190bf215546Sopenharmony_ci    * If we then still hit a retry, sleep until another thread
191bf215546Sopenharmony_ci    * wakes us up after it has released its buffers from the
192bf215546Sopenharmony_ci    * validate list.
193bf215546Sopenharmony_ci    *
194bf215546Sopenharmony_ci    * If we hit another error condition, we still need to broadcast since
195bf215546Sopenharmony_ci    * pb_validate_validate releases validated buffers in its error path.
196bf215546Sopenharmony_ci    */
197bf215546Sopenharmony_ci
198bf215546Sopenharmony_ci   ret = pb_validate_validate(vswc->validate);
199bf215546Sopenharmony_ci   if (ret != PIPE_OK) {
200bf215546Sopenharmony_ci      mtx_lock(&vws->cs_mutex);
201bf215546Sopenharmony_ci      while (ret == PIPE_ERROR_RETRY) {
202bf215546Sopenharmony_ci         ret = pb_validate_validate(vswc->validate);
203bf215546Sopenharmony_ci         if (ret == PIPE_ERROR_RETRY) {
204bf215546Sopenharmony_ci            cnd_wait(&vws->cs_cond, &vws->cs_mutex);
205bf215546Sopenharmony_ci         }
206bf215546Sopenharmony_ci      }
207bf215546Sopenharmony_ci      if (ret != PIPE_OK) {
208bf215546Sopenharmony_ci         cnd_broadcast(&vws->cs_cond);
209bf215546Sopenharmony_ci      }
210bf215546Sopenharmony_ci      mtx_unlock(&vws->cs_mutex);
211bf215546Sopenharmony_ci   }
212bf215546Sopenharmony_ci
213bf215546Sopenharmony_ci   assert(ret == PIPE_OK);
214bf215546Sopenharmony_ci   if(ret == PIPE_OK) {
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_ci      /* Apply relocations */
217bf215546Sopenharmony_ci      for(i = 0; i < vswc->region.used; ++i) {
218bf215546Sopenharmony_ci         struct vmw_buffer_relocation *reloc = &vswc->region.relocs[i];
219bf215546Sopenharmony_ci         struct SVGAGuestPtr ptr;
220bf215546Sopenharmony_ci
221bf215546Sopenharmony_ci         if(!vmw_gmr_bufmgr_region_ptr(reloc->buffer, &ptr))
222bf215546Sopenharmony_ci            assert(0);
223bf215546Sopenharmony_ci
224bf215546Sopenharmony_ci         ptr.offset += reloc->offset;
225bf215546Sopenharmony_ci
226bf215546Sopenharmony_ci	 if (reloc->is_mob) {
227bf215546Sopenharmony_ci	    if (reloc->mob.id)
228bf215546Sopenharmony_ci	       *reloc->mob.id = ptr.gmrId;
229bf215546Sopenharmony_ci	    if (reloc->mob.offset_into_mob)
230bf215546Sopenharmony_ci	       *reloc->mob.offset_into_mob = ptr.offset;
231bf215546Sopenharmony_ci	    else {
232bf215546Sopenharmony_ci	       assert(ptr.offset == 0);
233bf215546Sopenharmony_ci	    }
234bf215546Sopenharmony_ci	 } else
235bf215546Sopenharmony_ci	    *reloc->region.where = ptr;
236bf215546Sopenharmony_ci      }
237bf215546Sopenharmony_ci
238bf215546Sopenharmony_ci      if (vswc->command.used || pfence != NULL)
239bf215546Sopenharmony_ci         vmw_ioctl_command(vws,
240bf215546Sopenharmony_ci                           vswc->base.cid,
241bf215546Sopenharmony_ci                           0,
242bf215546Sopenharmony_ci                           vswc->command.buffer,
243bf215546Sopenharmony_ci                           vswc->command.used,
244bf215546Sopenharmony_ci                           &fence,
245bf215546Sopenharmony_ci                           vswc->base.imported_fence_fd,
246bf215546Sopenharmony_ci                           vswc->base.hints);
247bf215546Sopenharmony_ci
248bf215546Sopenharmony_ci      pb_validate_fence(vswc->validate, fence);
249bf215546Sopenharmony_ci      mtx_lock(&vws->cs_mutex);
250bf215546Sopenharmony_ci      cnd_broadcast(&vws->cs_cond);
251bf215546Sopenharmony_ci      mtx_unlock(&vws->cs_mutex);
252bf215546Sopenharmony_ci   }
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_ci   vswc->command.used = 0;
255bf215546Sopenharmony_ci   vswc->command.reserved = 0;
256bf215546Sopenharmony_ci
257bf215546Sopenharmony_ci   for(i = 0; i < vswc->surface.used + vswc->surface.staged; ++i) {
258bf215546Sopenharmony_ci      struct vmw_ctx_validate_item *isurf = &vswc->surface.items[i];
259bf215546Sopenharmony_ci      if (isurf->referenced)
260bf215546Sopenharmony_ci         p_atomic_dec(&isurf->vsurf->validated);
261bf215546Sopenharmony_ci      vmw_svga_winsys_surface_reference(&isurf->vsurf, NULL);
262bf215546Sopenharmony_ci   }
263bf215546Sopenharmony_ci
264bf215546Sopenharmony_ci   _mesa_hash_table_clear(vswc->hash, NULL);
265bf215546Sopenharmony_ci   vswc->surface.used = 0;
266bf215546Sopenharmony_ci   vswc->surface.reserved = 0;
267bf215546Sopenharmony_ci
268bf215546Sopenharmony_ci   for(i = 0; i < vswc->shader.used + vswc->shader.staged; ++i) {
269bf215546Sopenharmony_ci      struct vmw_ctx_validate_item *ishader = &vswc->shader.items[i];
270bf215546Sopenharmony_ci      if (ishader->referenced)
271bf215546Sopenharmony_ci         p_atomic_dec(&ishader->vshader->validated);
272bf215546Sopenharmony_ci      vmw_svga_winsys_shader_reference(&ishader->vshader, NULL);
273bf215546Sopenharmony_ci   }
274bf215546Sopenharmony_ci
275bf215546Sopenharmony_ci   vswc->shader.used = 0;
276bf215546Sopenharmony_ci   vswc->shader.reserved = 0;
277bf215546Sopenharmony_ci
278bf215546Sopenharmony_ci   vswc->region.used = 0;
279bf215546Sopenharmony_ci   vswc->region.reserved = 0;
280bf215546Sopenharmony_ci
281bf215546Sopenharmony_ci#ifdef DEBUG
282bf215546Sopenharmony_ci   vswc->must_flush = FALSE;
283bf215546Sopenharmony_ci   debug_flush_flush(vswc->fctx);
284bf215546Sopenharmony_ci#endif
285bf215546Sopenharmony_ci   swc->hints &= ~SVGA_HINT_FLAG_CAN_PRE_FLUSH;
286bf215546Sopenharmony_ci   swc->hints &= ~SVGA_HINT_FLAG_EXPORT_FENCE_FD;
287bf215546Sopenharmony_ci   vswc->preemptive_flush = FALSE;
288bf215546Sopenharmony_ci   vswc->seen_surfaces = 0;
289bf215546Sopenharmony_ci   vswc->seen_regions = 0;
290bf215546Sopenharmony_ci   vswc->seen_mobs = 0;
291bf215546Sopenharmony_ci
292bf215546Sopenharmony_ci   if (vswc->base.imported_fence_fd != -1) {
293bf215546Sopenharmony_ci      close(vswc->base.imported_fence_fd);
294bf215546Sopenharmony_ci      vswc->base.imported_fence_fd = -1;
295bf215546Sopenharmony_ci   }
296bf215546Sopenharmony_ci
297bf215546Sopenharmony_ci   if(pfence)
298bf215546Sopenharmony_ci      vmw_fence_reference(vswc->vws, pfence, fence);
299bf215546Sopenharmony_ci
300bf215546Sopenharmony_ci   vmw_fence_reference(vswc->vws, &fence, NULL);
301bf215546Sopenharmony_ci
302bf215546Sopenharmony_ci   return ret;
303bf215546Sopenharmony_ci}
304bf215546Sopenharmony_ci
305bf215546Sopenharmony_ci
306bf215546Sopenharmony_cistatic void *
307bf215546Sopenharmony_civmw_swc_reserve(struct svga_winsys_context *swc,
308bf215546Sopenharmony_ci                uint32_t nr_bytes, uint32_t nr_relocs )
309bf215546Sopenharmony_ci{
310bf215546Sopenharmony_ci   struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
311bf215546Sopenharmony_ci
312bf215546Sopenharmony_ci#ifdef DEBUG
313bf215546Sopenharmony_ci   /* Check if somebody forgot to check the previous failure */
314bf215546Sopenharmony_ci   if(vswc->must_flush) {
315bf215546Sopenharmony_ci      debug_printf("Forgot to flush:\n");
316bf215546Sopenharmony_ci      debug_backtrace_dump(vswc->must_flush_stack, VMW_MUST_FLUSH_STACK);
317bf215546Sopenharmony_ci      assert(!vswc->must_flush);
318bf215546Sopenharmony_ci   }
319bf215546Sopenharmony_ci   debug_flush_might_flush(vswc->fctx);
320bf215546Sopenharmony_ci#endif
321bf215546Sopenharmony_ci
322bf215546Sopenharmony_ci   assert(nr_bytes <= vswc->command.size);
323bf215546Sopenharmony_ci   if(nr_bytes > vswc->command.size)
324bf215546Sopenharmony_ci      return NULL;
325bf215546Sopenharmony_ci
326bf215546Sopenharmony_ci   if(vswc->preemptive_flush ||
327bf215546Sopenharmony_ci      vswc->command.used + nr_bytes > vswc->command.size ||
328bf215546Sopenharmony_ci      vswc->surface.used + nr_relocs > vswc->surface.size ||
329bf215546Sopenharmony_ci      vswc->shader.used + nr_relocs > vswc->shader.size ||
330bf215546Sopenharmony_ci      vswc->region.used + nr_relocs > vswc->region.size) {
331bf215546Sopenharmony_ci#ifdef DEBUG
332bf215546Sopenharmony_ci      vswc->must_flush = TRUE;
333bf215546Sopenharmony_ci      debug_backtrace_capture(vswc->must_flush_stack, 1,
334bf215546Sopenharmony_ci                              VMW_MUST_FLUSH_STACK);
335bf215546Sopenharmony_ci#endif
336bf215546Sopenharmony_ci      return NULL;
337bf215546Sopenharmony_ci   }
338bf215546Sopenharmony_ci
339bf215546Sopenharmony_ci   assert(vswc->command.used + nr_bytes <= vswc->command.size);
340bf215546Sopenharmony_ci   assert(vswc->surface.used + nr_relocs <= vswc->surface.size);
341bf215546Sopenharmony_ci   assert(vswc->shader.used + nr_relocs <= vswc->shader.size);
342bf215546Sopenharmony_ci   assert(vswc->region.used + nr_relocs <= vswc->region.size);
343bf215546Sopenharmony_ci
344bf215546Sopenharmony_ci   vswc->command.reserved = nr_bytes;
345bf215546Sopenharmony_ci   vswc->surface.reserved = nr_relocs;
346bf215546Sopenharmony_ci   vswc->surface.staged = 0;
347bf215546Sopenharmony_ci   vswc->shader.reserved = nr_relocs;
348bf215546Sopenharmony_ci   vswc->shader.staged = 0;
349bf215546Sopenharmony_ci   vswc->region.reserved = nr_relocs;
350bf215546Sopenharmony_ci   vswc->region.staged = 0;
351bf215546Sopenharmony_ci
352bf215546Sopenharmony_ci   return vswc->command.buffer + vswc->command.used;
353bf215546Sopenharmony_ci}
354bf215546Sopenharmony_ci
355bf215546Sopenharmony_cistatic unsigned
356bf215546Sopenharmony_civmw_swc_get_command_buffer_size(struct svga_winsys_context *swc)
357bf215546Sopenharmony_ci{
358bf215546Sopenharmony_ci   const struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
359bf215546Sopenharmony_ci   return vswc->command.used;
360bf215546Sopenharmony_ci}
361bf215546Sopenharmony_ci
362bf215546Sopenharmony_cistatic void
363bf215546Sopenharmony_civmw_swc_context_relocation(struct svga_winsys_context *swc,
364bf215546Sopenharmony_ci			   uint32 *cid)
365bf215546Sopenharmony_ci{
366bf215546Sopenharmony_ci   *cid = swc->cid;
367bf215546Sopenharmony_ci}
368bf215546Sopenharmony_ci
369bf215546Sopenharmony_cistatic boolean
370bf215546Sopenharmony_civmw_swc_add_validate_buffer(struct vmw_svga_winsys_context *vswc,
371bf215546Sopenharmony_ci			    struct pb_buffer *pb_buf,
372bf215546Sopenharmony_ci			    unsigned flags)
373bf215546Sopenharmony_ci{
374bf215546Sopenharmony_ci   ASSERTED enum pipe_error ret;
375bf215546Sopenharmony_ci   unsigned translated_flags;
376bf215546Sopenharmony_ci   boolean already_present;
377bf215546Sopenharmony_ci
378bf215546Sopenharmony_ci   translated_flags = vmw_translate_to_pb_flags(flags);
379bf215546Sopenharmony_ci   ret = pb_validate_add_buffer(vswc->validate, pb_buf, translated_flags,
380bf215546Sopenharmony_ci                                vswc->hash, &already_present);
381bf215546Sopenharmony_ci   assert(ret == PIPE_OK);
382bf215546Sopenharmony_ci   return !already_present;
383bf215546Sopenharmony_ci}
384bf215546Sopenharmony_ci
385bf215546Sopenharmony_cistatic void
386bf215546Sopenharmony_civmw_swc_region_relocation(struct svga_winsys_context *swc,
387bf215546Sopenharmony_ci                          struct SVGAGuestPtr *where,
388bf215546Sopenharmony_ci                          struct svga_winsys_buffer *buffer,
389bf215546Sopenharmony_ci                          uint32 offset,
390bf215546Sopenharmony_ci                          unsigned flags)
391bf215546Sopenharmony_ci{
392bf215546Sopenharmony_ci   struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
393bf215546Sopenharmony_ci   struct vmw_buffer_relocation *reloc;
394bf215546Sopenharmony_ci
395bf215546Sopenharmony_ci   assert(vswc->region.staged < vswc->region.reserved);
396bf215546Sopenharmony_ci
397bf215546Sopenharmony_ci   reloc = &vswc->region.relocs[vswc->region.used + vswc->region.staged];
398bf215546Sopenharmony_ci   reloc->region.where = where;
399bf215546Sopenharmony_ci
400bf215546Sopenharmony_ci   /*
401bf215546Sopenharmony_ci    * pb_validate holds a refcount to the buffer, so no need to
402bf215546Sopenharmony_ci    * refcount it again in the relocation.
403bf215546Sopenharmony_ci    */
404bf215546Sopenharmony_ci   reloc->buffer = vmw_pb_buffer(buffer);
405bf215546Sopenharmony_ci   reloc->offset = offset;
406bf215546Sopenharmony_ci   reloc->is_mob = FALSE;
407bf215546Sopenharmony_ci   ++vswc->region.staged;
408bf215546Sopenharmony_ci
409bf215546Sopenharmony_ci   if (vmw_swc_add_validate_buffer(vswc, reloc->buffer, flags)) {
410bf215546Sopenharmony_ci      vswc->seen_regions += reloc->buffer->size;
411bf215546Sopenharmony_ci      if ((swc->hints & SVGA_HINT_FLAG_CAN_PRE_FLUSH) &&
412bf215546Sopenharmony_ci          vswc->seen_regions >= VMW_GMR_POOL_SIZE/5)
413bf215546Sopenharmony_ci         vswc->preemptive_flush = TRUE;
414bf215546Sopenharmony_ci   }
415bf215546Sopenharmony_ci
416bf215546Sopenharmony_ci#ifdef DEBUG
417bf215546Sopenharmony_ci   if (!(flags & SVGA_RELOC_INTERNAL))
418bf215546Sopenharmony_ci      debug_flush_cb_reference(vswc->fctx, vmw_debug_flush_buf(buffer));
419bf215546Sopenharmony_ci#endif
420bf215546Sopenharmony_ci}
421bf215546Sopenharmony_ci
422bf215546Sopenharmony_cistatic void
423bf215546Sopenharmony_civmw_swc_mob_relocation(struct svga_winsys_context *swc,
424bf215546Sopenharmony_ci		       SVGAMobId *id,
425bf215546Sopenharmony_ci		       uint32 *offset_into_mob,
426bf215546Sopenharmony_ci		       struct svga_winsys_buffer *buffer,
427bf215546Sopenharmony_ci		       uint32 offset,
428bf215546Sopenharmony_ci		       unsigned flags)
429bf215546Sopenharmony_ci{
430bf215546Sopenharmony_ci   struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
431bf215546Sopenharmony_ci   struct vmw_buffer_relocation *reloc;
432bf215546Sopenharmony_ci   struct pb_buffer *pb_buffer = vmw_pb_buffer(buffer);
433bf215546Sopenharmony_ci
434bf215546Sopenharmony_ci   if (id) {
435bf215546Sopenharmony_ci      assert(vswc->region.staged < vswc->region.reserved);
436bf215546Sopenharmony_ci
437bf215546Sopenharmony_ci      reloc = &vswc->region.relocs[vswc->region.used + vswc->region.staged];
438bf215546Sopenharmony_ci      reloc->mob.id = id;
439bf215546Sopenharmony_ci      reloc->mob.offset_into_mob = offset_into_mob;
440bf215546Sopenharmony_ci
441bf215546Sopenharmony_ci      /*
442bf215546Sopenharmony_ci       * pb_validate holds a refcount to the buffer, so no need to
443bf215546Sopenharmony_ci       * refcount it again in the relocation.
444bf215546Sopenharmony_ci       */
445bf215546Sopenharmony_ci      reloc->buffer = pb_buffer;
446bf215546Sopenharmony_ci      reloc->offset = offset;
447bf215546Sopenharmony_ci      reloc->is_mob = TRUE;
448bf215546Sopenharmony_ci      ++vswc->region.staged;
449bf215546Sopenharmony_ci   }
450bf215546Sopenharmony_ci
451bf215546Sopenharmony_ci   if (vmw_swc_add_validate_buffer(vswc, pb_buffer, flags)) {
452bf215546Sopenharmony_ci      vswc->seen_mobs += pb_buffer->size;
453bf215546Sopenharmony_ci
454bf215546Sopenharmony_ci      if ((swc->hints & SVGA_HINT_FLAG_CAN_PRE_FLUSH) &&
455bf215546Sopenharmony_ci          vswc->seen_mobs >=
456bf215546Sopenharmony_ci            vswc->vws->ioctl.max_mob_memory / VMW_MAX_MOB_MEM_FACTOR)
457bf215546Sopenharmony_ci         vswc->preemptive_flush = TRUE;
458bf215546Sopenharmony_ci   }
459bf215546Sopenharmony_ci
460bf215546Sopenharmony_ci#ifdef DEBUG
461bf215546Sopenharmony_ci   if (!(flags & SVGA_RELOC_INTERNAL))
462bf215546Sopenharmony_ci      debug_flush_cb_reference(vswc->fctx, vmw_debug_flush_buf(buffer));
463bf215546Sopenharmony_ci#endif
464bf215546Sopenharmony_ci}
465bf215546Sopenharmony_ci
466bf215546Sopenharmony_ci
467bf215546Sopenharmony_ci/**
468bf215546Sopenharmony_ci * vmw_swc_surface_clear_reference - Clear referenced info for a surface
469bf215546Sopenharmony_ci *
470bf215546Sopenharmony_ci * @swc:   Pointer to an svga_winsys_context
471bf215546Sopenharmony_ci * @vsurf: Pointer to a vmw_svga_winsys_surface, the referenced info of which
472bf215546Sopenharmony_ci *         we want to clear
473bf215546Sopenharmony_ci *
474bf215546Sopenharmony_ci * This is primarily used by a discard surface map to indicate that the
475bf215546Sopenharmony_ci * surface data is no longer referenced by a draw call, and mapping it
476bf215546Sopenharmony_ci * should therefore no longer cause a flush.
477bf215546Sopenharmony_ci */
478bf215546Sopenharmony_civoid
479bf215546Sopenharmony_civmw_swc_surface_clear_reference(struct svga_winsys_context *swc,
480bf215546Sopenharmony_ci                                struct vmw_svga_winsys_surface *vsurf)
481bf215546Sopenharmony_ci{
482bf215546Sopenharmony_ci   struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
483bf215546Sopenharmony_ci   struct vmw_ctx_validate_item *isrf =
484bf215546Sopenharmony_ci      util_hash_table_get(vswc->hash, vsurf);
485bf215546Sopenharmony_ci
486bf215546Sopenharmony_ci   if (isrf && isrf->referenced) {
487bf215546Sopenharmony_ci      isrf->referenced = FALSE;
488bf215546Sopenharmony_ci      p_atomic_dec(&vsurf->validated);
489bf215546Sopenharmony_ci   }
490bf215546Sopenharmony_ci}
491bf215546Sopenharmony_ci
492bf215546Sopenharmony_cistatic void
493bf215546Sopenharmony_civmw_swc_surface_only_relocation(struct svga_winsys_context *swc,
494bf215546Sopenharmony_ci				uint32 *where,
495bf215546Sopenharmony_ci				struct vmw_svga_winsys_surface *vsurf,
496bf215546Sopenharmony_ci				unsigned flags)
497bf215546Sopenharmony_ci{
498bf215546Sopenharmony_ci   struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
499bf215546Sopenharmony_ci   struct vmw_ctx_validate_item *isrf;
500bf215546Sopenharmony_ci
501bf215546Sopenharmony_ci   assert(vswc->surface.staged < vswc->surface.reserved);
502bf215546Sopenharmony_ci   isrf = util_hash_table_get(vswc->hash, vsurf);
503bf215546Sopenharmony_ci
504bf215546Sopenharmony_ci   if (isrf == NULL) {
505bf215546Sopenharmony_ci      isrf = &vswc->surface.items[vswc->surface.used + vswc->surface.staged];
506bf215546Sopenharmony_ci      vmw_svga_winsys_surface_reference(&isrf->vsurf, vsurf);
507bf215546Sopenharmony_ci      isrf->referenced = FALSE;
508bf215546Sopenharmony_ci
509bf215546Sopenharmony_ci      _mesa_hash_table_insert(vswc->hash, vsurf, isrf);
510bf215546Sopenharmony_ci      ++vswc->surface.staged;
511bf215546Sopenharmony_ci
512bf215546Sopenharmony_ci      vswc->seen_surfaces += vsurf->size;
513bf215546Sopenharmony_ci      if ((swc->hints & SVGA_HINT_FLAG_CAN_PRE_FLUSH) &&
514bf215546Sopenharmony_ci          vswc->seen_surfaces >=
515bf215546Sopenharmony_ci            vswc->vws->ioctl.max_surface_memory / VMW_MAX_SURF_MEM_FACTOR)
516bf215546Sopenharmony_ci         vswc->preemptive_flush = TRUE;
517bf215546Sopenharmony_ci   }
518bf215546Sopenharmony_ci
519bf215546Sopenharmony_ci   if (!(flags & SVGA_RELOC_INTERNAL) && !isrf->referenced) {
520bf215546Sopenharmony_ci      isrf->referenced = TRUE;
521bf215546Sopenharmony_ci      p_atomic_inc(&vsurf->validated);
522bf215546Sopenharmony_ci   }
523bf215546Sopenharmony_ci
524bf215546Sopenharmony_ci   if (where)
525bf215546Sopenharmony_ci      *where = vsurf->sid;
526bf215546Sopenharmony_ci}
527bf215546Sopenharmony_ci
528bf215546Sopenharmony_cistatic void
529bf215546Sopenharmony_civmw_swc_surface_relocation(struct svga_winsys_context *swc,
530bf215546Sopenharmony_ci                           uint32 *where,
531bf215546Sopenharmony_ci                           uint32 *mobid,
532bf215546Sopenharmony_ci                           struct svga_winsys_surface *surface,
533bf215546Sopenharmony_ci                           unsigned flags)
534bf215546Sopenharmony_ci{
535bf215546Sopenharmony_ci   struct vmw_svga_winsys_surface *vsurf;
536bf215546Sopenharmony_ci
537bf215546Sopenharmony_ci   assert(swc->have_gb_objects || mobid == NULL);
538bf215546Sopenharmony_ci
539bf215546Sopenharmony_ci   if (!surface) {
540bf215546Sopenharmony_ci      *where = SVGA3D_INVALID_ID;
541bf215546Sopenharmony_ci      if (mobid)
542bf215546Sopenharmony_ci         *mobid = SVGA3D_INVALID_ID;
543bf215546Sopenharmony_ci      return;
544bf215546Sopenharmony_ci   }
545bf215546Sopenharmony_ci
546bf215546Sopenharmony_ci   vsurf = vmw_svga_winsys_surface(surface);
547bf215546Sopenharmony_ci   vmw_swc_surface_only_relocation(swc, where, vsurf, flags);
548bf215546Sopenharmony_ci
549bf215546Sopenharmony_ci   if (swc->have_gb_objects && vsurf->buf != NULL) {
550bf215546Sopenharmony_ci
551bf215546Sopenharmony_ci      /*
552bf215546Sopenharmony_ci       * Make sure backup buffer ends up fenced.
553bf215546Sopenharmony_ci       */
554bf215546Sopenharmony_ci
555bf215546Sopenharmony_ci      mtx_lock(&vsurf->mutex);
556bf215546Sopenharmony_ci      assert(vsurf->buf != NULL);
557bf215546Sopenharmony_ci
558bf215546Sopenharmony_ci      /*
559bf215546Sopenharmony_ci       * An internal reloc means that the surface transfer direction
560bf215546Sopenharmony_ci       * is opposite to the MOB transfer direction...
561bf215546Sopenharmony_ci       */
562bf215546Sopenharmony_ci      if ((flags & SVGA_RELOC_INTERNAL) &&
563bf215546Sopenharmony_ci          (flags & (SVGA_RELOC_READ | SVGA_RELOC_WRITE)) !=
564bf215546Sopenharmony_ci          (SVGA_RELOC_READ | SVGA_RELOC_WRITE))
565bf215546Sopenharmony_ci         flags ^= (SVGA_RELOC_READ | SVGA_RELOC_WRITE);
566bf215546Sopenharmony_ci      vmw_swc_mob_relocation(swc, mobid, NULL, (struct svga_winsys_buffer *)
567bf215546Sopenharmony_ci                             vsurf->buf, 0, flags);
568bf215546Sopenharmony_ci      mtx_unlock(&vsurf->mutex);
569bf215546Sopenharmony_ci   }
570bf215546Sopenharmony_ci}
571bf215546Sopenharmony_ci
572bf215546Sopenharmony_cistatic void
573bf215546Sopenharmony_civmw_swc_shader_relocation(struct svga_winsys_context *swc,
574bf215546Sopenharmony_ci			  uint32 *shid,
575bf215546Sopenharmony_ci			  uint32 *mobid,
576bf215546Sopenharmony_ci			  uint32 *offset,
577bf215546Sopenharmony_ci			  struct svga_winsys_gb_shader *shader,
578bf215546Sopenharmony_ci                          unsigned flags)
579bf215546Sopenharmony_ci{
580bf215546Sopenharmony_ci   struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
581bf215546Sopenharmony_ci   struct vmw_winsys_screen *vws = vswc->vws;
582bf215546Sopenharmony_ci   struct vmw_svga_winsys_shader *vshader;
583bf215546Sopenharmony_ci   struct vmw_ctx_validate_item *ishader;
584bf215546Sopenharmony_ci
585bf215546Sopenharmony_ci   if(!shader) {
586bf215546Sopenharmony_ci      *shid = SVGA3D_INVALID_ID;
587bf215546Sopenharmony_ci      return;
588bf215546Sopenharmony_ci   }
589bf215546Sopenharmony_ci
590bf215546Sopenharmony_ci   vshader = vmw_svga_winsys_shader(shader);
591bf215546Sopenharmony_ci
592bf215546Sopenharmony_ci   if (!vws->base.have_vgpu10) {
593bf215546Sopenharmony_ci      assert(vswc->shader.staged < vswc->shader.reserved);
594bf215546Sopenharmony_ci      ishader = util_hash_table_get(vswc->hash, vshader);
595bf215546Sopenharmony_ci
596bf215546Sopenharmony_ci      if (ishader == NULL) {
597bf215546Sopenharmony_ci         ishader = &vswc->shader.items[vswc->shader.used + vswc->shader.staged];
598bf215546Sopenharmony_ci         vmw_svga_winsys_shader_reference(&ishader->vshader, vshader);
599bf215546Sopenharmony_ci         ishader->referenced = FALSE;
600bf215546Sopenharmony_ci
601bf215546Sopenharmony_ci         _mesa_hash_table_insert(vswc->hash, vshader, ishader);
602bf215546Sopenharmony_ci         ++vswc->shader.staged;
603bf215546Sopenharmony_ci      }
604bf215546Sopenharmony_ci
605bf215546Sopenharmony_ci      if (!ishader->referenced) {
606bf215546Sopenharmony_ci         ishader->referenced = TRUE;
607bf215546Sopenharmony_ci         p_atomic_inc(&vshader->validated);
608bf215546Sopenharmony_ci      }
609bf215546Sopenharmony_ci   }
610bf215546Sopenharmony_ci
611bf215546Sopenharmony_ci   if (shid)
612bf215546Sopenharmony_ci      *shid = vshader->shid;
613bf215546Sopenharmony_ci
614bf215546Sopenharmony_ci   if (vshader->buf)
615bf215546Sopenharmony_ci      vmw_swc_mob_relocation(swc, mobid, offset, vshader->buf,
616bf215546Sopenharmony_ci			     0, SVGA_RELOC_READ);
617bf215546Sopenharmony_ci}
618bf215546Sopenharmony_ci
619bf215546Sopenharmony_cistatic void
620bf215546Sopenharmony_civmw_swc_query_relocation(struct svga_winsys_context *swc,
621bf215546Sopenharmony_ci                         SVGAMobId *id,
622bf215546Sopenharmony_ci                         struct svga_winsys_gb_query *query)
623bf215546Sopenharmony_ci{
624bf215546Sopenharmony_ci   /* Queries are backed by one big MOB */
625bf215546Sopenharmony_ci   vmw_swc_mob_relocation(swc, id, NULL, query->buf, 0,
626bf215546Sopenharmony_ci                          SVGA_RELOC_READ | SVGA_RELOC_WRITE);
627bf215546Sopenharmony_ci}
628bf215546Sopenharmony_ci
629bf215546Sopenharmony_cistatic void
630bf215546Sopenharmony_civmw_swc_commit(struct svga_winsys_context *swc)
631bf215546Sopenharmony_ci{
632bf215546Sopenharmony_ci   struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
633bf215546Sopenharmony_ci
634bf215546Sopenharmony_ci   assert(vswc->command.used + vswc->command.reserved <= vswc->command.size);
635bf215546Sopenharmony_ci   vswc->command.used += vswc->command.reserved;
636bf215546Sopenharmony_ci   vswc->command.reserved = 0;
637bf215546Sopenharmony_ci
638bf215546Sopenharmony_ci   assert(vswc->surface.staged <= vswc->surface.reserved);
639bf215546Sopenharmony_ci   assert(vswc->surface.used + vswc->surface.staged <= vswc->surface.size);
640bf215546Sopenharmony_ci   vswc->surface.used += vswc->surface.staged;
641bf215546Sopenharmony_ci   vswc->surface.staged = 0;
642bf215546Sopenharmony_ci   vswc->surface.reserved = 0;
643bf215546Sopenharmony_ci
644bf215546Sopenharmony_ci   assert(vswc->shader.staged <= vswc->shader.reserved);
645bf215546Sopenharmony_ci   assert(vswc->shader.used + vswc->shader.staged <= vswc->shader.size);
646bf215546Sopenharmony_ci   vswc->shader.used += vswc->shader.staged;
647bf215546Sopenharmony_ci   vswc->shader.staged = 0;
648bf215546Sopenharmony_ci   vswc->shader.reserved = 0;
649bf215546Sopenharmony_ci
650bf215546Sopenharmony_ci   assert(vswc->region.staged <= vswc->region.reserved);
651bf215546Sopenharmony_ci   assert(vswc->region.used + vswc->region.staged <= vswc->region.size);
652bf215546Sopenharmony_ci   vswc->region.used += vswc->region.staged;
653bf215546Sopenharmony_ci   vswc->region.staged = 0;
654bf215546Sopenharmony_ci   vswc->region.reserved = 0;
655bf215546Sopenharmony_ci}
656bf215546Sopenharmony_ci
657bf215546Sopenharmony_ci
658bf215546Sopenharmony_cistatic void
659bf215546Sopenharmony_civmw_swc_destroy(struct svga_winsys_context *swc)
660bf215546Sopenharmony_ci{
661bf215546Sopenharmony_ci   struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
662bf215546Sopenharmony_ci   unsigned i;
663bf215546Sopenharmony_ci
664bf215546Sopenharmony_ci   for(i = 0; i < vswc->surface.used; ++i) {
665bf215546Sopenharmony_ci      struct vmw_ctx_validate_item *isurf = &vswc->surface.items[i];
666bf215546Sopenharmony_ci      if (isurf->referenced)
667bf215546Sopenharmony_ci         p_atomic_dec(&isurf->vsurf->validated);
668bf215546Sopenharmony_ci      vmw_svga_winsys_surface_reference(&isurf->vsurf, NULL);
669bf215546Sopenharmony_ci   }
670bf215546Sopenharmony_ci
671bf215546Sopenharmony_ci   for(i = 0; i < vswc->shader.used; ++i) {
672bf215546Sopenharmony_ci      struct vmw_ctx_validate_item *ishader = &vswc->shader.items[i];
673bf215546Sopenharmony_ci      if (ishader->referenced)
674bf215546Sopenharmony_ci         p_atomic_dec(&ishader->vshader->validated);
675bf215546Sopenharmony_ci      vmw_svga_winsys_shader_reference(&ishader->vshader, NULL);
676bf215546Sopenharmony_ci   }
677bf215546Sopenharmony_ci
678bf215546Sopenharmony_ci   _mesa_hash_table_destroy(vswc->hash, NULL);
679bf215546Sopenharmony_ci   pb_validate_destroy(vswc->validate);
680bf215546Sopenharmony_ci   vmw_ioctl_context_destroy(vswc->vws, swc->cid);
681bf215546Sopenharmony_ci#ifdef DEBUG
682bf215546Sopenharmony_ci   debug_flush_ctx_destroy(vswc->fctx);
683bf215546Sopenharmony_ci#endif
684bf215546Sopenharmony_ci   FREE(vswc);
685bf215546Sopenharmony_ci}
686bf215546Sopenharmony_ci
687bf215546Sopenharmony_ci/**
688bf215546Sopenharmony_ci * vmw_svga_winsys_vgpu10_shader_screate - The winsys shader_crate callback
689bf215546Sopenharmony_ci *
690bf215546Sopenharmony_ci * @swc: The winsys context.
691bf215546Sopenharmony_ci * @shaderId: Previously allocated shader id.
692bf215546Sopenharmony_ci * @shaderType: The shader type.
693bf215546Sopenharmony_ci * @bytecode: The shader bytecode
694bf215546Sopenharmony_ci * @bytecodelen: The length of the bytecode.
695bf215546Sopenharmony_ci *
696bf215546Sopenharmony_ci * Creates an svga_winsys_gb_shader structure and allocates a buffer for the
697bf215546Sopenharmony_ci * shader code and copies the shader code into the buffer. Shader
698bf215546Sopenharmony_ci * resource creation is not done.
699bf215546Sopenharmony_ci */
700bf215546Sopenharmony_cistatic struct svga_winsys_gb_shader *
701bf215546Sopenharmony_civmw_svga_winsys_vgpu10_shader_create(struct svga_winsys_context *swc,
702bf215546Sopenharmony_ci                                     uint32 shaderId,
703bf215546Sopenharmony_ci                                     SVGA3dShaderType shaderType,
704bf215546Sopenharmony_ci                                     const uint32 *bytecode,
705bf215546Sopenharmony_ci                                     uint32 bytecodeLen,
706bf215546Sopenharmony_ci                                     const SVGA3dDXShaderSignatureHeader *sgnInfo,
707bf215546Sopenharmony_ci                                     uint32 sgnLen)
708bf215546Sopenharmony_ci{
709bf215546Sopenharmony_ci   struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
710bf215546Sopenharmony_ci   struct vmw_svga_winsys_shader *shader;
711bf215546Sopenharmony_ci   shader = vmw_svga_shader_create(&vswc->vws->base, shaderType, bytecode,
712bf215546Sopenharmony_ci                                   bytecodeLen, sgnInfo, sgnLen);
713bf215546Sopenharmony_ci   if (!shader)
714bf215546Sopenharmony_ci      return NULL;
715bf215546Sopenharmony_ci
716bf215546Sopenharmony_ci   shader->shid = shaderId;
717bf215546Sopenharmony_ci   return svga_winsys_shader(shader);
718bf215546Sopenharmony_ci}
719bf215546Sopenharmony_ci
720bf215546Sopenharmony_ci/**
721bf215546Sopenharmony_ci * vmw_svga_winsys_vgpu10_shader_destroy - The winsys shader_destroy callback.
722bf215546Sopenharmony_ci *
723bf215546Sopenharmony_ci * @swc: The winsys context.
724bf215546Sopenharmony_ci * @shader: A shader structure previously allocated by shader_create.
725bf215546Sopenharmony_ci *
726bf215546Sopenharmony_ci * Frees the shader structure and the buffer holding the shader code.
727bf215546Sopenharmony_ci */
728bf215546Sopenharmony_cistatic void
729bf215546Sopenharmony_civmw_svga_winsys_vgpu10_shader_destroy(struct svga_winsys_context *swc,
730bf215546Sopenharmony_ci                                      struct svga_winsys_gb_shader *shader)
731bf215546Sopenharmony_ci{
732bf215546Sopenharmony_ci   struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
733bf215546Sopenharmony_ci
734bf215546Sopenharmony_ci   vmw_svga_winsys_shader_destroy(&vswc->vws->base, shader);
735bf215546Sopenharmony_ci}
736bf215546Sopenharmony_ci
737bf215546Sopenharmony_ci/**
738bf215546Sopenharmony_ci * vmw_svga_winsys_resource_rebind - The winsys resource_rebind callback
739bf215546Sopenharmony_ci *
740bf215546Sopenharmony_ci * @swc: The winsys context.
741bf215546Sopenharmony_ci * @surface: The surface to be referenced.
742bf215546Sopenharmony_ci * @shader: The shader to be referenced.
743bf215546Sopenharmony_ci * @flags: Relocation flags.
744bf215546Sopenharmony_ci *
745bf215546Sopenharmony_ci * This callback is needed because shader backing buffers are sub-allocated, and
746bf215546Sopenharmony_ci * hence the kernel fencing is not sufficient. The buffers need to be put on
747bf215546Sopenharmony_ci * the context's validation list and fenced after command submission to avoid
748bf215546Sopenharmony_ci * reuse of busy shader buffers. In addition, surfaces need to be put on the
749bf215546Sopenharmony_ci * validation list in order for the driver to regard them as referenced
750bf215546Sopenharmony_ci * by the command stream.
751bf215546Sopenharmony_ci */
752bf215546Sopenharmony_cistatic enum pipe_error
753bf215546Sopenharmony_civmw_svga_winsys_resource_rebind(struct svga_winsys_context *swc,
754bf215546Sopenharmony_ci                                struct svga_winsys_surface *surface,
755bf215546Sopenharmony_ci                                struct svga_winsys_gb_shader *shader,
756bf215546Sopenharmony_ci                                unsigned flags)
757bf215546Sopenharmony_ci{
758bf215546Sopenharmony_ci   /**
759bf215546Sopenharmony_ci    * Need to reserve one validation item for either the surface or
760bf215546Sopenharmony_ci    * the shader.
761bf215546Sopenharmony_ci    */
762bf215546Sopenharmony_ci   if (!vmw_swc_reserve(swc, 0, 1))
763bf215546Sopenharmony_ci      return PIPE_ERROR_OUT_OF_MEMORY;
764bf215546Sopenharmony_ci
765bf215546Sopenharmony_ci   if (surface)
766bf215546Sopenharmony_ci      vmw_swc_surface_relocation(swc, NULL, NULL, surface, flags);
767bf215546Sopenharmony_ci   else if (shader)
768bf215546Sopenharmony_ci      vmw_swc_shader_relocation(swc, NULL, NULL, NULL, shader, flags);
769bf215546Sopenharmony_ci
770bf215546Sopenharmony_ci   vmw_swc_commit(swc);
771bf215546Sopenharmony_ci
772bf215546Sopenharmony_ci   return PIPE_OK;
773bf215546Sopenharmony_ci}
774bf215546Sopenharmony_ci
775bf215546Sopenharmony_cistruct svga_winsys_context *
776bf215546Sopenharmony_civmw_svga_winsys_context_create(struct svga_winsys_screen *sws)
777bf215546Sopenharmony_ci{
778bf215546Sopenharmony_ci   struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
779bf215546Sopenharmony_ci   struct vmw_svga_winsys_context *vswc;
780bf215546Sopenharmony_ci
781bf215546Sopenharmony_ci   vswc = CALLOC_STRUCT(vmw_svga_winsys_context);
782bf215546Sopenharmony_ci   if(!vswc)
783bf215546Sopenharmony_ci      return NULL;
784bf215546Sopenharmony_ci
785bf215546Sopenharmony_ci   vswc->base.destroy = vmw_swc_destroy;
786bf215546Sopenharmony_ci   vswc->base.reserve = vmw_swc_reserve;
787bf215546Sopenharmony_ci   vswc->base.get_command_buffer_size = vmw_swc_get_command_buffer_size;
788bf215546Sopenharmony_ci   vswc->base.surface_relocation = vmw_swc_surface_relocation;
789bf215546Sopenharmony_ci   vswc->base.region_relocation = vmw_swc_region_relocation;
790bf215546Sopenharmony_ci   vswc->base.mob_relocation = vmw_swc_mob_relocation;
791bf215546Sopenharmony_ci   vswc->base.query_relocation = vmw_swc_query_relocation;
792bf215546Sopenharmony_ci   vswc->base.query_bind = vmw_swc_query_bind;
793bf215546Sopenharmony_ci   vswc->base.context_relocation = vmw_swc_context_relocation;
794bf215546Sopenharmony_ci   vswc->base.shader_relocation = vmw_swc_shader_relocation;
795bf215546Sopenharmony_ci   vswc->base.commit = vmw_swc_commit;
796bf215546Sopenharmony_ci   vswc->base.flush = vmw_swc_flush;
797bf215546Sopenharmony_ci   vswc->base.surface_map = vmw_svga_winsys_surface_map;
798bf215546Sopenharmony_ci   vswc->base.surface_unmap = vmw_svga_winsys_surface_unmap;
799bf215546Sopenharmony_ci
800bf215546Sopenharmony_ci   vswc->base.shader_create = vmw_svga_winsys_vgpu10_shader_create;
801bf215546Sopenharmony_ci   vswc->base.shader_destroy = vmw_svga_winsys_vgpu10_shader_destroy;
802bf215546Sopenharmony_ci
803bf215546Sopenharmony_ci   vswc->base.resource_rebind = vmw_svga_winsys_resource_rebind;
804bf215546Sopenharmony_ci
805bf215546Sopenharmony_ci   if (sws->have_vgpu10)
806bf215546Sopenharmony_ci      vswc->base.cid = vmw_ioctl_extended_context_create(vws, sws->have_vgpu10);
807bf215546Sopenharmony_ci   else
808bf215546Sopenharmony_ci      vswc->base.cid = vmw_ioctl_context_create(vws);
809bf215546Sopenharmony_ci
810bf215546Sopenharmony_ci   if (vswc->base.cid == -1)
811bf215546Sopenharmony_ci      goto out_no_context;
812bf215546Sopenharmony_ci
813bf215546Sopenharmony_ci   vswc->base.imported_fence_fd = -1;
814bf215546Sopenharmony_ci
815bf215546Sopenharmony_ci   vswc->base.have_gb_objects = sws->have_gb_objects;
816bf215546Sopenharmony_ci
817bf215546Sopenharmony_ci   vswc->vws = vws;
818bf215546Sopenharmony_ci
819bf215546Sopenharmony_ci   vswc->command.size = VMW_COMMAND_SIZE;
820bf215546Sopenharmony_ci   vswc->surface.size = VMW_SURFACE_RELOCS;
821bf215546Sopenharmony_ci   vswc->shader.size = VMW_SHADER_RELOCS;
822bf215546Sopenharmony_ci   vswc->region.size = VMW_REGION_RELOCS;
823bf215546Sopenharmony_ci
824bf215546Sopenharmony_ci   vswc->validate = pb_validate_create();
825bf215546Sopenharmony_ci   if(!vswc->validate)
826bf215546Sopenharmony_ci      goto out_no_validate;
827bf215546Sopenharmony_ci
828bf215546Sopenharmony_ci   vswc->hash = util_hash_table_create_ptr_keys();
829bf215546Sopenharmony_ci   if (!vswc->hash)
830bf215546Sopenharmony_ci      goto out_no_hash;
831bf215546Sopenharmony_ci
832bf215546Sopenharmony_ci#ifdef DEBUG
833bf215546Sopenharmony_ci   vswc->fctx = debug_flush_ctx_create(TRUE, VMW_DEBUG_FLUSH_STACK);
834bf215546Sopenharmony_ci#endif
835bf215546Sopenharmony_ci
836bf215546Sopenharmony_ci   vswc->base.force_coherent = vws->force_coherent;
837bf215546Sopenharmony_ci   return &vswc->base;
838bf215546Sopenharmony_ci
839bf215546Sopenharmony_ciout_no_hash:
840bf215546Sopenharmony_ci   pb_validate_destroy(vswc->validate);
841bf215546Sopenharmony_ciout_no_validate:
842bf215546Sopenharmony_ci   vmw_ioctl_context_destroy(vws, vswc->base.cid);
843bf215546Sopenharmony_ciout_no_context:
844bf215546Sopenharmony_ci   FREE(vswc);
845bf215546Sopenharmony_ci   return NULL;
846bf215546Sopenharmony_ci}
847