/* SW TCL arrays, using Draw. */ boolean r300_swtcl_draw_arrays(struct pipe_context* pipe, unsigned mode, unsigned start, unsigned count) { struct r300_context* r300 = r300_context(pipe); int i; if (!u_trim_pipe_prim(mode, &count)) { return FALSE; } for (i = 0; i < r300->vertex_buffer_count; i++) { void* buf = pipe_buffer_map(pipe->screen, r300->vertex_buffer[i].buffer, PIPE_BUFFER_USAGE_CPU_READ); draw_set_mapped_vertex_buffer(r300->draw, i, buf); } draw_set_mapped_element_buffer(r300->draw, 0, NULL); draw_set_mapped_constant_buffer(r300->draw, r300->shader_constants[PIPE_SHADER_VERTEX].constants, r300->shader_constants[PIPE_SHADER_VERTEX].count * (sizeof(float) * 4)); draw_arrays(r300->draw, mode, start, count); for (i = 0; i < r300->vertex_buffer_count; i++) { pipe_buffer_unmap(pipe->screen, r300->vertex_buffer[i].buffer); draw_set_mapped_vertex_buffer(r300->draw, i, NULL); } return TRUE; }
/** * Called by VBO to draw arrays when in selection or feedback mode and * to implement glRasterPos. * This is very much like the normal draw_vbo() function above. * Look at code refactoring some day. * Might move this into the failover module some day. */ void st_feedback_draw_vbo(GLcontext *ctx, const struct gl_client_array **arrays, const struct _mesa_prim *prims, GLuint nr_prims, const struct _mesa_index_buffer *ib, GLboolean index_bounds_valid, GLuint min_index, GLuint max_index) { struct st_context *st = ctx->st; struct pipe_context *pipe = st->pipe; struct draw_context *draw = st->draw; const struct st_vertex_program *vp; const struct pipe_shader_state *vs; struct pipe_buffer *index_buffer_handle = 0; struct pipe_vertex_buffer vbuffers[PIPE_MAX_SHADER_INPUTS]; struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS]; GLuint attr, i; ubyte *mapped_constants; assert(draw); st_validate_state(ctx->st); if (!index_bounds_valid) vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index); /* must get these after state validation! */ vp = ctx->st->vp; vs = &st->vp->state; if (!st->vp->draw_shader) { st->vp->draw_shader = draw_create_vertex_shader(draw, vs); } /* * Set up the draw module's state. * * We'd like to do this less frequently, but the normal state-update * code sends state updates to the pipe, not to our private draw module. */ assert(draw); draw_set_viewport_state(draw, &st->state.viewport); draw_set_clip_state(draw, &st->state.clip); draw_set_rasterizer_state(draw, &st->state.rasterizer); draw_bind_vertex_shader(draw, st->vp->draw_shader); set_feedback_vertex_format(ctx); /* loop over TGSI shader inputs to determine vertex buffer * and attribute info */ for (attr = 0; attr < vp->num_inputs; attr++) { const GLuint mesaAttr = vp->index_to_input[attr]; struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj; void *map; if (bufobj && bufobj->Name) { /* Attribute data is in a VBO. * Recall that for VBOs, the gl_client_array->Ptr field is * really an offset from the start of the VBO, not a pointer. */ struct st_buffer_object *stobj = st_buffer_object(bufobj); assert(stobj->buffer); vbuffers[attr].buffer = NULL; pipe_buffer_reference(&vbuffers[attr].buffer, stobj->buffer); vbuffers[attr].buffer_offset = pointer_to_offset(arrays[0]->Ptr); velements[attr].src_offset = arrays[mesaAttr]->Ptr - arrays[0]->Ptr; } else { /* attribute data is in user-space memory, not a VBO */ uint bytes = (arrays[mesaAttr]->Size * _mesa_sizeof_type(arrays[mesaAttr]->Type) * (max_index + 1)); /* wrap user data */ vbuffers[attr].buffer = pipe_user_buffer_create(pipe->screen, (void *) arrays[mesaAttr]->Ptr, bytes); vbuffers[attr].buffer_offset = 0; velements[attr].src_offset = 0; } /* common-case setup */ vbuffers[attr].stride = arrays[mesaAttr]->StrideB; /* in bytes */ vbuffers[attr].max_index = max_index; velements[attr].vertex_buffer_index = attr; velements[attr].nr_components = arrays[mesaAttr]->Size; velements[attr].src_format = st_pipe_vertex_format(arrays[mesaAttr]->Type, arrays[mesaAttr]->Size, arrays[mesaAttr]->Format, arrays[mesaAttr]->Normalized); assert(velements[attr].src_format); /* tell draw about this attribute */ #if 0 draw_set_vertex_buffer(draw, attr, &vbuffer[attr]); #endif /* map the attrib buffer */ map = pipe_buffer_map(pipe->screen, vbuffers[attr].buffer, PIPE_BUFFER_USAGE_CPU_READ); draw_set_mapped_vertex_buffer(draw, attr, map); } draw_set_vertex_buffers(draw, vp->num_inputs, vbuffers); draw_set_vertex_elements(draw, vp->num_inputs, velements); if (ib) { struct gl_buffer_object *bufobj = ib->obj; unsigned indexSize; void *map; switch (ib->type) { case GL_UNSIGNED_INT: indexSize = 4; break; case GL_UNSIGNED_SHORT: indexSize = 2; break; default: assert(0); return; } if (bufobj && bufobj->Name) { struct st_buffer_object *stobj = st_buffer_object(bufobj); index_buffer_handle = stobj->buffer; map = pipe_buffer_map(pipe->screen, index_buffer_handle, PIPE_BUFFER_USAGE_CPU_READ); draw_set_mapped_element_buffer(draw, indexSize, map); } else { draw_set_mapped_element_buffer(draw, indexSize, (void *) ib->ptr); } } else { /* no index/element buffer */ draw_set_mapped_element_buffer(draw, 0, NULL); } /* map constant buffers */ mapped_constants = pipe_buffer_map(pipe->screen, st->state.constants[PIPE_SHADER_VERTEX].buffer, PIPE_BUFFER_USAGE_CPU_READ); draw_set_mapped_constant_buffer(st->draw, mapped_constants, st->state.constants[PIPE_SHADER_VERTEX].buffer->size); /* draw here */ for (i = 0; i < nr_prims; i++) { draw_arrays(draw, prims[i].mode, prims[i].start, prims[i].count); } /* unmap constant buffers */ pipe_buffer_unmap(pipe->screen, st->state.constants[PIPE_SHADER_VERTEX].buffer); /* * unmap vertex/index buffers */ for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { if (draw->pt.vertex_buffer[i].buffer) { pipe_buffer_unmap(pipe->screen, draw->pt.vertex_buffer[i].buffer); pipe_buffer_reference(&draw->pt.vertex_buffer[i].buffer, NULL); draw_set_mapped_vertex_buffer(draw, i, NULL); } } if (index_buffer_handle) { pipe_buffer_unmap(pipe->screen, index_buffer_handle); draw_set_mapped_element_buffer(draw, 0, NULL); } }
static boolean i915_draw_range_elements(struct pipe_context *pipe, struct pipe_buffer *indexBuffer, unsigned indexSize, unsigned min_index, unsigned max_index, unsigned prim, unsigned start, unsigned count) { struct i915_context *i915 = i915_context(pipe); struct draw_context *draw = i915->draw; unsigned i; if (i915->dirty) i915_update_derived(i915); /* * Map vertex buffers */ for (i = 0; i < i915->num_vertex_buffers; i++) { void *buf = pipe_buffer_map(pipe->screen, i915->vertex_buffer[i].buffer, PIPE_BUFFER_USAGE_CPU_READ); draw_set_mapped_vertex_buffer(draw, i, buf); } /* * Map index buffer, if present */ if (indexBuffer) { void *mapped_indexes = pipe_buffer_map(pipe->screen, indexBuffer, PIPE_BUFFER_USAGE_CPU_READ); draw_set_mapped_element_buffer_range(draw, indexSize, min_index, max_index, mapped_indexes); } else { draw_set_mapped_element_buffer(draw, 0, NULL); } draw_set_mapped_constant_buffer(draw, i915->current.constants[PIPE_SHADER_VERTEX], (i915->current.num_user_constants[PIPE_SHADER_VERTEX] * 4 * sizeof(float))); /* * Do the drawing */ draw_arrays(i915->draw, prim, start, count); /* * unmap vertex/index buffers */ for (i = 0; i < i915->num_vertex_buffers; i++) { pipe_buffer_unmap(pipe->screen, i915->vertex_buffer[i].buffer); draw_set_mapped_vertex_buffer(draw, i, NULL); } if (indexBuffer) { pipe_buffer_unmap(pipe->screen, indexBuffer); draw_set_mapped_element_buffer_range(draw, 0, start, start + count - 1, NULL); } return TRUE; }
enum pipe_error svga_swtnl_draw_range_elements(struct svga_context *svga, struct pipe_buffer *indexBuffer, unsigned indexSize, unsigned min_index, unsigned max_index, unsigned prim, unsigned start, unsigned count) { struct draw_context *draw = svga->swtnl.draw; unsigned i; const void *map; enum pipe_error ret; assert(!svga->dirty); assert(svga->state.sw.need_swtnl); assert(draw); ret = svga_update_state(svga, SVGA_STATE_SWTNL_DRAW); if (ret) { svga_context_flush(svga, NULL); ret = svga_update_state(svga, SVGA_STATE_SWTNL_DRAW); svga->swtnl.new_vbuf = TRUE; assert(ret == PIPE_OK); } /* * Map vertex buffers */ for (i = 0; i < svga->curr.num_vertex_buffers; i++) { map = pipe_buffer_map(svga->pipe.screen, svga->curr.vb[i].buffer, PIPE_BUFFER_USAGE_CPU_READ); draw_set_mapped_vertex_buffer(draw, i, map); } /* Map index buffer, if present */ if (indexBuffer) { map = pipe_buffer_map(svga->pipe.screen, indexBuffer, PIPE_BUFFER_USAGE_CPU_READ); draw_set_mapped_element_buffer_range(draw, indexSize, min_index, max_index, map); } if (svga->curr.cb[PIPE_SHADER_VERTEX]) { map = pipe_buffer_map(svga->pipe.screen, svga->curr.cb[PIPE_SHADER_VERTEX], PIPE_BUFFER_USAGE_CPU_READ); assert(map); draw_set_mapped_constant_buffer( draw, PIPE_SHADER_VERTEX, 0, map, svga->curr.cb[PIPE_SHADER_VERTEX]->size); } draw_arrays(svga->swtnl.draw, prim, start, count); draw_flush(svga->swtnl.draw); /* Ensure the draw module didn't touch this */ assert(i == svga->curr.num_vertex_buffers); /* * unmap vertex/index buffers */ for (i = 0; i < svga->curr.num_vertex_buffers; i++) { pipe_buffer_unmap(svga->pipe.screen, svga->curr.vb[i].buffer); draw_set_mapped_vertex_buffer(draw, i, NULL); } if (indexBuffer) { pipe_buffer_unmap(svga->pipe.screen, indexBuffer); draw_set_mapped_element_buffer(draw, 0, NULL); } if (svga->curr.cb[PIPE_SHADER_VERTEX]) { pipe_buffer_unmap(svga->pipe.screen, svga->curr.cb[PIPE_SHADER_VERTEX]); } return ret; }
/** * Draw vertex arrays, with optional indexing. * Basically, map the vertex buffers (and drawing surfaces), then hand off * the drawing to the 'draw' module. */ boolean llvmpipe_draw_range_elements(struct pipe_context *pipe, struct pipe_buffer *indexBuffer, unsigned indexSize, unsigned min_index, unsigned max_index, unsigned mode, unsigned start, unsigned count) { struct llvmpipe_context *lp = llvmpipe_context(pipe); struct draw_context *draw = lp->draw; unsigned i; lp->reduced_api_prim = u_reduced_prim(mode); if (lp->dirty) llvmpipe_update_derived( lp ); llvmpipe_map_transfers(lp); /* * Map vertex buffers */ for (i = 0; i < lp->num_vertex_buffers; i++) { void *buf = llvmpipe_buffer(lp->vertex_buffer[i].buffer)->data; draw_set_mapped_vertex_buffer(draw, i, buf); } /* Map index buffer, if present */ if (indexBuffer) { void *mapped_indexes = llvmpipe_buffer(indexBuffer)->data; draw_set_mapped_element_buffer_range(draw, indexSize, min_index, max_index, mapped_indexes); } else { /* no index/element buffer */ draw_set_mapped_element_buffer_range(draw, 0, start, start + count - 1, NULL); } /* draw! */ draw_arrays(draw, mode, start, count); /* * unmap vertex/index buffers */ for (i = 0; i < lp->num_vertex_buffers; i++) { draw_set_mapped_vertex_buffer(draw, i, NULL); } if (indexBuffer) { draw_set_mapped_element_buffer(draw, 0, NULL); } /* * TODO: Flush only when a user vertex/index buffer is present * (or even better, modify draw module to do this * internally when this condition is seen?) */ draw_flush(draw); /* Note: leave drawing surfaces mapped */ lp->dirty_render_cache = TRUE; return TRUE; }
/** * Draw vertex arrays, with optional indexing. * Basically, map the vertex buffers (and drawing surfaces), then hand off * the drawing to the 'draw' module. * * XXX should the element buffer be specified/bound with a separate function? */ static boolean cell_draw_range_elements(struct pipe_context *pipe, struct pipe_buffer *indexBuffer, unsigned indexSize, unsigned min_index, unsigned max_index, unsigned mode, unsigned start, unsigned count) { struct cell_context *sp = cell_context(pipe); struct draw_context *draw = sp->draw; unsigned i; if (sp->dirty) cell_update_derived( sp ); #if 0 cell_map_surfaces(sp); #endif cell_map_constant_buffers(sp); /* * Map vertex buffers */ for (i = 0; i < sp->num_vertex_buffers; i++) { void *buf = pipe_buffer_map(pipe->screen, sp->vertex_buffer[i].buffer, PIPE_BUFFER_USAGE_CPU_READ); cell_flush_buffer_range(sp, buf, sp->vertex_buffer[i].buffer->size); draw_set_mapped_vertex_buffer(draw, i, buf); } /* Map index buffer, if present */ if (indexBuffer) { void *mapped_indexes = pipe_buffer_map(pipe->screen, indexBuffer, PIPE_BUFFER_USAGE_CPU_READ); draw_set_mapped_element_buffer(draw, indexSize, mapped_indexes); } else { /* no index/element buffer */ draw_set_mapped_element_buffer(draw, 0, NULL); } /* draw! */ draw_arrays(draw, mode, start, count); /* * unmap vertex/index buffers - will cause draw module to flush */ for (i = 0; i < sp->num_vertex_buffers; i++) { draw_set_mapped_vertex_buffer(draw, i, NULL); pipe_buffer_unmap(pipe->screen, sp->vertex_buffer[i].buffer); } if (indexBuffer) { draw_set_mapped_element_buffer(draw, 0, NULL); pipe_buffer_unmap(pipe->screen, indexBuffer); } /* Note: leave drawing surfaces mapped */ cell_unmap_constant_buffers(sp); return TRUE; }