static void svga_vbuf_render_set_primitive( struct vbuf_render *render, enum pipe_prim_type prim ) { struct svga_vbuf_render *svga_render = svga_vbuf_render(render); svga_render->prim = prim; }
static void svga_vbuf_render_draw_arrays( struct vbuf_render *render, unsigned start, uint nr ) { struct svga_vbuf_render *svga_render = svga_vbuf_render(render); struct svga_context *svga = svga_render->svga; unsigned bias = (svga_render->vbuf_offset - svga_render->vdecl_offset) / svga_render->vertex_size; enum pipe_error ret = PIPE_OK; /* off to hardware */ svga_vbuf_submit_state(svga_render); /* Need to call update_state() again as the draw module may have * altered some of our state behind our backs. Testcase: * redbook/polys.c */ svga_update_state_retry( svga, SVGA_STATE_HW_DRAW ); ret = svga_hwtnl_draw_arrays(svga->hwtnl, svga_render->prim, start + bias, nr); if (ret != PIPE_OK) { svga_context_flush(svga, NULL); ret = svga_hwtnl_draw_arrays(svga->hwtnl, svga_render->prim, start + bias, nr); svga->swtnl.new_vbuf = TRUE; assert(ret == PIPE_OK); } }
static void svga_vbuf_render_unmap_vertices( struct vbuf_render *render, ushort min_index, ushort max_index ) { struct svga_vbuf_render *svga_render = svga_vbuf_render(render); struct svga_context *svga = svga_render->svga; unsigned offset, length; size_t used = svga_render->vertex_size * ((size_t)max_index + 1); offset = svga_render->vbuf_offset + svga_render->vertex_size * min_index; length = svga_render->vertex_size * (max_index + 1 - min_index); if (0) { /* dump vertex data */ const float *f = (const float *) ((char *) svga_render->vbuf_ptr + svga_render->vbuf_offset); unsigned i; debug_printf("swtnl vertex data:\n"); for (i = 0; i < length / 4; i += 4) { debug_printf("%u: %f %f %f %f\n", i, f[i], f[i+1], f[i+2], f[i+3]); } } pipe_buffer_flush_mapped_range(&svga->pipe, svga_render->vbuf_transfer, offset, length); pipe_buffer_unmap(&svga->pipe, svga_render->vbuf_transfer); svga_render->min_index = min_index; svga_render->max_index = max_index; svga_render->vbuf_used = MAX2(svga_render->vbuf_used, used); }
static void * svga_vbuf_render_map_vertices( struct vbuf_render *render ) { struct svga_vbuf_render *svga_render = svga_vbuf_render(render); struct svga_context *svga = svga_render->svga; if (svga_render->vbuf) { char *ptr = (char*)pipe_buffer_map(&svga->pipe, svga_render->vbuf, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_FLUSH_EXPLICIT | PIPE_TRANSFER_DISCARD_RANGE | PIPE_TRANSFER_UNSYNCHRONIZED, &svga_render->vbuf_transfer); if (ptr) { svga_render->vbuf_ptr = ptr; return ptr + svga_render->vbuf_offset; } else { svga_render->vbuf_ptr = NULL; svga_render->vbuf_transfer = NULL; return NULL; } } else { /* we probably ran out of memory when allocating the vertex buffer */ return NULL; } }
static boolean svga_vbuf_render_allocate_vertices( struct vbuf_render *render, ushort vertex_size, ushort nr_vertices ) { struct svga_vbuf_render *svga_render = svga_vbuf_render(render); struct svga_context *svga = svga_render->svga; struct pipe_screen *screen = svga->pipe.screen; size_t size = (size_t)nr_vertices * (size_t)vertex_size; boolean new_vbuf = FALSE; boolean new_ibuf = FALSE; if (svga_render->vertex_size != vertex_size) svga->swtnl.new_vdecl = TRUE; svga_render->vertex_size = (size_t)vertex_size; if (svga->swtnl.new_vbuf) new_ibuf = new_vbuf = TRUE; svga->swtnl.new_vbuf = FALSE; if (svga_render->vbuf_size < svga_render->vbuf_offset + svga_render->vbuf_used + size) new_vbuf = TRUE; if (new_vbuf) pipe_resource_reference(&svga_render->vbuf, NULL); if (new_ibuf) pipe_resource_reference(&svga_render->ibuf, NULL); if (!svga_render->vbuf) { svga_render->vbuf_size = MAX2(size, svga_render->vbuf_alloc_size); svga_render->vbuf = pipe_buffer_create(screen, PIPE_BIND_VERTEX_BUFFER, PIPE_USAGE_STREAM, svga_render->vbuf_size); if(!svga_render->vbuf) { svga_context_flush(svga, NULL); assert(!svga_render->vbuf); svga_render->vbuf = pipe_buffer_create(screen, PIPE_BIND_VERTEX_BUFFER, PIPE_USAGE_STREAM, svga_render->vbuf_size); /* The buffer allocation may fail if we run out of memory. * The draw module's vbuf code should handle that without crashing. */ } svga->swtnl.new_vdecl = TRUE; svga_render->vbuf_offset = 0; } else { svga_render->vbuf_offset += svga_render->vbuf_used; } svga_render->vbuf_used = 0; if (svga->swtnl.new_vdecl) svga_render->vdecl_offset = svga_render->vbuf_offset; return TRUE; }
static void svga_vbuf_render_destroy( struct vbuf_render *render ) { struct svga_vbuf_render *svga_render = svga_vbuf_render(render); pipe_resource_reference(&svga_render->vbuf, NULL); pipe_resource_reference(&svga_render->ibuf, NULL); FREE(svga_render); }
static boolean svga_vbuf_render_set_primitive( struct vbuf_render *render, unsigned prim ) { struct svga_vbuf_render *svga_render = svga_vbuf_render(render); svga_render->prim = prim; return TRUE; }
static boolean svga_vbuf_render_allocate_vertices( struct vbuf_render *render, ushort vertex_size, ushort nr_vertices ) { struct svga_vbuf_render *svga_render = svga_vbuf_render(render); struct svga_context *svga = svga_render->svga; struct pipe_screen *screen = svga->pipe.screen; size_t size = (size_t)nr_vertices * (size_t)vertex_size; boolean new_vbuf = FALSE; boolean new_ibuf = FALSE; if (svga_render->vertex_size != vertex_size) svga->swtnl.new_vdecl = TRUE; svga_render->vertex_size = (size_t)vertex_size; if (svga->swtnl.new_vbuf) new_ibuf = new_vbuf = TRUE; svga->swtnl.new_vbuf = FALSE; if (svga_render->vbuf_size < svga_render->vbuf_offset + svga_render->vbuf_used + size) new_vbuf = TRUE; if (new_vbuf) pipe_buffer_reference(&svga_render->vbuf, NULL); if (new_ibuf) pipe_buffer_reference(&svga_render->ibuf, NULL); if (!svga_render->vbuf) { svga_render->vbuf_size = MAX2(size, svga_render->vbuf_alloc_size); svga_render->vbuf = pipe_buffer_create(screen, 16, PIPE_BUFFER_USAGE_VERTEX, svga_render->vbuf_size); if(!svga_render->vbuf) { svga_context_flush(svga, NULL); svga_render->vbuf = pipe_buffer_create(screen, 16, PIPE_BUFFER_USAGE_VERTEX, svga_render->vbuf_size); assert(svga_render->vbuf); } svga->swtnl.new_vdecl = TRUE; svga_render->vbuf_offset = 0; } else { svga_render->vbuf_offset += svga_render->vbuf_used; } svga_render->vbuf_used = 0; if (svga->swtnl.new_vdecl) svga_render->vdecl_offset = svga_render->vbuf_offset; return TRUE; }
static const struct vertex_info * svga_vbuf_render_get_vertex_info( struct vbuf_render *render ) { struct svga_vbuf_render *svga_render = svga_vbuf_render(render); struct svga_context *svga = svga_render->svga; svga_swtnl_update_vdecl(svga); return &svga_render->vertex_info; }
static void * svga_vbuf_render_map_vertices( struct vbuf_render *render ) { struct svga_vbuf_render *svga_render = svga_vbuf_render(render); struct svga_context *svga = svga_render->svga; struct pipe_screen *screen = svga->pipe.screen; char *ptr = (char*)pipe_buffer_map(screen, svga_render->vbuf, PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_FLUSH_EXPLICIT | PIPE_BUFFER_USAGE_DISCARD | PIPE_BUFFER_USAGE_UNSYNCHRONIZED); return ptr + svga_render->vbuf_offset; }
static void svga_vbuf_render_unmap_vertices( struct vbuf_render *render, ushort min_index, ushort max_index ) { struct svga_vbuf_render *svga_render = svga_vbuf_render(render); struct svga_context *svga = svga_render->svga; struct pipe_screen *screen = svga->pipe.screen; unsigned offset, length; size_t used = svga_render->vertex_size * ((size_t)max_index + 1); offset = svga_render->vbuf_offset + svga_render->vertex_size * min_index; length = svga_render->vertex_size * (max_index + 1 - min_index); pipe_buffer_flush_mapped_range(screen, svga_render->vbuf, offset, length); pipe_buffer_unmap(screen, svga_render->vbuf); svga_render->min_index = min_index; svga_render->max_index = max_index; svga_render->vbuf_used = MAX2(svga_render->vbuf_used, used); }
static void svga_vbuf_render_draw_elements( struct vbuf_render *render, const ushort *indices, uint nr_indices) { struct svga_vbuf_render *svga_render = svga_vbuf_render(render); struct svga_context *svga = svga_render->svga; struct pipe_screen *screen = svga->pipe.screen; int bias = (svga_render->vbuf_offset - svga_render->vdecl_offset) / svga_render->vertex_size; boolean ret; size_t size = 2 * nr_indices; assert(( svga_render->vbuf_offset - svga_render->vdecl_offset) % svga_render->vertex_size == 0); if (svga_render->ibuf_size < svga_render->ibuf_offset + size) pipe_resource_reference(&svga_render->ibuf, NULL); if (!svga_render->ibuf) { svga_render->ibuf_size = MAX2(size, svga_render->ibuf_alloc_size); svga_render->ibuf = pipe_buffer_create(screen, PIPE_BIND_INDEX_BUFFER, PIPE_USAGE_STREAM, svga_render->ibuf_size); svga_render->ibuf_offset = 0; } pipe_buffer_write_nooverlap(&svga->pipe, svga_render->ibuf, svga_render->ibuf_offset, 2 * nr_indices, indices); /* off to hardware */ svga_vbuf_submit_state(svga_render); /* Need to call update_state() again as the draw module may have * altered some of our state behind our backs. Testcase: * redbook/polys.c */ svga_update_state_retry( svga, SVGA_STATE_HW_DRAW ); ret = svga_hwtnl_draw_range_elements(svga->hwtnl, svga_render->ibuf, 2, bias, svga_render->min_index, svga_render->max_index, svga_render->prim, svga_render->ibuf_offset / 2, nr_indices); if(ret != PIPE_OK) { svga_context_flush(svga, NULL); ret = svga_hwtnl_draw_range_elements(svga->hwtnl, svga_render->ibuf, 2, bias, svga_render->min_index, svga_render->max_index, svga_render->prim, svga_render->ibuf_offset / 2, nr_indices); svga->swtnl.new_vbuf = TRUE; assert(ret == PIPE_OK); } svga_render->ibuf_offset += size; }
enum pipe_error svga_swtnl_update_vdecl( struct svga_context *svga ) { struct svga_vbuf_render *svga_render = svga_vbuf_render(svga->swtnl.backend); struct draw_context *draw = svga->swtnl.draw; struct vertex_info *vinfo = &svga_render->vertex_info; SVGA3dVertexDecl vdecl[PIPE_MAX_ATTRIBS]; const enum interp_mode colorInterp = svga->curr.rast->templ.flatshade ? INTERP_CONSTANT : INTERP_LINEAR; struct svga_fragment_shader *fs = svga->curr.fs; int offset = 0; int nr_decls = 0; int src; unsigned i; memset(vinfo, 0, sizeof(*vinfo)); memset(vdecl, 0, sizeof(vdecl)); /* always add position */ src = draw_find_shader_output(draw, TGSI_SEMANTIC_POSITION, 0); draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_LINEAR, src); vinfo->attrib[0].emit = EMIT_4F; vdecl[0].array.offset = offset; vdecl[0].identity.type = SVGA3D_DECLTYPE_FLOAT4; vdecl[0].identity.usage = SVGA3D_DECLUSAGE_POSITIONT; vdecl[0].identity.usageIndex = 0; offset += 16; nr_decls++; for (i = 0; i < fs->base.info.num_inputs; i++) { const unsigned sem_name = fs->base.info.input_semantic_name[i]; const unsigned sem_index = fs->base.info.input_semantic_index[i]; src = draw_find_shader_output(draw, sem_name, sem_index); vdecl[nr_decls].array.offset = offset; vdecl[nr_decls].identity.usageIndex = sem_index; switch (sem_name) { case TGSI_SEMANTIC_COLOR: draw_emit_vertex_attr(vinfo, EMIT_4F, colorInterp, src); vdecl[nr_decls].identity.usage = SVGA3D_DECLUSAGE_COLOR; vdecl[nr_decls].identity.type = SVGA3D_DECLTYPE_FLOAT4; offset += 16; nr_decls++; break; case TGSI_SEMANTIC_GENERIC: draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, src); vdecl[nr_decls].identity.usage = SVGA3D_DECLUSAGE_TEXCOORD; vdecl[nr_decls].identity.type = SVGA3D_DECLTYPE_FLOAT4; vdecl[nr_decls].identity.usageIndex = svga_remap_generic_index(fs->generic_remap_table, sem_index); offset += 16; nr_decls++; break; case TGSI_SEMANTIC_FOG: draw_emit_vertex_attr(vinfo, EMIT_1F, INTERP_PERSPECTIVE, src); vdecl[nr_decls].identity.usage = SVGA3D_DECLUSAGE_TEXCOORD; vdecl[nr_decls].identity.type = SVGA3D_DECLTYPE_FLOAT1; assert(vdecl[nr_decls].identity.usageIndex == 0); offset += 4; nr_decls++; break; case TGSI_SEMANTIC_POSITION: /* generated internally, not a vertex shader output */ break; default: assert(0); } } draw_compute_vertex_size(vinfo); svga_render->vdecl_count = nr_decls; for (i = 0; i < svga_render->vdecl_count; i++) vdecl[i].array.stride = offset; if (memcmp(svga_render->vdecl, vdecl, sizeof(vdecl)) == 0) return 0; memcpy(svga_render->vdecl, vdecl, sizeof(vdecl)); svga->swtnl.new_vdecl = TRUE; return 0; }