OSDN Git Service

3eda09acc7c01a0cd5d817e13beffc34470baeba
[android-x86/external-mesa.git] / src / gallium / drivers / svga / svga_draw.c
1 /**********************************************************
2  * Copyright 2008-2009 VMware, Inc.  All rights reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person
5  * obtaining a copy of this software and associated documentation
6  * files (the "Software"), to deal in the Software without
7  * restriction, including without limitation the rights to use, copy,
8  * modify, merge, publish, distribute, sublicense, and/or sell copies
9  * of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  *
24  **********************************************************/
25
26 #include "pipe/p_compiler.h"
27 #include "util/u_inlines.h"
28 #include "pipe/p_defines.h"
29 #include "util/u_helpers.h"
30 #include "util/u_memory.h"
31 #include "util/u_math.h"
32
33 #include "svga_context.h"
34 #include "svga_draw.h"
35 #include "svga_draw_private.h"
36 #include "svga_debug.h"
37 #include "svga_screen.h"
38 #include "svga_resource.h"
39 #include "svga_resource_buffer.h"
40 #include "svga_resource_texture.h"
41 #include "svga_shader.h"
42 #include "svga_surface.h"
43 #include "svga_winsys.h"
44 #include "svga_cmd.h"
45
46
47 struct svga_hwtnl *
48 svga_hwtnl_create(struct svga_context *svga)
49 {
50    struct svga_hwtnl *hwtnl = CALLOC_STRUCT(svga_hwtnl);
51    if (!hwtnl)
52       goto fail;
53
54    hwtnl->svga = svga;
55
56    hwtnl->cmd.swc = svga->swc;
57
58    return hwtnl;
59
60 fail:
61    return NULL;
62 }
63
64
65 void
66 svga_hwtnl_destroy(struct svga_hwtnl *hwtnl)
67 {
68    unsigned i, j;
69
70    for (i = 0; i < PIPE_PRIM_MAX; i++) {
71       for (j = 0; j < IDX_CACHE_MAX; j++) {
72          pipe_resource_reference(&hwtnl->index_cache[i][j].buffer, NULL);
73       }
74    }
75
76    for (i = 0; i < hwtnl->cmd.vbuf_count; i++)
77       pipe_resource_reference(&hwtnl->cmd.vbufs[i].buffer, NULL);
78
79    for (i = 0; i < hwtnl->cmd.prim_count; i++)
80       pipe_resource_reference(&hwtnl->cmd.prim_ib[i], NULL);
81
82    FREE(hwtnl);
83 }
84
85
86 void
87 svga_hwtnl_set_flatshade(struct svga_hwtnl *hwtnl,
88                          boolean flatshade, boolean flatshade_first)
89 {
90    struct svga_screen *svgascreen = svga_screen(hwtnl->svga->pipe.screen);
91
92    /* User-specified PV */
93    hwtnl->api_pv = (flatshade && !flatshade_first) ? PV_LAST : PV_FIRST;
94
95    /* Device supported PV */
96    if (svgascreen->haveProvokingVertex) {
97       /* use the mode specified by the user */
98       hwtnl->hw_pv = hwtnl->api_pv;
99    }
100    else {
101       /* the device only support first provoking vertex */
102       hwtnl->hw_pv = PV_FIRST;
103    }
104 }
105
106
107 void
108 svga_hwtnl_set_fillmode(struct svga_hwtnl *hwtnl, unsigned mode)
109 {
110    hwtnl->api_fillmode = mode;
111 }
112
113
114 void
115 svga_hwtnl_vertex_decls(struct svga_hwtnl *hwtnl,
116                         unsigned count,
117                         const SVGA3dVertexDecl * decls,
118                         const unsigned *buffer_indexes,
119                         SVGA3dElementLayoutId layout_id)
120 {
121    assert(hwtnl->cmd.prim_count == 0);
122    hwtnl->cmd.vdecl_count = count;
123    hwtnl->cmd.vdecl_layout_id = layout_id;
124    memcpy(hwtnl->cmd.vdecl, decls, count * sizeof(*decls));
125    memcpy(hwtnl->cmd.vdecl_buffer_index, buffer_indexes,
126           count * sizeof(unsigned));
127 }
128
129
130 /**
131  * Specify vertex buffers for hardware drawing.
132  */
133 void
134 svga_hwtnl_vertex_buffers(struct svga_hwtnl *hwtnl,
135                           unsigned count, struct pipe_vertex_buffer *buffers)
136 {
137    util_set_vertex_buffers_count(hwtnl->cmd.vbufs,
138                                  &hwtnl->cmd.vbuf_count, buffers, 0, count);
139 }
140
141
142 /**
143  * Determine whether the specified buffer is referred in the primitive queue,
144  * for which no commands have been written yet.
145  */
146 boolean
147 svga_hwtnl_is_buffer_referred(struct svga_hwtnl *hwtnl,
148                               struct pipe_resource *buffer)
149 {
150    unsigned i;
151
152    if (svga_buffer_is_user_buffer(buffer)) {
153       return FALSE;
154    }
155
156    if (!hwtnl->cmd.prim_count) {
157       return FALSE;
158    }
159
160    for (i = 0; i < hwtnl->cmd.vbuf_count; ++i) {
161       if (hwtnl->cmd.vbufs[i].buffer == buffer) {
162          return TRUE;
163       }
164    }
165
166    for (i = 0; i < hwtnl->cmd.prim_count; ++i) {
167       if (hwtnl->cmd.prim_ib[i] == buffer) {
168          return TRUE;
169       }
170    }
171
172    return FALSE;
173 }
174
175
176 static enum pipe_error
177 draw_vgpu9(struct svga_hwtnl *hwtnl)
178 {
179    struct svga_winsys_context *swc = hwtnl->cmd.swc;
180    struct svga_context *svga = hwtnl->svga;
181    enum pipe_error ret;
182    struct svga_winsys_surface *vb_handle[SVGA3D_INPUTREG_MAX];
183    struct svga_winsys_surface *ib_handle[QSZ];
184    struct svga_winsys_surface *handle;
185    SVGA3dVertexDecl *vdecl;
186    SVGA3dPrimitiveRange *prim;
187    unsigned i;
188
189    for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
190       unsigned j = hwtnl->cmd.vdecl_buffer_index[i];
191       handle = svga_buffer_handle(svga, hwtnl->cmd.vbufs[j].buffer);
192       if (!handle)
193          return PIPE_ERROR_OUT_OF_MEMORY;
194
195       vb_handle[i] = handle;
196    }
197
198    for (i = 0; i < hwtnl->cmd.prim_count; i++) {
199       if (hwtnl->cmd.prim_ib[i]) {
200          handle = svga_buffer_handle(svga, hwtnl->cmd.prim_ib[i]);
201          if (!handle)
202             return PIPE_ERROR_OUT_OF_MEMORY;
203       }
204       else
205          handle = NULL;
206
207       ib_handle[i] = handle;
208    }
209
210    if (svga->rebind.flags.rendertargets) {
211       ret = svga_reemit_framebuffer_bindings(svga);
212       if (ret != PIPE_OK) {
213          return ret;
214       }
215    }
216
217    if (svga->rebind.flags.texture_samplers) {
218       ret = svga_reemit_tss_bindings(svga);
219       if (ret != PIPE_OK) {
220          return ret;
221       }
222    }
223
224    if (svga->rebind.flags.vs) {
225       ret = svga_reemit_vs_bindings(svga);
226       if (ret != PIPE_OK) {
227          return ret;
228       }
229    }
230
231    if (svga->rebind.flags.fs) {
232       ret = svga_reemit_fs_bindings(svga);
233       if (ret != PIPE_OK) {
234          return ret;
235       }
236    }
237
238    SVGA_DBG(DEBUG_DMA, "draw to sid %p, %d prims\n",
239             svga->curr.framebuffer.cbufs[0] ?
240             svga_surface(svga->curr.framebuffer.cbufs[0])->handle : NULL,
241             hwtnl->cmd.prim_count);
242
243    ret = SVGA3D_BeginDrawPrimitives(swc,
244                                     &vdecl,
245                                     hwtnl->cmd.vdecl_count,
246                                     &prim, hwtnl->cmd.prim_count);
247    if (ret != PIPE_OK)
248       return ret;
249
250    memcpy(vdecl,
251           hwtnl->cmd.vdecl,
252           hwtnl->cmd.vdecl_count * sizeof hwtnl->cmd.vdecl[0]);
253
254    for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
255       /* check for 4-byte alignment */
256       assert(vdecl[i].array.offset % 4 == 0);
257       assert(vdecl[i].array.stride % 4 == 0);
258
259       /* Given rangeHint is considered to be relative to indexBias, and
260        * indexBias varies per primitive, we cannot accurately supply an
261        * rangeHint when emitting more than one primitive per draw command.
262        */
263       if (hwtnl->cmd.prim_count == 1) {
264          vdecl[i].rangeHint.first = hwtnl->cmd.min_index[0];
265          vdecl[i].rangeHint.last = hwtnl->cmd.max_index[0] + 1;
266       }
267       else {
268          vdecl[i].rangeHint.first = 0;
269          vdecl[i].rangeHint.last = 0;
270       }
271
272       swc->surface_relocation(swc,
273                               &vdecl[i].array.surfaceId,
274                               NULL, vb_handle[i], SVGA_RELOC_READ);
275    }
276
277    memcpy(prim,
278           hwtnl->cmd.prim, hwtnl->cmd.prim_count * sizeof hwtnl->cmd.prim[0]);
279
280    for (i = 0; i < hwtnl->cmd.prim_count; i++) {
281       swc->surface_relocation(swc,
282                               &prim[i].indexArray.surfaceId,
283                               NULL, ib_handle[i], SVGA_RELOC_READ);
284       pipe_resource_reference(&hwtnl->cmd.prim_ib[i], NULL);
285    }
286
287    SVGA_FIFOCommitAll(swc);
288
289    hwtnl->cmd.prim_count = 0;
290
291    return PIPE_OK;
292 }
293
294
295 static SVGA3dSurfaceFormat
296 xlate_index_format(unsigned indexWidth)
297 {
298    if (indexWidth == 2) {
299       return SVGA3D_R16_UINT;
300    }
301    else if (indexWidth == 4) {
302       return SVGA3D_R32_UINT;
303    }
304    else {
305       assert(!"Bad indexWidth");
306       return SVGA3D_R32_UINT;
307    }
308 }
309
310
311 static enum pipe_error
312 validate_sampler_resources(struct svga_context *svga)
313 {
314    unsigned shader;
315
316    assert(svga_have_vgpu10(svga));
317
318    for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) {
319       unsigned count = svga->curr.num_sampler_views[shader];
320       unsigned i;
321       struct svga_winsys_surface *surfaces[PIPE_MAX_SAMPLERS];
322       enum pipe_error ret;
323
324       /*
325        * Reference bound sampler resources to ensure pending updates are
326        * noticed by the device.
327        */
328       for (i = 0; i < count; i++) {
329          struct svga_pipe_sampler_view *sv =
330             svga_pipe_sampler_view(svga->curr.sampler_views[shader][i]);
331
332          if (sv) {
333             if (sv->base.texture->target == PIPE_BUFFER) {
334                surfaces[i] = svga_buffer_handle(svga, sv->base.texture);
335             }
336             else {
337                surfaces[i] = svga_texture(sv->base.texture)->handle;
338             }
339          }
340          else {
341             surfaces[i] = NULL;
342          }
343       }
344
345       if (shader == PIPE_SHADER_FRAGMENT &&
346           svga->curr.rast->templ.poly_stipple_enable) {
347          const unsigned unit = svga->state.hw_draw.fs->pstipple_sampler_unit;
348          struct svga_pipe_sampler_view *sv =
349             svga->polygon_stipple.sampler_view;
350
351          assert(sv);
352          surfaces[unit] = svga_texture(sv->base.texture)->handle;
353          count = MAX2(count, unit+1);
354       }
355
356       /* rebind the shader resources if needed */
357       if (svga->rebind.flags.texture_samplers) {
358          for (i = 0; i < count; i++) {
359             if (surfaces[i]) {
360                ret = svga->swc->resource_rebind(svga->swc,
361                                                 surfaces[i],
362                                                 NULL,
363                                                 SVGA_RELOC_READ);
364                if (ret != PIPE_OK)
365                   return ret;
366             }
367          }
368       }
369    }
370    svga->rebind.flags.texture_samplers = FALSE;
371
372    return PIPE_OK;
373 }
374
375
376 static enum pipe_error
377 validate_constant_buffers(struct svga_context *svga)
378 {
379    unsigned shader;
380
381    assert(svga_have_vgpu10(svga));
382
383    for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) {
384       enum pipe_error ret;
385       struct svga_buffer *buffer;
386       struct svga_winsys_surface *handle;
387       unsigned enabled_constbufs;
388
389       /* Rebind the default constant buffer if needed */
390       if (svga->rebind.flags.constbufs) {
391          buffer = svga_buffer(svga->state.hw_draw.constbuf[shader]);
392          if (buffer) {
393             ret = svga->swc->resource_rebind(svga->swc,
394                                              buffer->handle,
395                                              NULL,
396                                              SVGA_RELOC_READ);
397             if (ret != PIPE_OK)
398                return ret;
399          }
400       }
401
402       /*
403        * Reference other bound constant buffers to ensure pending updates are
404        * noticed by the device.
405        */
406       enabled_constbufs = svga->state.hw_draw.enabled_constbufs[shader] & ~1u;
407       while (enabled_constbufs) {
408          unsigned i = u_bit_scan(&enabled_constbufs);
409          buffer = svga_buffer(svga->curr.constbufs[shader][i].buffer);
410          if (buffer) {
411             handle = svga_buffer_handle(svga, &buffer->b.b);
412
413             if (svga->rebind.flags.constbufs) {
414                ret = svga->swc->resource_rebind(svga->swc,
415                                                 handle,
416                                                 NULL,
417                                                 SVGA_RELOC_READ);
418                if (ret != PIPE_OK)
419                   return ret;
420             }
421          }
422       }
423    }
424    svga->rebind.flags.constbufs = FALSE;
425
426    return PIPE_OK;
427 }
428
429
430 static enum pipe_error
431 draw_vgpu10(struct svga_hwtnl *hwtnl,
432             const SVGA3dPrimitiveRange *range,
433             unsigned vcount,
434             unsigned min_index,
435             unsigned max_index, struct pipe_resource *ib,
436             unsigned start_instance, unsigned instance_count)
437 {
438    struct svga_context *svga = hwtnl->svga;
439    struct svga_winsys_surface *vb_handle[SVGA3D_INPUTREG_MAX];
440    struct svga_winsys_surface *ib_handle;
441    const unsigned vbuf_count = hwtnl->cmd.vbuf_count;
442    enum pipe_error ret;
443    unsigned i;
444
445    assert(svga_have_vgpu10(svga));
446    assert(hwtnl->cmd.prim_count == 0);
447
448    /* We need to reemit all the current resource bindings along with the Draw
449     * command to be sure that the referenced resources are available for the
450     * Draw command, just in case the surfaces associated with the resources
451     * are paged out.
452     */
453    if (svga->rebind.val) {
454       ret = svga_rebind_framebuffer_bindings(svga);
455       if (ret != PIPE_OK)
456          return ret;
457
458       ret = svga_rebind_shaders(svga);
459       if (ret != PIPE_OK)
460          return ret;
461
462       /* Rebind index buffer */
463       if (svga->state.hw_draw.ib) {
464          struct svga_winsys_context *swc = svga->swc;
465          ret = swc->resource_rebind(swc, svga->state.hw_draw.ib, NULL, SVGA_RELOC_READ);
466          if (ret != PIPE_OK)
467             return ret;
468       }
469    }
470
471    ret = validate_sampler_resources(svga);
472    if (ret != PIPE_OK)
473       return ret;
474
475    ret = validate_constant_buffers(svga);
476    if (ret != PIPE_OK)
477       return ret;
478
479    /* Get handle for each referenced vertex buffer */
480    for (i = 0; i < vbuf_count; i++) {
481       struct svga_buffer *sbuf = svga_buffer(hwtnl->cmd.vbufs[i].buffer);
482
483       if (sbuf) {
484          assert(sbuf->key.flags & SVGA3D_SURFACE_BIND_VERTEX_BUFFER);
485          vb_handle[i] = svga_buffer_handle(svga, &sbuf->b.b);
486          if (vb_handle[i] == NULL)
487             return PIPE_ERROR_OUT_OF_MEMORY;
488       }
489       else {
490          vb_handle[i] = NULL;
491       }
492    }
493
494    /* Get handles for the index buffers */
495    if (ib) {
496       struct svga_buffer *sbuf = svga_buffer(ib);
497
498       assert(sbuf->key.flags & SVGA3D_SURFACE_BIND_INDEX_BUFFER);
499       (void) sbuf; /* silence unused var warning */
500
501       ib_handle = svga_buffer_handle(svga, ib);
502       if (!ib_handle)
503          return PIPE_ERROR_OUT_OF_MEMORY;
504    }
505    else {
506       ib_handle = NULL;
507    }
508
509    /* setup vertex attribute input layout */
510    if (svga->state.hw_draw.layout_id != hwtnl->cmd.vdecl_layout_id) {
511       ret = SVGA3D_vgpu10_SetInputLayout(svga->swc,
512                                          hwtnl->cmd.vdecl_layout_id);
513       if (ret != PIPE_OK)
514          return ret;
515
516       svga->state.hw_draw.layout_id = hwtnl->cmd.vdecl_layout_id;
517    }
518
519    /* setup vertex buffers */
520    {
521       SVGA3dVertexBuffer buffers[PIPE_MAX_ATTRIBS];
522
523       for (i = 0; i < vbuf_count; i++) {
524          buffers[i].stride = hwtnl->cmd.vbufs[i].stride;
525          buffers[i].offset = hwtnl->cmd.vbufs[i].buffer_offset;
526       }
527       if (vbuf_count > 0) {
528          /* If we haven't yet emitted a drawing command or if any
529           * vertex buffer state is changing, issue that state now.
530           */
531          if (((hwtnl->cmd.swc->hints & SVGA_HINT_FLAG_CAN_PRE_FLUSH) == 0) ||
532              vbuf_count != svga->state.hw_draw.num_vbuffers ||
533              memcmp(buffers, svga->state.hw_draw.vbuffers,
534                     vbuf_count * sizeof(buffers[0])) ||
535              memcmp(vb_handle, svga->state.hw_draw.vbuffer_handles,
536                     vbuf_count * sizeof(vb_handle[0]))) {
537             ret = SVGA3D_vgpu10_SetVertexBuffers(svga->swc, vbuf_count,
538                                                  0,    /* startBuffer */
539                                                  buffers, vb_handle);
540             if (ret != PIPE_OK)
541                return ret;
542
543             svga->state.hw_draw.num_vbuffers = vbuf_count;
544             memcpy(svga->state.hw_draw.vbuffers, buffers,
545                    vbuf_count * sizeof(buffers[0]));
546             memcpy(svga->state.hw_draw.vbuffer_handles, vb_handle,
547                    vbuf_count * sizeof(vb_handle[0]));
548          }
549       }
550    }
551
552    /* Set primitive type (line, tri, etc) */
553    if (svga->state.hw_draw.topology != range->primType) {
554       ret = SVGA3D_vgpu10_SetTopology(svga->swc, range->primType);
555       if (ret != PIPE_OK)
556          return ret;
557
558       svga->state.hw_draw.topology = range->primType;
559    }
560
561    if (ib_handle) {
562       /* indexed drawing */
563       SVGA3dSurfaceFormat indexFormat = xlate_index_format(range->indexWidth);
564
565       /* setup index buffer */
566       if (ib_handle != svga->state.hw_draw.ib ||
567           indexFormat != svga->state.hw_draw.ib_format ||
568           range->indexArray.offset != svga->state.hw_draw.ib_offset) {
569          ret = SVGA3D_vgpu10_SetIndexBuffer(svga->swc, ib_handle,
570                                             indexFormat,
571                                             range->indexArray.offset);
572          if (ret != PIPE_OK)
573             return ret;
574          svga->state.hw_draw.ib = ib_handle;
575          svga->state.hw_draw.ib_format = indexFormat;
576          svga->state.hw_draw.ib_offset = range->indexArray.offset;
577       }
578
579       if (instance_count > 1) {
580          ret = SVGA3D_vgpu10_DrawIndexedInstanced(svga->swc,
581                                                   vcount,
582                                                   instance_count,
583                                                   0, /* startIndexLocation */
584                                                   range->indexBias,
585                                                   start_instance);
586          if (ret != PIPE_OK)
587             return ret;
588       }
589       else {
590          /* non-instanced drawing */
591          ret = SVGA3D_vgpu10_DrawIndexed(svga->swc,
592                                          vcount,
593                                          0,      /* startIndexLocation */
594                                          range->indexBias);
595          if (ret != PIPE_OK)
596             return ret;
597       }
598    }
599    else {
600       /* non-indexed drawing */
601       if (svga->state.hw_draw.ib_format != SVGA3D_FORMAT_INVALID) {
602          /* Unbind previously bound index buffer */
603          ret = SVGA3D_vgpu10_SetIndexBuffer(svga->swc, NULL,
604                                             SVGA3D_FORMAT_INVALID, 0);
605          if (ret != PIPE_OK)
606             return ret;
607          svga->state.hw_draw.ib_format = SVGA3D_FORMAT_INVALID;
608          svga->state.hw_draw.ib = NULL;
609       }
610
611       if (instance_count > 1) {
612          ret = SVGA3D_vgpu10_DrawInstanced(svga->swc,
613                                            vcount,
614                                            instance_count,
615                                            range->indexBias,
616                                            start_instance);
617          if (ret != PIPE_OK)
618             return ret;
619       }
620       else {
621          /* non-instanced */
622          ret = SVGA3D_vgpu10_Draw(svga->swc,
623                                   vcount,
624                                   range->indexBias);
625          if (ret != PIPE_OK)
626             return ret;
627       }
628    }
629
630    hwtnl->cmd.prim_count = 0;
631
632    return PIPE_OK;
633 }
634
635
636
637 /**
638  * Emit any pending drawing commands to the command buffer.
639  * When we receive VGPU9 drawing commands we accumulate them and don't
640  * immediately emit them into the command buffer.
641  * This function needs to be called before we change state that could
642  * effect those pending draws.
643  */
644 enum pipe_error
645 svga_hwtnl_flush(struct svga_hwtnl *hwtnl)
646 {
647    if (!svga_have_vgpu10(hwtnl->svga) && hwtnl->cmd.prim_count) {
648       /* we only queue up primitive for VGPU9 */
649       return draw_vgpu9(hwtnl);
650    }
651    return PIPE_OK;
652 }
653
654
655 void
656 svga_hwtnl_set_index_bias(struct svga_hwtnl *hwtnl, int index_bias)
657 {
658    hwtnl->index_bias = index_bias;
659 }
660
661
662
663 /***********************************************************************
664  * Internal functions:
665  */
666
667 /**
668  * For debugging only.
669  */
670 static void
671 check_draw_params(struct svga_hwtnl *hwtnl,
672                   const SVGA3dPrimitiveRange *range,
673                   unsigned min_index, unsigned max_index,
674                   struct pipe_resource *ib)
675 {
676    unsigned i;
677
678    assert(!svga_have_vgpu10(hwtnl->svga));
679
680    for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
681       unsigned j = hwtnl->cmd.vdecl_buffer_index[i];
682       const struct pipe_vertex_buffer *vb = &hwtnl->cmd.vbufs[j];
683       unsigned size = vb->buffer ? vb->buffer->width0 : 0;
684       unsigned offset = hwtnl->cmd.vdecl[i].array.offset;
685       unsigned stride = hwtnl->cmd.vdecl[i].array.stride;
686       int index_bias = (int) range->indexBias + hwtnl->index_bias;
687       unsigned width;
688
689       if (size == 0)
690          continue;
691
692       assert(vb);
693       assert(size);
694       assert(offset < size);
695       assert(min_index <= max_index);
696       (void) width;
697       (void) stride;
698       (void) offset;
699       (void) size;
700
701       switch (hwtnl->cmd.vdecl[i].identity.type) {
702       case SVGA3D_DECLTYPE_FLOAT1:
703          width = 4;
704          break;
705       case SVGA3D_DECLTYPE_FLOAT2:
706          width = 4 * 2;
707          break;
708       case SVGA3D_DECLTYPE_FLOAT3:
709          width = 4 * 3;
710          break;
711       case SVGA3D_DECLTYPE_FLOAT4:
712          width = 4 * 4;
713          break;
714       case SVGA3D_DECLTYPE_D3DCOLOR:
715          width = 4;
716          break;
717       case SVGA3D_DECLTYPE_UBYTE4:
718          width = 1 * 4;
719          break;
720       case SVGA3D_DECLTYPE_SHORT2:
721          width = 2 * 2;
722          break;
723       case SVGA3D_DECLTYPE_SHORT4:
724          width = 2 * 4;
725          break;
726       case SVGA3D_DECLTYPE_UBYTE4N:
727          width = 1 * 4;
728          break;
729       case SVGA3D_DECLTYPE_SHORT2N:
730          width = 2 * 2;
731          break;
732       case SVGA3D_DECLTYPE_SHORT4N:
733          width = 2 * 4;
734          break;
735       case SVGA3D_DECLTYPE_USHORT2N:
736          width = 2 * 2;
737          break;
738       case SVGA3D_DECLTYPE_USHORT4N:
739          width = 2 * 4;
740          break;
741       case SVGA3D_DECLTYPE_UDEC3:
742          width = 4;
743          break;
744       case SVGA3D_DECLTYPE_DEC3N:
745          width = 4;
746          break;
747       case SVGA3D_DECLTYPE_FLOAT16_2:
748          width = 2 * 2;
749          break;
750       case SVGA3D_DECLTYPE_FLOAT16_4:
751          width = 2 * 4;
752          break;
753       default:
754          assert(0);
755          width = 0;
756          break;
757       }
758
759       if (index_bias >= 0) {
760          assert(offset + index_bias * stride + width <= size);
761       }
762
763       /*
764        * min_index/max_index are merely conservative guesses, so we can't
765        * make buffer overflow detection based on their values.
766        */
767    }
768
769    assert(range->indexWidth == range->indexArray.stride);
770
771    if (ib) {
772       unsigned size = ib->width0;
773       unsigned offset = range->indexArray.offset;
774       unsigned stride = range->indexArray.stride;
775       unsigned count;
776
777       assert(size);
778       assert(offset < size);
779       assert(stride);
780       (void) size;
781       (void) offset;
782       (void) stride;
783
784       switch (range->primType) {
785       case SVGA3D_PRIMITIVE_POINTLIST:
786          count = range->primitiveCount;
787          break;
788       case SVGA3D_PRIMITIVE_LINELIST:
789          count = range->primitiveCount * 2;
790          break;
791       case SVGA3D_PRIMITIVE_LINESTRIP:
792          count = range->primitiveCount + 1;
793          break;
794       case SVGA3D_PRIMITIVE_TRIANGLELIST:
795          count = range->primitiveCount * 3;
796          break;
797       case SVGA3D_PRIMITIVE_TRIANGLESTRIP:
798          count = range->primitiveCount + 2;
799          break;
800       case SVGA3D_PRIMITIVE_TRIANGLEFAN:
801          count = range->primitiveCount + 2;
802          break;
803       default:
804          assert(0);
805          count = 0;
806          break;
807       }
808
809       assert(offset + count * stride <= size);
810    }
811 }
812
813
814 /**
815  * All drawing filters down into this function, either directly
816  * on the hardware path or after doing software vertex processing.
817  */
818 enum pipe_error
819 svga_hwtnl_prim(struct svga_hwtnl *hwtnl,
820                 const SVGA3dPrimitiveRange * range,
821                 unsigned vcount,
822                 unsigned min_index,
823                 unsigned max_index, struct pipe_resource *ib,
824                 unsigned start_instance, unsigned instance_count)
825 {
826    enum pipe_error ret = PIPE_OK;
827
828    if (svga_have_vgpu10(hwtnl->svga)) {
829       /* draw immediately */
830       ret = draw_vgpu10(hwtnl, range, vcount, min_index, max_index, ib,
831                         start_instance, instance_count);
832       if (ret != PIPE_OK) {
833          svga_context_flush(hwtnl->svga, NULL);
834          ret = draw_vgpu10(hwtnl, range, vcount, min_index, max_index, ib,
835                            start_instance, instance_count);
836          assert(ret == PIPE_OK);
837       }
838    }
839    else {
840       /* batch up drawing commands */
841 #ifdef DEBUG
842       check_draw_params(hwtnl, range, min_index, max_index, ib);
843       assert(start_instance == 0);
844       assert(instance_count <= 1);
845 #else
846       (void) check_draw_params;
847 #endif
848
849       if (hwtnl->cmd.prim_count + 1 >= QSZ) {
850          ret = svga_hwtnl_flush(hwtnl);
851          if (ret != PIPE_OK)
852             return ret;
853       }
854
855       /* min/max indices are relative to bias */
856       hwtnl->cmd.min_index[hwtnl->cmd.prim_count] = min_index;
857       hwtnl->cmd.max_index[hwtnl->cmd.prim_count] = max_index;
858
859       hwtnl->cmd.prim[hwtnl->cmd.prim_count] = *range;
860       hwtnl->cmd.prim[hwtnl->cmd.prim_count].indexBias += hwtnl->index_bias;
861
862       pipe_resource_reference(&hwtnl->cmd.prim_ib[hwtnl->cmd.prim_count], ib);
863       hwtnl->cmd.prim_count++;
864    }
865
866    return ret;
867 }