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 ); } }
/* 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); } }