1 /**********************************************************
2 * Copyright 2008-2009 VMware, Inc. All rights reserved.
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:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
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
24 **********************************************************/
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"
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"
48 svga_hwtnl_create(struct svga_context
*svga
)
50 struct svga_hwtnl
*hwtnl
= CALLOC_STRUCT(svga_hwtnl
);
56 hwtnl
->cmd
.swc
= svga
->swc
;
66 svga_hwtnl_destroy(struct svga_hwtnl
*hwtnl
)
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
);
76 for (i
= 0; i
< hwtnl
->cmd
.vbuf_count
; i
++)
77 pipe_resource_reference(&hwtnl
->cmd
.vbufs
[i
].buffer
, NULL
);
79 for (i
= 0; i
< hwtnl
->cmd
.prim_count
; i
++)
80 pipe_resource_reference(&hwtnl
->cmd
.prim_ib
[i
], NULL
);
87 svga_hwtnl_set_flatshade(struct svga_hwtnl
*hwtnl
,
88 boolean flatshade
, boolean flatshade_first
)
90 struct svga_screen
*svgascreen
= svga_screen(hwtnl
->svga
->pipe
.screen
);
92 /* User-specified PV */
93 hwtnl
->api_pv
= (flatshade
&& !flatshade_first
) ? PV_LAST
: PV_FIRST
;
95 /* Device supported PV */
96 if (svgascreen
->haveProvokingVertex
) {
97 /* use the mode specified by the user */
98 hwtnl
->hw_pv
= hwtnl
->api_pv
;
101 /* the device only support first provoking vertex */
102 hwtnl
->hw_pv
= PV_FIRST
;
108 svga_hwtnl_set_fillmode(struct svga_hwtnl
*hwtnl
, unsigned mode
)
110 hwtnl
->api_fillmode
= mode
;
115 svga_hwtnl_vertex_decls(struct svga_hwtnl
*hwtnl
,
117 const SVGA3dVertexDecl
* decls
,
118 const unsigned *buffer_indexes
,
119 SVGA3dElementLayoutId layout_id
)
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));
131 * Specify vertex buffers for hardware drawing.
134 svga_hwtnl_vertex_buffers(struct svga_hwtnl
*hwtnl
,
135 unsigned count
, struct pipe_vertex_buffer
*buffers
)
137 util_set_vertex_buffers_count(hwtnl
->cmd
.vbufs
,
138 &hwtnl
->cmd
.vbuf_count
, buffers
, 0, count
);
143 * Determine whether the specified buffer is referred in the primitive queue,
144 * for which no commands have been written yet.
147 svga_hwtnl_is_buffer_referred(struct svga_hwtnl
*hwtnl
,
148 struct pipe_resource
*buffer
)
152 if (svga_buffer_is_user_buffer(buffer
)) {
156 if (!hwtnl
->cmd
.prim_count
) {
160 for (i
= 0; i
< hwtnl
->cmd
.vbuf_count
; ++i
) {
161 if (hwtnl
->cmd
.vbufs
[i
].buffer
== buffer
) {
166 for (i
= 0; i
< hwtnl
->cmd
.prim_count
; ++i
) {
167 if (hwtnl
->cmd
.prim_ib
[i
] == buffer
) {
176 static enum pipe_error
177 draw_vgpu9(struct svga_hwtnl
*hwtnl
)
179 struct svga_winsys_context
*swc
= hwtnl
->cmd
.swc
;
180 struct svga_context
*svga
= hwtnl
->svga
;
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
;
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
);
193 return PIPE_ERROR_OUT_OF_MEMORY
;
195 vb_handle
[i
] = handle
;
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
]);
202 return PIPE_ERROR_OUT_OF_MEMORY
;
207 ib_handle
[i
] = handle
;
210 if (svga
->rebind
.flags
.rendertargets
) {
211 ret
= svga_reemit_framebuffer_bindings(svga
);
212 if (ret
!= PIPE_OK
) {
217 if (svga
->rebind
.flags
.texture_samplers
) {
218 ret
= svga_reemit_tss_bindings(svga
);
219 if (ret
!= PIPE_OK
) {
224 if (svga
->rebind
.flags
.vs
) {
225 ret
= svga_reemit_vs_bindings(svga
);
226 if (ret
!= PIPE_OK
) {
231 if (svga
->rebind
.flags
.fs
) {
232 ret
= svga_reemit_fs_bindings(svga
);
233 if (ret
!= PIPE_OK
) {
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
);
243 ret
= SVGA3D_BeginDrawPrimitives(swc
,
245 hwtnl
->cmd
.vdecl_count
,
246 &prim
, hwtnl
->cmd
.prim_count
);
252 hwtnl
->cmd
.vdecl_count
* sizeof hwtnl
->cmd
.vdecl
[0]);
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);
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.
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;
268 vdecl
[i
].rangeHint
.first
= 0;
269 vdecl
[i
].rangeHint
.last
= 0;
272 swc
->surface_relocation(swc
,
273 &vdecl
[i
].array
.surfaceId
,
274 NULL
, vb_handle
[i
], SVGA_RELOC_READ
);
278 hwtnl
->cmd
.prim
, hwtnl
->cmd
.prim_count
* sizeof hwtnl
->cmd
.prim
[0]);
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
);
287 SVGA_FIFOCommitAll(swc
);
289 hwtnl
->cmd
.prim_count
= 0;
295 static SVGA3dSurfaceFormat
296 xlate_index_format(unsigned indexWidth
)
298 if (indexWidth
== 2) {
299 return SVGA3D_R16_UINT
;
301 else if (indexWidth
== 4) {
302 return SVGA3D_R32_UINT
;
305 assert(!"Bad indexWidth");
306 return SVGA3D_R32_UINT
;
311 static enum pipe_error
312 validate_sampler_resources(struct svga_context
*svga
)
314 enum pipe_shader_type shader
;
316 assert(svga_have_vgpu10(svga
));
318 for (shader
= PIPE_SHADER_VERTEX
; shader
<= PIPE_SHADER_GEOMETRY
; shader
++) {
319 unsigned count
= svga
->curr
.num_sampler_views
[shader
];
321 struct svga_winsys_surface
*surfaces
[PIPE_MAX_SAMPLERS
];
325 * Reference bound sampler resources to ensure pending updates are
326 * noticed by the device.
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
]);
333 if (sv
->base
.texture
->target
== PIPE_BUFFER
) {
334 surfaces
[i
] = svga_buffer_handle(svga
, sv
->base
.texture
);
337 surfaces
[i
] = svga_texture(sv
->base
.texture
)->handle
;
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
;
352 surfaces
[unit
] = svga_texture(sv
->base
.texture
)->handle
;
353 count
= MAX2(count
, unit
+1);
356 /* rebind the shader resources if needed */
357 if (svga
->rebind
.flags
.texture_samplers
) {
358 for (i
= 0; i
< count
; i
++) {
360 ret
= svga
->swc
->resource_rebind(svga
->swc
,
370 svga
->rebind
.flags
.texture_samplers
= FALSE
;
376 static enum pipe_error
377 validate_constant_buffers(struct svga_context
*svga
)
379 enum pipe_shader_type shader
;
381 assert(svga_have_vgpu10(svga
));
383 for (shader
= PIPE_SHADER_VERTEX
; shader
<= PIPE_SHADER_GEOMETRY
; shader
++) {
385 struct svga_buffer
*buffer
;
386 struct svga_winsys_surface
*handle
;
387 unsigned enabled_constbufs
;
389 /* Rebind the default constant buffer if needed */
390 if (svga
->rebind
.flags
.constbufs
) {
391 buffer
= svga_buffer(svga
->state
.hw_draw
.constbuf
[shader
]);
393 ret
= svga
->swc
->resource_rebind(svga
->swc
,
403 * Reference other bound constant buffers to ensure pending updates are
404 * noticed by the device.
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
);
411 handle
= svga_buffer_handle(svga
, &buffer
->b
.b
);
413 if (svga
->rebind
.flags
.constbufs
) {
414 ret
= svga
->swc
->resource_rebind(svga
->swc
,
424 svga
->rebind
.flags
.constbufs
= FALSE
;
431 * Was the last command put into the command buffer a drawing command?
432 * We use this to determine if we can skip emitting buffer re-bind
433 * commands when we have a sequence of drawing commands that use the
434 * same vertex/index buffers with no intervening commands.
436 * The first drawing command will bind the vertex/index buffers. If
437 * the immediately following command is also a drawing command using the
438 * same buffers, we shouldn't have to rebind them.
441 last_command_was_draw(const struct svga_context
*svga
)
443 switch (SVGA3D_GetLastCommand(svga
->swc
)) {
444 case SVGA_3D_CMD_DX_DRAW
:
445 case SVGA_3D_CMD_DX_DRAW_INDEXED
:
446 case SVGA_3D_CMD_DX_DRAW_INSTANCED
:
447 case SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED
:
448 case SVGA_3D_CMD_DX_DRAW_AUTO
:
456 static enum pipe_error
457 draw_vgpu10(struct svga_hwtnl
*hwtnl
,
458 const SVGA3dPrimitiveRange
*range
,
461 unsigned max_index
, struct pipe_resource
*ib
,
462 unsigned start_instance
, unsigned instance_count
)
464 struct svga_context
*svga
= hwtnl
->svga
;
465 struct pipe_resource
*vbuffers
[SVGA3D_INPUTREG_MAX
];
466 struct svga_winsys_surface
*vbuffer_handles
[SVGA3D_INPUTREG_MAX
];
467 struct svga_winsys_surface
*ib_handle
;
468 const unsigned vbuf_count
= hwtnl
->cmd
.vbuf_count
;
473 assert(svga_have_vgpu10(svga
));
474 assert(hwtnl
->cmd
.prim_count
== 0);
476 /* We need to reemit all the current resource bindings along with the Draw
477 * command to be sure that the referenced resources are available for the
478 * Draw command, just in case the surfaces associated with the resources
481 if (svga
->rebind
.val
) {
482 ret
= svga_rebind_framebuffer_bindings(svga
);
486 ret
= svga_rebind_shaders(svga
);
490 /* Rebind stream output targets */
491 ret
= svga_rebind_stream_output_targets(svga
);
495 /* No need to explicitly rebind index buffer and vertex buffers here.
496 * Even if the same index buffer or vertex buffers are referenced for this
497 * draw and we skip emitting the redundant set command, we will still
498 * reference the associated resources.
502 ret
= validate_sampler_resources(svga
);
506 ret
= validate_constant_buffers(svga
);
510 /* Get handle for each referenced vertex buffer */
511 for (i
= 0; i
< vbuf_count
; i
++) {
512 struct svga_buffer
*sbuf
= svga_buffer(hwtnl
->cmd
.vbufs
[i
].buffer
);
515 assert(sbuf
->key
.flags
& SVGA3D_SURFACE_BIND_VERTEX_BUFFER
);
516 vbuffer_handles
[i
] = svga_buffer_handle(svga
, &sbuf
->b
.b
);
517 if (vbuffer_handles
[i
] == NULL
)
518 return PIPE_ERROR_OUT_OF_MEMORY
;
519 vbuffers
[i
] = &sbuf
->b
.b
;
524 vbuffer_handles
[i
] = NULL
;
528 for (; i
< svga
->state
.hw_draw
.num_vbuffers
; i
++) {
530 vbuffer_handles
[i
] = NULL
;
533 /* Get handle for the index buffer */
535 struct svga_buffer
*sbuf
= svga_buffer(ib
);
537 assert(sbuf
->key
.flags
& SVGA3D_SURFACE_BIND_INDEX_BUFFER
);
538 (void) sbuf
; /* silence unused var warning */
540 ib_handle
= svga_buffer_handle(svga
, ib
);
542 return PIPE_ERROR_OUT_OF_MEMORY
;
548 /* setup vertex attribute input layout */
549 if (svga
->state
.hw_draw
.layout_id
!= hwtnl
->cmd
.vdecl_layout_id
) {
550 ret
= SVGA3D_vgpu10_SetInputLayout(svga
->swc
,
551 hwtnl
->cmd
.vdecl_layout_id
);
555 svga
->state
.hw_draw
.layout_id
= hwtnl
->cmd
.vdecl_layout_id
;
558 /* setup vertex buffers */
560 SVGA3dVertexBuffer vbuffer_attrs
[PIPE_MAX_ATTRIBS
];
562 for (i
= 0; i
< vbuf_count
; i
++) {
563 vbuffer_attrs
[i
].stride
= hwtnl
->cmd
.vbufs
[i
].stride
;
564 vbuffer_attrs
[i
].offset
= hwtnl
->cmd
.vbufs
[i
].buffer_offset
;
565 vbuffer_attrs
[i
].sid
= 0;
568 /* If we haven't yet emitted a drawing command or if any
569 * vertex buffer state is changing, issue that state now.
571 if (((hwtnl
->cmd
.swc
->hints
& SVGA_HINT_FLAG_CAN_PRE_FLUSH
) == 0) ||
572 vbuf_count
!= svga
->state
.hw_draw
.num_vbuffers
||
573 memcmp(vbuffer_attrs
, svga
->state
.hw_draw
.vbuffer_attrs
,
574 vbuf_count
* sizeof(vbuffer_attrs
[0])) ||
575 memcmp(vbuffers
, svga
->state
.hw_draw
.vbuffers
,
576 vbuf_count
* sizeof(vbuffers
[0]))) {
578 unsigned num_vbuffers
;
580 /* get the max of the current bound vertex buffers count and
581 * the to-be-bound vertex buffers count, so as to unbind
582 * the unused vertex buffers.
584 num_vbuffers
= MAX2(vbuf_count
, svga
->state
.hw_draw
.num_vbuffers
);
586 if (num_vbuffers
> 0) {
588 ret
= SVGA3D_vgpu10_SetVertexBuffers(svga
->swc
, num_vbuffers
,
595 /* save the number of vertex buffers sent to the device, not
596 * including trailing unbound vertex buffers.
598 svga
->state
.hw_draw
.num_vbuffers
= last_vbuf
+ 1;
599 memcpy(svga
->state
.hw_draw
.vbuffer_attrs
, vbuffer_attrs
,
600 num_vbuffers
* sizeof(vbuffer_attrs
[0]));
601 for (i
= 0; i
< num_vbuffers
; i
++) {
602 pipe_resource_reference(&svga
->state
.hw_draw
.vbuffers
[i
],
608 /* Even though we can avoid emitting the redundant SetVertexBuffers
609 * command, we still need to reference the vertex buffers surfaces.
611 for (i
= 0; i
< vbuf_count
; i
++) {
612 if (vbuffer_handles
[i
] && !last_command_was_draw(svga
)) {
613 ret
= svga
->swc
->resource_rebind(svga
->swc
, vbuffer_handles
[i
],
614 NULL
, SVGA_RELOC_READ
);
622 /* Set primitive type (line, tri, etc) */
623 if (svga
->state
.hw_draw
.topology
!= range
->primType
) {
624 ret
= SVGA3D_vgpu10_SetTopology(svga
->swc
, range
->primType
);
628 svga
->state
.hw_draw
.topology
= range
->primType
;
632 /* indexed drawing */
633 SVGA3dSurfaceFormat indexFormat
= xlate_index_format(range
->indexWidth
);
635 /* setup index buffer */
636 if (ib
!= svga
->state
.hw_draw
.ib
||
637 indexFormat
!= svga
->state
.hw_draw
.ib_format
||
638 range
->indexArray
.offset
!= svga
->state
.hw_draw
.ib_offset
) {
640 assert(indexFormat
!= SVGA3D_FORMAT_INVALID
);
641 ret
= SVGA3D_vgpu10_SetIndexBuffer(svga
->swc
, ib_handle
,
643 range
->indexArray
.offset
);
647 pipe_resource_reference(&svga
->state
.hw_draw
.ib
, ib
);
648 svga
->state
.hw_draw
.ib_format
= indexFormat
;
649 svga
->state
.hw_draw
.ib_offset
= range
->indexArray
.offset
;
652 /* Even though we can avoid emitting the redundant SetIndexBuffer
653 * command, we still need to reference the index buffer surface.
655 if (!last_command_was_draw(svga
)) {
656 ret
= svga
->swc
->resource_rebind(svga
->swc
, ib_handle
,
657 NULL
, SVGA_RELOC_READ
);
663 if (instance_count
> 1) {
664 ret
= SVGA3D_vgpu10_DrawIndexedInstanced(svga
->swc
,
667 0, /* startIndexLocation */
674 /* non-instanced drawing */
675 ret
= SVGA3D_vgpu10_DrawIndexed(svga
->swc
,
677 0, /* startIndexLocation */
684 /* non-indexed drawing */
685 if (svga
->state
.hw_draw
.ib_format
!= SVGA3D_FORMAT_INVALID
||
686 svga
->state
.hw_draw
.ib
!= NULL
) {
687 /* Unbind previously bound index buffer */
688 ret
= SVGA3D_vgpu10_SetIndexBuffer(svga
->swc
, NULL
,
689 SVGA3D_FORMAT_INVALID
, 0);
692 pipe_resource_reference(&svga
->state
.hw_draw
.ib
, NULL
);
693 svga
->state
.hw_draw
.ib_format
= SVGA3D_FORMAT_INVALID
;
696 assert(svga
->state
.hw_draw
.ib
== NULL
);
698 if (instance_count
> 1) {
699 ret
= SVGA3D_vgpu10_DrawInstanced(svga
->swc
,
709 ret
= SVGA3D_vgpu10_Draw(svga
->swc
,
717 hwtnl
->cmd
.prim_count
= 0;
725 * Emit any pending drawing commands to the command buffer.
726 * When we receive VGPU9 drawing commands we accumulate them and don't
727 * immediately emit them into the command buffer.
728 * This function needs to be called before we change state that could
729 * effect those pending draws.
732 svga_hwtnl_flush(struct svga_hwtnl
*hwtnl
)
734 enum pipe_error ret
= PIPE_OK
;
736 SVGA_STATS_TIME_PUSH(svga_sws(hwtnl
->svga
), SVGA_STATS_TIME_HWTNLFLUSH
);
738 if (!svga_have_vgpu10(hwtnl
->svga
) && hwtnl
->cmd
.prim_count
) {
739 /* we only queue up primitive for VGPU9 */
740 ret
= draw_vgpu9(hwtnl
);
743 SVGA_STATS_TIME_POP(svga_screen(hwtnl
->svga
->pipe
.screen
)->sws
);
749 svga_hwtnl_set_index_bias(struct svga_hwtnl
*hwtnl
, int index_bias
)
751 hwtnl
->index_bias
= index_bias
;
756 /***********************************************************************
757 * Internal functions:
761 * For debugging only.
764 check_draw_params(struct svga_hwtnl
*hwtnl
,
765 const SVGA3dPrimitiveRange
*range
,
766 unsigned min_index
, unsigned max_index
,
767 struct pipe_resource
*ib
)
771 assert(!svga_have_vgpu10(hwtnl
->svga
));
773 for (i
= 0; i
< hwtnl
->cmd
.vdecl_count
; i
++) {
774 unsigned j
= hwtnl
->cmd
.vdecl_buffer_index
[i
];
775 const struct pipe_vertex_buffer
*vb
= &hwtnl
->cmd
.vbufs
[j
];
776 unsigned size
= vb
->buffer
? vb
->buffer
->width0
: 0;
777 unsigned offset
= hwtnl
->cmd
.vdecl
[i
].array
.offset
;
778 unsigned stride
= hwtnl
->cmd
.vdecl
[i
].array
.stride
;
779 int index_bias
= (int) range
->indexBias
+ hwtnl
->index_bias
;
787 assert(offset
< size
);
788 assert(min_index
<= max_index
);
794 switch (hwtnl
->cmd
.vdecl
[i
].identity
.type
) {
795 case SVGA3D_DECLTYPE_FLOAT1
:
798 case SVGA3D_DECLTYPE_FLOAT2
:
801 case SVGA3D_DECLTYPE_FLOAT3
:
804 case SVGA3D_DECLTYPE_FLOAT4
:
807 case SVGA3D_DECLTYPE_D3DCOLOR
:
810 case SVGA3D_DECLTYPE_UBYTE4
:
813 case SVGA3D_DECLTYPE_SHORT2
:
816 case SVGA3D_DECLTYPE_SHORT4
:
819 case SVGA3D_DECLTYPE_UBYTE4N
:
822 case SVGA3D_DECLTYPE_SHORT2N
:
825 case SVGA3D_DECLTYPE_SHORT4N
:
828 case SVGA3D_DECLTYPE_USHORT2N
:
831 case SVGA3D_DECLTYPE_USHORT4N
:
834 case SVGA3D_DECLTYPE_UDEC3
:
837 case SVGA3D_DECLTYPE_DEC3N
:
840 case SVGA3D_DECLTYPE_FLOAT16_2
:
843 case SVGA3D_DECLTYPE_FLOAT16_4
:
852 if (index_bias
>= 0) {
853 assert(offset
+ index_bias
* stride
+ width
<= size
);
857 * min_index/max_index are merely conservative guesses, so we can't
858 * make buffer overflow detection based on their values.
862 assert(range
->indexWidth
== range
->indexArray
.stride
);
865 MAYBE_UNUSED
unsigned size
= ib
->width0
;
866 MAYBE_UNUSED
unsigned offset
= range
->indexArray
.offset
;
867 MAYBE_UNUSED
unsigned stride
= range
->indexArray
.stride
;
868 MAYBE_UNUSED
unsigned count
;
871 assert(offset
< size
);
874 switch (range
->primType
) {
875 case SVGA3D_PRIMITIVE_POINTLIST
:
876 count
= range
->primitiveCount
;
878 case SVGA3D_PRIMITIVE_LINELIST
:
879 count
= range
->primitiveCount
* 2;
881 case SVGA3D_PRIMITIVE_LINESTRIP
:
882 count
= range
->primitiveCount
+ 1;
884 case SVGA3D_PRIMITIVE_TRIANGLELIST
:
885 count
= range
->primitiveCount
* 3;
887 case SVGA3D_PRIMITIVE_TRIANGLESTRIP
:
888 count
= range
->primitiveCount
+ 2;
890 case SVGA3D_PRIMITIVE_TRIANGLEFAN
:
891 count
= range
->primitiveCount
+ 2;
899 assert(offset
+ count
* stride
<= size
);
905 * All drawing filters down into this function, either directly
906 * on the hardware path or after doing software vertex processing.
909 svga_hwtnl_prim(struct svga_hwtnl
*hwtnl
,
910 const SVGA3dPrimitiveRange
* range
,
913 unsigned max_index
, struct pipe_resource
*ib
,
914 unsigned start_instance
, unsigned instance_count
)
916 enum pipe_error ret
= PIPE_OK
;
918 SVGA_STATS_TIME_PUSH(svga_sws(hwtnl
->svga
), SVGA_STATS_TIME_HWTNLPRIM
);
920 if (svga_have_vgpu10(hwtnl
->svga
)) {
921 /* draw immediately */
922 ret
= draw_vgpu10(hwtnl
, range
, vcount
, min_index
, max_index
, ib
,
923 start_instance
, instance_count
);
924 if (ret
!= PIPE_OK
) {
925 svga_context_flush(hwtnl
->svga
, NULL
);
926 ret
= draw_vgpu10(hwtnl
, range
, vcount
, min_index
, max_index
, ib
,
927 start_instance
, instance_count
);
928 assert(ret
== PIPE_OK
);
932 /* batch up drawing commands */
934 check_draw_params(hwtnl
, range
, min_index
, max_index
, ib
);
935 assert(start_instance
== 0);
936 assert(instance_count
<= 1);
938 (void) check_draw_params
;
941 if (hwtnl
->cmd
.prim_count
+ 1 >= QSZ
) {
942 ret
= svga_hwtnl_flush(hwtnl
);
947 /* min/max indices are relative to bias */
948 hwtnl
->cmd
.min_index
[hwtnl
->cmd
.prim_count
] = min_index
;
949 hwtnl
->cmd
.max_index
[hwtnl
->cmd
.prim_count
] = max_index
;
951 hwtnl
->cmd
.prim
[hwtnl
->cmd
.prim_count
] = *range
;
952 hwtnl
->cmd
.prim
[hwtnl
->cmd
.prim_count
].indexBias
+= hwtnl
->index_bias
;
954 pipe_resource_reference(&hwtnl
->cmd
.prim_ib
[hwtnl
->cmd
.prim_count
], ib
);
955 hwtnl
->cmd
.prim_count
++;
959 SVGA_STATS_TIME_POP(svga_screen(hwtnl
->svga
->pipe
.screen
)->sws
);