1bf215546Sopenharmony_ci/********************************************************** 2bf215546Sopenharmony_ci * Copyright 2008-2009 VMware, Inc. All rights reserved. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person 5bf215546Sopenharmony_ci * obtaining a copy of this software and associated documentation 6bf215546Sopenharmony_ci * files (the "Software"), to deal in the Software without 7bf215546Sopenharmony_ci * restriction, including without limitation the rights to use, copy, 8bf215546Sopenharmony_ci * modify, merge, publish, distribute, sublicense, and/or sell copies 9bf215546Sopenharmony_ci * of the Software, and to permit persons to whom the Software is 10bf215546Sopenharmony_ci * furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be 13bf215546Sopenharmony_ci * included in all copies or substantial portions of the Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16bf215546Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18bf215546Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19bf215546Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20bf215546Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21bf215546Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22bf215546Sopenharmony_ci * SOFTWARE. 23bf215546Sopenharmony_ci * 24bf215546Sopenharmony_ci **********************************************************/ 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#include "pipe/p_defines.h" 27bf215546Sopenharmony_ci#include "util/u_bitmask.h" 28bf215546Sopenharmony_ci#include "util/format/u_format.h" 29bf215546Sopenharmony_ci#include "util/u_helpers.h" 30bf215546Sopenharmony_ci#include "util/u_inlines.h" 31bf215546Sopenharmony_ci#include "util/u_math.h" 32bf215546Sopenharmony_ci#include "util/u_memory.h" 33bf215546Sopenharmony_ci#include "util/u_transfer.h" 34bf215546Sopenharmony_ci#include "tgsi/tgsi_parse.h" 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_ci#include "svga_context.h" 37bf215546Sopenharmony_ci#include "svga_cmd.h" 38bf215546Sopenharmony_ci#include "svga_format.h" 39bf215546Sopenharmony_ci#include "svga_resource_buffer.h" 40bf215546Sopenharmony_ci#include "svga_screen.h" 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_cistatic void 44bf215546Sopenharmony_cisvga_set_vertex_buffers(struct pipe_context *pipe, 45bf215546Sopenharmony_ci unsigned start_slot, unsigned count, 46bf215546Sopenharmony_ci unsigned unbind_num_trailing_slots, 47bf215546Sopenharmony_ci bool take_ownership, 48bf215546Sopenharmony_ci const struct pipe_vertex_buffer *buffers) 49bf215546Sopenharmony_ci{ 50bf215546Sopenharmony_ci struct svga_context *svga = svga_context(pipe); 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_ci util_set_vertex_buffers_count(svga->curr.vb, 53bf215546Sopenharmony_ci &svga->curr.num_vertex_buffers, 54bf215546Sopenharmony_ci buffers, start_slot, count, 55bf215546Sopenharmony_ci unbind_num_trailing_slots, 56bf215546Sopenharmony_ci take_ownership); 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci svga->dirty |= SVGA_NEW_VBUFFER; 59bf215546Sopenharmony_ci} 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci/** 63bf215546Sopenharmony_ci * Does the given vertex attrib format need range adjustment in the VS? 64bf215546Sopenharmony_ci * Range adjustment scales and biases values from [0,1] to [-1,1]. 65bf215546Sopenharmony_ci * This lets us avoid the swtnl path. 66bf215546Sopenharmony_ci */ 67bf215546Sopenharmony_cistatic boolean 68bf215546Sopenharmony_ciattrib_needs_range_adjustment(enum pipe_format format) 69bf215546Sopenharmony_ci{ 70bf215546Sopenharmony_ci switch (format) { 71bf215546Sopenharmony_ci case PIPE_FORMAT_R8G8B8_SNORM: 72bf215546Sopenharmony_ci return TRUE; 73bf215546Sopenharmony_ci default: 74bf215546Sopenharmony_ci return FALSE; 75bf215546Sopenharmony_ci } 76bf215546Sopenharmony_ci} 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci 79bf215546Sopenharmony_ci/** 80bf215546Sopenharmony_ci * Given a gallium vertex element format, return the corresponding 81bf215546Sopenharmony_ci * SVGA3dDeclType. 82bf215546Sopenharmony_ci */ 83bf215546Sopenharmony_cistatic SVGA3dDeclType 84bf215546Sopenharmony_citranslate_vertex_format_to_decltype(enum pipe_format format) 85bf215546Sopenharmony_ci{ 86bf215546Sopenharmony_ci switch (format) { 87bf215546Sopenharmony_ci case PIPE_FORMAT_R32_FLOAT: return SVGA3D_DECLTYPE_FLOAT1; 88bf215546Sopenharmony_ci case PIPE_FORMAT_R32G32_FLOAT: return SVGA3D_DECLTYPE_FLOAT2; 89bf215546Sopenharmony_ci case PIPE_FORMAT_R32G32B32_FLOAT: return SVGA3D_DECLTYPE_FLOAT3; 90bf215546Sopenharmony_ci case PIPE_FORMAT_R32G32B32A32_FLOAT: return SVGA3D_DECLTYPE_FLOAT4; 91bf215546Sopenharmony_ci case PIPE_FORMAT_B8G8R8A8_UNORM: return SVGA3D_DECLTYPE_D3DCOLOR; 92bf215546Sopenharmony_ci case PIPE_FORMAT_R8G8B8A8_USCALED: return SVGA3D_DECLTYPE_UBYTE4; 93bf215546Sopenharmony_ci case PIPE_FORMAT_R16G16_SSCALED: return SVGA3D_DECLTYPE_SHORT2; 94bf215546Sopenharmony_ci case PIPE_FORMAT_R16G16B16A16_SSCALED: return SVGA3D_DECLTYPE_SHORT4; 95bf215546Sopenharmony_ci case PIPE_FORMAT_R8G8B8A8_UNORM: return SVGA3D_DECLTYPE_UBYTE4N; 96bf215546Sopenharmony_ci case PIPE_FORMAT_R16G16_SNORM: return SVGA3D_DECLTYPE_SHORT2N; 97bf215546Sopenharmony_ci case PIPE_FORMAT_R16G16B16A16_SNORM: return SVGA3D_DECLTYPE_SHORT4N; 98bf215546Sopenharmony_ci case PIPE_FORMAT_R16G16_UNORM: return SVGA3D_DECLTYPE_USHORT2N; 99bf215546Sopenharmony_ci case PIPE_FORMAT_R16G16B16A16_UNORM: return SVGA3D_DECLTYPE_USHORT4N; 100bf215546Sopenharmony_ci case PIPE_FORMAT_R10G10B10X2_USCALED: return SVGA3D_DECLTYPE_UDEC3; 101bf215546Sopenharmony_ci case PIPE_FORMAT_R10G10B10X2_SNORM: return SVGA3D_DECLTYPE_DEC3N; 102bf215546Sopenharmony_ci case PIPE_FORMAT_R16G16_FLOAT: return SVGA3D_DECLTYPE_FLOAT16_2; 103bf215546Sopenharmony_ci case PIPE_FORMAT_R16G16B16A16_FLOAT: return SVGA3D_DECLTYPE_FLOAT16_4; 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_ci /* See attrib_needs_adjustment() and attrib_needs_w_to_1() above */ 106bf215546Sopenharmony_ci case PIPE_FORMAT_R8G8B8_SNORM: return SVGA3D_DECLTYPE_UBYTE4N; 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ci /* See attrib_needs_w_to_1() above */ 109bf215546Sopenharmony_ci case PIPE_FORMAT_R16G16B16_SNORM: return SVGA3D_DECLTYPE_SHORT4N; 110bf215546Sopenharmony_ci case PIPE_FORMAT_R16G16B16_UNORM: return SVGA3D_DECLTYPE_USHORT4N; 111bf215546Sopenharmony_ci case PIPE_FORMAT_R8G8B8_UNORM: return SVGA3D_DECLTYPE_UBYTE4N; 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_ci default: 114bf215546Sopenharmony_ci /* There are many formats without hardware support. This case 115bf215546Sopenharmony_ci * will be hit regularly, meaning we'll need swvfetch. 116bf215546Sopenharmony_ci */ 117bf215546Sopenharmony_ci return SVGA3D_DECLTYPE_MAX; 118bf215546Sopenharmony_ci } 119bf215546Sopenharmony_ci} 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_cistatic void 123bf215546Sopenharmony_cidefine_input_element_object(struct svga_context *svga, 124bf215546Sopenharmony_ci struct svga_velems_state *velems) 125bf215546Sopenharmony_ci{ 126bf215546Sopenharmony_ci SVGA3dInputElementDesc elements[PIPE_MAX_ATTRIBS]; 127bf215546Sopenharmony_ci unsigned i; 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci assert(velems->count <= PIPE_MAX_ATTRIBS); 130bf215546Sopenharmony_ci assert(svga_have_vgpu10(svga)); 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci for (i = 0; i < velems->count; i++) { 133bf215546Sopenharmony_ci const struct pipe_vertex_element *elem = velems->velem + i; 134bf215546Sopenharmony_ci SVGA3dSurfaceFormat svga_format; 135bf215546Sopenharmony_ci unsigned vf_flags; 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci svga_translate_vertex_format_vgpu10(elem->src_format, 138bf215546Sopenharmony_ci &svga_format, &vf_flags); 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_ci velems->decl_type[i] = 141bf215546Sopenharmony_ci translate_vertex_format_to_decltype(elem->src_format); 142bf215546Sopenharmony_ci elements[i].inputSlot = elem->vertex_buffer_index; 143bf215546Sopenharmony_ci elements[i].alignedByteOffset = elem->src_offset; 144bf215546Sopenharmony_ci elements[i].format = svga_format; 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_ci if (elem->instance_divisor) { 147bf215546Sopenharmony_ci elements[i].inputSlotClass = SVGA3D_INPUT_PER_INSTANCE_DATA; 148bf215546Sopenharmony_ci elements[i].instanceDataStepRate = elem->instance_divisor; 149bf215546Sopenharmony_ci } 150bf215546Sopenharmony_ci else { 151bf215546Sopenharmony_ci elements[i].inputSlotClass = SVGA3D_INPUT_PER_VERTEX_DATA; 152bf215546Sopenharmony_ci elements[i].instanceDataStepRate = 0; 153bf215546Sopenharmony_ci } 154bf215546Sopenharmony_ci elements[i].inputRegister = i; 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_ci if (elements[i].format == SVGA3D_FORMAT_INVALID) { 157bf215546Sopenharmony_ci velems->need_swvfetch = TRUE; 158bf215546Sopenharmony_ci } 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_ci if (util_format_is_pure_integer(elem->src_format)) { 161bf215546Sopenharmony_ci velems->attrib_is_pure_int |= (1 << i); 162bf215546Sopenharmony_ci } 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_ci if (vf_flags & VF_W_TO_1) { 165bf215546Sopenharmony_ci velems->adjust_attrib_w_1 |= (1 << i); 166bf215546Sopenharmony_ci } 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_ci if (vf_flags & VF_U_TO_F_CAST) { 169bf215546Sopenharmony_ci velems->adjust_attrib_utof |= (1 << i); 170bf215546Sopenharmony_ci } 171bf215546Sopenharmony_ci else if (vf_flags & VF_I_TO_F_CAST) { 172bf215546Sopenharmony_ci velems->adjust_attrib_itof |= (1 << i); 173bf215546Sopenharmony_ci } 174bf215546Sopenharmony_ci 175bf215546Sopenharmony_ci if (vf_flags & VF_BGRA) { 176bf215546Sopenharmony_ci velems->attrib_is_bgra |= (1 << i); 177bf215546Sopenharmony_ci } 178bf215546Sopenharmony_ci 179bf215546Sopenharmony_ci if (vf_flags & VF_PUINT_TO_SNORM) { 180bf215546Sopenharmony_ci velems->attrib_puint_to_snorm |= (1 << i); 181bf215546Sopenharmony_ci } 182bf215546Sopenharmony_ci else if (vf_flags & VF_PUINT_TO_USCALED) { 183bf215546Sopenharmony_ci velems->attrib_puint_to_uscaled |= (1 << i); 184bf215546Sopenharmony_ci } 185bf215546Sopenharmony_ci else if (vf_flags & VF_PUINT_TO_SSCALED) { 186bf215546Sopenharmony_ci velems->attrib_puint_to_sscaled |= (1 << i); 187bf215546Sopenharmony_ci } 188bf215546Sopenharmony_ci } 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_ci velems->id = util_bitmask_add(svga->input_element_object_id_bm); 191bf215546Sopenharmony_ci 192bf215546Sopenharmony_ci SVGA_RETRY(svga, SVGA3D_vgpu10_DefineElementLayout(svga->swc, velems->count, 193bf215546Sopenharmony_ci velems->id, elements)); 194bf215546Sopenharmony_ci} 195bf215546Sopenharmony_ci 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_ci/** 198bf215546Sopenharmony_ci * Translate the vertex element types to SVGA3dDeclType and check 199bf215546Sopenharmony_ci * for VS-based vertex attribute adjustments. 200bf215546Sopenharmony_ci */ 201bf215546Sopenharmony_cistatic void 202bf215546Sopenharmony_citranslate_vertex_decls(struct svga_context *svga, 203bf215546Sopenharmony_ci struct svga_velems_state *velems) 204bf215546Sopenharmony_ci{ 205bf215546Sopenharmony_ci unsigned i; 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ci assert(!svga_have_vgpu10(svga)); 208bf215546Sopenharmony_ci 209bf215546Sopenharmony_ci for (i = 0; i < velems->count; i++) { 210bf215546Sopenharmony_ci const enum pipe_format f = velems->velem[i].src_format; 211bf215546Sopenharmony_ci SVGA3dSurfaceFormat svga_format; 212bf215546Sopenharmony_ci unsigned vf_flags; 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci svga_translate_vertex_format_vgpu10(f, &svga_format, &vf_flags); 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci velems->decl_type[i] = translate_vertex_format_to_decltype(f); 217bf215546Sopenharmony_ci if (velems->decl_type[i] == SVGA3D_DECLTYPE_MAX) { 218bf215546Sopenharmony_ci /* Unsupported format - use software fetch */ 219bf215546Sopenharmony_ci velems->need_swvfetch = TRUE; 220bf215546Sopenharmony_ci } 221bf215546Sopenharmony_ci 222bf215546Sopenharmony_ci /* Check for VS-based adjustments */ 223bf215546Sopenharmony_ci if (attrib_needs_range_adjustment(f)) { 224bf215546Sopenharmony_ci velems->adjust_attrib_range |= (1 << i); 225bf215546Sopenharmony_ci } 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_ci if (vf_flags & VF_W_TO_1) { 228bf215546Sopenharmony_ci velems->adjust_attrib_w_1 |= (1 << i); 229bf215546Sopenharmony_ci } 230bf215546Sopenharmony_ci } 231bf215546Sopenharmony_ci} 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci 234bf215546Sopenharmony_cistatic void * 235bf215546Sopenharmony_cisvga_create_vertex_elements_state(struct pipe_context *pipe, 236bf215546Sopenharmony_ci unsigned count, 237bf215546Sopenharmony_ci const struct pipe_vertex_element *attribs) 238bf215546Sopenharmony_ci{ 239bf215546Sopenharmony_ci struct svga_context *svga = svga_context(pipe); 240bf215546Sopenharmony_ci struct svga_velems_state *velems; 241bf215546Sopenharmony_ci 242bf215546Sopenharmony_ci assert(count <= PIPE_MAX_ATTRIBS); 243bf215546Sopenharmony_ci velems = (struct svga_velems_state *) MALLOC(sizeof(struct svga_velems_state)); 244bf215546Sopenharmony_ci if (velems) { 245bf215546Sopenharmony_ci velems->count = count; 246bf215546Sopenharmony_ci memcpy(velems->velem, attribs, sizeof(*attribs) * count); 247bf215546Sopenharmony_ci 248bf215546Sopenharmony_ci velems->need_swvfetch = FALSE; 249bf215546Sopenharmony_ci velems->adjust_attrib_range = 0x0; 250bf215546Sopenharmony_ci velems->attrib_is_pure_int = 0x0; 251bf215546Sopenharmony_ci velems->adjust_attrib_w_1 = 0x0; 252bf215546Sopenharmony_ci velems->adjust_attrib_itof = 0x0; 253bf215546Sopenharmony_ci velems->adjust_attrib_utof = 0x0; 254bf215546Sopenharmony_ci velems->attrib_is_bgra = 0x0; 255bf215546Sopenharmony_ci velems->attrib_puint_to_snorm = 0x0; 256bf215546Sopenharmony_ci velems->attrib_puint_to_uscaled = 0x0; 257bf215546Sopenharmony_ci velems->attrib_puint_to_sscaled = 0x0; 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_ci if (svga_have_vgpu10(svga)) { 260bf215546Sopenharmony_ci define_input_element_object(svga, velems); 261bf215546Sopenharmony_ci } 262bf215546Sopenharmony_ci else { 263bf215546Sopenharmony_ci translate_vertex_decls(svga, velems); 264bf215546Sopenharmony_ci } 265bf215546Sopenharmony_ci } 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_ci svga->hud.num_vertexelement_objects++; 268bf215546Sopenharmony_ci SVGA_STATS_COUNT_INC(svga_screen(svga->pipe.screen)->sws, 269bf215546Sopenharmony_ci SVGA_STATS_COUNT_VERTEXELEMENT); 270bf215546Sopenharmony_ci 271bf215546Sopenharmony_ci return velems; 272bf215546Sopenharmony_ci} 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_ci 275bf215546Sopenharmony_cistatic void 276bf215546Sopenharmony_cisvga_bind_vertex_elements_state(struct pipe_context *pipe, void *state) 277bf215546Sopenharmony_ci{ 278bf215546Sopenharmony_ci struct svga_context *svga = svga_context(pipe); 279bf215546Sopenharmony_ci struct svga_velems_state *velems = (struct svga_velems_state *) state; 280bf215546Sopenharmony_ci 281bf215546Sopenharmony_ci svga->curr.velems = velems; 282bf215546Sopenharmony_ci svga->dirty |= SVGA_NEW_VELEMENT; 283bf215546Sopenharmony_ci} 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_ci 286bf215546Sopenharmony_cistatic void 287bf215546Sopenharmony_cisvga_delete_vertex_elements_state(struct pipe_context *pipe, void *state) 288bf215546Sopenharmony_ci{ 289bf215546Sopenharmony_ci struct svga_context *svga = svga_context(pipe); 290bf215546Sopenharmony_ci struct svga_velems_state *velems = (struct svga_velems_state *) state; 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci if (svga_have_vgpu10(svga)) { 293bf215546Sopenharmony_ci svga_hwtnl_flush_retry(svga); 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_ci SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyElementLayout(svga->swc, 296bf215546Sopenharmony_ci velems->id)); 297bf215546Sopenharmony_ci 298bf215546Sopenharmony_ci if (velems->id == svga->state.hw_draw.layout_id) 299bf215546Sopenharmony_ci svga->state.hw_draw.layout_id = SVGA3D_INVALID_ID; 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_ci util_bitmask_clear(svga->input_element_object_id_bm, velems->id); 302bf215546Sopenharmony_ci velems->id = SVGA3D_INVALID_ID; 303bf215546Sopenharmony_ci } 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_ci FREE(velems); 306bf215546Sopenharmony_ci svga->hud.num_vertexelement_objects--; 307bf215546Sopenharmony_ci} 308bf215546Sopenharmony_ci 309bf215546Sopenharmony_ci 310bf215546Sopenharmony_civoid 311bf215546Sopenharmony_cisvga_cleanup_vertex_state(struct svga_context *svga) 312bf215546Sopenharmony_ci{ 313bf215546Sopenharmony_ci unsigned i; 314bf215546Sopenharmony_ci 315bf215546Sopenharmony_ci for (i = 0 ; i < svga->curr.num_vertex_buffers; i++) 316bf215546Sopenharmony_ci pipe_vertex_buffer_unreference(&svga->curr.vb[i]); 317bf215546Sopenharmony_ci 318bf215546Sopenharmony_ci pipe_resource_reference(&svga->state.hw_draw.ib, NULL); 319bf215546Sopenharmony_ci 320bf215546Sopenharmony_ci for (i = 0; i < svga->state.hw_draw.num_vbuffers; i++) 321bf215546Sopenharmony_ci pipe_resource_reference(&svga->state.hw_draw.vbuffers[i], NULL); 322bf215546Sopenharmony_ci} 323bf215546Sopenharmony_ci 324bf215546Sopenharmony_ci 325bf215546Sopenharmony_civoid 326bf215546Sopenharmony_cisvga_init_vertex_functions(struct svga_context *svga) 327bf215546Sopenharmony_ci{ 328bf215546Sopenharmony_ci svga->pipe.set_vertex_buffers = svga_set_vertex_buffers; 329bf215546Sopenharmony_ci svga->pipe.create_vertex_elements_state = svga_create_vertex_elements_state; 330bf215546Sopenharmony_ci svga->pipe.bind_vertex_elements_state = svga_bind_vertex_elements_state; 331bf215546Sopenharmony_ci svga->pipe.delete_vertex_elements_state = svga_delete_vertex_elements_state; 332bf215546Sopenharmony_ci} 333