static void r300_render_draw_arrays(struct vbuf_render* render, unsigned start, unsigned count) { struct r300_render* r300render = r300_render(render); struct r300_context* r300 = r300render->r300; uint8_t* ptr; unsigned i; unsigned dwords = 6; CS_LOCALS(r300); (void) i; (void) ptr; assert(start == 0); assert(count < (1 << 16)); DBG(r300, DBG_DRAW, "r300: render_draw_arrays (count: %d)\n", count); if (!r300_prepare_for_rendering(r300, PREP_EMIT_STATES | PREP_EMIT_VARRAYS_SWTCL, NULL, dwords, 0, 0, -1)) { return; } BEGIN_CS(dwords); OUT_CS_REG(R300_GA_COLOR_CONTROL, r300_provoking_vertex_fixes(r300, r300render->prim)); OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, count - 1); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) | r300render->hwprim); END_CS; }
static void r300_render_draw_arrays(struct vbuf_render* render, unsigned start, unsigned count) { struct r300_render* r300render = r300_render(render); struct r300_context* r300 = r300render->r300; uint8_t* ptr; unsigned i; unsigned dwords = 6; CS_LOCALS(r300); (void) i; (void) ptr; DBG(r300, DBG_DRAW, "r300: render_draw_arrays (count: %d)\n", count); if (r300->draw_first_emitted) { if (!r300_prepare_for_rendering(r300, PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL, NULL, 6, 0, 0)) return; } else { if (!r300_emit_states(r300, PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL, NULL, 0, 0)) return; } /* Uncomment to dump all VBOs rendered through this interface. * Slow and noisy! ptr = pipe_buffer_map(&r300render->r300->context, r300render->vbo, PIPE_TRANSFER_READ, &r300render->vbo_transfer); for (i = 0; i < count; i++) { printf("r300: Vertex %d\n", i); draw_dump_emitted_vertex(&r300->vertex_info, ptr); ptr += r300->vertex_info.size * 4; printf("\n"); } pipe_buffer_unmap(&r300render->r300->context, r300render->vbo, r300render->vbo_transfer); */ BEGIN_CS(dwords); OUT_CS_REG(R300_GA_COLOR_CONTROL, r300_provoking_vertex_fixes(r300, r300render->prim)); OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, count - 1); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) | r300render->hwprim); END_CS; r300->draw_first_emitted = TRUE; }
static void r300_draw_arrays(struct r300_context *r300, const struct pipe_draw_info *info, int instance_id) { boolean alt_num_verts = r300->screen->caps.is_r500 && info->count > 65536; unsigned start = info->start; unsigned count = info->count; unsigned short_count; /* 9 spare dwords for emit_draw_arrays. Give up if the function fails. */ if (!r300_prepare_for_rendering(r300, PREP_EMIT_STATES | PREP_VALIDATE_VBOS | PREP_EMIT_VARRAYS, NULL, 9, start, 0, instance_id)) return; if (alt_num_verts || count <= 65535) { r300_emit_draw_arrays(r300, info->mode, count); } else { do { /* The maximum must be divisible by 4 and 3, * so that quad and triangle lists are split correctly. * * Strips, loops, and fans won't work. */ short_count = MIN2(count, 65532); r300_emit_draw_arrays(r300, info->mode, short_count); start += short_count; count -= short_count; /* 9 spare dwords for emit_draw_arrays. Give up if the function fails. */ if (count) { if (!r300_prepare_for_rendering(r300, PREP_VALIDATE_VBOS | PREP_EMIT_VARRAYS, NULL, 9, start, 0, instance_id)) return; } } while (count); } }
static void r300_render_draw_elements(struct vbuf_render* render, const ushort* indices, uint count) { struct r300_render* r300render = r300_render(render); struct r300_context* r300 = r300render->r300; unsigned max_index = (r300->vbo->size - r300->draw_vbo_offset) / (r300render->r300->vertex_info.size * 4) - 1; struct pipe_resource *index_buffer = NULL; unsigned index_buffer_offset; CS_LOCALS(r300); DBG(r300, DBG_DRAW, "r300: render_draw_elements (count: %d)\n", count); u_upload_data(r300->uploader, 0, count * 2, indices, &index_buffer_offset, &index_buffer); if (!index_buffer) { return; } if (!r300_prepare_for_rendering(r300, PREP_EMIT_STATES | PREP_EMIT_VARRAYS_SWTCL | PREP_INDEXED, index_buffer, 12, 0, 0, -1)) { pipe_resource_reference(&index_buffer, NULL); return; } BEGIN_CS(12); OUT_CS_REG(R300_GA_COLOR_CONTROL, r300_provoking_vertex_fixes(r300, r300render->prim)); OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, max_index); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, 0); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | r300render->hwprim); OUT_CS_PKT3(R300_PACKET3_INDX_BUFFER, 2); OUT_CS(R300_INDX_BUFFER_ONE_REG_WR | (R300_VAP_PORT_IDX0 >> 2)); OUT_CS(index_buffer_offset); OUT_CS((count + 1) / 2); OUT_CS_RELOC(r300_resource(index_buffer)); END_CS; pipe_resource_reference(&index_buffer, NULL); }
static void r300_draw_elements(struct r300_context *r300, const struct pipe_draw_info *info, int instance_id) { struct pipe_resource *indexBuffer = r300->index_buffer.buffer; unsigned indexSize = r300->index_buffer.index_size; struct pipe_resource* orgIndexBuffer = indexBuffer; unsigned start = info->start; unsigned count = info->count; boolean alt_num_verts = r300->screen->caps.is_r500 && count > 65536; unsigned short_count; int buffer_offset = 0, index_offset = 0; /* for index bias emulation */ uint16_t indices3[3]; if (info->index_bias && !r300->screen->caps.is_r500) { r300_split_index_bias(r300, info->index_bias, &buffer_offset, &index_offset); } r300_translate_index_buffer(r300, &r300->index_buffer, &indexBuffer, &indexSize, index_offset, &start, count); /* Fallback for misaligned ushort indices. */ if (indexSize == 2 && (start & 1) && indexBuffer) { /* If we got here, then orgIndexBuffer == indexBuffer. */ uint16_t *ptr = r300->rws->buffer_map(r300_resource(orgIndexBuffer)->cs_buf, r300->cs, PIPE_TRANSFER_READ | PIPE_TRANSFER_UNSYNCHRONIZED); if (info->mode == PIPE_PRIM_TRIANGLES) { memcpy(indices3, ptr + start, 6); } else { /* Copy the mapped index buffer directly to the upload buffer. * The start index will be aligned simply from the fact that * every sub-buffer in the upload buffer is aligned. */ r300_upload_index_buffer(r300, &indexBuffer, indexSize, &start, count, (uint8_t*)ptr); } } else { if (r300->index_buffer.user_buffer) r300_upload_index_buffer(r300, &indexBuffer, indexSize, &start, count, r300->index_buffer.user_buffer); } /* 19 dwords for emit_draw_elements. Give up if the function fails. */ if (!r300_prepare_for_rendering(r300, PREP_EMIT_STATES | PREP_VALIDATE_VBOS | PREP_EMIT_VARRAYS | PREP_INDEXED, indexBuffer, 19, buffer_offset, info->index_bias, instance_id)) goto done; if (alt_num_verts || count <= 65535) { r300_emit_draw_elements(r300, indexBuffer, indexSize, info->max_index, info->mode, start, count, indices3); } else { do { /* The maximum must be divisible by 4 and 3, * so that quad and triangle lists are split correctly. * * Strips, loops, and fans won't work. */ short_count = MIN2(count, 65532); r300_emit_draw_elements(r300, indexBuffer, indexSize, info->max_index, info->mode, start, short_count, indices3); start += short_count; count -= short_count; /* 15 dwords for emit_draw_elements */ if (count) { if (!r300_prepare_for_rendering(r300, PREP_VALIDATE_VBOS | PREP_EMIT_VARRAYS | PREP_INDEXED, indexBuffer, 19, buffer_offset, info->index_bias, instance_id)) goto done; } } while (count); } done: if (indexBuffer != orgIndexBuffer) { pipe_resource_reference( &indexBuffer, NULL ); } }
static void r300_draw_elements_immediate(struct r300_context *r300, const struct pipe_draw_info *info) { const uint8_t *ptr1; const uint16_t *ptr2; const uint32_t *ptr4; unsigned index_size = r300->index_buffer.index_size; unsigned i, count_dwords = index_size == 4 ? info->count : (info->count + 1) / 2; CS_LOCALS(r300); /* 19 dwords for r300_draw_elements_immediate. Give up if the function fails. */ if (!r300_prepare_for_rendering(r300, PREP_EMIT_STATES | PREP_VALIDATE_VBOS | PREP_EMIT_VARRAYS | PREP_INDEXED, NULL, 2+count_dwords, 0, info->index_bias, -1)) return; r300_emit_draw_init(r300, info->mode, info->max_index); BEGIN_CS(2 + count_dwords); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, count_dwords); switch (index_size) { case 1: ptr1 = (uint8_t*)r300->index_buffer.user_buffer; ptr1 += info->start; OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (info->count << 16) | r300_translate_primitive(info->mode)); if (info->index_bias && !r300->screen->caps.is_r500) { for (i = 0; i < info->count-1; i += 2) OUT_CS(((ptr1[i+1] + info->index_bias) << 16) | (ptr1[i] + info->index_bias)); if (info->count & 1) OUT_CS(ptr1[i] + info->index_bias); } else { for (i = 0; i < info->count-1; i += 2) OUT_CS(((ptr1[i+1]) << 16) | (ptr1[i] )); if (info->count & 1) OUT_CS(ptr1[i]); } break; case 2: ptr2 = (uint16_t*)r300->index_buffer.user_buffer; ptr2 += info->start; OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (info->count << 16) | r300_translate_primitive(info->mode)); if (info->index_bias && !r300->screen->caps.is_r500) { for (i = 0; i < info->count-1; i += 2) OUT_CS(((ptr2[i+1] + info->index_bias) << 16) | (ptr2[i] + info->index_bias)); if (info->count & 1) OUT_CS(ptr2[i] + info->index_bias); } else { OUT_CS_TABLE(ptr2, count_dwords); } break; case 4: ptr4 = (uint32_t*)r300->index_buffer.user_buffer; ptr4 += info->start; OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (info->count << 16) | R300_VAP_VF_CNTL__INDEX_SIZE_32bit | r300_translate_primitive(info->mode)); if (info->index_bias && !r300->screen->caps.is_r500) { for (i = 0; i < info->count; i++) OUT_CS(ptr4[i] + info->index_bias); } else { OUT_CS_TABLE(ptr4, count_dwords); } break; } END_CS; }
static void r300_draw_arrays_immediate(struct r300_context *r300, const struct pipe_draw_info *info) { struct pipe_vertex_element* velem; struct pipe_vertex_buffer* vbuf; unsigned vertex_element_count = r300->velems->count; unsigned i, v, vbi; /* Size of the vertex, in dwords. */ unsigned vertex_size = r300->velems->vertex_size_dwords; /* The number of dwords for this draw operation. */ unsigned dwords = 4 + info->count * vertex_size; /* Size of the vertex element, in dwords. */ unsigned size[PIPE_MAX_ATTRIBS]; /* Stride to the same attrib in the next vertex in the vertex buffer, * in dwords. */ unsigned stride[PIPE_MAX_ATTRIBS]; /* Mapped vertex buffers. */ uint32_t* map[PIPE_MAX_ATTRIBS] = {0}; uint32_t* mapelem[PIPE_MAX_ATTRIBS]; CS_LOCALS(r300); if (!r300_prepare_for_rendering(r300, PREP_EMIT_STATES, NULL, dwords, 0, 0, -1)) return; /* Calculate the vertex size, offsets, strides etc. and map the buffers. */ for (i = 0; i < vertex_element_count; i++) { velem = &r300->velems->velem[i]; size[i] = r300->velems->format_size[i] / 4; vbi = velem->vertex_buffer_index; vbuf = &r300->vertex_buffer[vbi]; stride[i] = vbuf->stride / 4; /* Map the buffer. */ if (!map[vbi]) { map[vbi] = (uint32_t*)r300->rws->buffer_map( r300_resource(vbuf->buffer)->cs_buf, r300->cs, PIPE_TRANSFER_READ | PIPE_TRANSFER_UNSYNCHRONIZED); map[vbi] += (vbuf->buffer_offset / 4) + stride[i] * info->start; } mapelem[i] = map[vbi] + (velem->src_offset / 4); } r300_emit_draw_init(r300, info->mode, info->count-1); BEGIN_CS(dwords); OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, info->count * vertex_size); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (info->count << 16) | r300_translate_primitive(info->mode)); /* Emit vertices. */ for (v = 0; v < info->count; v++) { for (i = 0; i < vertex_element_count; i++) { OUT_CS_TABLE(&mapelem[i][stride[i] * v], size[i]); } } END_CS; }
/* This functions is used to draw a rectangle for the blitter module. * * If we rendered a quad, the pixels on the main diagonal * would be computed and stored twice, which makes the clear/copy codepaths * somewhat inefficient. Instead we use a rectangular point sprite. */ void r300_blitter_draw_rectangle(struct blitter_context *blitter, int x1, int y1, int x2, int y2, float depth, enum blitter_attrib_type type, const union pipe_color_union *attrib) { struct r300_context *r300 = r300_context(util_blitter_get_pipe(blitter)); unsigned last_sprite_coord_enable = r300->sprite_coord_enable; unsigned width = x2 - x1; unsigned height = y2 - y1; unsigned vertex_size = type == UTIL_BLITTER_ATTRIB_COLOR || !r300->draw ? 8 : 4; unsigned dwords = 13 + vertex_size + (type == UTIL_BLITTER_ATTRIB_TEXCOORD ? 7 : 0); static const union pipe_color_union zeros; CS_LOCALS(r300); /* XXX workaround for a lockup in MSAA resolve on SWTCL chipsets, this * function most probably doesn't handle type=NONE correctly */ if (!r300->screen->caps.has_tcl && type == UTIL_BLITTER_ATTRIB_NONE) { util_blitter_draw_rectangle(blitter, x1, y1, x2, y2, depth, type, attrib); return; } if (r300->skip_rendering) return; if (type == UTIL_BLITTER_ATTRIB_TEXCOORD) r300->sprite_coord_enable = 1; r300_update_derived_state(r300); /* Mark some states we don't care about as non-dirty. */ r300->viewport_state.dirty = FALSE; if (!r300_prepare_for_rendering(r300, PREP_EMIT_STATES, NULL, dwords, 0, 0, -1)) goto done; DBG(r300, DBG_DRAW, "r300: draw_rectangle\n"); BEGIN_CS(dwords); /* Set up GA. */ OUT_CS_REG(R300_GA_POINT_SIZE, (height * 6) | ((width * 6) << 16)); if (type == UTIL_BLITTER_ATTRIB_TEXCOORD) { /* Set up the GA to generate texcoords. */ OUT_CS_REG(R300_GB_ENABLE, R300_GB_POINT_STUFF_ENABLE | (R300_GB_TEX_STR << R300_GB_TEX0_SOURCE_SHIFT)); OUT_CS_REG_SEQ(R300_GA_POINT_S0, 4); OUT_CS_32F(attrib->f[0]); OUT_CS_32F(attrib->f[3]); OUT_CS_32F(attrib->f[2]); OUT_CS_32F(attrib->f[1]); } /* Set up VAP controls. */ OUT_CS_REG(R300_VAP_CLIP_CNTL, R300_CLIP_DISABLE); OUT_CS_REG(R300_VAP_VTE_CNTL, R300_VTX_XY_FMT | R300_VTX_Z_FMT); OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size); OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); OUT_CS(1); OUT_CS(0); /* Draw. */ OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, vertex_size); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (1 << 16) | R300_VAP_VF_CNTL__PRIM_POINTS); OUT_CS_32F(x1 + width * 0.5f); OUT_CS_32F(y1 + height * 0.5f); OUT_CS_32F(depth); OUT_CS_32F(1); if (vertex_size == 8) { if (!attrib) attrib = &zeros; OUT_CS_TABLE(attrib->f, 4); } END_CS; done: /* Restore the state. */ r300_mark_atom_dirty(r300, &r300->rs_state); r300_mark_atom_dirty(r300, &r300->viewport_state); r300->sprite_coord_enable = last_sprite_coord_enable; }
static void r300_render_draw_elements(struct vbuf_render* render, const ushort* indices, uint count) { struct r300_render* r300render = r300_render(render); struct r300_context* r300 = r300render->r300; int i; unsigned end_cs_dwords; unsigned max_index = (r300->draw_vbo_size - r300->draw_vbo_offset) / (r300render->r300->vertex_info.size * 4) - 1; unsigned short_count; unsigned free_dwords; CS_LOCALS(r300); DBG(r300, DBG_DRAW, "r300: render_draw_elements (count: %d)\n", count); if (r300->draw_first_emitted) { if (!r300_prepare_for_rendering(r300, PREP_EMIT_STATES | PREP_EMIT_VARRAYS_SWTCL | PREP_INDEXED, NULL, 256, 0, 0, -1)) return; } else { if (!r300_emit_states(r300, PREP_EMIT_STATES | PREP_EMIT_VARRAYS_SWTCL | PREP_INDEXED, NULL, 0, 0, -1)) return; } /* Below we manage the CS space manually because there may be more * indices than it can fit in CS. */ end_cs_dwords = r300_get_num_cs_end_dwords(r300); while (count) { free_dwords = RADEON_MAX_CMDBUF_DWORDS - r300->cs->cdw; short_count = MIN2(count, (free_dwords - end_cs_dwords - 6) * 2); BEGIN_CS(6 + (short_count+1)/2); OUT_CS_REG(R300_GA_COLOR_CONTROL, r300_provoking_vertex_fixes(r300, r300render->prim)); OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, max_index); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, (short_count+1)/2); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (short_count << 16) | r300render->hwprim); for (i = 0; i < short_count-1; i += 2) { OUT_CS(indices[i+1] << 16 | indices[i]); } if (short_count % 2) { OUT_CS(indices[short_count-1]); } END_CS; /* OK now subtract the emitted indices and see if we need to emit * another draw packet. */ indices += short_count; count -= short_count; if (count) { if (!r300_prepare_for_rendering(r300, PREP_EMIT_VARRAYS_SWTCL | PREP_INDEXED, NULL, 256, 0, 0, -1)) return; end_cs_dwords = r300_get_num_cs_end_dwords(r300); } } r300->draw_first_emitted = TRUE; }
static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, unsigned start, unsigned count) { struct r300_context* r300 = r300_context(pipe); boolean alt_num_verts = r300->screen->caps.is_r500 && count > 65536 && r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0); unsigned short_count; boolean translate = FALSE; if (r300->skip_rendering) { return; } if (!u_trim_pipe_prim(mode, &count)) { return; } /* Set up fallback for incompatible vertex layout if needed. */ if (r300->incompatible_vb_layout || r300->velems->incompatible_layout) { r300_begin_vertex_translate(r300); translate = TRUE; } r300_update_derived_state(r300); if (immd_is_good_idea(r300, count)) { r300_emit_draw_arrays_immediate(r300, mode, start, count); } else { /* 9 spare dwords for emit_draw_arrays. Give up if the function fails. */ if (!r300_prepare_for_rendering(r300, PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS, NULL, 9, start, 0)) goto done; if (alt_num_verts || count <= 65535) { r300_emit_draw_arrays(r300, mode, count); } else { do { short_count = MIN2(count, 65535); r300_emit_draw_arrays(r300, mode, short_count); start += short_count; count -= short_count; /* 9 spare dwords for emit_draw_arrays. Give up if the function fails. */ if (count) { if (!r300_prepare_for_rendering(r300, PREP_VALIDATE_VBOS | PREP_EMIT_AOS, NULL, 9, start, 0)) goto done; } } while (count); } } done: if (translate) { r300_end_vertex_translate(r300); } }
/* This is the fast-path drawing & emission for HW TCL. */ static void r300_draw_range_elements(struct pipe_context* pipe, struct pipe_resource* indexBuffer, unsigned indexSize, int indexBias, unsigned minIndex, unsigned maxIndex, unsigned mode, unsigned start, unsigned count) { struct r300_context* r300 = r300_context(pipe); struct pipe_resource* orgIndexBuffer = indexBuffer; boolean alt_num_verts = r300->screen->caps.is_r500 && count > 65536 && r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0); unsigned short_count; int buffer_offset = 0, index_offset = 0; /* for index bias emulation */ boolean translate = FALSE; unsigned new_offset; if (r300->skip_rendering) { return; } if (!u_trim_pipe_prim(mode, &count)) { return; } /* Index buffer range checking. */ if ((start + count) * indexSize > indexBuffer->width0) { fprintf(stderr, "r300: Invalid index buffer range. Skipping rendering.\n"); return; } /* Set up fallback for incompatible vertex layout if needed. */ if (r300->incompatible_vb_layout || r300->velems->incompatible_layout) { r300_begin_vertex_translate(r300); translate = TRUE; } if (indexBias && !r500_index_bias_supported(r300)) { r300_split_index_bias(r300, indexBias, &buffer_offset, &index_offset); } r300_translate_index_buffer(r300, &indexBuffer, &indexSize, index_offset, &start, count); r300_update_derived_state(r300); r300_upload_index_buffer(r300, &indexBuffer, indexSize, start, count, &new_offset); start = new_offset; /* 15 dwords for emit_draw_elements. Give up if the function fails. */ if (!r300_prepare_for_rendering(r300, PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS | PREP_INDEXED, indexBuffer, 15, buffer_offset, indexBias)) goto done; if (alt_num_verts || count <= 65535) { r300_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, maxIndex, mode, start, count); } else { do { short_count = MIN2(count, 65534); r300_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, maxIndex, mode, start, short_count); start += short_count; count -= short_count; /* 15 dwords for emit_draw_elements */ if (count) { if (!r300_prepare_for_rendering(r300, PREP_VALIDATE_VBOS | PREP_EMIT_AOS | PREP_INDEXED, indexBuffer, 15, buffer_offset, indexBias)) goto done; } } while (count); } done: if (indexBuffer != orgIndexBuffer) { pipe_resource_reference( &indexBuffer, NULL ); } if (translate) { r300_end_vertex_translate(r300); } }
static void r300_emit_draw_arrays_immediate(struct r300_context *r300, unsigned mode, unsigned start, unsigned count) { struct pipe_vertex_element* velem; struct pipe_vertex_buffer* vbuf; unsigned vertex_element_count = r300->velems->count; unsigned i, v, vbi; /* Size of the vertex, in dwords. */ unsigned vertex_size = r300->velems->vertex_size_dwords; /* The number of dwords for this draw operation. */ unsigned dwords = 9 + count * vertex_size; /* Size of the vertex element, in dwords. */ unsigned size[PIPE_MAX_ATTRIBS]; /* Stride to the same attrib in the next vertex in the vertex buffer, * in dwords. */ unsigned stride[PIPE_MAX_ATTRIBS]; /* Mapped vertex buffers. */ uint32_t* map[PIPE_MAX_ATTRIBS]; uint32_t* mapelem[PIPE_MAX_ATTRIBS]; struct pipe_transfer* transfer[PIPE_MAX_ATTRIBS] = {0}; CS_LOCALS(r300); if (!r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0)) return; /* Calculate the vertex size, offsets, strides etc. and map the buffers. */ for (i = 0; i < vertex_element_count; i++) { velem = &r300->velems->velem[i]; size[i] = r300->velems->hw_format_size[i] / 4; vbi = velem->vertex_buffer_index; vbuf = &r300->vertex_buffer[vbi]; stride[i] = vbuf->stride / 4; /* Map the buffer. */ if (!transfer[vbi]) { map[vbi] = (uint32_t*)pipe_buffer_map(&r300->context, vbuf->buffer, PIPE_TRANSFER_READ, &transfer[vbi]); map[vbi] += (vbuf->buffer_offset / 4) + stride[i] * start; } mapelem[i] = map[vbi] + (velem->src_offset / 4); } BEGIN_CS(dwords); OUT_CS_REG(R300_GA_COLOR_CONTROL, r300_provoking_vertex_fixes(r300, mode)); OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size); OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); OUT_CS(count - 1); OUT_CS(0); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, count * vertex_size); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (count << 16) | r300_translate_primitive(mode)); /* Emit vertices. */ for (v = 0; v < count; v++) { for (i = 0; i < vertex_element_count; i++) { OUT_CS_TABLE(&mapelem[i][stride[i] * v], size[i]); } } END_CS; /* Unmap buffers. */ for (i = 0; i < vertex_element_count; i++) { vbi = r300->velems->velem[i].vertex_buffer_index; if (transfer[vbi]) { vbuf = &r300->vertex_buffer[vbi]; pipe_buffer_unmap(&r300->context, vbuf->buffer, transfer[vbi]); transfer[vbi] = NULL; } } }
/* This functions is used to draw a rectangle for the blitter module. * * If we rendered a quad, the pixels on the main diagonal * would be computed and stored twice, which makes the clear/copy codepaths * somewhat inefficient. Instead we use a rectangular point sprite. */ static void r300_blitter_draw_rectangle(struct blitter_context *blitter, unsigned x1, unsigned y1, unsigned x2, unsigned y2, float depth, enum blitter_attrib_type type, const float attrib[4]) { struct r300_context *r300 = r300_context(util_blitter_get_pipe(blitter)); unsigned last_sprite_coord_enable = r300->sprite_coord_enable; unsigned width = x2 - x1; unsigned height = y2 - y1; unsigned vertex_size = type == UTIL_BLITTER_ATTRIB_COLOR || !r300->draw ? 8 : 4; unsigned dwords = 13 + vertex_size + (type == UTIL_BLITTER_ATTRIB_TEXCOORD ? 7 : 0); const float zeros[4] = {0, 0, 0, 0}; CS_LOCALS(r300); if (type == UTIL_BLITTER_ATTRIB_TEXCOORD) r300->sprite_coord_enable = 1; r300_update_derived_state(r300); /* Mark some states we don't care about as non-dirty. */ r300->clip_state.dirty = FALSE; r300->viewport_state.dirty = FALSE; if (!r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0)) goto done; DBG(r300, DBG_DRAW, "r300: draw_rectangle\n"); BEGIN_CS(dwords); /* Set up GA. */ OUT_CS_REG(R300_GA_POINT_SIZE, (height * 6) | ((width * 6) << 16)); if (type == UTIL_BLITTER_ATTRIB_TEXCOORD) { /* Set up the GA to generate texcoords. */ OUT_CS_REG(R300_GB_ENABLE, R300_GB_POINT_STUFF_ENABLE | (R300_GB_TEX_STR << R300_GB_TEX0_SOURCE_SHIFT)); OUT_CS_REG_SEQ(R300_GA_POINT_S0, 4); OUT_CS_32F(attrib[0]); OUT_CS_32F(attrib[3]); OUT_CS_32F(attrib[2]); OUT_CS_32F(attrib[1]); } /* Set up VAP controls. */ OUT_CS_REG(R300_VAP_CLIP_CNTL, R300_CLIP_DISABLE); OUT_CS_REG(R300_VAP_VTE_CNTL, R300_VTX_XY_FMT | R300_VTX_Z_FMT); OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size); OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); OUT_CS(1); OUT_CS(0); /* Draw. */ OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, vertex_size); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (1 << 16) | R300_VAP_VF_CNTL__PRIM_POINTS); OUT_CS_32F(x1 + width * 0.5f); OUT_CS_32F(y1 + height * 0.5f); OUT_CS_32F(depth); OUT_CS_32F(1); if (vertex_size == 8) { if (!attrib) attrib = zeros; OUT_CS_TABLE(attrib, 4); } END_CS; done: /* Restore the state. */ r300->clip_state.dirty = TRUE; r300->rs_state.dirty = TRUE; r300->viewport_state.dirty = TRUE; r300->sprite_coord_enable = last_sprite_coord_enable; }