1848b8605Smrg/********************************************************** 2848b8605Smrg * Copyright 2008-2009 VMware, Inc. All rights reserved. 3848b8605Smrg * 4848b8605Smrg * Permission is hereby granted, free of charge, to any person 5848b8605Smrg * obtaining a copy of this software and associated documentation 6848b8605Smrg * files (the "Software"), to deal in the Software without 7848b8605Smrg * restriction, including without limitation the rights to use, copy, 8848b8605Smrg * modify, merge, publish, distribute, sublicense, and/or sell copies 9848b8605Smrg * of the Software, and to permit persons to whom the Software is 10848b8605Smrg * furnished to do so, subject to the following conditions: 11848b8605Smrg * 12848b8605Smrg * The above copyright notice and this permission notice shall be 13848b8605Smrg * included in all copies or substantial portions of the Software. 14848b8605Smrg * 15848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16848b8605Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18848b8605Smrg * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19848b8605Smrg * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20848b8605Smrg * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21848b8605Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22848b8605Smrg * SOFTWARE. 23848b8605Smrg * 24848b8605Smrg **********************************************************/ 25848b8605Smrg 26848b8605Smrg#include "pipe/p_compiler.h" 27848b8605Smrg#include "util/u_inlines.h" 28848b8605Smrg#include "pipe/p_defines.h" 29b8e80941Smrg#include "util/u_helpers.h" 30848b8605Smrg#include "util/u_memory.h" 31848b8605Smrg#include "util/u_math.h" 32848b8605Smrg 33848b8605Smrg#include "svga_context.h" 34848b8605Smrg#include "svga_draw.h" 35848b8605Smrg#include "svga_draw_private.h" 36848b8605Smrg#include "svga_debug.h" 37848b8605Smrg#include "svga_screen.h" 38b8e80941Smrg#include "svga_resource.h" 39848b8605Smrg#include "svga_resource_buffer.h" 40848b8605Smrg#include "svga_resource_texture.h" 41b8e80941Smrg#include "svga_sampler_view.h" 42b8e80941Smrg#include "svga_shader.h" 43848b8605Smrg#include "svga_surface.h" 44848b8605Smrg#include "svga_winsys.h" 45848b8605Smrg#include "svga_cmd.h" 46848b8605Smrg 47848b8605Smrg 48848b8605Smrgstruct svga_hwtnl * 49848b8605Smrgsvga_hwtnl_create(struct svga_context *svga) 50848b8605Smrg{ 51848b8605Smrg struct svga_hwtnl *hwtnl = CALLOC_STRUCT(svga_hwtnl); 52b8e80941Smrg if (!hwtnl) 53848b8605Smrg goto fail; 54848b8605Smrg 55848b8605Smrg hwtnl->svga = svga; 56848b8605Smrg 57848b8605Smrg hwtnl->cmd.swc = svga->swc; 58848b8605Smrg 59848b8605Smrg return hwtnl; 60848b8605Smrg 61848b8605Smrgfail: 62848b8605Smrg return NULL; 63848b8605Smrg} 64848b8605Smrg 65848b8605Smrg 66848b8605Smrgvoid 67848b8605Smrgsvga_hwtnl_destroy(struct svga_hwtnl *hwtnl) 68848b8605Smrg{ 69848b8605Smrg unsigned i, j; 70848b8605Smrg 71848b8605Smrg for (i = 0; i < PIPE_PRIM_MAX; i++) { 72848b8605Smrg for (j = 0; j < IDX_CACHE_MAX; j++) { 73848b8605Smrg pipe_resource_reference(&hwtnl->index_cache[i][j].buffer, NULL); 74848b8605Smrg } 75848b8605Smrg } 76848b8605Smrg 77b8e80941Smrg for (i = 0; i < hwtnl->cmd.vbuf_count; i++) 78b8e80941Smrg pipe_vertex_buffer_unreference(&hwtnl->cmd.vbufs[i]); 79848b8605Smrg 80848b8605Smrg for (i = 0; i < hwtnl->cmd.prim_count; i++) 81848b8605Smrg pipe_resource_reference(&hwtnl->cmd.prim_ib[i], NULL); 82848b8605Smrg 83848b8605Smrg FREE(hwtnl); 84848b8605Smrg} 85848b8605Smrg 86848b8605Smrg 87848b8605Smrgvoid 88848b8605Smrgsvga_hwtnl_set_flatshade(struct svga_hwtnl *hwtnl, 89848b8605Smrg boolean flatshade, boolean flatshade_first) 90848b8605Smrg{ 91b8e80941Smrg struct svga_screen *svgascreen = svga_screen(hwtnl->svga->pipe.screen); 92b8e80941Smrg 93b8e80941Smrg /* User-specified PV */ 94848b8605Smrg hwtnl->api_pv = (flatshade && !flatshade_first) ? PV_LAST : PV_FIRST; 95b8e80941Smrg 96b8e80941Smrg /* Device supported PV */ 97b8e80941Smrg if (svgascreen->haveProvokingVertex) { 98b8e80941Smrg /* use the mode specified by the user */ 99b8e80941Smrg hwtnl->hw_pv = hwtnl->api_pv; 100b8e80941Smrg } 101b8e80941Smrg else { 102b8e80941Smrg /* the device only support first provoking vertex */ 103b8e80941Smrg hwtnl->hw_pv = PV_FIRST; 104b8e80941Smrg } 105848b8605Smrg} 106848b8605Smrg 107848b8605Smrg 108848b8605Smrgvoid 109b8e80941Smrgsvga_hwtnl_set_fillmode(struct svga_hwtnl *hwtnl, unsigned mode) 110848b8605Smrg{ 111848b8605Smrg hwtnl->api_fillmode = mode; 112848b8605Smrg} 113848b8605Smrg 114848b8605Smrg 115848b8605Smrgvoid 116b8e80941Smrgsvga_hwtnl_vertex_decls(struct svga_hwtnl *hwtnl, 117b8e80941Smrg unsigned count, 118b8e80941Smrg const SVGA3dVertexDecl * decls, 119b8e80941Smrg const unsigned *buffer_indexes, 120b8e80941Smrg SVGA3dElementLayoutId layout_id) 121848b8605Smrg{ 122848b8605Smrg assert(hwtnl->cmd.prim_count == 0); 123848b8605Smrg hwtnl->cmd.vdecl_count = count; 124b8e80941Smrg hwtnl->cmd.vdecl_layout_id = layout_id; 125b8e80941Smrg memcpy(hwtnl->cmd.vdecl, decls, count * sizeof(*decls)); 126b8e80941Smrg memcpy(hwtnl->cmd.vdecl_buffer_index, buffer_indexes, 127b8e80941Smrg count * sizeof(unsigned)); 128848b8605Smrg} 129848b8605Smrg 130848b8605Smrg 131b8e80941Smrg/** 132b8e80941Smrg * Specify vertex buffers for hardware drawing. 133b8e80941Smrg */ 134848b8605Smrgvoid 135b8e80941Smrgsvga_hwtnl_vertex_buffers(struct svga_hwtnl *hwtnl, 136b8e80941Smrg unsigned count, struct pipe_vertex_buffer *buffers) 137848b8605Smrg{ 138b8e80941Smrg struct pipe_vertex_buffer *dst = hwtnl->cmd.vbufs; 139b8e80941Smrg const struct pipe_vertex_buffer *src = buffers; 140b8e80941Smrg unsigned i; 141848b8605Smrg 142b8e80941Smrg for (i = 0; i < count; i++) { 143b8e80941Smrg pipe_vertex_buffer_reference(&dst[i], &src[i]); 144b8e80941Smrg } 145848b8605Smrg 146b8e80941Smrg /* release old buffer references */ 147b8e80941Smrg for ( ; i < hwtnl->cmd.vbuf_count; i++) { 148b8e80941Smrg pipe_vertex_buffer_unreference(&dst[i]); 149b8e80941Smrg /* don't bother zeroing stride/offset fields */ 150b8e80941Smrg } 151848b8605Smrg 152b8e80941Smrg hwtnl->cmd.vbuf_count = count; 153848b8605Smrg} 154848b8605Smrg 155848b8605Smrg 156848b8605Smrg/** 157848b8605Smrg * Determine whether the specified buffer is referred in the primitive queue, 158848b8605Smrg * for which no commands have been written yet. 159848b8605Smrg */ 160848b8605Smrgboolean 161848b8605Smrgsvga_hwtnl_is_buffer_referred(struct svga_hwtnl *hwtnl, 162848b8605Smrg struct pipe_resource *buffer) 163848b8605Smrg{ 164848b8605Smrg unsigned i; 165848b8605Smrg 166848b8605Smrg if (svga_buffer_is_user_buffer(buffer)) { 167848b8605Smrg return FALSE; 168848b8605Smrg } 169848b8605Smrg 170848b8605Smrg if (!hwtnl->cmd.prim_count) { 171848b8605Smrg return FALSE; 172848b8605Smrg } 173848b8605Smrg 174b8e80941Smrg for (i = 0; i < hwtnl->cmd.vbuf_count; ++i) { 175b8e80941Smrg if (hwtnl->cmd.vbufs[i].buffer.resource == buffer) { 176848b8605Smrg return TRUE; 177848b8605Smrg } 178848b8605Smrg } 179848b8605Smrg 180848b8605Smrg for (i = 0; i < hwtnl->cmd.prim_count; ++i) { 181848b8605Smrg if (hwtnl->cmd.prim_ib[i] == buffer) { 182848b8605Smrg return TRUE; 183848b8605Smrg } 184848b8605Smrg } 185848b8605Smrg 186848b8605Smrg return FALSE; 187848b8605Smrg} 188848b8605Smrg 189848b8605Smrg 190b8e80941Smrgstatic enum pipe_error 191b8e80941Smrgdraw_vgpu9(struct svga_hwtnl *hwtnl) 192848b8605Smrg{ 193848b8605Smrg struct svga_winsys_context *swc = hwtnl->cmd.swc; 194848b8605Smrg struct svga_context *svga = hwtnl->svga; 195848b8605Smrg enum pipe_error ret; 196b8e80941Smrg struct svga_winsys_surface *vb_handle[SVGA3D_INPUTREG_MAX]; 197b8e80941Smrg struct svga_winsys_surface *ib_handle[QSZ]; 198b8e80941Smrg struct svga_winsys_surface *handle; 199b8e80941Smrg SVGA3dVertexDecl *vdecl; 200b8e80941Smrg SVGA3dPrimitiveRange *prim; 201b8e80941Smrg unsigned i; 202848b8605Smrg 203b8e80941Smrg /* Re-validate those sampler views with backing copy 204b8e80941Smrg * of texture whose original copy has been updated. 205b8e80941Smrg * This is done here at draw time because the texture binding might not 206b8e80941Smrg * have modified, hence validation is not triggered at state update time, 207b8e80941Smrg * and yet the texture might have been updated in another context, so 208b8e80941Smrg * we need to re-validate the sampler view in order to update the backing 209b8e80941Smrg * copy of the updated texture. 210b8e80941Smrg */ 211b8e80941Smrg if (svga->state.hw_draw.num_backed_views) { 212b8e80941Smrg for (i = 0; i < svga->state.hw_draw.num_views; i++) { 213b8e80941Smrg struct svga_hw_view_state *view = &svga->state.hw_draw.views[i]; 214b8e80941Smrg struct svga_texture *tex = svga_texture(view->texture); 215b8e80941Smrg struct svga_sampler_view *sv = view->v; 216b8e80941Smrg if (sv && tex && sv->handle != tex->handle && sv->age < tex->age) 217b8e80941Smrg svga_validate_sampler_view(svga, view->v); 218b8e80941Smrg } 219b8e80941Smrg } 220848b8605Smrg 221b8e80941Smrg for (i = 0; i < hwtnl->cmd.vdecl_count; i++) { 222b8e80941Smrg unsigned j = hwtnl->cmd.vdecl_buffer_index[i]; 223b8e80941Smrg handle = svga_buffer_handle(svga, hwtnl->cmd.vbufs[j].buffer.resource, 224b8e80941Smrg PIPE_BIND_VERTEX_BUFFER); 225b8e80941Smrg if (!handle) 226b8e80941Smrg return PIPE_ERROR_OUT_OF_MEMORY; 227b8e80941Smrg 228b8e80941Smrg vb_handle[i] = handle; 229b8e80941Smrg } 230b8e80941Smrg 231b8e80941Smrg for (i = 0; i < hwtnl->cmd.prim_count; i++) { 232b8e80941Smrg if (hwtnl->cmd.prim_ib[i]) { 233b8e80941Smrg handle = svga_buffer_handle(svga, hwtnl->cmd.prim_ib[i], 234b8e80941Smrg PIPE_BIND_INDEX_BUFFER); 235b8e80941Smrg if (!handle) 236848b8605Smrg return PIPE_ERROR_OUT_OF_MEMORY; 237b8e80941Smrg } 238b8e80941Smrg else 239b8e80941Smrg handle = NULL; 240b8e80941Smrg 241b8e80941Smrg ib_handle[i] = handle; 242b8e80941Smrg } 243848b8605Smrg 244b8e80941Smrg if (svga->rebind.flags.rendertargets) { 245b8e80941Smrg ret = svga_reemit_framebuffer_bindings(svga); 246b8e80941Smrg if (ret != PIPE_OK) { 247b8e80941Smrg return ret; 248b8e80941Smrg } 249b8e80941Smrg } 250b8e80941Smrg 251b8e80941Smrg if (svga->rebind.flags.texture_samplers) { 252b8e80941Smrg ret = svga_reemit_tss_bindings(svga); 253b8e80941Smrg if (ret != PIPE_OK) { 254b8e80941Smrg return ret; 255848b8605Smrg } 256b8e80941Smrg } 257b8e80941Smrg 258b8e80941Smrg if (svga->rebind.flags.vs) { 259b8e80941Smrg ret = svga_reemit_vs_bindings(svga); 260b8e80941Smrg if (ret != PIPE_OK) { 261b8e80941Smrg return ret; 262b8e80941Smrg } 263b8e80941Smrg } 264b8e80941Smrg 265b8e80941Smrg if (svga->rebind.flags.fs) { 266b8e80941Smrg ret = svga_reemit_fs_bindings(svga); 267b8e80941Smrg if (ret != PIPE_OK) { 268b8e80941Smrg return ret; 269b8e80941Smrg } 270b8e80941Smrg } 271b8e80941Smrg 272b8e80941Smrg SVGA_DBG(DEBUG_DMA, "draw to sid %p, %d prims\n", 273b8e80941Smrg svga->curr.framebuffer.cbufs[0] ? 274b8e80941Smrg svga_surface(svga->curr.framebuffer.cbufs[0])->handle : NULL, 275b8e80941Smrg hwtnl->cmd.prim_count); 276b8e80941Smrg 277b8e80941Smrg ret = SVGA3D_BeginDrawPrimitives(swc, 278b8e80941Smrg &vdecl, 279b8e80941Smrg hwtnl->cmd.vdecl_count, 280b8e80941Smrg &prim, hwtnl->cmd.prim_count); 281b8e80941Smrg if (ret != PIPE_OK) 282b8e80941Smrg return ret; 283b8e80941Smrg 284b8e80941Smrg memcpy(vdecl, 285b8e80941Smrg hwtnl->cmd.vdecl, 286b8e80941Smrg hwtnl->cmd.vdecl_count * sizeof hwtnl->cmd.vdecl[0]); 287b8e80941Smrg 288b8e80941Smrg for (i = 0; i < hwtnl->cmd.vdecl_count; i++) { 289b8e80941Smrg /* check for 4-byte alignment */ 290b8e80941Smrg assert(vdecl[i].array.offset % 4 == 0); 291b8e80941Smrg assert(vdecl[i].array.stride % 4 == 0); 292b8e80941Smrg 293b8e80941Smrg /* Given rangeHint is considered to be relative to indexBias, and 294b8e80941Smrg * indexBias varies per primitive, we cannot accurately supply an 295b8e80941Smrg * rangeHint when emitting more than one primitive per draw command. 296b8e80941Smrg */ 297b8e80941Smrg if (hwtnl->cmd.prim_count == 1) { 298b8e80941Smrg vdecl[i].rangeHint.first = hwtnl->cmd.min_index[0]; 299b8e80941Smrg vdecl[i].rangeHint.last = hwtnl->cmd.max_index[0] + 1; 300b8e80941Smrg } 301b8e80941Smrg else { 302b8e80941Smrg vdecl[i].rangeHint.first = 0; 303b8e80941Smrg vdecl[i].rangeHint.last = 0; 304b8e80941Smrg } 305b8e80941Smrg 306b8e80941Smrg swc->surface_relocation(swc, 307b8e80941Smrg &vdecl[i].array.surfaceId, 308b8e80941Smrg NULL, vb_handle[i], SVGA_RELOC_READ); 309b8e80941Smrg } 310b8e80941Smrg 311b8e80941Smrg memcpy(prim, 312b8e80941Smrg hwtnl->cmd.prim, hwtnl->cmd.prim_count * sizeof hwtnl->cmd.prim[0]); 313b8e80941Smrg 314b8e80941Smrg for (i = 0; i < hwtnl->cmd.prim_count; i++) { 315b8e80941Smrg swc->surface_relocation(swc, 316b8e80941Smrg &prim[i].indexArray.surfaceId, 317b8e80941Smrg NULL, ib_handle[i], SVGA_RELOC_READ); 318b8e80941Smrg pipe_resource_reference(&hwtnl->cmd.prim_ib[i], NULL); 319b8e80941Smrg } 320848b8605Smrg 321b8e80941Smrg SVGA_FIFOCommitAll(swc); 322b8e80941Smrg 323b8e80941Smrg hwtnl->cmd.prim_count = 0; 324b8e80941Smrg 325b8e80941Smrg return PIPE_OK; 326b8e80941Smrg} 327b8e80941Smrg 328b8e80941Smrg 329b8e80941Smrgstatic SVGA3dSurfaceFormat 330b8e80941Smrgxlate_index_format(unsigned indexWidth) 331b8e80941Smrg{ 332b8e80941Smrg if (indexWidth == 2) { 333b8e80941Smrg return SVGA3D_R16_UINT; 334b8e80941Smrg } 335b8e80941Smrg else if (indexWidth == 4) { 336b8e80941Smrg return SVGA3D_R32_UINT; 337b8e80941Smrg } 338b8e80941Smrg else { 339b8e80941Smrg assert(!"Bad indexWidth"); 340b8e80941Smrg return SVGA3D_R32_UINT; 341b8e80941Smrg } 342b8e80941Smrg} 343b8e80941Smrg 344b8e80941Smrg 345b8e80941Smrgstatic enum pipe_error 346b8e80941Smrgvalidate_sampler_resources(struct svga_context *svga) 347b8e80941Smrg{ 348b8e80941Smrg enum pipe_shader_type shader; 349b8e80941Smrg 350b8e80941Smrg assert(svga_have_vgpu10(svga)); 351b8e80941Smrg 352b8e80941Smrg for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) { 353b8e80941Smrg unsigned count = svga->curr.num_sampler_views[shader]; 354b8e80941Smrg unsigned i; 355b8e80941Smrg struct svga_winsys_surface *surfaces[PIPE_MAX_SAMPLERS]; 356b8e80941Smrg enum pipe_error ret; 357b8e80941Smrg 358b8e80941Smrg /* 359b8e80941Smrg * Reference bound sampler resources to ensure pending updates are 360b8e80941Smrg * noticed by the device. 361b8e80941Smrg */ 362b8e80941Smrg for (i = 0; i < count; i++) { 363b8e80941Smrg struct svga_pipe_sampler_view *sv = 364b8e80941Smrg svga_pipe_sampler_view(svga->curr.sampler_views[shader][i]); 365b8e80941Smrg 366b8e80941Smrg if (sv) { 367b8e80941Smrg if (sv->base.texture->target == PIPE_BUFFER) { 368b8e80941Smrg surfaces[i] = svga_buffer_handle(svga, sv->base.texture, 369b8e80941Smrg PIPE_BIND_SAMPLER_VIEW); 370b8e80941Smrg } 371b8e80941Smrg else { 372b8e80941Smrg surfaces[i] = svga_texture(sv->base.texture)->handle; 373b8e80941Smrg } 374848b8605Smrg } 375848b8605Smrg else { 376b8e80941Smrg surfaces[i] = NULL; 377848b8605Smrg } 378b8e80941Smrg } 379b8e80941Smrg 380b8e80941Smrg if (shader == PIPE_SHADER_FRAGMENT && 381b8e80941Smrg svga->curr.rast->templ.poly_stipple_enable) { 382b8e80941Smrg const unsigned unit = svga->state.hw_draw.fs->pstipple_sampler_unit; 383b8e80941Smrg struct svga_pipe_sampler_view *sv = 384b8e80941Smrg svga->polygon_stipple.sampler_view; 385848b8605Smrg 386b8e80941Smrg assert(sv); 387b8e80941Smrg surfaces[unit] = svga_texture(sv->base.texture)->handle; 388b8e80941Smrg count = MAX2(count, unit+1); 389848b8605Smrg } 390848b8605Smrg 391b8e80941Smrg /* rebind the shader resources if needed */ 392b8e80941Smrg if (svga->rebind.flags.texture_samplers) { 393b8e80941Smrg for (i = 0; i < count; i++) { 394b8e80941Smrg if (surfaces[i]) { 395b8e80941Smrg ret = svga->swc->resource_rebind(svga->swc, 396b8e80941Smrg surfaces[i], 397b8e80941Smrg NULL, 398b8e80941Smrg SVGA_RELOC_READ); 399b8e80941Smrg if (ret != PIPE_OK) 400b8e80941Smrg return ret; 401b8e80941Smrg } 402848b8605Smrg } 403848b8605Smrg } 404b8e80941Smrg } 405b8e80941Smrg svga->rebind.flags.texture_samplers = FALSE; 406848b8605Smrg 407b8e80941Smrg return PIPE_OK; 408b8e80941Smrg} 409b8e80941Smrg 410b8e80941Smrg 411b8e80941Smrgstatic enum pipe_error 412b8e80941Smrgvalidate_constant_buffers(struct svga_context *svga) 413b8e80941Smrg{ 414b8e80941Smrg enum pipe_shader_type shader; 415b8e80941Smrg 416b8e80941Smrg assert(svga_have_vgpu10(svga)); 417b8e80941Smrg 418b8e80941Smrg for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) { 419b8e80941Smrg enum pipe_error ret; 420b8e80941Smrg struct svga_buffer *buffer; 421b8e80941Smrg struct svga_winsys_surface *handle; 422b8e80941Smrg unsigned enabled_constbufs; 423b8e80941Smrg 424b8e80941Smrg /* Rebind the default constant buffer if needed */ 425b8e80941Smrg if (svga->rebind.flags.constbufs) { 426b8e80941Smrg buffer = svga_buffer(svga->state.hw_draw.constbuf[shader]); 427b8e80941Smrg if (buffer) { 428b8e80941Smrg ret = svga->swc->resource_rebind(svga->swc, 429b8e80941Smrg buffer->handle, 430b8e80941Smrg NULL, 431b8e80941Smrg SVGA_RELOC_READ); 432b8e80941Smrg if (ret != PIPE_OK) 433b8e80941Smrg return ret; 434848b8605Smrg } 435848b8605Smrg } 436848b8605Smrg 437b8e80941Smrg /* 438b8e80941Smrg * Reference other bound constant buffers to ensure pending updates are 439b8e80941Smrg * noticed by the device. 440b8e80941Smrg */ 441b8e80941Smrg enabled_constbufs = svga->state.hw_draw.enabled_constbufs[shader] & ~1u; 442b8e80941Smrg while (enabled_constbufs) { 443b8e80941Smrg unsigned i = u_bit_scan(&enabled_constbufs); 444b8e80941Smrg buffer = svga_buffer(svga->curr.constbufs[shader][i].buffer); 445b8e80941Smrg if (buffer) { 446b8e80941Smrg handle = svga_buffer_handle(svga, &buffer->b.b, 447b8e80941Smrg PIPE_BIND_CONSTANT_BUFFER); 448b8e80941Smrg 449b8e80941Smrg if (svga->rebind.flags.constbufs) { 450b8e80941Smrg ret = svga->swc->resource_rebind(svga->swc, 451b8e80941Smrg handle, 452b8e80941Smrg NULL, 453b8e80941Smrg SVGA_RELOC_READ); 454b8e80941Smrg if (ret != PIPE_OK) 455b8e80941Smrg return ret; 456b8e80941Smrg } 457848b8605Smrg } 458848b8605Smrg } 459b8e80941Smrg } 460b8e80941Smrg svga->rebind.flags.constbufs = FALSE; 461848b8605Smrg 462b8e80941Smrg return PIPE_OK; 463b8e80941Smrg} 464b8e80941Smrg 465b8e80941Smrg 466b8e80941Smrg/** 467b8e80941Smrg * Was the last command put into the command buffer a drawing command? 468b8e80941Smrg * We use this to determine if we can skip emitting buffer re-bind 469b8e80941Smrg * commands when we have a sequence of drawing commands that use the 470b8e80941Smrg * same vertex/index buffers with no intervening commands. 471b8e80941Smrg * 472b8e80941Smrg * The first drawing command will bind the vertex/index buffers. If 473b8e80941Smrg * the immediately following command is also a drawing command using the 474b8e80941Smrg * same buffers, we shouldn't have to rebind them. 475b8e80941Smrg */ 476b8e80941Smrgstatic bool 477b8e80941Smrglast_command_was_draw(const struct svga_context *svga) 478b8e80941Smrg{ 479b8e80941Smrg switch (SVGA3D_GetLastCommand(svga->swc)) { 480b8e80941Smrg case SVGA_3D_CMD_DX_DRAW: 481b8e80941Smrg case SVGA_3D_CMD_DX_DRAW_INDEXED: 482b8e80941Smrg case SVGA_3D_CMD_DX_DRAW_INSTANCED: 483b8e80941Smrg case SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED: 484b8e80941Smrg case SVGA_3D_CMD_DX_DRAW_AUTO: 485b8e80941Smrg return true; 486b8e80941Smrg default: 487b8e80941Smrg return false; 488b8e80941Smrg } 489b8e80941Smrg} 490b8e80941Smrg 491b8e80941Smrg 492b8e80941Smrg/** 493b8e80941Smrg * A helper function to compare vertex buffers. 494b8e80941Smrg * They are equal if the vertex buffer attributes and the vertex buffer 495b8e80941Smrg * resources are identical. 496b8e80941Smrg */ 497b8e80941Smrgstatic boolean 498b8e80941Smrgvertex_buffers_equal(unsigned count, 499b8e80941Smrg SVGA3dVertexBuffer *pVBufAttr1, 500b8e80941Smrg struct pipe_resource **pVBuf1, 501b8e80941Smrg SVGA3dVertexBuffer *pVBufAttr2, 502b8e80941Smrg struct pipe_resource **pVBuf2) 503b8e80941Smrg{ 504b8e80941Smrg return (memcmp(pVBufAttr1, pVBufAttr2, 505b8e80941Smrg count * sizeof(*pVBufAttr1)) == 0) && 506b8e80941Smrg (memcmp(pVBuf1, pVBuf2, count * sizeof(*pVBuf1)) == 0); 507b8e80941Smrg} 508b8e80941Smrg 509b8e80941Smrg 510b8e80941Smrg/* 511b8e80941Smrg * Prepare the vertex buffers for a drawing command. 512b8e80941Smrg */ 513b8e80941Smrgstatic enum pipe_error 514b8e80941Smrgvalidate_vertex_buffers(struct svga_hwtnl *hwtnl) 515b8e80941Smrg{ 516b8e80941Smrg struct svga_context *svga = hwtnl->svga; 517b8e80941Smrg struct pipe_resource *vbuffers[SVGA3D_INPUTREG_MAX]; 518b8e80941Smrg struct svga_winsys_surface *vbuffer_handles[SVGA3D_INPUTREG_MAX]; 519b8e80941Smrg const unsigned vbuf_count = hwtnl->cmd.vbuf_count; 520b8e80941Smrg int last_vbuf = -1; 521b8e80941Smrg unsigned i; 522b8e80941Smrg 523b8e80941Smrg assert(svga_have_vgpu10(svga)); 524b8e80941Smrg 525b8e80941Smrg /* Get handle for each referenced vertex buffer */ 526b8e80941Smrg for (i = 0; i < vbuf_count; i++) { 527b8e80941Smrg struct svga_buffer *sbuf = 528b8e80941Smrg svga_buffer(hwtnl->cmd.vbufs[i].buffer.resource); 529b8e80941Smrg 530b8e80941Smrg if (sbuf) { 531b8e80941Smrg vbuffer_handles[i] = svga_buffer_handle(svga, &sbuf->b.b, 532b8e80941Smrg PIPE_BIND_VERTEX_BUFFER); 533b8e80941Smrg assert(sbuf->key.flags & SVGA3D_SURFACE_BIND_VERTEX_BUFFER); 534b8e80941Smrg if (vbuffer_handles[i] == NULL) 535b8e80941Smrg return PIPE_ERROR_OUT_OF_MEMORY; 536b8e80941Smrg vbuffers[i] = &sbuf->b.b; 537b8e80941Smrg last_vbuf = i; 538b8e80941Smrg } 539b8e80941Smrg else { 540b8e80941Smrg vbuffers[i] = NULL; 541b8e80941Smrg vbuffer_handles[i] = NULL; 542848b8605Smrg } 543b8e80941Smrg } 544848b8605Smrg 545b8e80941Smrg for (; i < svga->state.hw_draw.num_vbuffers; i++) { 546b8e80941Smrg vbuffers[i] = NULL; 547b8e80941Smrg vbuffer_handles[i] = NULL; 548b8e80941Smrg } 549848b8605Smrg 550b8e80941Smrg /* setup vertex attribute input layout */ 551b8e80941Smrg if (svga->state.hw_draw.layout_id != hwtnl->cmd.vdecl_layout_id) { 552b8e80941Smrg enum pipe_error ret = 553b8e80941Smrg SVGA3D_vgpu10_SetInputLayout(svga->swc, 554b8e80941Smrg hwtnl->cmd.vdecl_layout_id); 555848b8605Smrg if (ret != PIPE_OK) 556848b8605Smrg return ret; 557848b8605Smrg 558b8e80941Smrg svga->state.hw_draw.layout_id = hwtnl->cmd.vdecl_layout_id; 559b8e80941Smrg } 560b8e80941Smrg 561b8e80941Smrg /* setup vertex buffers */ 562b8e80941Smrg { 563b8e80941Smrg SVGA3dVertexBuffer vbuffer_attrs[PIPE_MAX_ATTRIBS]; 564848b8605Smrg 565b8e80941Smrg for (i = 0; i < vbuf_count; i++) { 566b8e80941Smrg vbuffer_attrs[i].stride = hwtnl->cmd.vbufs[i].stride; 567b8e80941Smrg vbuffer_attrs[i].offset = hwtnl->cmd.vbufs[i].buffer_offset; 568b8e80941Smrg vbuffer_attrs[i].sid = 0; 569b8e80941Smrg } 570b8e80941Smrg 571b8e80941Smrg /* If any of the vertex buffer state has changed, issue 572b8e80941Smrg * the SetVertexBuffers command. Otherwise, we will just 573b8e80941Smrg * need to rebind the resources. 574b8e80941Smrg */ 575b8e80941Smrg if (vbuf_count != svga->state.hw_draw.num_vbuffers || 576b8e80941Smrg !vertex_buffers_equal(vbuf_count, 577b8e80941Smrg vbuffer_attrs, 578b8e80941Smrg vbuffers, 579b8e80941Smrg svga->state.hw_draw.vbuffer_attrs, 580b8e80941Smrg svga->state.hw_draw.vbuffers)) { 581b8e80941Smrg 582b8e80941Smrg unsigned num_vbuffers; 583b8e80941Smrg 584b8e80941Smrg /* get the max of the current bound vertex buffers count and 585b8e80941Smrg * the to-be-bound vertex buffers count, so as to unbind 586b8e80941Smrg * the unused vertex buffers. 587848b8605Smrg */ 588b8e80941Smrg num_vbuffers = MAX2(vbuf_count, svga->state.hw_draw.num_vbuffers); 589b8e80941Smrg 590b8e80941Smrg /* Zero-out the old buffers we want to unbind (the number of loop 591b8e80941Smrg * iterations here is typically very small, and often zero.) 592b8e80941Smrg */ 593b8e80941Smrg for (i = vbuf_count; i < num_vbuffers; i++) { 594b8e80941Smrg vbuffer_attrs[i].sid = 0; 595b8e80941Smrg vbuffer_attrs[i].stride = 0; 596b8e80941Smrg vbuffer_attrs[i].offset = 0; 597b8e80941Smrg vbuffer_handles[i] = NULL; 598848b8605Smrg } 599b8e80941Smrg 600b8e80941Smrg if (num_vbuffers > 0) { 601b8e80941Smrg SVGA3dVertexBuffer *pbufAttrs = vbuffer_attrs; 602b8e80941Smrg struct svga_winsys_surface **pbufHandles = vbuffer_handles; 603b8e80941Smrg unsigned numVBuf = 0; 604b8e80941Smrg 605b8e80941Smrg /* Loop through the vertex buffer lists to only emit 606b8e80941Smrg * those vertex buffers that are not already in the 607b8e80941Smrg * corresponding entries in the device's vertex buffer list. 608b8e80941Smrg */ 609b8e80941Smrg for (i = 0; i < num_vbuffers; i++) { 610b8e80941Smrg boolean emit = 611b8e80941Smrg vertex_buffers_equal(1, 612b8e80941Smrg &vbuffer_attrs[i], 613b8e80941Smrg &vbuffers[i], 614b8e80941Smrg &svga->state.hw_draw.vbuffer_attrs[i], 615b8e80941Smrg &svga->state.hw_draw.vbuffers[i]); 616b8e80941Smrg 617b8e80941Smrg if (!emit && i == num_vbuffers-1) { 618b8e80941Smrg /* Include the last vertex buffer in the next emit 619b8e80941Smrg * if it is different. 620b8e80941Smrg */ 621b8e80941Smrg emit = TRUE; 622b8e80941Smrg numVBuf++; 623b8e80941Smrg i++; 624b8e80941Smrg } 625b8e80941Smrg 626b8e80941Smrg if (emit) { 627b8e80941Smrg /* numVBuf can only be 0 if the first vertex buffer 628b8e80941Smrg * is the same as the one in the device's list. 629b8e80941Smrg * In this case, there is nothing to send yet. 630b8e80941Smrg */ 631b8e80941Smrg if (numVBuf) { 632b8e80941Smrg enum pipe_error ret = 633b8e80941Smrg SVGA3D_vgpu10_SetVertexBuffers(svga->swc, 634b8e80941Smrg numVBuf, 635b8e80941Smrg i - numVBuf, 636b8e80941Smrg pbufAttrs, pbufHandles); 637b8e80941Smrg if (ret != PIPE_OK) 638b8e80941Smrg return ret; 639b8e80941Smrg } 640b8e80941Smrg pbufAttrs += (numVBuf + 1); 641b8e80941Smrg pbufHandles += (numVBuf + 1); 642b8e80941Smrg numVBuf = 0; 643b8e80941Smrg } 644b8e80941Smrg else 645b8e80941Smrg numVBuf++; 646b8e80941Smrg } 647b8e80941Smrg 648b8e80941Smrg /* save the number of vertex buffers sent to the device, not 649b8e80941Smrg * including trailing unbound vertex buffers. 650b8e80941Smrg */ 651b8e80941Smrg svga->state.hw_draw.num_vbuffers = last_vbuf + 1; 652b8e80941Smrg memcpy(svga->state.hw_draw.vbuffer_attrs, vbuffer_attrs, 653b8e80941Smrg num_vbuffers * sizeof(vbuffer_attrs[0])); 654b8e80941Smrg for (i = 0; i < num_vbuffers; i++) { 655b8e80941Smrg pipe_resource_reference(&svga->state.hw_draw.vbuffers[i], 656b8e80941Smrg vbuffers[i]); 657b8e80941Smrg } 658b8e80941Smrg } 659b8e80941Smrg } 660b8e80941Smrg else { 661b8e80941Smrg /* Even though we can avoid emitting the redundant SetVertexBuffers 662b8e80941Smrg * command, we still need to reference the vertex buffers surfaces. 663b8e80941Smrg */ 664b8e80941Smrg for (i = 0; i < vbuf_count; i++) { 665b8e80941Smrg if (vbuffer_handles[i] && !last_command_was_draw(svga)) { 666b8e80941Smrg enum pipe_error ret = 667b8e80941Smrg svga->swc->resource_rebind(svga->swc, vbuffer_handles[i], 668b8e80941Smrg NULL, SVGA_RELOC_READ); 669b8e80941Smrg if (ret != PIPE_OK) 670b8e80941Smrg return ret; 671b8e80941Smrg } 672848b8605Smrg } 673b8e80941Smrg } 674b8e80941Smrg } 675b8e80941Smrg 676b8e80941Smrg return PIPE_OK; 677b8e80941Smrg} 678b8e80941Smrg 679b8e80941Smrg 680b8e80941Smrg/* 681b8e80941Smrg * Prepare the index buffer for a drawing command. 682b8e80941Smrg */ 683b8e80941Smrgstatic enum pipe_error 684b8e80941Smrgvalidate_index_buffer(struct svga_hwtnl *hwtnl, 685b8e80941Smrg const SVGA3dPrimitiveRange *range, 686b8e80941Smrg struct pipe_resource *ib) 687b8e80941Smrg{ 688b8e80941Smrg struct svga_context *svga = hwtnl->svga; 689b8e80941Smrg struct svga_winsys_surface *ib_handle = 690b8e80941Smrg svga_buffer_handle(svga, ib, PIPE_BIND_INDEX_BUFFER); 691b8e80941Smrg 692b8e80941Smrg if (!ib_handle) 693b8e80941Smrg return PIPE_ERROR_OUT_OF_MEMORY; 694848b8605Smrg 695b8e80941Smrg struct svga_buffer *sbuf = svga_buffer(ib); 696b8e80941Smrg assert(sbuf->key.flags & SVGA3D_SURFACE_BIND_INDEX_BUFFER); 697b8e80941Smrg (void) sbuf; /* silence unused var warning */ 698b8e80941Smrg 699b8e80941Smrg SVGA3dSurfaceFormat indexFormat = xlate_index_format(range->indexWidth); 700b8e80941Smrg 701b8e80941Smrg if (ib != svga->state.hw_draw.ib || 702b8e80941Smrg indexFormat != svga->state.hw_draw.ib_format || 703b8e80941Smrg range->indexArray.offset != svga->state.hw_draw.ib_offset) { 704b8e80941Smrg 705b8e80941Smrg assert(indexFormat != SVGA3D_FORMAT_INVALID); 706b8e80941Smrg enum pipe_error ret = 707b8e80941Smrg SVGA3D_vgpu10_SetIndexBuffer(svga->swc, ib_handle, 708b8e80941Smrg indexFormat, 709b8e80941Smrg range->indexArray.offset); 710b8e80941Smrg if (ret != PIPE_OK) 711b8e80941Smrg return ret; 712b8e80941Smrg 713b8e80941Smrg pipe_resource_reference(&svga->state.hw_draw.ib, ib); 714b8e80941Smrg svga->state.hw_draw.ib_format = indexFormat; 715b8e80941Smrg svga->state.hw_draw.ib_offset = range->indexArray.offset; 716b8e80941Smrg } 717b8e80941Smrg else { 718b8e80941Smrg /* Even though we can avoid emitting the redundant SetIndexBuffer 719b8e80941Smrg * command, we still need to reference the index buffer surface. 720b8e80941Smrg */ 721b8e80941Smrg if (!last_command_was_draw(svga)) { 722b8e80941Smrg enum pipe_error ret = svga->swc->resource_rebind(svga->swc, 723b8e80941Smrg ib_handle, 724b8e80941Smrg NULL, 725b8e80941Smrg SVGA_RELOC_READ); 726b8e80941Smrg if (ret != PIPE_OK) 727b8e80941Smrg return ret; 728848b8605Smrg } 729b8e80941Smrg } 730b8e80941Smrg 731b8e80941Smrg return PIPE_OK; 732b8e80941Smrg} 733b8e80941Smrg 734b8e80941Smrg 735b8e80941Smrgstatic enum pipe_error 736b8e80941Smrgdraw_vgpu10(struct svga_hwtnl *hwtnl, 737b8e80941Smrg const SVGA3dPrimitiveRange *range, 738b8e80941Smrg unsigned vcount, 739b8e80941Smrg struct pipe_resource *ib, 740b8e80941Smrg unsigned start_instance, unsigned instance_count) 741b8e80941Smrg{ 742b8e80941Smrg struct svga_context *svga = hwtnl->svga; 743b8e80941Smrg enum pipe_error ret; 744b8e80941Smrg 745b8e80941Smrg assert(svga_have_vgpu10(svga)); 746b8e80941Smrg assert(hwtnl->cmd.prim_count == 0); 747b8e80941Smrg 748b8e80941Smrg /* We need to reemit all the current resource bindings along with the Draw 749b8e80941Smrg * command to be sure that the referenced resources are available for the 750b8e80941Smrg * Draw command, just in case the surfaces associated with the resources 751b8e80941Smrg * are paged out. 752b8e80941Smrg */ 753b8e80941Smrg if (svga->rebind.val) { 754b8e80941Smrg ret = svga_rebind_framebuffer_bindings(svga); 755b8e80941Smrg if (ret != PIPE_OK) 756b8e80941Smrg return ret; 757b8e80941Smrg 758b8e80941Smrg ret = svga_rebind_shaders(svga); 759b8e80941Smrg if (ret != PIPE_OK) 760b8e80941Smrg return ret; 761b8e80941Smrg 762b8e80941Smrg /* Rebind stream output targets */ 763b8e80941Smrg ret = svga_rebind_stream_output_targets(svga); 764b8e80941Smrg if (ret != PIPE_OK) 765b8e80941Smrg return ret; 766b8e80941Smrg 767b8e80941Smrg /* No need to explicitly rebind index buffer and vertex buffers here. 768b8e80941Smrg * Even if the same index buffer or vertex buffers are referenced for this 769b8e80941Smrg * draw and we skip emitting the redundant set command, we will still 770b8e80941Smrg * reference the associated resources. 771b8e80941Smrg */ 772b8e80941Smrg } 773b8e80941Smrg 774b8e80941Smrg ret = validate_sampler_resources(svga); 775b8e80941Smrg if (ret != PIPE_OK) 776b8e80941Smrg return ret; 777848b8605Smrg 778b8e80941Smrg ret = validate_constant_buffers(svga); 779b8e80941Smrg if (ret != PIPE_OK) 780b8e80941Smrg return ret; 781848b8605Smrg 782b8e80941Smrg ret = validate_vertex_buffers(hwtnl); 783b8e80941Smrg if (ret != PIPE_OK) 784b8e80941Smrg return ret; 785b8e80941Smrg 786b8e80941Smrg if (ib) { 787b8e80941Smrg ret = validate_index_buffer(hwtnl, range, ib); 788b8e80941Smrg if (ret != PIPE_OK) 789b8e80941Smrg return ret; 790b8e80941Smrg } 791b8e80941Smrg 792b8e80941Smrg /* Set primitive type (line, tri, etc) */ 793b8e80941Smrg if (svga->state.hw_draw.topology != range->primType) { 794b8e80941Smrg ret = SVGA3D_vgpu10_SetTopology(svga->swc, range->primType); 795b8e80941Smrg if (ret != PIPE_OK) 796b8e80941Smrg return ret; 797b8e80941Smrg 798b8e80941Smrg svga->state.hw_draw.topology = range->primType; 799b8e80941Smrg } 800b8e80941Smrg 801b8e80941Smrg if (ib) { 802b8e80941Smrg /* indexed drawing */ 803b8e80941Smrg if (instance_count > 1) { 804b8e80941Smrg ret = SVGA3D_vgpu10_DrawIndexedInstanced(svga->swc, 805b8e80941Smrg vcount, 806b8e80941Smrg instance_count, 807b8e80941Smrg 0, /* startIndexLocation */ 808b8e80941Smrg range->indexBias, 809b8e80941Smrg start_instance); 810b8e80941Smrg if (ret != PIPE_OK) 811b8e80941Smrg return ret; 812b8e80941Smrg } 813b8e80941Smrg else { 814b8e80941Smrg /* non-instanced drawing */ 815b8e80941Smrg ret = SVGA3D_vgpu10_DrawIndexed(svga->swc, 816b8e80941Smrg vcount, 817b8e80941Smrg 0, /* startIndexLocation */ 818b8e80941Smrg range->indexBias); 819b8e80941Smrg if (ret != PIPE_OK) 820b8e80941Smrg return ret; 821b8e80941Smrg } 822b8e80941Smrg } 823b8e80941Smrg else { 824b8e80941Smrg /* non-indexed drawing */ 825b8e80941Smrg if (svga->state.hw_draw.ib_format != SVGA3D_FORMAT_INVALID || 826b8e80941Smrg svga->state.hw_draw.ib != NULL) { 827b8e80941Smrg /* Unbind previously bound index buffer */ 828b8e80941Smrg ret = SVGA3D_vgpu10_SetIndexBuffer(svga->swc, NULL, 829b8e80941Smrg SVGA3D_FORMAT_INVALID, 0); 830b8e80941Smrg if (ret != PIPE_OK) 831b8e80941Smrg return ret; 832b8e80941Smrg pipe_resource_reference(&svga->state.hw_draw.ib, NULL); 833b8e80941Smrg svga->state.hw_draw.ib_format = SVGA3D_FORMAT_INVALID; 834848b8605Smrg } 835848b8605Smrg 836b8e80941Smrg assert(svga->state.hw_draw.ib == NULL); 837b8e80941Smrg 838b8e80941Smrg if (instance_count > 1) { 839b8e80941Smrg ret = SVGA3D_vgpu10_DrawInstanced(svga->swc, 840b8e80941Smrg vcount, 841b8e80941Smrg instance_count, 842b8e80941Smrg range->indexBias, 843b8e80941Smrg start_instance); 844b8e80941Smrg if (ret != PIPE_OK) 845b8e80941Smrg return ret; 846b8e80941Smrg } 847b8e80941Smrg else { 848b8e80941Smrg /* non-instanced */ 849b8e80941Smrg ret = SVGA3D_vgpu10_Draw(svga->swc, 850b8e80941Smrg vcount, 851b8e80941Smrg range->indexBias); 852b8e80941Smrg if (ret != PIPE_OK) 853b8e80941Smrg return ret; 854b8e80941Smrg } 855848b8605Smrg } 856848b8605Smrg 857b8e80941Smrg hwtnl->cmd.prim_count = 0; 858b8e80941Smrg 859848b8605Smrg return PIPE_OK; 860848b8605Smrg} 861848b8605Smrg 862848b8605Smrg 863b8e80941Smrg 864b8e80941Smrg/** 865b8e80941Smrg * Emit any pending drawing commands to the command buffer. 866b8e80941Smrg * When we receive VGPU9 drawing commands we accumulate them and don't 867b8e80941Smrg * immediately emit them into the command buffer. 868b8e80941Smrg * This function needs to be called before we change state that could 869b8e80941Smrg * effect those pending draws. 870b8e80941Smrg */ 871b8e80941Smrgenum pipe_error 872b8e80941Smrgsvga_hwtnl_flush(struct svga_hwtnl *hwtnl) 873b8e80941Smrg{ 874b8e80941Smrg enum pipe_error ret = PIPE_OK; 875b8e80941Smrg 876b8e80941Smrg SVGA_STATS_TIME_PUSH(svga_sws(hwtnl->svga), SVGA_STATS_TIME_HWTNLFLUSH); 877b8e80941Smrg 878b8e80941Smrg if (!svga_have_vgpu10(hwtnl->svga) && hwtnl->cmd.prim_count) { 879b8e80941Smrg /* we only queue up primitive for VGPU9 */ 880b8e80941Smrg ret = draw_vgpu9(hwtnl); 881b8e80941Smrg } 882b8e80941Smrg 883b8e80941Smrg SVGA_STATS_TIME_POP(svga_screen(hwtnl->svga->pipe.screen)->sws); 884b8e80941Smrg return ret; 885b8e80941Smrg} 886b8e80941Smrg 887b8e80941Smrg 888848b8605Smrgvoid 889848b8605Smrgsvga_hwtnl_set_index_bias(struct svga_hwtnl *hwtnl, int index_bias) 890848b8605Smrg{ 891848b8605Smrg hwtnl->index_bias = index_bias; 892848b8605Smrg} 893848b8605Smrg 894848b8605Smrg 895848b8605Smrg 896848b8605Smrg/*********************************************************************** 897848b8605Smrg * Internal functions: 898848b8605Smrg */ 899848b8605Smrg 900848b8605Smrg/** 901848b8605Smrg * For debugging only. 902848b8605Smrg */ 903848b8605Smrgstatic void 904848b8605Smrgcheck_draw_params(struct svga_hwtnl *hwtnl, 905848b8605Smrg const SVGA3dPrimitiveRange *range, 906848b8605Smrg unsigned min_index, unsigned max_index, 907848b8605Smrg struct pipe_resource *ib) 908848b8605Smrg{ 909848b8605Smrg unsigned i; 910848b8605Smrg 911b8e80941Smrg assert(!svga_have_vgpu10(hwtnl->svga)); 912b8e80941Smrg 913848b8605Smrg for (i = 0; i < hwtnl->cmd.vdecl_count; i++) { 914b8e80941Smrg unsigned j = hwtnl->cmd.vdecl_buffer_index[i]; 915b8e80941Smrg const struct pipe_vertex_buffer *vb = &hwtnl->cmd.vbufs[j]; 916b8e80941Smrg unsigned size = vb->buffer.resource ? vb->buffer.resource->width0 : 0; 917848b8605Smrg unsigned offset = hwtnl->cmd.vdecl[i].array.offset; 918848b8605Smrg unsigned stride = hwtnl->cmd.vdecl[i].array.stride; 919848b8605Smrg int index_bias = (int) range->indexBias + hwtnl->index_bias; 920848b8605Smrg unsigned width; 921848b8605Smrg 922b8e80941Smrg if (size == 0) 923b8e80941Smrg continue; 924b8e80941Smrg 925848b8605Smrg assert(vb); 926848b8605Smrg assert(size); 927848b8605Smrg assert(offset < size); 928848b8605Smrg assert(min_index <= max_index); 929b8e80941Smrg (void) width; 930b8e80941Smrg (void) stride; 931b8e80941Smrg (void) offset; 932b8e80941Smrg (void) size; 933848b8605Smrg 934848b8605Smrg switch (hwtnl->cmd.vdecl[i].identity.type) { 935848b8605Smrg case SVGA3D_DECLTYPE_FLOAT1: 936848b8605Smrg width = 4; 937848b8605Smrg break; 938848b8605Smrg case SVGA3D_DECLTYPE_FLOAT2: 939848b8605Smrg width = 4 * 2; 940848b8605Smrg break; 941848b8605Smrg case SVGA3D_DECLTYPE_FLOAT3: 942848b8605Smrg width = 4 * 3; 943848b8605Smrg break; 944848b8605Smrg case SVGA3D_DECLTYPE_FLOAT4: 945848b8605Smrg width = 4 * 4; 946848b8605Smrg break; 947848b8605Smrg case SVGA3D_DECLTYPE_D3DCOLOR: 948848b8605Smrg width = 4; 949848b8605Smrg break; 950848b8605Smrg case SVGA3D_DECLTYPE_UBYTE4: 951848b8605Smrg width = 1 * 4; 952848b8605Smrg break; 953848b8605Smrg case SVGA3D_DECLTYPE_SHORT2: 954848b8605Smrg width = 2 * 2; 955848b8605Smrg break; 956848b8605Smrg case SVGA3D_DECLTYPE_SHORT4: 957848b8605Smrg width = 2 * 4; 958848b8605Smrg break; 959848b8605Smrg case SVGA3D_DECLTYPE_UBYTE4N: 960848b8605Smrg width = 1 * 4; 961848b8605Smrg break; 962848b8605Smrg case SVGA3D_DECLTYPE_SHORT2N: 963848b8605Smrg width = 2 * 2; 964848b8605Smrg break; 965848b8605Smrg case SVGA3D_DECLTYPE_SHORT4N: 966848b8605Smrg width = 2 * 4; 967848b8605Smrg break; 968848b8605Smrg case SVGA3D_DECLTYPE_USHORT2N: 969848b8605Smrg width = 2 * 2; 970848b8605Smrg break; 971848b8605Smrg case SVGA3D_DECLTYPE_USHORT4N: 972848b8605Smrg width = 2 * 4; 973848b8605Smrg break; 974848b8605Smrg case SVGA3D_DECLTYPE_UDEC3: 975848b8605Smrg width = 4; 976848b8605Smrg break; 977848b8605Smrg case SVGA3D_DECLTYPE_DEC3N: 978848b8605Smrg width = 4; 979848b8605Smrg break; 980848b8605Smrg case SVGA3D_DECLTYPE_FLOAT16_2: 981848b8605Smrg width = 2 * 2; 982848b8605Smrg break; 983848b8605Smrg case SVGA3D_DECLTYPE_FLOAT16_4: 984848b8605Smrg width = 2 * 4; 985848b8605Smrg break; 986848b8605Smrg default: 987848b8605Smrg assert(0); 988848b8605Smrg width = 0; 989848b8605Smrg break; 990848b8605Smrg } 991848b8605Smrg 992848b8605Smrg if (index_bias >= 0) { 993848b8605Smrg assert(offset + index_bias * stride + width <= size); 994848b8605Smrg } 995848b8605Smrg 996848b8605Smrg /* 997848b8605Smrg * min_index/max_index are merely conservative guesses, so we can't 998848b8605Smrg * make buffer overflow detection based on their values. 999848b8605Smrg */ 1000848b8605Smrg } 1001848b8605Smrg 1002848b8605Smrg assert(range->indexWidth == range->indexArray.stride); 1003848b8605Smrg 1004848b8605Smrg if (ib) { 1005b8e80941Smrg MAYBE_UNUSED unsigned size = ib->width0; 1006b8e80941Smrg MAYBE_UNUSED unsigned offset = range->indexArray.offset; 1007b8e80941Smrg MAYBE_UNUSED unsigned stride = range->indexArray.stride; 1008b8e80941Smrg MAYBE_UNUSED unsigned count; 1009848b8605Smrg 1010848b8605Smrg assert(size); 1011848b8605Smrg assert(offset < size); 1012848b8605Smrg assert(stride); 1013848b8605Smrg 1014848b8605Smrg switch (range->primType) { 1015848b8605Smrg case SVGA3D_PRIMITIVE_POINTLIST: 1016848b8605Smrg count = range->primitiveCount; 1017848b8605Smrg break; 1018848b8605Smrg case SVGA3D_PRIMITIVE_LINELIST: 1019848b8605Smrg count = range->primitiveCount * 2; 1020848b8605Smrg break; 1021848b8605Smrg case SVGA3D_PRIMITIVE_LINESTRIP: 1022848b8605Smrg count = range->primitiveCount + 1; 1023848b8605Smrg break; 1024848b8605Smrg case SVGA3D_PRIMITIVE_TRIANGLELIST: 1025848b8605Smrg count = range->primitiveCount * 3; 1026848b8605Smrg break; 1027848b8605Smrg case SVGA3D_PRIMITIVE_TRIANGLESTRIP: 1028848b8605Smrg count = range->primitiveCount + 2; 1029848b8605Smrg break; 1030848b8605Smrg case SVGA3D_PRIMITIVE_TRIANGLEFAN: 1031848b8605Smrg count = range->primitiveCount + 2; 1032848b8605Smrg break; 1033848b8605Smrg default: 1034848b8605Smrg assert(0); 1035848b8605Smrg count = 0; 1036848b8605Smrg break; 1037848b8605Smrg } 1038848b8605Smrg 1039848b8605Smrg assert(offset + count * stride <= size); 1040848b8605Smrg } 1041848b8605Smrg} 1042848b8605Smrg 1043848b8605Smrg 1044b8e80941Smrg/** 1045b8e80941Smrg * All drawing filters down into this function, either directly 1046b8e80941Smrg * on the hardware path or after doing software vertex processing. 1047b8e80941Smrg */ 1048848b8605Smrgenum pipe_error 1049848b8605Smrgsvga_hwtnl_prim(struct svga_hwtnl *hwtnl, 1050848b8605Smrg const SVGA3dPrimitiveRange * range, 1051b8e80941Smrg unsigned vcount, 1052848b8605Smrg unsigned min_index, 1053b8e80941Smrg unsigned max_index, struct pipe_resource *ib, 1054b8e80941Smrg unsigned start_instance, unsigned instance_count) 1055848b8605Smrg{ 1056848b8605Smrg enum pipe_error ret = PIPE_OK; 1057848b8605Smrg 1058b8e80941Smrg SVGA_STATS_TIME_PUSH(svga_sws(hwtnl->svga), SVGA_STATS_TIME_HWTNLPRIM); 1059b8e80941Smrg 1060b8e80941Smrg if (svga_have_vgpu10(hwtnl->svga)) { 1061b8e80941Smrg /* draw immediately */ 1062b8e80941Smrg ret = draw_vgpu10(hwtnl, range, vcount, ib, 1063b8e80941Smrg start_instance, instance_count); 1064b8e80941Smrg if (ret != PIPE_OK) { 1065b8e80941Smrg svga_context_flush(hwtnl->svga, NULL); 1066b8e80941Smrg ret = draw_vgpu10(hwtnl, range, vcount, ib, 1067b8e80941Smrg start_instance, instance_count); 1068b8e80941Smrg assert(ret == PIPE_OK); 1069b8e80941Smrg } 1070b8e80941Smrg } 1071b8e80941Smrg else { 1072b8e80941Smrg /* batch up drawing commands */ 1073848b8605Smrg#ifdef DEBUG 1074b8e80941Smrg check_draw_params(hwtnl, range, min_index, max_index, ib); 1075b8e80941Smrg assert(start_instance == 0); 1076b8e80941Smrg assert(instance_count <= 1); 1077b8e80941Smrg#else 1078b8e80941Smrg (void) check_draw_params; 1079848b8605Smrg#endif 1080848b8605Smrg 1081b8e80941Smrg if (hwtnl->cmd.prim_count + 1 >= QSZ) { 1082b8e80941Smrg ret = svga_hwtnl_flush(hwtnl); 1083b8e80941Smrg if (ret != PIPE_OK) 1084b8e80941Smrg goto done; 1085b8e80941Smrg } 1086848b8605Smrg 1087b8e80941Smrg /* min/max indices are relative to bias */ 1088b8e80941Smrg hwtnl->cmd.min_index[hwtnl->cmd.prim_count] = min_index; 1089b8e80941Smrg hwtnl->cmd.max_index[hwtnl->cmd.prim_count] = max_index; 1090848b8605Smrg 1091b8e80941Smrg hwtnl->cmd.prim[hwtnl->cmd.prim_count] = *range; 1092b8e80941Smrg hwtnl->cmd.prim[hwtnl->cmd.prim_count].indexBias += hwtnl->index_bias; 1093848b8605Smrg 1094b8e80941Smrg pipe_resource_reference(&hwtnl->cmd.prim_ib[hwtnl->cmd.prim_count], ib); 1095b8e80941Smrg hwtnl->cmd.prim_count++; 1096b8e80941Smrg } 1097848b8605Smrg 1098b8e80941Smrgdone: 1099b8e80941Smrg SVGA_STATS_TIME_POP(svga_screen(hwtnl->svga->pipe.screen)->sws); 1100848b8605Smrg return ret; 1101848b8605Smrg} 1102