/** * Set the draw module's clipping state. */ void draw_set_clip_state( struct draw_context *draw, const struct pipe_clip_state *clip ) { draw_do_flush(draw, DRAW_FLUSH_PARAMETER_CHANGE); memcpy(&draw->plane[6], clip->ucp, sizeof(clip->ucp)); }
void draw_set_mapped_constant_buffer(struct draw_context *draw, unsigned shader_type, unsigned slot, const void *buffer, unsigned size ) { debug_assert(shader_type == PIPE_SHADER_VERTEX || shader_type == PIPE_SHADER_GEOMETRY); debug_assert(slot < PIPE_MAX_CONSTANT_BUFFERS); draw_do_flush(draw, DRAW_FLUSH_PARAMETER_CHANGE); switch (shader_type) { case PIPE_SHADER_VERTEX: draw->pt.user.vs_constants[slot] = buffer; draw->pt.user.vs_constants_size[slot] = size; break; case PIPE_SHADER_GEOMETRY: draw->pt.user.gs_constants[slot] = buffer; draw->pt.user.gs_constants_size[slot] = size; break; default: assert(0 && "invalid shader type in draw_set_mapped_constant_buffer"); } }
void draw_pt_so_emit_prepare(struct pt_so_emit *emit) { struct draw_context *draw = emit->draw; emit->has_so = (draw->vs.vertex_shader->state.stream_output.num_outputs > 0); /* if we have a state with outputs make sure we have * buffers to output to */ if (emit->has_so) { boolean has_valid_buffer = FALSE; unsigned i; for (i = 0; i < draw->so.num_targets; ++i) { if (draw->so.targets[i]) { has_valid_buffer = TRUE; break; } } emit->has_so = has_valid_buffer; } if (!emit->has_so) return; /* XXX: need to flush to get prim_vbuf.c to release its allocation?? */ draw_do_flush( draw, DRAW_FLUSH_BACKEND ); }
void draw_set_samplers(struct draw_context *draw, unsigned shader_stage, struct pipe_sampler_state **samplers, unsigned num) { unsigned i; debug_assert(shader_stage < PIPE_SHADER_TYPES); debug_assert(num <= PIPE_MAX_SAMPLERS); draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); for (i = 0; i < num; ++i) draw->samplers[shader_stage][i] = samplers[i]; for (i = num; i < PIPE_MAX_SAMPLERS; ++i) draw->samplers[shader_stage][i] = NULL; draw->num_samplers[shader_stage] = num; #ifdef HAVE_LLVM if (draw->llvm && shader_stage == PIPE_SHADER_VERTEX) draw_llvm_set_sampler_state(draw); #endif }
static void fse_run_linear(struct draw_pt_middle_end *middle, unsigned start, unsigned count, unsigned prim_flags) { struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle; struct draw_context *draw = fse->draw; char *hw_verts; /* XXX: need to flush to get prim_vbuf.c to release its allocation?? */ draw_do_flush( draw, DRAW_FLUSH_BACKEND ); if (!draw->render->allocate_vertices( draw->render, (ushort)fse->key.output_stride, (ushort)count )) goto fail; hw_verts = draw->render->map_vertices( draw->render ); if (!hw_verts) goto fail; /* Single routine to fetch vertices, run shader and emit HW verts. * Clipping is done elsewhere -- either by the API or on hardware, * or for some other reason not required... */ fse->active->run_linear( fse->active, start, count, hw_verts ); if (0) { unsigned i; for (i = 0; i < count; i++) { debug_printf("\n\n%s vertex %d: (stride %d, offset %d)\n", __FUNCTION__, i, fse->key.output_stride, fse->key.output_stride * i); draw_dump_emitted_vertex( fse->vinfo, (const uint8_t *)hw_verts + fse->key.output_stride * i ); } } draw->render->unmap_vertices( draw->render, 0, (ushort)(count - 1) ); /* Draw arrays path to avoid re-emitting index list again and * again. */ draw->render->draw_arrays( draw->render, 0, count ); draw->render->release_vertices( draw->render ); return; fail: debug_warn_once("allocate or map of vertex buffer failed (out of memory?)"); return; }
/** * Set the draw module's viewport state. */ void draw_set_viewport_states( struct draw_context *draw, unsigned start_slot, unsigned num_viewports, const struct pipe_viewport_state *vps ) { const struct pipe_viewport_state *viewport = vps; draw_do_flush(draw, DRAW_FLUSH_PARAMETER_CHANGE); debug_assert(start_slot < PIPE_MAX_VIEWPORTS); debug_assert((start_slot + num_viewports) <= PIPE_MAX_VIEWPORTS); memcpy(draw->viewports + start_slot, vps, sizeof(struct pipe_viewport_state) * num_viewports); draw->identity_viewport = (num_viewports == 1) && (viewport->scale[0] == 1.0f && viewport->scale[1] == 1.0f && viewport->scale[2] == 1.0f && viewport->scale[3] == 1.0f && viewport->translate[0] == 0.0f && viewport->translate[1] == 0.0f && viewport->translate[2] == 0.0f && viewport->translate[3] == 0.0f); draw->driver.bypass_clip_xy = vps[0].scale[3] == 0.0f; draw->clip_xy = !draw->driver.bypass_clip_xy; draw->identity_viewport = draw->identity_viewport || vps[0].scale[3] == 0.0f; }
/** * Plug in the primitive rendering/rasterization stage (which is the last * stage in the drawing pipeline). * This is provided by the device driver. */ void draw_set_rasterize_stage( struct draw_context *draw, struct draw_stage *stage ) { draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); draw->pipeline.rasterize = stage; }
void draw_pt_so_emit_prepare(struct pt_so_emit *emit, boolean use_pre_clip_pos) { struct draw_context *draw = emit->draw; emit->use_pre_clip_pos = use_pre_clip_pos; emit->has_so = draw_has_so(draw); if (use_pre_clip_pos) emit->pos_idx = draw_current_shader_position_output(draw); /* if we have a state with outputs make sure we have * buffers to output to */ if (emit->has_so) { boolean has_valid_buffer = FALSE; unsigned i; for (i = 0; i < draw->so.num_targets; ++i) { if (draw->so.targets[i]) { has_valid_buffer = TRUE; break; } } emit->has_so = has_valid_buffer; } if (!emit->has_so) return; /* XXX: need to flush to get prim_vbuf.c to release its allocation?? */ draw_do_flush( draw, DRAW_FLUSH_BACKEND ); }
static void fetch_emit_run( struct draw_pt_middle_end *middle, const unsigned *fetch_elts, unsigned fetch_count, const ushort *draw_elts, unsigned draw_count, unsigned prim_flags ) { struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle; struct draw_context *draw = feme->draw; void *hw_verts; /* XXX: need to flush to get prim_vbuf.c to release its allocation?? */ draw_do_flush( draw, DRAW_FLUSH_BACKEND ); draw->render->allocate_vertices( draw->render, (ushort)feme->translate->key.output_stride, (ushort)fetch_count ); hw_verts = draw->render->map_vertices( draw->render ); if (!hw_verts) { assert(0); return; } /* Single routine to fetch vertices and emit HW verts. */ feme->translate->run_elts( feme->translate, fetch_elts, fetch_count, draw->instance_id, hw_verts ); if (0) { unsigned i; for (i = 0; i < fetch_count; i++) { debug_printf("\n\nvertex %d:\n", i); draw_dump_emitted_vertex( feme->vinfo, (const uint8_t *)hw_verts + feme->vinfo->size * 4 * i ); } } draw->render->unmap_vertices( draw->render, 0, (ushort)(fetch_count - 1) ); /* XXX: Draw arrays path to avoid re-emitting index list again and * again. */ draw->render->draw_elements( draw->render, draw_elts, draw_count ); /* Done -- that was easy, wasn't it: */ draw->render->release_vertices( draw->render ); }
void draw_bind_fragment_shader(struct draw_context *draw, struct draw_fragment_shader *dfs) { draw_do_flush(draw, DRAW_FLUSH_STATE_CHANGE); draw->fs.fragment_shader = dfs; }
void draw_set_driver_clipping( struct draw_context *draw, boolean bypass_clipping ) { draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); draw->driver.bypass_clipping = bypass_clipping; draw->bypass_clipping = draw->driver.bypass_clipping; }
static void fse_run(struct draw_pt_middle_end *middle, const unsigned *fetch_elts, unsigned fetch_count, const ushort *draw_elts, unsigned draw_count, unsigned prim_flags ) { struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle; struct draw_context *draw = fse->draw; void *hw_verts; /* XXX: need to flush to get prim_vbuf.c to release its allocation?? */ draw_do_flush( draw, DRAW_FLUSH_BACKEND ); if (!draw->render->allocate_vertices( draw->render, (ushort)fse->key.output_stride, (ushort)fetch_count )) goto fail; hw_verts = draw->render->map_vertices( draw->render ); if (!hw_verts) goto fail; /* Single routine to fetch vertices, run shader and emit HW verts. */ fse->active->run_elts( fse->active, fetch_elts, fetch_count, hw_verts ); if (0) { unsigned i; for (i = 0; i < fetch_count; i++) { debug_printf("\n\n%s vertex %d:\n", __FUNCTION__, i); draw_dump_emitted_vertex( fse->vinfo, (const uint8_t *)hw_verts + fse->key.output_stride * i ); } } draw->render->unmap_vertices( draw->render, 0, (ushort)(fetch_count - 1) ); draw->render->draw_elements( draw->render, draw_elts, draw_count ); draw->render->release_vertices( draw->render ); return; fail: assert(0); return; }
/** * Set the draw module's clipping state. */ void draw_set_clip_state( struct draw_context *draw, const struct pipe_clip_state *clip ) { draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); assert(clip->nr <= PIPE_MAX_CLIP_PLANES); memcpy(&draw->plane[6], clip->ucp, clip->nr * sizeof(clip->ucp[0])); draw->nr_planes = 6 + clip->nr; }
static void fetch_emit_run_linear( struct draw_pt_middle_end *middle, unsigned start, unsigned count ) { struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle; struct draw_context *draw = feme->draw; void *hw_verts; /* XXX: need to flush to get prim_vbuf.c to release its allocation?? */ draw_do_flush( draw, DRAW_FLUSH_BACKEND ); if (count >= UNDEFINED_VERTEX_ID) goto fail; if (!draw->render->allocate_vertices( draw->render, (ushort)feme->translate->key.output_stride, (ushort)count )) goto fail; hw_verts = draw->render->map_vertices( draw->render ); if (!hw_verts) goto fail; /* Single routine to fetch vertices and emit HW verts. */ feme->translate->run( feme->translate, start, count, hw_verts ); if (0) { unsigned i; for (i = 0; i < count; i++) { debug_printf("\n\nvertex %d:\n", i); draw_dump_emitted_vertex( feme->vinfo, (const uint8_t *)hw_verts + feme->vinfo->size * 4 * i ); } } draw->render->unmap_vertices( draw->render, 0, count - 1 ); /* XXX: Draw arrays path to avoid re-emitting index list again and * again. */ draw->render->draw_arrays( draw->render, 0, count ); /* Done -- that was easy, wasn't it: */ draw->render->release_vertices( draw->render ); return; fail: assert(0); return; }
/** * Register new primitive rasterization/rendering state. * This causes the drawing pipeline to be rebuilt. */ void draw_set_rasterizer_state( struct draw_context *draw, const struct pipe_rasterizer_state *raster ) { draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); draw->rasterizer = raster; draw->bypass_clipping = ((draw->rasterizer && draw->rasterizer->bypass_clipping) || draw->driver.bypass_clipping); }
/* With a little more work, llvmpipe will be able to turn this off and * do its own x/y clipping. * * Some hardware can turn off clipping altogether - in particular any * hardware with a TNL unit can do its own clipping, even if it is * relying on the draw module for some other reason. */ void draw_set_driver_clipping( struct draw_context *draw, boolean bypass_clip_xy, boolean bypass_clip_z ) { draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); draw->driver.bypass_clip_xy = bypass_clip_xy; draw->driver.bypass_clip_z = bypass_clip_z; update_clip_flags(draw); }
/** * Register new primitive rasterization/rendering state. * This causes the drawing pipeline to be rebuilt. */ void draw_set_rasterizer_state( struct draw_context *draw, const struct pipe_rasterizer_state *raster, void *rast_handle ) { if (!draw->suspend_flushing) { draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); draw->rasterizer = raster; draw->rast_handle = rast_handle; } }
/** * Draw vertex arrays * This is the main entrypoint into the drawing module. * \param prim one of PIPE_PRIM_x * \param start index of first vertex to draw * \param count number of vertices to draw */ void draw_arrays(struct draw_context *draw, unsigned prim, unsigned start, unsigned count) { unsigned reduced_prim = draw_pt_reduced_prim(prim); if (reduced_prim != draw->reduced_prim) { draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); draw->reduced_prim = reduced_prim; } /* drawing done here: */ draw_pt_arrays(draw, prim, start, count); }
/* With a little more work, llvmpipe will be able to turn this off and * do its own x/y clipping. * * Some hardware can turn off clipping altogether - in particular any * hardware with a TNL unit can do its own clipping, even if it is * relying on the draw module for some other reason. * Setting bypass_clip_points to achieve d3d-style point clipping (the driver * will need to do the "vp scissoring") _requires_ the driver to implement * wide points / point sprites itself (points will still be clipped if rasterizer * point_tri_clip isn't set). Only relevant if bypass_clip_xy isn't set. */ void draw_set_driver_clipping( struct draw_context *draw, boolean bypass_clip_xy, boolean bypass_clip_z, boolean guard_band_xy, boolean bypass_clip_points) { draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); draw->driver.bypass_clip_xy = bypass_clip_xy; draw->driver.bypass_clip_z = bypass_clip_z; draw->driver.guard_band_xy = guard_band_xy; draw->driver.bypass_clip_points = bypass_clip_points; draw_update_clip_flags(draw); }
void draw_set_vertex_elements(struct draw_context *draw, unsigned count, const struct pipe_vertex_element *elements) { assert(count <= PIPE_MAX_ATTRIBS); /* We could improve this by only flushing the frontend and the fetch part * of the middle. This would avoid recalculating the emit keys.*/ draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); memcpy(draw->pt.vertex_element, elements, count * sizeof(elements[0])); draw->pt.nr_vertex_elements = count; }
static boolean fetch_emit_run_linear_elts( struct draw_pt_middle_end *middle, unsigned start, unsigned count, const ushort *draw_elts, unsigned draw_count ) { struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle; struct draw_context *draw = feme->draw; void *hw_verts; /* XXX: need to flush to get prim_vbuf.c to release its allocation?? */ draw_do_flush( draw, DRAW_FLUSH_BACKEND ); if (count >= UNDEFINED_VERTEX_ID) return FALSE; if (!draw->render->allocate_vertices( draw->render, (ushort)feme->translate->key.output_stride, (ushort)count )) return FALSE; hw_verts = draw->render->map_vertices( draw->render ); if (!hw_verts) return FALSE; /* Single routine to fetch vertices and emit HW verts. */ feme->translate->run( feme->translate, start, count, draw->instance_id, hw_verts ); draw->render->unmap_vertices( draw->render, 0, (ushort)(count - 1) ); /* XXX: Draw arrays path to avoid re-emitting index list again and * again. */ draw->render->draw( draw->render, draw_elts, draw_count ); /* Done -- that was easy, wasn't it: */ draw->render->release_vertices( draw->render ); return TRUE; }
void draw_bind_geometry_shader(struct draw_context *draw, struct draw_geometry_shader *dgs) { draw_do_flush(draw, DRAW_FLUSH_STATE_CHANGE); if (dgs) { draw->gs.geometry_shader = dgs; draw->gs.num_gs_outputs = dgs->info.num_outputs; draw->gs.position_output = dgs->position_output; draw_geometry_shader_prepare(dgs, draw); } else { draw->gs.geometry_shader = NULL; draw->gs.num_gs_outputs = 0; } }
/** * Set the draw module's viewport state. */ void draw_set_viewport_state( struct draw_context *draw, const struct pipe_viewport_state *viewport ) { draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); draw->viewport = *viewport; /* struct copy */ draw->identity_viewport = (viewport->scale[0] == 1.0f && viewport->scale[1] == 1.0f && viewport->scale[2] == 1.0f && viewport->scale[3] == 1.0f && viewport->translate[0] == 0.0f && viewport->translate[1] == 0.0f && viewport->translate[2] == 0.0f && viewport->translate[3] == 0.0f); draw_vs_set_viewport( draw, viewport ); }
void draw_pt_so_emit( struct pt_so_emit *emit, const struct draw_vertex_info *input_verts, const struct draw_prim_info *input_prims ) { struct draw_context *draw = emit->draw; struct vbuf_render *render = draw->render; unsigned start, i; if (!emit->has_so) return; if (!draw->so.num_targets) return; emit->emitted_vertices = 0; emit->emitted_primitives = 0; emit->generated_primitives = 0; emit->input_vertex_stride = input_verts->stride; if (emit->use_pre_clip_pos) emit->pre_clip_pos = input_verts->verts->pre_clip_pos; emit->inputs = (const float (*)[4])input_verts->verts->data; /* XXX: need to flush to get prim_vbuf.c to release its allocation??*/ draw_do_flush( draw, DRAW_FLUSH_BACKEND ); for (start = i = 0; i < input_prims->primitive_count; start += input_prims->primitive_lengths[i], i++) { unsigned count = input_prims->primitive_lengths[i]; if (input_prims->linear) { so_run_linear(emit, input_prims, input_verts, start, count); } else { so_run_elts(emit, input_prims, input_verts, start, count); } } render->set_stream_output_info(render, emit->emitted_primitives, emit->emitted_vertices, emit->generated_primitives); }
static boolean fse_run_linear_elts( struct draw_pt_middle_end *middle, unsigned start, unsigned count, const ushort *draw_elts, unsigned draw_count, unsigned prim_flags ) { struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle; struct draw_context *draw = fse->draw; char *hw_verts; /* XXX: need to flush to get prim_vbuf.c to release its allocation?? */ draw_do_flush( draw, DRAW_FLUSH_BACKEND ); if (!draw->render->allocate_vertices( draw->render, (ushort)fse->key.output_stride, (ushort)count )) return FALSE; hw_verts = draw->render->map_vertices( draw->render ); if (!hw_verts) return FALSE; /* Single routine to fetch vertices, run shader and emit HW verts. * Clipping is done elsewhere -- either by the API or on hardware, * or for some other reason not required... */ fse->active->run_linear( fse->active, start, count, hw_verts ); draw->render->draw_elements( draw->render, draw_elts, draw_count ); draw->render->unmap_vertices( draw->render, 0, (ushort)(count - 1) ); draw->render->release_vertices( draw->render ); return TRUE; }
void draw_set_sampler_views(struct draw_context *draw, unsigned shader_stage, struct pipe_sampler_view **views, unsigned num) { unsigned i; debug_assert(shader_stage < PIPE_SHADER_TYPES); debug_assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS); draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); for (i = 0; i < num; ++i) draw->sampler_views[shader_stage][i] = views[i]; for (i = num; i < PIPE_MAX_SHADER_SAMPLER_VIEWS; ++i) draw->sampler_views[shader_stage][i] = NULL; draw->num_sampler_views[shader_stage] = num; }
void draw_pt_emit_prepare(struct pt_emit *emit, unsigned prim, unsigned *max_vertices) { struct draw_context *draw = emit->draw; const struct vertex_info *vinfo; unsigned dst_offset; struct translate_key hw_key; unsigned i; /* XXX: need to flush to get prim_vbuf.c to release its allocation?? */ draw_do_flush( draw, DRAW_FLUSH_BACKEND ); /* XXX: may need to defensively reset this later on as clipping can * clobber this state in the render backend. */ emit->prim = prim; draw->render->set_primitive(draw->render, emit->prim); /* Must do this after set_primitive() above: */ emit->vinfo = vinfo = draw->render->get_vertex_info(draw->render); /* Translate from pipeline vertices to hw vertices. */ dst_offset = 0; for (i = 0; i < vinfo->num_attribs; i++) { unsigned emit_sz = 0; unsigned src_buffer = 0; unsigned output_format; unsigned src_offset = (vinfo->attrib[i].src_index * 4 * sizeof(float) ); output_format = draw_translate_vinfo_format(vinfo->attrib[i].emit); emit_sz = draw_translate_vinfo_size(vinfo->attrib[i].emit); /* doesn't handle EMIT_OMIT */ assert(emit_sz != 0); if (vinfo->attrib[i].emit == EMIT_1F_PSIZE) { src_buffer = 1; src_offset = 0; } hw_key.element[i].type = TRANSLATE_ELEMENT_NORMAL; hw_key.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT; hw_key.element[i].input_buffer = src_buffer; hw_key.element[i].input_offset = src_offset; hw_key.element[i].instance_divisor = 0; hw_key.element[i].output_format = output_format; hw_key.element[i].output_offset = dst_offset; dst_offset += emit_sz; } hw_key.nr_elements = vinfo->num_attribs; hw_key.output_stride = vinfo->size * 4; if (!emit->translate || translate_key_compare(&emit->translate->key, &hw_key) != 0) { translate_key_sanitize(&hw_key); emit->translate = translate_cache_find(emit->cache, &hw_key); } *max_vertices = (draw->render->max_vertex_buffer_bytes / (vinfo->size * 4)); }
void draw_pt_emit_linear(struct pt_emit *emit, const struct draw_vertex_info *vert_info, const struct draw_prim_info *prim_info) { const float (*vertex_data)[4] = (const float (*)[4])vert_info->verts->data; unsigned stride = vert_info->stride; unsigned count = vert_info->count; struct draw_context *draw = emit->draw; struct translate *translate = emit->translate; struct vbuf_render *render = draw->render; void *hw_verts; unsigned start, i; #if 0 debug_printf("Linear emit\n"); #endif /* XXX: need to flush to get prim_vbuf.c to release its allocation?? */ draw_do_flush( draw, DRAW_FLUSH_BACKEND ); /* XXX: and work out some way to coordinate the render primitive * between vbuf.c and here... */ draw->render->set_primitive(draw->render, emit->prim); if (!render->allocate_vertices(render, (ushort)translate->key.output_stride, (ushort)count)) goto fail; hw_verts = render->map_vertices( render ); if (!hw_verts) goto fail; translate->set_buffer(translate, 0, vertex_data, stride, count - 1); translate->set_buffer(translate, 1, &draw->rasterizer->point_size, 0, ~0); translate->run(translate, 0, count, draw->start_instance, draw->instance_id, hw_verts); if (0) { unsigned i; for (i = 0; i < count; i++) { debug_printf("\n\n%s vertex %d:\n", __FUNCTION__, i); draw_dump_emitted_vertex( emit->vinfo, (const uint8_t *)hw_verts + translate->key.output_stride * i ); } } render->unmap_vertices( render, 0, count - 1 ); for (start = i = 0; i < prim_info->primitive_count; start += prim_info->primitive_lengths[i], i++) { render->draw_arrays(render, start, prim_info->primitive_lengths[i]); } render->release_vertices(render); return; fail: debug_warn_once("allocate or map of vertex buffer failed (out of memory?)"); return; }
void draw_pt_emit(struct pt_emit *emit, const struct draw_vertex_info *vert_info, const struct draw_prim_info *prim_info) { const float (*vertex_data)[4] = (const float (*)[4])vert_info->verts->data; unsigned vertex_count = vert_info->count; unsigned stride = vert_info->stride; const ushort *elts = prim_info->elts; struct draw_context *draw = emit->draw; struct translate *translate = emit->translate; struct vbuf_render *render = draw->render; unsigned start, i; void *hw_verts; /* XXX: need to flush to get prim_vbuf.c to release its allocation?? */ draw_do_flush( draw, DRAW_FLUSH_BACKEND ); if (vertex_count == 0) return; /* XXX: and work out some way to coordinate the render primitive * between vbuf.c and here... */ draw->render->set_primitive(draw->render, emit->prim); render->allocate_vertices(render, (ushort)translate->key.output_stride, (ushort)vertex_count); hw_verts = render->map_vertices( render ); if (!hw_verts) { debug_warn_once("map of vertex buffer failed (out of memory?)"); return; } translate->set_buffer(translate, 0, vertex_data, stride, ~0); translate->set_buffer(translate, 1, &draw->rasterizer->point_size, 0, ~0); /* fetch/translate vertex attribs to fill hw_verts[] */ translate->run(translate, 0, vertex_count, draw->start_instance, draw->instance_id, hw_verts ); render->unmap_vertices(render, 0, vertex_count - 1); for (start = i = 0; i < prim_info->primitive_count; start += prim_info->primitive_lengths[i], i++) { render->draw_elements(render, elts + start, prim_info->primitive_lengths[i]); } render->release_vertices(render); }
void draw_set_force_passthrough( struct draw_context *draw, boolean enable ) { draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); draw->force_passthrough = enable; }