| /********************************************************** |
| * Copyright 2008-2009 VMware, Inc. All rights reserved. |
| * |
| * Permission is hereby granted, free of charge, to any person |
| * obtaining a copy of this software and associated documentation |
| * files (the "Software"), to deal in the Software without |
| * restriction, including without limitation the rights to use, copy, |
| * modify, merge, publish, distribute, sublicense, and/or sell copies |
| * of the Software, and to permit persons to whom the Software is |
| * furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be |
| * included in all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| * SOFTWARE. |
| * |
| **********************************************************/ |
| |
| #include "util/u_inlines.h" |
| #include "pipe/p_defines.h" |
| #include "util/u_math.h" |
| #include "util/u_upload_mgr.h" |
| |
| #include "svga_context.h" |
| #include "svga_state.h" |
| #include "svga_draw.h" |
| #include "svga_tgsi.h" |
| #include "svga_screen.h" |
| #include "svga_shader.h" |
| #include "svga_resource_buffer.h" |
| #include "svga_hw_reg.h" |
| |
| |
| |
| static enum pipe_error |
| emit_hw_vs_vdecl(struct svga_context *svga, unsigned dirty) |
| { |
| const struct pipe_vertex_element *ve = svga->curr.velems->velem; |
| SVGA3dVertexDecl decls[SVGA3D_INPUTREG_MAX]; |
| unsigned buffer_indexes[SVGA3D_INPUTREG_MAX]; |
| unsigned i; |
| unsigned neg_bias = 0; |
| |
| assert(svga->curr.velems->count >= |
| svga->curr.vs->base.info.file_count[TGSI_FILE_INPUT]); |
| |
| /** |
| * We can't set the VDECL offset to something negative, so we |
| * must calculate a common negative additional index bias, and modify |
| * the VDECL offsets accordingly so they *all* end up positive. |
| * |
| * Note that the exact value of the negative index bias is not that |
| * important, since we compensate for it when we calculate the vertex |
| * buffer offset below. The important thing is that all vertex buffer |
| * offsets remain positive. |
| * |
| * Note that we use a negative bias variable in order to make the |
| * rounding maths more easy to follow, and to avoid int / unsigned |
| * confusion. |
| */ |
| |
| for (i = 0; i < svga->curr.velems->count; i++) { |
| const struct pipe_vertex_buffer *vb = |
| &svga->curr.vb[ve[i].vertex_buffer_index]; |
| struct svga_buffer *buffer; |
| unsigned int offset = vb->buffer_offset + ve[i].src_offset; |
| unsigned tmp_neg_bias = 0; |
| |
| if (!vb->buffer.resource) |
| continue; |
| |
| buffer = svga_buffer(vb->buffer.resource); |
| if (buffer->uploaded.start > offset) { |
| tmp_neg_bias = buffer->uploaded.start - offset; |
| if (vb->stride) |
| tmp_neg_bias = (tmp_neg_bias + vb->stride - 1) / vb->stride; |
| neg_bias = MAX2(neg_bias, tmp_neg_bias); |
| } |
| } |
| |
| for (i = 0; i < svga->curr.velems->count; i++) { |
| const struct pipe_vertex_buffer *vb = |
| &svga->curr.vb[ve[i].vertex_buffer_index]; |
| unsigned usage, index; |
| struct svga_buffer *buffer; |
| |
| if (!vb->buffer.resource) |
| continue; |
| |
| buffer = svga_buffer(vb->buffer.resource); |
| svga_generate_vdecl_semantics( i, &usage, &index ); |
| |
| /* SVGA_NEW_VELEMENT |
| */ |
| decls[i].identity.type = svga->curr.velems->decl_type[i]; |
| decls[i].identity.method = SVGA3D_DECLMETHOD_DEFAULT; |
| decls[i].identity.usage = usage; |
| decls[i].identity.usageIndex = index; |
| decls[i].array.stride = vb->stride; |
| |
| /* Compensate for partially uploaded vbo, and |
| * for the negative index bias. |
| */ |
| decls[i].array.offset = (vb->buffer_offset |
| + ve[i].src_offset |
| + neg_bias * vb->stride |
| - buffer->uploaded.start); |
| |
| assert(decls[i].array.offset >= 0); |
| |
| buffer_indexes[i] = ve[i].vertex_buffer_index; |
| |
| assert(!buffer->uploaded.buffer); |
| } |
| |
| svga_hwtnl_vertex_decls(svga->hwtnl, |
| svga->curr.velems->count, |
| decls, |
| buffer_indexes, |
| svga->curr.velems->id); |
| |
| svga_hwtnl_vertex_buffers(svga->hwtnl, |
| svga->curr.num_vertex_buffers, |
| svga->curr.vb); |
| |
| svga_hwtnl_set_index_bias( svga->hwtnl, -(int) neg_bias ); |
| return PIPE_OK; |
| } |
| |
| |
| static enum pipe_error |
| emit_hw_vdecl(struct svga_context *svga, unsigned dirty) |
| { |
| /* SVGA_NEW_NEED_SWTNL |
| */ |
| if (svga->state.sw.need_swtnl) |
| return PIPE_OK; /* Do not emit during swtnl */ |
| |
| return emit_hw_vs_vdecl( svga, dirty ); |
| } |
| |
| |
| struct svga_tracked_state svga_hw_vdecl = |
| { |
| "hw vertex decl state (hwtnl version)", |
| ( SVGA_NEW_NEED_SWTNL | |
| SVGA_NEW_VELEMENT | |
| SVGA_NEW_VBUFFER | |
| SVGA_NEW_RAST | |
| SVGA_NEW_FS | |
| SVGA_NEW_VS ), |
| emit_hw_vdecl |
| }; |