1848b8605Smrg/**********************************************************
2848b8605Smrg * Copyright 2008-2009 VMware, Inc.  All rights reserved.
3848b8605Smrg *
4848b8605Smrg * Permission is hereby granted, free of charge, to any person
5848b8605Smrg * obtaining a copy of this software and associated documentation
6848b8605Smrg * files (the "Software"), to deal in the Software without
7848b8605Smrg * restriction, including without limitation the rights to use, copy,
8848b8605Smrg * modify, merge, publish, distribute, sublicense, and/or sell copies
9848b8605Smrg * of the Software, and to permit persons to whom the Software is
10848b8605Smrg * furnished to do so, subject to the following conditions:
11848b8605Smrg *
12848b8605Smrg * The above copyright notice and this permission notice shall be
13848b8605Smrg * included in all copies or substantial portions of the Software.
14848b8605Smrg *
15848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16848b8605Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18848b8605Smrg * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19848b8605Smrg * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20848b8605Smrg * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21848b8605Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22848b8605Smrg * SOFTWARE.
23848b8605Smrg *
24848b8605Smrg **********************************************************/
25848b8605Smrg
26848b8605Smrg#include "pipe/p_compiler.h"
27848b8605Smrg#include "util/u_inlines.h"
28848b8605Smrg#include "pipe/p_defines.h"
29b8e80941Smrg#include "util/u_helpers.h"
30848b8605Smrg#include "util/u_memory.h"
31848b8605Smrg#include "util/u_math.h"
32848b8605Smrg
33848b8605Smrg#include "svga_context.h"
34848b8605Smrg#include "svga_draw.h"
35848b8605Smrg#include "svga_draw_private.h"
36848b8605Smrg#include "svga_debug.h"
37848b8605Smrg#include "svga_screen.h"
38b8e80941Smrg#include "svga_resource.h"
39848b8605Smrg#include "svga_resource_buffer.h"
40848b8605Smrg#include "svga_resource_texture.h"
41b8e80941Smrg#include "svga_sampler_view.h"
42b8e80941Smrg#include "svga_shader.h"
43848b8605Smrg#include "svga_surface.h"
44848b8605Smrg#include "svga_winsys.h"
45848b8605Smrg#include "svga_cmd.h"
46848b8605Smrg
47848b8605Smrg
48848b8605Smrgstruct svga_hwtnl *
49848b8605Smrgsvga_hwtnl_create(struct svga_context *svga)
50848b8605Smrg{
51848b8605Smrg   struct svga_hwtnl *hwtnl = CALLOC_STRUCT(svga_hwtnl);
52b8e80941Smrg   if (!hwtnl)
53848b8605Smrg      goto fail;
54848b8605Smrg
55848b8605Smrg   hwtnl->svga = svga;
56848b8605Smrg
57848b8605Smrg   hwtnl->cmd.swc = svga->swc;
58848b8605Smrg
59848b8605Smrg   return hwtnl;
60848b8605Smrg
61848b8605Smrgfail:
62848b8605Smrg   return NULL;
63848b8605Smrg}
64848b8605Smrg
65848b8605Smrg
66848b8605Smrgvoid
67848b8605Smrgsvga_hwtnl_destroy(struct svga_hwtnl *hwtnl)
68848b8605Smrg{
69848b8605Smrg   unsigned i, j;
70848b8605Smrg
71848b8605Smrg   for (i = 0; i < PIPE_PRIM_MAX; i++) {
72848b8605Smrg      for (j = 0; j < IDX_CACHE_MAX; j++) {
73848b8605Smrg         pipe_resource_reference(&hwtnl->index_cache[i][j].buffer, NULL);
74848b8605Smrg      }
75848b8605Smrg   }
76848b8605Smrg
77b8e80941Smrg   for (i = 0; i < hwtnl->cmd.vbuf_count; i++)
78b8e80941Smrg      pipe_vertex_buffer_unreference(&hwtnl->cmd.vbufs[i]);
79848b8605Smrg
80848b8605Smrg   for (i = 0; i < hwtnl->cmd.prim_count; i++)
81848b8605Smrg      pipe_resource_reference(&hwtnl->cmd.prim_ib[i], NULL);
82848b8605Smrg
83848b8605Smrg   FREE(hwtnl);
84848b8605Smrg}
85848b8605Smrg
86848b8605Smrg
87848b8605Smrgvoid
88848b8605Smrgsvga_hwtnl_set_flatshade(struct svga_hwtnl *hwtnl,
89848b8605Smrg                         boolean flatshade, boolean flatshade_first)
90848b8605Smrg{
91b8e80941Smrg   struct svga_screen *svgascreen = svga_screen(hwtnl->svga->pipe.screen);
92b8e80941Smrg
93b8e80941Smrg   /* User-specified PV */
94848b8605Smrg   hwtnl->api_pv = (flatshade && !flatshade_first) ? PV_LAST : PV_FIRST;
95b8e80941Smrg
96b8e80941Smrg   /* Device supported PV */
97b8e80941Smrg   if (svgascreen->haveProvokingVertex) {
98b8e80941Smrg      /* use the mode specified by the user */
99b8e80941Smrg      hwtnl->hw_pv = hwtnl->api_pv;
100b8e80941Smrg   }
101b8e80941Smrg   else {
102b8e80941Smrg      /* the device only support first provoking vertex */
103b8e80941Smrg      hwtnl->hw_pv = PV_FIRST;
104b8e80941Smrg   }
105848b8605Smrg}
106848b8605Smrg
107848b8605Smrg
108848b8605Smrgvoid
109b8e80941Smrgsvga_hwtnl_set_fillmode(struct svga_hwtnl *hwtnl, unsigned mode)
110848b8605Smrg{
111848b8605Smrg   hwtnl->api_fillmode = mode;
112848b8605Smrg}
113848b8605Smrg
114848b8605Smrg
115848b8605Smrgvoid
116b8e80941Smrgsvga_hwtnl_vertex_decls(struct svga_hwtnl *hwtnl,
117b8e80941Smrg                        unsigned count,
118b8e80941Smrg                        const SVGA3dVertexDecl * decls,
119b8e80941Smrg                        const unsigned *buffer_indexes,
120b8e80941Smrg                        SVGA3dElementLayoutId layout_id)
121848b8605Smrg{
122848b8605Smrg   assert(hwtnl->cmd.prim_count == 0);
123848b8605Smrg   hwtnl->cmd.vdecl_count = count;
124b8e80941Smrg   hwtnl->cmd.vdecl_layout_id = layout_id;
125b8e80941Smrg   memcpy(hwtnl->cmd.vdecl, decls, count * sizeof(*decls));
126b8e80941Smrg   memcpy(hwtnl->cmd.vdecl_buffer_index, buffer_indexes,
127b8e80941Smrg          count * sizeof(unsigned));
128848b8605Smrg}
129848b8605Smrg
130848b8605Smrg
131b8e80941Smrg/**
132b8e80941Smrg * Specify vertex buffers for hardware drawing.
133b8e80941Smrg */
134848b8605Smrgvoid
135b8e80941Smrgsvga_hwtnl_vertex_buffers(struct svga_hwtnl *hwtnl,
136b8e80941Smrg                          unsigned count, struct pipe_vertex_buffer *buffers)
137848b8605Smrg{
138b8e80941Smrg   struct pipe_vertex_buffer *dst = hwtnl->cmd.vbufs;
139b8e80941Smrg   const struct pipe_vertex_buffer *src = buffers;
140b8e80941Smrg   unsigned i;
141848b8605Smrg
142b8e80941Smrg   for (i = 0; i < count; i++) {
143b8e80941Smrg      pipe_vertex_buffer_reference(&dst[i], &src[i]);
144b8e80941Smrg   }
145848b8605Smrg
146b8e80941Smrg   /* release old buffer references */
147b8e80941Smrg   for ( ; i < hwtnl->cmd.vbuf_count; i++) {
148b8e80941Smrg      pipe_vertex_buffer_unreference(&dst[i]);
149b8e80941Smrg      /* don't bother zeroing stride/offset fields */
150b8e80941Smrg   }
151848b8605Smrg
152b8e80941Smrg   hwtnl->cmd.vbuf_count = count;
153848b8605Smrg}
154848b8605Smrg
155848b8605Smrg
156848b8605Smrg/**
157848b8605Smrg * Determine whether the specified buffer is referred in the primitive queue,
158848b8605Smrg * for which no commands have been written yet.
159848b8605Smrg */
160848b8605Smrgboolean
161848b8605Smrgsvga_hwtnl_is_buffer_referred(struct svga_hwtnl *hwtnl,
162848b8605Smrg                              struct pipe_resource *buffer)
163848b8605Smrg{
164848b8605Smrg   unsigned i;
165848b8605Smrg
166848b8605Smrg   if (svga_buffer_is_user_buffer(buffer)) {
167848b8605Smrg      return FALSE;
168848b8605Smrg   }
169848b8605Smrg
170848b8605Smrg   if (!hwtnl->cmd.prim_count) {
171848b8605Smrg      return FALSE;
172848b8605Smrg   }
173848b8605Smrg
174b8e80941Smrg   for (i = 0; i < hwtnl->cmd.vbuf_count; ++i) {
175b8e80941Smrg      if (hwtnl->cmd.vbufs[i].buffer.resource == buffer) {
176848b8605Smrg         return TRUE;
177848b8605Smrg      }
178848b8605Smrg   }
179848b8605Smrg
180848b8605Smrg   for (i = 0; i < hwtnl->cmd.prim_count; ++i) {
181848b8605Smrg      if (hwtnl->cmd.prim_ib[i] == buffer) {
182848b8605Smrg         return TRUE;
183848b8605Smrg      }
184848b8605Smrg   }
185848b8605Smrg
186848b8605Smrg   return FALSE;
187848b8605Smrg}
188848b8605Smrg
189848b8605Smrg
190b8e80941Smrgstatic enum pipe_error
191b8e80941Smrgdraw_vgpu9(struct svga_hwtnl *hwtnl)
192848b8605Smrg{
193848b8605Smrg   struct svga_winsys_context *swc = hwtnl->cmd.swc;
194848b8605Smrg   struct svga_context *svga = hwtnl->svga;
195848b8605Smrg   enum pipe_error ret;
196b8e80941Smrg   struct svga_winsys_surface *vb_handle[SVGA3D_INPUTREG_MAX];
197b8e80941Smrg   struct svga_winsys_surface *ib_handle[QSZ];
198b8e80941Smrg   struct svga_winsys_surface *handle;
199b8e80941Smrg   SVGA3dVertexDecl *vdecl;
200b8e80941Smrg   SVGA3dPrimitiveRange *prim;
201b8e80941Smrg   unsigned i;
202848b8605Smrg
203b8e80941Smrg   /* Re-validate those sampler views with backing copy
204b8e80941Smrg    * of texture whose original copy has been updated.
205b8e80941Smrg    * This is done here at draw time because the texture binding might not
206b8e80941Smrg    * have modified, hence validation is not triggered at state update time,
207b8e80941Smrg    * and yet the texture might have been updated in another context, so
208b8e80941Smrg    * we need to re-validate the sampler view in order to update the backing
209b8e80941Smrg    * copy of the updated texture.
210b8e80941Smrg    */
211b8e80941Smrg   if (svga->state.hw_draw.num_backed_views) {
212b8e80941Smrg      for (i = 0; i < svga->state.hw_draw.num_views; i++) {
213b8e80941Smrg         struct svga_hw_view_state *view = &svga->state.hw_draw.views[i];
214b8e80941Smrg         struct svga_texture *tex = svga_texture(view->texture);
215b8e80941Smrg         struct svga_sampler_view *sv = view->v;
216b8e80941Smrg         if (sv && tex && sv->handle != tex->handle && sv->age < tex->age)
217b8e80941Smrg            svga_validate_sampler_view(svga, view->v);
218b8e80941Smrg      }
219b8e80941Smrg   }
220848b8605Smrg
221b8e80941Smrg   for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
222b8e80941Smrg      unsigned j = hwtnl->cmd.vdecl_buffer_index[i];
223b8e80941Smrg      handle = svga_buffer_handle(svga, hwtnl->cmd.vbufs[j].buffer.resource,
224b8e80941Smrg                                  PIPE_BIND_VERTEX_BUFFER);
225b8e80941Smrg      if (!handle)
226b8e80941Smrg         return PIPE_ERROR_OUT_OF_MEMORY;
227b8e80941Smrg
228b8e80941Smrg      vb_handle[i] = handle;
229b8e80941Smrg   }
230b8e80941Smrg
231b8e80941Smrg   for (i = 0; i < hwtnl->cmd.prim_count; i++) {
232b8e80941Smrg      if (hwtnl->cmd.prim_ib[i]) {
233b8e80941Smrg         handle = svga_buffer_handle(svga, hwtnl->cmd.prim_ib[i],
234b8e80941Smrg                                     PIPE_BIND_INDEX_BUFFER);
235b8e80941Smrg         if (!handle)
236848b8605Smrg            return PIPE_ERROR_OUT_OF_MEMORY;
237b8e80941Smrg      }
238b8e80941Smrg      else
239b8e80941Smrg         handle = NULL;
240b8e80941Smrg
241b8e80941Smrg      ib_handle[i] = handle;
242b8e80941Smrg   }
243848b8605Smrg
244b8e80941Smrg   if (svga->rebind.flags.rendertargets) {
245b8e80941Smrg      ret = svga_reemit_framebuffer_bindings(svga);
246b8e80941Smrg      if (ret != PIPE_OK) {
247b8e80941Smrg         return ret;
248b8e80941Smrg      }
249b8e80941Smrg   }
250b8e80941Smrg
251b8e80941Smrg   if (svga->rebind.flags.texture_samplers) {
252b8e80941Smrg      ret = svga_reemit_tss_bindings(svga);
253b8e80941Smrg      if (ret != PIPE_OK) {
254b8e80941Smrg         return ret;
255848b8605Smrg      }
256b8e80941Smrg   }
257b8e80941Smrg
258b8e80941Smrg   if (svga->rebind.flags.vs) {
259b8e80941Smrg      ret = svga_reemit_vs_bindings(svga);
260b8e80941Smrg      if (ret != PIPE_OK) {
261b8e80941Smrg         return ret;
262b8e80941Smrg      }
263b8e80941Smrg   }
264b8e80941Smrg
265b8e80941Smrg   if (svga->rebind.flags.fs) {
266b8e80941Smrg      ret = svga_reemit_fs_bindings(svga);
267b8e80941Smrg      if (ret != PIPE_OK) {
268b8e80941Smrg         return ret;
269b8e80941Smrg      }
270b8e80941Smrg   }
271b8e80941Smrg
272b8e80941Smrg   SVGA_DBG(DEBUG_DMA, "draw to sid %p, %d prims\n",
273b8e80941Smrg            svga->curr.framebuffer.cbufs[0] ?
274b8e80941Smrg            svga_surface(svga->curr.framebuffer.cbufs[0])->handle : NULL,
275b8e80941Smrg            hwtnl->cmd.prim_count);
276b8e80941Smrg
277b8e80941Smrg   ret = SVGA3D_BeginDrawPrimitives(swc,
278b8e80941Smrg                                    &vdecl,
279b8e80941Smrg                                    hwtnl->cmd.vdecl_count,
280b8e80941Smrg                                    &prim, hwtnl->cmd.prim_count);
281b8e80941Smrg   if (ret != PIPE_OK)
282b8e80941Smrg      return ret;
283b8e80941Smrg
284b8e80941Smrg   memcpy(vdecl,
285b8e80941Smrg          hwtnl->cmd.vdecl,
286b8e80941Smrg          hwtnl->cmd.vdecl_count * sizeof hwtnl->cmd.vdecl[0]);
287b8e80941Smrg
288b8e80941Smrg   for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
289b8e80941Smrg      /* check for 4-byte alignment */
290b8e80941Smrg      assert(vdecl[i].array.offset % 4 == 0);
291b8e80941Smrg      assert(vdecl[i].array.stride % 4 == 0);
292b8e80941Smrg
293b8e80941Smrg      /* Given rangeHint is considered to be relative to indexBias, and
294b8e80941Smrg       * indexBias varies per primitive, we cannot accurately supply an
295b8e80941Smrg       * rangeHint when emitting more than one primitive per draw command.
296b8e80941Smrg       */
297b8e80941Smrg      if (hwtnl->cmd.prim_count == 1) {
298b8e80941Smrg         vdecl[i].rangeHint.first = hwtnl->cmd.min_index[0];
299b8e80941Smrg         vdecl[i].rangeHint.last = hwtnl->cmd.max_index[0] + 1;
300b8e80941Smrg      }
301b8e80941Smrg      else {
302b8e80941Smrg         vdecl[i].rangeHint.first = 0;
303b8e80941Smrg         vdecl[i].rangeHint.last = 0;
304b8e80941Smrg      }
305b8e80941Smrg
306b8e80941Smrg      swc->surface_relocation(swc,
307b8e80941Smrg                              &vdecl[i].array.surfaceId,
308b8e80941Smrg                              NULL, vb_handle[i], SVGA_RELOC_READ);
309b8e80941Smrg   }
310b8e80941Smrg
311b8e80941Smrg   memcpy(prim,
312b8e80941Smrg          hwtnl->cmd.prim, hwtnl->cmd.prim_count * sizeof hwtnl->cmd.prim[0]);
313b8e80941Smrg
314b8e80941Smrg   for (i = 0; i < hwtnl->cmd.prim_count; i++) {
315b8e80941Smrg      swc->surface_relocation(swc,
316b8e80941Smrg                              &prim[i].indexArray.surfaceId,
317b8e80941Smrg                              NULL, ib_handle[i], SVGA_RELOC_READ);
318b8e80941Smrg      pipe_resource_reference(&hwtnl->cmd.prim_ib[i], NULL);
319b8e80941Smrg   }
320848b8605Smrg
321b8e80941Smrg   SVGA_FIFOCommitAll(swc);
322b8e80941Smrg
323b8e80941Smrg   hwtnl->cmd.prim_count = 0;
324b8e80941Smrg
325b8e80941Smrg   return PIPE_OK;
326b8e80941Smrg}
327b8e80941Smrg
328b8e80941Smrg
329b8e80941Smrgstatic SVGA3dSurfaceFormat
330b8e80941Smrgxlate_index_format(unsigned indexWidth)
331b8e80941Smrg{
332b8e80941Smrg   if (indexWidth == 2) {
333b8e80941Smrg      return SVGA3D_R16_UINT;
334b8e80941Smrg   }
335b8e80941Smrg   else if (indexWidth == 4) {
336b8e80941Smrg      return SVGA3D_R32_UINT;
337b8e80941Smrg   }
338b8e80941Smrg   else {
339b8e80941Smrg      assert(!"Bad indexWidth");
340b8e80941Smrg      return SVGA3D_R32_UINT;
341b8e80941Smrg   }
342b8e80941Smrg}
343b8e80941Smrg
344b8e80941Smrg
345b8e80941Smrgstatic enum pipe_error
346b8e80941Smrgvalidate_sampler_resources(struct svga_context *svga)
347b8e80941Smrg{
348b8e80941Smrg   enum pipe_shader_type shader;
349b8e80941Smrg
350b8e80941Smrg   assert(svga_have_vgpu10(svga));
351b8e80941Smrg
352b8e80941Smrg   for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) {
353b8e80941Smrg      unsigned count = svga->curr.num_sampler_views[shader];
354b8e80941Smrg      unsigned i;
355b8e80941Smrg      struct svga_winsys_surface *surfaces[PIPE_MAX_SAMPLERS];
356b8e80941Smrg      enum pipe_error ret;
357b8e80941Smrg
358b8e80941Smrg      /*
359b8e80941Smrg       * Reference bound sampler resources to ensure pending updates are
360b8e80941Smrg       * noticed by the device.
361b8e80941Smrg       */
362b8e80941Smrg      for (i = 0; i < count; i++) {
363b8e80941Smrg         struct svga_pipe_sampler_view *sv =
364b8e80941Smrg            svga_pipe_sampler_view(svga->curr.sampler_views[shader][i]);
365b8e80941Smrg
366b8e80941Smrg         if (sv) {
367b8e80941Smrg            if (sv->base.texture->target == PIPE_BUFFER) {
368b8e80941Smrg               surfaces[i] = svga_buffer_handle(svga, sv->base.texture,
369b8e80941Smrg                                                PIPE_BIND_SAMPLER_VIEW);
370b8e80941Smrg            }
371b8e80941Smrg            else {
372b8e80941Smrg               surfaces[i] = svga_texture(sv->base.texture)->handle;
373b8e80941Smrg            }
374848b8605Smrg         }
375848b8605Smrg         else {
376b8e80941Smrg            surfaces[i] = NULL;
377848b8605Smrg         }
378b8e80941Smrg      }
379b8e80941Smrg
380b8e80941Smrg      if (shader == PIPE_SHADER_FRAGMENT &&
381b8e80941Smrg          svga->curr.rast->templ.poly_stipple_enable) {
382b8e80941Smrg         const unsigned unit = svga->state.hw_draw.fs->pstipple_sampler_unit;
383b8e80941Smrg         struct svga_pipe_sampler_view *sv =
384b8e80941Smrg            svga->polygon_stipple.sampler_view;
385848b8605Smrg
386b8e80941Smrg         assert(sv);
387b8e80941Smrg         surfaces[unit] = svga_texture(sv->base.texture)->handle;
388b8e80941Smrg         count = MAX2(count, unit+1);
389848b8605Smrg      }
390848b8605Smrg
391b8e80941Smrg      /* rebind the shader resources if needed */
392b8e80941Smrg      if (svga->rebind.flags.texture_samplers) {
393b8e80941Smrg         for (i = 0; i < count; i++) {
394b8e80941Smrg            if (surfaces[i]) {
395b8e80941Smrg               ret = svga->swc->resource_rebind(svga->swc,
396b8e80941Smrg                                                surfaces[i],
397b8e80941Smrg                                                NULL,
398b8e80941Smrg                                                SVGA_RELOC_READ);
399b8e80941Smrg               if (ret != PIPE_OK)
400b8e80941Smrg                  return ret;
401b8e80941Smrg            }
402848b8605Smrg         }
403848b8605Smrg      }
404b8e80941Smrg   }
405b8e80941Smrg   svga->rebind.flags.texture_samplers = FALSE;
406848b8605Smrg
407b8e80941Smrg   return PIPE_OK;
408b8e80941Smrg}
409b8e80941Smrg
410b8e80941Smrg
411b8e80941Smrgstatic enum pipe_error
412b8e80941Smrgvalidate_constant_buffers(struct svga_context *svga)
413b8e80941Smrg{
414b8e80941Smrg   enum pipe_shader_type shader;
415b8e80941Smrg
416b8e80941Smrg   assert(svga_have_vgpu10(svga));
417b8e80941Smrg
418b8e80941Smrg   for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) {
419b8e80941Smrg      enum pipe_error ret;
420b8e80941Smrg      struct svga_buffer *buffer;
421b8e80941Smrg      struct svga_winsys_surface *handle;
422b8e80941Smrg      unsigned enabled_constbufs;
423b8e80941Smrg
424b8e80941Smrg      /* Rebind the default constant buffer if needed */
425b8e80941Smrg      if (svga->rebind.flags.constbufs) {
426b8e80941Smrg         buffer = svga_buffer(svga->state.hw_draw.constbuf[shader]);
427b8e80941Smrg         if (buffer) {
428b8e80941Smrg            ret = svga->swc->resource_rebind(svga->swc,
429b8e80941Smrg                                             buffer->handle,
430b8e80941Smrg                                             NULL,
431b8e80941Smrg                                             SVGA_RELOC_READ);
432b8e80941Smrg            if (ret != PIPE_OK)
433b8e80941Smrg               return ret;
434848b8605Smrg         }
435848b8605Smrg      }
436848b8605Smrg
437b8e80941Smrg      /*
438b8e80941Smrg       * Reference other bound constant buffers to ensure pending updates are
439b8e80941Smrg       * noticed by the device.
440b8e80941Smrg       */
441b8e80941Smrg      enabled_constbufs = svga->state.hw_draw.enabled_constbufs[shader] & ~1u;
442b8e80941Smrg      while (enabled_constbufs) {
443b8e80941Smrg         unsigned i = u_bit_scan(&enabled_constbufs);
444b8e80941Smrg         buffer = svga_buffer(svga->curr.constbufs[shader][i].buffer);
445b8e80941Smrg         if (buffer) {
446b8e80941Smrg            handle = svga_buffer_handle(svga, &buffer->b.b,
447b8e80941Smrg                                        PIPE_BIND_CONSTANT_BUFFER);
448b8e80941Smrg
449b8e80941Smrg            if (svga->rebind.flags.constbufs) {
450b8e80941Smrg               ret = svga->swc->resource_rebind(svga->swc,
451b8e80941Smrg                                                handle,
452b8e80941Smrg                                                NULL,
453b8e80941Smrg                                                SVGA_RELOC_READ);
454b8e80941Smrg               if (ret != PIPE_OK)
455b8e80941Smrg                  return ret;
456b8e80941Smrg            }
457848b8605Smrg         }
458848b8605Smrg      }
459b8e80941Smrg   }
460b8e80941Smrg   svga->rebind.flags.constbufs = FALSE;
461848b8605Smrg
462b8e80941Smrg   return PIPE_OK;
463b8e80941Smrg}
464b8e80941Smrg
465b8e80941Smrg
466b8e80941Smrg/**
467b8e80941Smrg * Was the last command put into the command buffer a drawing command?
468b8e80941Smrg * We use this to determine if we can skip emitting buffer re-bind
469b8e80941Smrg * commands when we have a sequence of drawing commands that use the
470b8e80941Smrg * same vertex/index buffers with no intervening commands.
471b8e80941Smrg *
472b8e80941Smrg * The first drawing command will bind the vertex/index buffers.  If
473b8e80941Smrg * the immediately following command is also a drawing command using the
474b8e80941Smrg * same buffers, we shouldn't have to rebind them.
475b8e80941Smrg */
476b8e80941Smrgstatic bool
477b8e80941Smrglast_command_was_draw(const struct svga_context *svga)
478b8e80941Smrg{
479b8e80941Smrg   switch (SVGA3D_GetLastCommand(svga->swc)) {
480b8e80941Smrg   case SVGA_3D_CMD_DX_DRAW:
481b8e80941Smrg   case SVGA_3D_CMD_DX_DRAW_INDEXED:
482b8e80941Smrg   case SVGA_3D_CMD_DX_DRAW_INSTANCED:
483b8e80941Smrg   case SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED:
484b8e80941Smrg   case SVGA_3D_CMD_DX_DRAW_AUTO:
485b8e80941Smrg      return true;
486b8e80941Smrg   default:
487b8e80941Smrg      return false;
488b8e80941Smrg   }
489b8e80941Smrg}
490b8e80941Smrg
491b8e80941Smrg
492b8e80941Smrg/**
493b8e80941Smrg * A helper function to compare vertex buffers.
494b8e80941Smrg * They are equal if the vertex buffer attributes and the vertex buffer
495b8e80941Smrg * resources are identical.
496b8e80941Smrg */
497b8e80941Smrgstatic boolean
498b8e80941Smrgvertex_buffers_equal(unsigned count,
499b8e80941Smrg                     SVGA3dVertexBuffer *pVBufAttr1,
500b8e80941Smrg                     struct pipe_resource **pVBuf1,
501b8e80941Smrg                     SVGA3dVertexBuffer *pVBufAttr2,
502b8e80941Smrg                     struct pipe_resource **pVBuf2)
503b8e80941Smrg{
504b8e80941Smrg   return (memcmp(pVBufAttr1, pVBufAttr2,
505b8e80941Smrg                  count * sizeof(*pVBufAttr1)) == 0) &&
506b8e80941Smrg          (memcmp(pVBuf1, pVBuf2, count * sizeof(*pVBuf1)) == 0);
507b8e80941Smrg}
508b8e80941Smrg
509b8e80941Smrg
510b8e80941Smrg/*
511b8e80941Smrg * Prepare the vertex buffers for a drawing command.
512b8e80941Smrg */
513b8e80941Smrgstatic enum pipe_error
514b8e80941Smrgvalidate_vertex_buffers(struct svga_hwtnl *hwtnl)
515b8e80941Smrg{
516b8e80941Smrg   struct svga_context *svga = hwtnl->svga;
517b8e80941Smrg   struct pipe_resource *vbuffers[SVGA3D_INPUTREG_MAX];
518b8e80941Smrg   struct svga_winsys_surface *vbuffer_handles[SVGA3D_INPUTREG_MAX];
519b8e80941Smrg   const unsigned vbuf_count = hwtnl->cmd.vbuf_count;
520b8e80941Smrg   int last_vbuf = -1;
521b8e80941Smrg   unsigned i;
522b8e80941Smrg
523b8e80941Smrg   assert(svga_have_vgpu10(svga));
524b8e80941Smrg
525b8e80941Smrg   /* Get handle for each referenced vertex buffer */
526b8e80941Smrg   for (i = 0; i < vbuf_count; i++) {
527b8e80941Smrg      struct svga_buffer *sbuf =
528b8e80941Smrg         svga_buffer(hwtnl->cmd.vbufs[i].buffer.resource);
529b8e80941Smrg
530b8e80941Smrg      if (sbuf) {
531b8e80941Smrg         vbuffer_handles[i] = svga_buffer_handle(svga, &sbuf->b.b,
532b8e80941Smrg                                                 PIPE_BIND_VERTEX_BUFFER);
533b8e80941Smrg         assert(sbuf->key.flags & SVGA3D_SURFACE_BIND_VERTEX_BUFFER);
534b8e80941Smrg         if (vbuffer_handles[i] == NULL)
535b8e80941Smrg            return PIPE_ERROR_OUT_OF_MEMORY;
536b8e80941Smrg         vbuffers[i] = &sbuf->b.b;
537b8e80941Smrg         last_vbuf = i;
538b8e80941Smrg      }
539b8e80941Smrg      else {
540b8e80941Smrg         vbuffers[i] = NULL;
541b8e80941Smrg         vbuffer_handles[i] = NULL;
542848b8605Smrg      }
543b8e80941Smrg   }
544848b8605Smrg
545b8e80941Smrg   for (; i < svga->state.hw_draw.num_vbuffers; i++) {
546b8e80941Smrg      vbuffers[i] = NULL;
547b8e80941Smrg      vbuffer_handles[i] = NULL;
548b8e80941Smrg   }
549848b8605Smrg
550b8e80941Smrg   /* setup vertex attribute input layout */
551b8e80941Smrg   if (svga->state.hw_draw.layout_id != hwtnl->cmd.vdecl_layout_id) {
552b8e80941Smrg      enum pipe_error ret =
553b8e80941Smrg         SVGA3D_vgpu10_SetInputLayout(svga->swc,
554b8e80941Smrg                                      hwtnl->cmd.vdecl_layout_id);
555848b8605Smrg      if (ret != PIPE_OK)
556848b8605Smrg         return ret;
557848b8605Smrg
558b8e80941Smrg      svga->state.hw_draw.layout_id = hwtnl->cmd.vdecl_layout_id;
559b8e80941Smrg   }
560b8e80941Smrg
561b8e80941Smrg   /* setup vertex buffers */
562b8e80941Smrg   {
563b8e80941Smrg      SVGA3dVertexBuffer vbuffer_attrs[PIPE_MAX_ATTRIBS];
564848b8605Smrg
565b8e80941Smrg      for (i = 0; i < vbuf_count; i++) {
566b8e80941Smrg         vbuffer_attrs[i].stride = hwtnl->cmd.vbufs[i].stride;
567b8e80941Smrg         vbuffer_attrs[i].offset = hwtnl->cmd.vbufs[i].buffer_offset;
568b8e80941Smrg         vbuffer_attrs[i].sid = 0;
569b8e80941Smrg      }
570b8e80941Smrg
571b8e80941Smrg      /* If any of the vertex buffer state has changed, issue
572b8e80941Smrg       * the SetVertexBuffers command. Otherwise, we will just
573b8e80941Smrg       * need to rebind the resources.
574b8e80941Smrg       */
575b8e80941Smrg      if (vbuf_count != svga->state.hw_draw.num_vbuffers ||
576b8e80941Smrg          !vertex_buffers_equal(vbuf_count,
577b8e80941Smrg                                vbuffer_attrs,
578b8e80941Smrg                                vbuffers,
579b8e80941Smrg                                svga->state.hw_draw.vbuffer_attrs,
580b8e80941Smrg                                svga->state.hw_draw.vbuffers)) {
581b8e80941Smrg
582b8e80941Smrg         unsigned num_vbuffers;
583b8e80941Smrg
584b8e80941Smrg         /* get the max of the current bound vertex buffers count and
585b8e80941Smrg          * the to-be-bound vertex buffers count, so as to unbind
586b8e80941Smrg          * the unused vertex buffers.
587848b8605Smrg          */
588b8e80941Smrg         num_vbuffers = MAX2(vbuf_count, svga->state.hw_draw.num_vbuffers);
589b8e80941Smrg
590b8e80941Smrg         /* Zero-out the old buffers we want to unbind (the number of loop
591b8e80941Smrg          * iterations here is typically very small, and often zero.)
592b8e80941Smrg          */
593b8e80941Smrg         for (i = vbuf_count; i < num_vbuffers; i++) {
594b8e80941Smrg            vbuffer_attrs[i].sid = 0;
595b8e80941Smrg            vbuffer_attrs[i].stride = 0;
596b8e80941Smrg            vbuffer_attrs[i].offset = 0;
597b8e80941Smrg            vbuffer_handles[i] = NULL;
598848b8605Smrg         }
599b8e80941Smrg
600b8e80941Smrg         if (num_vbuffers > 0) {
601b8e80941Smrg            SVGA3dVertexBuffer *pbufAttrs = vbuffer_attrs;
602b8e80941Smrg            struct svga_winsys_surface **pbufHandles = vbuffer_handles;
603b8e80941Smrg            unsigned numVBuf = 0;
604b8e80941Smrg
605b8e80941Smrg            /* Loop through the vertex buffer lists to only emit
606b8e80941Smrg             * those vertex buffers that are not already in the
607b8e80941Smrg             * corresponding entries in the device's vertex buffer list.
608b8e80941Smrg             */
609b8e80941Smrg            for (i = 0; i < num_vbuffers; i++) {
610b8e80941Smrg               boolean emit =
611b8e80941Smrg                  vertex_buffers_equal(1,
612b8e80941Smrg                                       &vbuffer_attrs[i],
613b8e80941Smrg                                       &vbuffers[i],
614b8e80941Smrg                                       &svga->state.hw_draw.vbuffer_attrs[i],
615b8e80941Smrg                                       &svga->state.hw_draw.vbuffers[i]);
616b8e80941Smrg
617b8e80941Smrg               if (!emit && i == num_vbuffers-1) {
618b8e80941Smrg                  /* Include the last vertex buffer in the next emit
619b8e80941Smrg                   * if it is different.
620b8e80941Smrg                   */
621b8e80941Smrg                  emit = TRUE;
622b8e80941Smrg                  numVBuf++;
623b8e80941Smrg                  i++;
624b8e80941Smrg               }
625b8e80941Smrg
626b8e80941Smrg               if (emit) {
627b8e80941Smrg                  /* numVBuf can only be 0 if the first vertex buffer
628b8e80941Smrg                   * is the same as the one in the device's list.
629b8e80941Smrg                   * In this case, there is nothing to send yet.
630b8e80941Smrg                   */
631b8e80941Smrg                  if (numVBuf) {
632b8e80941Smrg                     enum pipe_error ret =
633b8e80941Smrg                        SVGA3D_vgpu10_SetVertexBuffers(svga->swc,
634b8e80941Smrg                                                       numVBuf,
635b8e80941Smrg                                                       i - numVBuf,
636b8e80941Smrg                                                       pbufAttrs, pbufHandles);
637b8e80941Smrg                     if (ret != PIPE_OK)
638b8e80941Smrg                        return ret;
639b8e80941Smrg                  }
640b8e80941Smrg                  pbufAttrs += (numVBuf + 1);
641b8e80941Smrg                  pbufHandles += (numVBuf + 1);
642b8e80941Smrg                  numVBuf = 0;
643b8e80941Smrg               }
644b8e80941Smrg               else
645b8e80941Smrg                  numVBuf++;
646b8e80941Smrg            }
647b8e80941Smrg
648b8e80941Smrg            /* save the number of vertex buffers sent to the device, not
649b8e80941Smrg             * including trailing unbound vertex buffers.
650b8e80941Smrg             */
651b8e80941Smrg            svga->state.hw_draw.num_vbuffers = last_vbuf + 1;
652b8e80941Smrg            memcpy(svga->state.hw_draw.vbuffer_attrs, vbuffer_attrs,
653b8e80941Smrg                   num_vbuffers * sizeof(vbuffer_attrs[0]));
654b8e80941Smrg            for (i = 0; i < num_vbuffers; i++) {
655b8e80941Smrg               pipe_resource_reference(&svga->state.hw_draw.vbuffers[i],
656b8e80941Smrg                                       vbuffers[i]);
657b8e80941Smrg            }
658b8e80941Smrg         }
659b8e80941Smrg      }
660b8e80941Smrg      else {
661b8e80941Smrg         /* Even though we can avoid emitting the redundant SetVertexBuffers
662b8e80941Smrg          * command, we still need to reference the vertex buffers surfaces.
663b8e80941Smrg          */
664b8e80941Smrg         for (i = 0; i < vbuf_count; i++) {
665b8e80941Smrg            if (vbuffer_handles[i] && !last_command_was_draw(svga)) {
666b8e80941Smrg               enum pipe_error ret =
667b8e80941Smrg                  svga->swc->resource_rebind(svga->swc, vbuffer_handles[i],
668b8e80941Smrg                                             NULL, SVGA_RELOC_READ);
669b8e80941Smrg               if (ret != PIPE_OK)
670b8e80941Smrg                  return ret;
671b8e80941Smrg            }
672848b8605Smrg         }
673b8e80941Smrg      }
674b8e80941Smrg   }
675b8e80941Smrg
676b8e80941Smrg   return PIPE_OK;
677b8e80941Smrg}
678b8e80941Smrg
679b8e80941Smrg
680b8e80941Smrg/*
681b8e80941Smrg * Prepare the index buffer for a drawing command.
682b8e80941Smrg */
683b8e80941Smrgstatic enum pipe_error
684b8e80941Smrgvalidate_index_buffer(struct svga_hwtnl *hwtnl,
685b8e80941Smrg                      const SVGA3dPrimitiveRange *range,
686b8e80941Smrg                      struct pipe_resource *ib)
687b8e80941Smrg{
688b8e80941Smrg   struct svga_context *svga = hwtnl->svga;
689b8e80941Smrg   struct svga_winsys_surface *ib_handle =
690b8e80941Smrg      svga_buffer_handle(svga, ib, PIPE_BIND_INDEX_BUFFER);
691b8e80941Smrg
692b8e80941Smrg   if (!ib_handle)
693b8e80941Smrg      return PIPE_ERROR_OUT_OF_MEMORY;
694848b8605Smrg
695b8e80941Smrg   struct svga_buffer *sbuf = svga_buffer(ib);
696b8e80941Smrg   assert(sbuf->key.flags & SVGA3D_SURFACE_BIND_INDEX_BUFFER);
697b8e80941Smrg   (void) sbuf; /* silence unused var warning */
698b8e80941Smrg
699b8e80941Smrg   SVGA3dSurfaceFormat indexFormat = xlate_index_format(range->indexWidth);
700b8e80941Smrg
701b8e80941Smrg   if (ib != svga->state.hw_draw.ib ||
702b8e80941Smrg       indexFormat != svga->state.hw_draw.ib_format ||
703b8e80941Smrg       range->indexArray.offset != svga->state.hw_draw.ib_offset) {
704b8e80941Smrg
705b8e80941Smrg      assert(indexFormat != SVGA3D_FORMAT_INVALID);
706b8e80941Smrg      enum pipe_error ret =
707b8e80941Smrg         SVGA3D_vgpu10_SetIndexBuffer(svga->swc, ib_handle,
708b8e80941Smrg                                      indexFormat,
709b8e80941Smrg                                      range->indexArray.offset);
710b8e80941Smrg      if (ret != PIPE_OK)
711b8e80941Smrg         return ret;
712b8e80941Smrg
713b8e80941Smrg      pipe_resource_reference(&svga->state.hw_draw.ib, ib);
714b8e80941Smrg      svga->state.hw_draw.ib_format = indexFormat;
715b8e80941Smrg      svga->state.hw_draw.ib_offset = range->indexArray.offset;
716b8e80941Smrg   }
717b8e80941Smrg   else {
718b8e80941Smrg      /* Even though we can avoid emitting the redundant SetIndexBuffer
719b8e80941Smrg       * command, we still need to reference the index buffer surface.
720b8e80941Smrg       */
721b8e80941Smrg      if (!last_command_was_draw(svga)) {
722b8e80941Smrg         enum pipe_error ret = svga->swc->resource_rebind(svga->swc,
723b8e80941Smrg                                                          ib_handle,
724b8e80941Smrg                                                          NULL,
725b8e80941Smrg                                                          SVGA_RELOC_READ);
726b8e80941Smrg         if (ret != PIPE_OK)
727b8e80941Smrg            return ret;
728848b8605Smrg      }
729b8e80941Smrg   }
730b8e80941Smrg
731b8e80941Smrg   return PIPE_OK;
732b8e80941Smrg}
733b8e80941Smrg
734b8e80941Smrg
735b8e80941Smrgstatic enum pipe_error
736b8e80941Smrgdraw_vgpu10(struct svga_hwtnl *hwtnl,
737b8e80941Smrg            const SVGA3dPrimitiveRange *range,
738b8e80941Smrg            unsigned vcount,
739b8e80941Smrg            struct pipe_resource *ib,
740b8e80941Smrg            unsigned start_instance, unsigned instance_count)
741b8e80941Smrg{
742b8e80941Smrg   struct svga_context *svga = hwtnl->svga;
743b8e80941Smrg   enum pipe_error ret;
744b8e80941Smrg
745b8e80941Smrg   assert(svga_have_vgpu10(svga));
746b8e80941Smrg   assert(hwtnl->cmd.prim_count == 0);
747b8e80941Smrg
748b8e80941Smrg   /* We need to reemit all the current resource bindings along with the Draw
749b8e80941Smrg    * command to be sure that the referenced resources are available for the
750b8e80941Smrg    * Draw command, just in case the surfaces associated with the resources
751b8e80941Smrg    * are paged out.
752b8e80941Smrg    */
753b8e80941Smrg   if (svga->rebind.val) {
754b8e80941Smrg      ret = svga_rebind_framebuffer_bindings(svga);
755b8e80941Smrg      if (ret != PIPE_OK)
756b8e80941Smrg         return ret;
757b8e80941Smrg
758b8e80941Smrg      ret = svga_rebind_shaders(svga);
759b8e80941Smrg      if (ret != PIPE_OK)
760b8e80941Smrg         return ret;
761b8e80941Smrg
762b8e80941Smrg      /* Rebind stream output targets */
763b8e80941Smrg      ret = svga_rebind_stream_output_targets(svga);
764b8e80941Smrg      if (ret != PIPE_OK)
765b8e80941Smrg         return ret;
766b8e80941Smrg
767b8e80941Smrg      /* No need to explicitly rebind index buffer and vertex buffers here.
768b8e80941Smrg       * Even if the same index buffer or vertex buffers are referenced for this
769b8e80941Smrg       * draw and we skip emitting the redundant set command, we will still
770b8e80941Smrg       * reference the associated resources.
771b8e80941Smrg       */
772b8e80941Smrg   }
773b8e80941Smrg
774b8e80941Smrg   ret = validate_sampler_resources(svga);
775b8e80941Smrg   if (ret != PIPE_OK)
776b8e80941Smrg      return ret;
777848b8605Smrg
778b8e80941Smrg   ret = validate_constant_buffers(svga);
779b8e80941Smrg   if (ret != PIPE_OK)
780b8e80941Smrg      return ret;
781848b8605Smrg
782b8e80941Smrg   ret = validate_vertex_buffers(hwtnl);
783b8e80941Smrg   if (ret != PIPE_OK)
784b8e80941Smrg      return ret;
785b8e80941Smrg
786b8e80941Smrg   if (ib) {
787b8e80941Smrg      ret = validate_index_buffer(hwtnl, range, ib);
788b8e80941Smrg      if (ret != PIPE_OK)
789b8e80941Smrg         return ret;
790b8e80941Smrg   }
791b8e80941Smrg
792b8e80941Smrg   /* Set primitive type (line, tri, etc) */
793b8e80941Smrg   if (svga->state.hw_draw.topology != range->primType) {
794b8e80941Smrg      ret = SVGA3D_vgpu10_SetTopology(svga->swc, range->primType);
795b8e80941Smrg      if (ret != PIPE_OK)
796b8e80941Smrg         return ret;
797b8e80941Smrg
798b8e80941Smrg      svga->state.hw_draw.topology = range->primType;
799b8e80941Smrg   }
800b8e80941Smrg
801b8e80941Smrg   if (ib) {
802b8e80941Smrg      /* indexed drawing */
803b8e80941Smrg      if (instance_count > 1) {
804b8e80941Smrg         ret = SVGA3D_vgpu10_DrawIndexedInstanced(svga->swc,
805b8e80941Smrg                                                  vcount,
806b8e80941Smrg                                                  instance_count,
807b8e80941Smrg                                                  0, /* startIndexLocation */
808b8e80941Smrg                                                  range->indexBias,
809b8e80941Smrg                                                  start_instance);
810b8e80941Smrg         if (ret != PIPE_OK)
811b8e80941Smrg            return ret;
812b8e80941Smrg      }
813b8e80941Smrg      else {
814b8e80941Smrg         /* non-instanced drawing */
815b8e80941Smrg         ret = SVGA3D_vgpu10_DrawIndexed(svga->swc,
816b8e80941Smrg                                         vcount,
817b8e80941Smrg                                         0,      /* startIndexLocation */
818b8e80941Smrg                                         range->indexBias);
819b8e80941Smrg         if (ret != PIPE_OK)
820b8e80941Smrg            return ret;
821b8e80941Smrg      }
822b8e80941Smrg   }
823b8e80941Smrg   else {
824b8e80941Smrg      /* non-indexed drawing */
825b8e80941Smrg      if (svga->state.hw_draw.ib_format != SVGA3D_FORMAT_INVALID ||
826b8e80941Smrg          svga->state.hw_draw.ib != NULL) {
827b8e80941Smrg         /* Unbind previously bound index buffer */
828b8e80941Smrg         ret = SVGA3D_vgpu10_SetIndexBuffer(svga->swc, NULL,
829b8e80941Smrg                                            SVGA3D_FORMAT_INVALID, 0);
830b8e80941Smrg         if (ret != PIPE_OK)
831b8e80941Smrg            return ret;
832b8e80941Smrg         pipe_resource_reference(&svga->state.hw_draw.ib, NULL);
833b8e80941Smrg         svga->state.hw_draw.ib_format = SVGA3D_FORMAT_INVALID;
834848b8605Smrg      }
835848b8605Smrg
836b8e80941Smrg      assert(svga->state.hw_draw.ib == NULL);
837b8e80941Smrg
838b8e80941Smrg      if (instance_count > 1) {
839b8e80941Smrg         ret = SVGA3D_vgpu10_DrawInstanced(svga->swc,
840b8e80941Smrg                                           vcount,
841b8e80941Smrg                                           instance_count,
842b8e80941Smrg                                           range->indexBias,
843b8e80941Smrg                                           start_instance);
844b8e80941Smrg         if (ret != PIPE_OK)
845b8e80941Smrg            return ret;
846b8e80941Smrg      }
847b8e80941Smrg      else {
848b8e80941Smrg         /* non-instanced */
849b8e80941Smrg         ret = SVGA3D_vgpu10_Draw(svga->swc,
850b8e80941Smrg                                  vcount,
851b8e80941Smrg                                  range->indexBias);
852b8e80941Smrg         if (ret != PIPE_OK)
853b8e80941Smrg            return ret;
854b8e80941Smrg      }
855848b8605Smrg   }
856848b8605Smrg
857b8e80941Smrg   hwtnl->cmd.prim_count = 0;
858b8e80941Smrg
859848b8605Smrg   return PIPE_OK;
860848b8605Smrg}
861848b8605Smrg
862848b8605Smrg
863b8e80941Smrg
864b8e80941Smrg/**
865b8e80941Smrg * Emit any pending drawing commands to the command buffer.
866b8e80941Smrg * When we receive VGPU9 drawing commands we accumulate them and don't
867b8e80941Smrg * immediately emit them into the command buffer.
868b8e80941Smrg * This function needs to be called before we change state that could
869b8e80941Smrg * effect those pending draws.
870b8e80941Smrg */
871b8e80941Smrgenum pipe_error
872b8e80941Smrgsvga_hwtnl_flush(struct svga_hwtnl *hwtnl)
873b8e80941Smrg{
874b8e80941Smrg   enum pipe_error ret = PIPE_OK;
875b8e80941Smrg
876b8e80941Smrg   SVGA_STATS_TIME_PUSH(svga_sws(hwtnl->svga), SVGA_STATS_TIME_HWTNLFLUSH);
877b8e80941Smrg
878b8e80941Smrg   if (!svga_have_vgpu10(hwtnl->svga) && hwtnl->cmd.prim_count) {
879b8e80941Smrg      /* we only queue up primitive for VGPU9 */
880b8e80941Smrg      ret = draw_vgpu9(hwtnl);
881b8e80941Smrg   }
882b8e80941Smrg
883b8e80941Smrg   SVGA_STATS_TIME_POP(svga_screen(hwtnl->svga->pipe.screen)->sws);
884b8e80941Smrg   return ret;
885b8e80941Smrg}
886b8e80941Smrg
887b8e80941Smrg
888848b8605Smrgvoid
889848b8605Smrgsvga_hwtnl_set_index_bias(struct svga_hwtnl *hwtnl, int index_bias)
890848b8605Smrg{
891848b8605Smrg   hwtnl->index_bias = index_bias;
892848b8605Smrg}
893848b8605Smrg
894848b8605Smrg
895848b8605Smrg
896848b8605Smrg/***********************************************************************
897848b8605Smrg * Internal functions:
898848b8605Smrg */
899848b8605Smrg
900848b8605Smrg/**
901848b8605Smrg * For debugging only.
902848b8605Smrg */
903848b8605Smrgstatic void
904848b8605Smrgcheck_draw_params(struct svga_hwtnl *hwtnl,
905848b8605Smrg                  const SVGA3dPrimitiveRange *range,
906848b8605Smrg                  unsigned min_index, unsigned max_index,
907848b8605Smrg                  struct pipe_resource *ib)
908848b8605Smrg{
909848b8605Smrg   unsigned i;
910848b8605Smrg
911b8e80941Smrg   assert(!svga_have_vgpu10(hwtnl->svga));
912b8e80941Smrg
913848b8605Smrg   for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
914b8e80941Smrg      unsigned j = hwtnl->cmd.vdecl_buffer_index[i];
915b8e80941Smrg      const struct pipe_vertex_buffer *vb = &hwtnl->cmd.vbufs[j];
916b8e80941Smrg      unsigned size = vb->buffer.resource ? vb->buffer.resource->width0 : 0;
917848b8605Smrg      unsigned offset = hwtnl->cmd.vdecl[i].array.offset;
918848b8605Smrg      unsigned stride = hwtnl->cmd.vdecl[i].array.stride;
919848b8605Smrg      int index_bias = (int) range->indexBias + hwtnl->index_bias;
920848b8605Smrg      unsigned width;
921848b8605Smrg
922b8e80941Smrg      if (size == 0)
923b8e80941Smrg         continue;
924b8e80941Smrg
925848b8605Smrg      assert(vb);
926848b8605Smrg      assert(size);
927848b8605Smrg      assert(offset < size);
928848b8605Smrg      assert(min_index <= max_index);
929b8e80941Smrg      (void) width;
930b8e80941Smrg      (void) stride;
931b8e80941Smrg      (void) offset;
932b8e80941Smrg      (void) size;
933848b8605Smrg
934848b8605Smrg      switch (hwtnl->cmd.vdecl[i].identity.type) {
935848b8605Smrg      case SVGA3D_DECLTYPE_FLOAT1:
936848b8605Smrg         width = 4;
937848b8605Smrg         break;
938848b8605Smrg      case SVGA3D_DECLTYPE_FLOAT2:
939848b8605Smrg         width = 4 * 2;
940848b8605Smrg         break;
941848b8605Smrg      case SVGA3D_DECLTYPE_FLOAT3:
942848b8605Smrg         width = 4 * 3;
943848b8605Smrg         break;
944848b8605Smrg      case SVGA3D_DECLTYPE_FLOAT4:
945848b8605Smrg         width = 4 * 4;
946848b8605Smrg         break;
947848b8605Smrg      case SVGA3D_DECLTYPE_D3DCOLOR:
948848b8605Smrg         width = 4;
949848b8605Smrg         break;
950848b8605Smrg      case SVGA3D_DECLTYPE_UBYTE4:
951848b8605Smrg         width = 1 * 4;
952848b8605Smrg         break;
953848b8605Smrg      case SVGA3D_DECLTYPE_SHORT2:
954848b8605Smrg         width = 2 * 2;
955848b8605Smrg         break;
956848b8605Smrg      case SVGA3D_DECLTYPE_SHORT4:
957848b8605Smrg         width = 2 * 4;
958848b8605Smrg         break;
959848b8605Smrg      case SVGA3D_DECLTYPE_UBYTE4N:
960848b8605Smrg         width = 1 * 4;
961848b8605Smrg         break;
962848b8605Smrg      case SVGA3D_DECLTYPE_SHORT2N:
963848b8605Smrg         width = 2 * 2;
964848b8605Smrg         break;
965848b8605Smrg      case SVGA3D_DECLTYPE_SHORT4N:
966848b8605Smrg         width = 2 * 4;
967848b8605Smrg         break;
968848b8605Smrg      case SVGA3D_DECLTYPE_USHORT2N:
969848b8605Smrg         width = 2 * 2;
970848b8605Smrg         break;
971848b8605Smrg      case SVGA3D_DECLTYPE_USHORT4N:
972848b8605Smrg         width = 2 * 4;
973848b8605Smrg         break;
974848b8605Smrg      case SVGA3D_DECLTYPE_UDEC3:
975848b8605Smrg         width = 4;
976848b8605Smrg         break;
977848b8605Smrg      case SVGA3D_DECLTYPE_DEC3N:
978848b8605Smrg         width = 4;
979848b8605Smrg         break;
980848b8605Smrg      case SVGA3D_DECLTYPE_FLOAT16_2:
981848b8605Smrg         width = 2 * 2;
982848b8605Smrg         break;
983848b8605Smrg      case SVGA3D_DECLTYPE_FLOAT16_4:
984848b8605Smrg         width = 2 * 4;
985848b8605Smrg         break;
986848b8605Smrg      default:
987848b8605Smrg         assert(0);
988848b8605Smrg         width = 0;
989848b8605Smrg         break;
990848b8605Smrg      }
991848b8605Smrg
992848b8605Smrg      if (index_bias >= 0) {
993848b8605Smrg         assert(offset + index_bias * stride + width <= size);
994848b8605Smrg      }
995848b8605Smrg
996848b8605Smrg      /*
997848b8605Smrg       * min_index/max_index are merely conservative guesses, so we can't
998848b8605Smrg       * make buffer overflow detection based on their values.
999848b8605Smrg       */
1000848b8605Smrg   }
1001848b8605Smrg
1002848b8605Smrg   assert(range->indexWidth == range->indexArray.stride);
1003848b8605Smrg
1004848b8605Smrg   if (ib) {
1005b8e80941Smrg      MAYBE_UNUSED unsigned size = ib->width0;
1006b8e80941Smrg      MAYBE_UNUSED unsigned offset = range->indexArray.offset;
1007b8e80941Smrg      MAYBE_UNUSED unsigned stride = range->indexArray.stride;
1008b8e80941Smrg      MAYBE_UNUSED unsigned count;
1009848b8605Smrg
1010848b8605Smrg      assert(size);
1011848b8605Smrg      assert(offset < size);
1012848b8605Smrg      assert(stride);
1013848b8605Smrg
1014848b8605Smrg      switch (range->primType) {
1015848b8605Smrg      case SVGA3D_PRIMITIVE_POINTLIST:
1016848b8605Smrg         count = range->primitiveCount;
1017848b8605Smrg         break;
1018848b8605Smrg      case SVGA3D_PRIMITIVE_LINELIST:
1019848b8605Smrg         count = range->primitiveCount * 2;
1020848b8605Smrg         break;
1021848b8605Smrg      case SVGA3D_PRIMITIVE_LINESTRIP:
1022848b8605Smrg         count = range->primitiveCount + 1;
1023848b8605Smrg         break;
1024848b8605Smrg      case SVGA3D_PRIMITIVE_TRIANGLELIST:
1025848b8605Smrg         count = range->primitiveCount * 3;
1026848b8605Smrg         break;
1027848b8605Smrg      case SVGA3D_PRIMITIVE_TRIANGLESTRIP:
1028848b8605Smrg         count = range->primitiveCount + 2;
1029848b8605Smrg         break;
1030848b8605Smrg      case SVGA3D_PRIMITIVE_TRIANGLEFAN:
1031848b8605Smrg         count = range->primitiveCount + 2;
1032848b8605Smrg         break;
1033848b8605Smrg      default:
1034848b8605Smrg         assert(0);
1035848b8605Smrg         count = 0;
1036848b8605Smrg         break;
1037848b8605Smrg      }
1038848b8605Smrg
1039848b8605Smrg      assert(offset + count * stride <= size);
1040848b8605Smrg   }
1041848b8605Smrg}
1042848b8605Smrg
1043848b8605Smrg
1044b8e80941Smrg/**
1045b8e80941Smrg * All drawing filters down into this function, either directly
1046b8e80941Smrg * on the hardware path or after doing software vertex processing.
1047b8e80941Smrg */
1048848b8605Smrgenum pipe_error
1049848b8605Smrgsvga_hwtnl_prim(struct svga_hwtnl *hwtnl,
1050848b8605Smrg                const SVGA3dPrimitiveRange * range,
1051b8e80941Smrg                unsigned vcount,
1052848b8605Smrg                unsigned min_index,
1053b8e80941Smrg                unsigned max_index, struct pipe_resource *ib,
1054b8e80941Smrg                unsigned start_instance, unsigned instance_count)
1055848b8605Smrg{
1056848b8605Smrg   enum pipe_error ret = PIPE_OK;
1057848b8605Smrg
1058b8e80941Smrg   SVGA_STATS_TIME_PUSH(svga_sws(hwtnl->svga), SVGA_STATS_TIME_HWTNLPRIM);
1059b8e80941Smrg
1060b8e80941Smrg   if (svga_have_vgpu10(hwtnl->svga)) {
1061b8e80941Smrg      /* draw immediately */
1062b8e80941Smrg      ret = draw_vgpu10(hwtnl, range, vcount, ib,
1063b8e80941Smrg                        start_instance, instance_count);
1064b8e80941Smrg      if (ret != PIPE_OK) {
1065b8e80941Smrg         svga_context_flush(hwtnl->svga, NULL);
1066b8e80941Smrg         ret = draw_vgpu10(hwtnl, range, vcount, ib,
1067b8e80941Smrg                           start_instance, instance_count);
1068b8e80941Smrg         assert(ret == PIPE_OK);
1069b8e80941Smrg      }
1070b8e80941Smrg   }
1071b8e80941Smrg   else {
1072b8e80941Smrg      /* batch up drawing commands */
1073848b8605Smrg#ifdef DEBUG
1074b8e80941Smrg      check_draw_params(hwtnl, range, min_index, max_index, ib);
1075b8e80941Smrg      assert(start_instance == 0);
1076b8e80941Smrg      assert(instance_count <= 1);
1077b8e80941Smrg#else
1078b8e80941Smrg      (void) check_draw_params;
1079848b8605Smrg#endif
1080848b8605Smrg
1081b8e80941Smrg      if (hwtnl->cmd.prim_count + 1 >= QSZ) {
1082b8e80941Smrg         ret = svga_hwtnl_flush(hwtnl);
1083b8e80941Smrg         if (ret != PIPE_OK)
1084b8e80941Smrg            goto done;
1085b8e80941Smrg      }
1086848b8605Smrg
1087b8e80941Smrg      /* min/max indices are relative to bias */
1088b8e80941Smrg      hwtnl->cmd.min_index[hwtnl->cmd.prim_count] = min_index;
1089b8e80941Smrg      hwtnl->cmd.max_index[hwtnl->cmd.prim_count] = max_index;
1090848b8605Smrg
1091b8e80941Smrg      hwtnl->cmd.prim[hwtnl->cmd.prim_count] = *range;
1092b8e80941Smrg      hwtnl->cmd.prim[hwtnl->cmd.prim_count].indexBias += hwtnl->index_bias;
1093848b8605Smrg
1094b8e80941Smrg      pipe_resource_reference(&hwtnl->cmd.prim_ib[hwtnl->cmd.prim_count], ib);
1095b8e80941Smrg      hwtnl->cmd.prim_count++;
1096b8e80941Smrg   }
1097848b8605Smrg
1098b8e80941Smrgdone:
1099b8e80941Smrg   SVGA_STATS_TIME_POP(svga_screen(hwtnl->svga->pipe.screen)->sws);
1100848b8605Smrg   return ret;
1101848b8605Smrg}
1102