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_defines.h" 27#include "util/u_bitmask.h" 28#include "util/format/u_format.h" 29#include "util/u_helpers.h" 30#include "util/u_inlines.h" 31#include "util/u_math.h" 32#include "util/u_memory.h" 33#include "util/u_transfer.h" 34#include "tgsi/tgsi_parse.h" 35 36#include "svga_context.h" 37#include "svga_cmd.h" 38#include "svga_format.h" 39#include "svga_resource_buffer.h" 40#include "svga_screen.h" 41 42 43static void 44svga_set_vertex_buffers(struct pipe_context *pipe, 45 unsigned start_slot, unsigned count, 46 unsigned unbind_num_trailing_slots, 47 bool take_ownership, 48 const struct pipe_vertex_buffer *buffers) 49{ 50 struct svga_context *svga = svga_context(pipe); 51 52 util_set_vertex_buffers_count(svga->curr.vb, 53 &svga->curr.num_vertex_buffers, 54 buffers, start_slot, count, 55 unbind_num_trailing_slots, 56 take_ownership); 57 58 svga->dirty |= SVGA_NEW_VBUFFER; 59} 60 61 62/** 63 * Does the given vertex attrib format need range adjustment in the VS? 64 * Range adjustment scales and biases values from [0,1] to [-1,1]. 65 * This lets us avoid the swtnl path. 66 */ 67static boolean 68attrib_needs_range_adjustment(enum pipe_format format) 69{ 70 switch (format) { 71 case PIPE_FORMAT_R8G8B8_SNORM: 72 return TRUE; 73 default: 74 return FALSE; 75 } 76} 77 78 79/** 80 * Given a gallium vertex element format, return the corresponding 81 * SVGA3dDeclType. 82 */ 83static SVGA3dDeclType 84translate_vertex_format_to_decltype(enum pipe_format format) 85{ 86 switch (format) { 87 case PIPE_FORMAT_R32_FLOAT: return SVGA3D_DECLTYPE_FLOAT1; 88 case PIPE_FORMAT_R32G32_FLOAT: return SVGA3D_DECLTYPE_FLOAT2; 89 case PIPE_FORMAT_R32G32B32_FLOAT: return SVGA3D_DECLTYPE_FLOAT3; 90 case PIPE_FORMAT_R32G32B32A32_FLOAT: return SVGA3D_DECLTYPE_FLOAT4; 91 case PIPE_FORMAT_B8G8R8A8_UNORM: return SVGA3D_DECLTYPE_D3DCOLOR; 92 case PIPE_FORMAT_R8G8B8A8_USCALED: return SVGA3D_DECLTYPE_UBYTE4; 93 case PIPE_FORMAT_R16G16_SSCALED: return SVGA3D_DECLTYPE_SHORT2; 94 case PIPE_FORMAT_R16G16B16A16_SSCALED: return SVGA3D_DECLTYPE_SHORT4; 95 case PIPE_FORMAT_R8G8B8A8_UNORM: return SVGA3D_DECLTYPE_UBYTE4N; 96 case PIPE_FORMAT_R16G16_SNORM: return SVGA3D_DECLTYPE_SHORT2N; 97 case PIPE_FORMAT_R16G16B16A16_SNORM: return SVGA3D_DECLTYPE_SHORT4N; 98 case PIPE_FORMAT_R16G16_UNORM: return SVGA3D_DECLTYPE_USHORT2N; 99 case PIPE_FORMAT_R16G16B16A16_UNORM: return SVGA3D_DECLTYPE_USHORT4N; 100 case PIPE_FORMAT_R10G10B10X2_USCALED: return SVGA3D_DECLTYPE_UDEC3; 101 case PIPE_FORMAT_R10G10B10X2_SNORM: return SVGA3D_DECLTYPE_DEC3N; 102 case PIPE_FORMAT_R16G16_FLOAT: return SVGA3D_DECLTYPE_FLOAT16_2; 103 case PIPE_FORMAT_R16G16B16A16_FLOAT: return SVGA3D_DECLTYPE_FLOAT16_4; 104 105 /* See attrib_needs_adjustment() and attrib_needs_w_to_1() above */ 106 case PIPE_FORMAT_R8G8B8_SNORM: return SVGA3D_DECLTYPE_UBYTE4N; 107 108 /* See attrib_needs_w_to_1() above */ 109 case PIPE_FORMAT_R16G16B16_SNORM: return SVGA3D_DECLTYPE_SHORT4N; 110 case PIPE_FORMAT_R16G16B16_UNORM: return SVGA3D_DECLTYPE_USHORT4N; 111 case PIPE_FORMAT_R8G8B8_UNORM: return SVGA3D_DECLTYPE_UBYTE4N; 112 113 default: 114 /* There are many formats without hardware support. This case 115 * will be hit regularly, meaning we'll need swvfetch. 116 */ 117 return SVGA3D_DECLTYPE_MAX; 118 } 119} 120 121 122static void 123define_input_element_object(struct svga_context *svga, 124 struct svga_velems_state *velems) 125{ 126 SVGA3dInputElementDesc elements[PIPE_MAX_ATTRIBS]; 127 unsigned i; 128 129 assert(velems->count <= PIPE_MAX_ATTRIBS); 130 assert(svga_have_vgpu10(svga)); 131 132 for (i = 0; i < velems->count; i++) { 133 const struct pipe_vertex_element *elem = velems->velem + i; 134 SVGA3dSurfaceFormat svga_format; 135 unsigned vf_flags; 136 137 svga_translate_vertex_format_vgpu10(elem->src_format, 138 &svga_format, &vf_flags); 139 140 velems->decl_type[i] = 141 translate_vertex_format_to_decltype(elem->src_format); 142 elements[i].inputSlot = elem->vertex_buffer_index; 143 elements[i].alignedByteOffset = elem->src_offset; 144 elements[i].format = svga_format; 145 146 if (elem->instance_divisor) { 147 elements[i].inputSlotClass = SVGA3D_INPUT_PER_INSTANCE_DATA; 148 elements[i].instanceDataStepRate = elem->instance_divisor; 149 } 150 else { 151 elements[i].inputSlotClass = SVGA3D_INPUT_PER_VERTEX_DATA; 152 elements[i].instanceDataStepRate = 0; 153 } 154 elements[i].inputRegister = i; 155 156 if (elements[i].format == SVGA3D_FORMAT_INVALID) { 157 velems->need_swvfetch = TRUE; 158 } 159 160 if (util_format_is_pure_integer(elem->src_format)) { 161 velems->attrib_is_pure_int |= (1 << i); 162 } 163 164 if (vf_flags & VF_W_TO_1) { 165 velems->adjust_attrib_w_1 |= (1 << i); 166 } 167 168 if (vf_flags & VF_U_TO_F_CAST) { 169 velems->adjust_attrib_utof |= (1 << i); 170 } 171 else if (vf_flags & VF_I_TO_F_CAST) { 172 velems->adjust_attrib_itof |= (1 << i); 173 } 174 175 if (vf_flags & VF_BGRA) { 176 velems->attrib_is_bgra |= (1 << i); 177 } 178 179 if (vf_flags & VF_PUINT_TO_SNORM) { 180 velems->attrib_puint_to_snorm |= (1 << i); 181 } 182 else if (vf_flags & VF_PUINT_TO_USCALED) { 183 velems->attrib_puint_to_uscaled |= (1 << i); 184 } 185 else if (vf_flags & VF_PUINT_TO_SSCALED) { 186 velems->attrib_puint_to_sscaled |= (1 << i); 187 } 188 } 189 190 velems->id = util_bitmask_add(svga->input_element_object_id_bm); 191 192 SVGA_RETRY(svga, SVGA3D_vgpu10_DefineElementLayout(svga->swc, velems->count, 193 velems->id, elements)); 194} 195 196 197/** 198 * Translate the vertex element types to SVGA3dDeclType and check 199 * for VS-based vertex attribute adjustments. 200 */ 201static void 202translate_vertex_decls(struct svga_context *svga, 203 struct svga_velems_state *velems) 204{ 205 unsigned i; 206 207 assert(!svga_have_vgpu10(svga)); 208 209 for (i = 0; i < velems->count; i++) { 210 const enum pipe_format f = velems->velem[i].src_format; 211 SVGA3dSurfaceFormat svga_format; 212 unsigned vf_flags; 213 214 svga_translate_vertex_format_vgpu10(f, &svga_format, &vf_flags); 215 216 velems->decl_type[i] = translate_vertex_format_to_decltype(f); 217 if (velems->decl_type[i] == SVGA3D_DECLTYPE_MAX) { 218 /* Unsupported format - use software fetch */ 219 velems->need_swvfetch = TRUE; 220 } 221 222 /* Check for VS-based adjustments */ 223 if (attrib_needs_range_adjustment(f)) { 224 velems->adjust_attrib_range |= (1 << i); 225 } 226 227 if (vf_flags & VF_W_TO_1) { 228 velems->adjust_attrib_w_1 |= (1 << i); 229 } 230 } 231} 232 233 234static void * 235svga_create_vertex_elements_state(struct pipe_context *pipe, 236 unsigned count, 237 const struct pipe_vertex_element *attribs) 238{ 239 struct svga_context *svga = svga_context(pipe); 240 struct svga_velems_state *velems; 241 242 assert(count <= PIPE_MAX_ATTRIBS); 243 velems = (struct svga_velems_state *) MALLOC(sizeof(struct svga_velems_state)); 244 if (velems) { 245 velems->count = count; 246 memcpy(velems->velem, attribs, sizeof(*attribs) * count); 247 248 velems->need_swvfetch = FALSE; 249 velems->adjust_attrib_range = 0x0; 250 velems->attrib_is_pure_int = 0x0; 251 velems->adjust_attrib_w_1 = 0x0; 252 velems->adjust_attrib_itof = 0x0; 253 velems->adjust_attrib_utof = 0x0; 254 velems->attrib_is_bgra = 0x0; 255 velems->attrib_puint_to_snorm = 0x0; 256 velems->attrib_puint_to_uscaled = 0x0; 257 velems->attrib_puint_to_sscaled = 0x0; 258 259 if (svga_have_vgpu10(svga)) { 260 define_input_element_object(svga, velems); 261 } 262 else { 263 translate_vertex_decls(svga, velems); 264 } 265 } 266 267 svga->hud.num_vertexelement_objects++; 268 SVGA_STATS_COUNT_INC(svga_screen(svga->pipe.screen)->sws, 269 SVGA_STATS_COUNT_VERTEXELEMENT); 270 271 return velems; 272} 273 274 275static void 276svga_bind_vertex_elements_state(struct pipe_context *pipe, void *state) 277{ 278 struct svga_context *svga = svga_context(pipe); 279 struct svga_velems_state *velems = (struct svga_velems_state *) state; 280 281 svga->curr.velems = velems; 282 svga->dirty |= SVGA_NEW_VELEMENT; 283} 284 285 286static void 287svga_delete_vertex_elements_state(struct pipe_context *pipe, void *state) 288{ 289 struct svga_context *svga = svga_context(pipe); 290 struct svga_velems_state *velems = (struct svga_velems_state *) state; 291 292 if (svga_have_vgpu10(svga)) { 293 svga_hwtnl_flush_retry(svga); 294 295 SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyElementLayout(svga->swc, 296 velems->id)); 297 298 if (velems->id == svga->state.hw_draw.layout_id) 299 svga->state.hw_draw.layout_id = SVGA3D_INVALID_ID; 300 301 util_bitmask_clear(svga->input_element_object_id_bm, velems->id); 302 velems->id = SVGA3D_INVALID_ID; 303 } 304 305 FREE(velems); 306 svga->hud.num_vertexelement_objects--; 307} 308 309 310void 311svga_cleanup_vertex_state(struct svga_context *svga) 312{ 313 unsigned i; 314 315 for (i = 0 ; i < svga->curr.num_vertex_buffers; i++) 316 pipe_vertex_buffer_unreference(&svga->curr.vb[i]); 317 318 pipe_resource_reference(&svga->state.hw_draw.ib, NULL); 319 320 for (i = 0; i < svga->state.hw_draw.num_vbuffers; i++) 321 pipe_resource_reference(&svga->state.hw_draw.vbuffers[i], NULL); 322} 323 324 325void 326svga_init_vertex_functions(struct svga_context *svga) 327{ 328 svga->pipe.set_vertex_buffers = svga_set_vertex_buffers; 329 svga->pipe.create_vertex_elements_state = svga_create_vertex_elements_state; 330 svga->pipe.bind_vertex_elements_state = svga_bind_vertex_elements_state; 331 svga->pipe.delete_vertex_elements_state = svga_delete_vertex_elements_state; 332} 333