14a49301eSmrg/* 24a49301eSmrg * Copyright 2009 Corbin Simpson <MostAwesomeDude@gmail.com> 33464ebd5Sriastradh * Copyright 2010 Marek Olšák <maraeo@gmail.com> 44a49301eSmrg * 54a49301eSmrg * Permission is hereby granted, free of charge, to any person obtaining a 64a49301eSmrg * copy of this software and associated documentation files (the "Software"), 74a49301eSmrg * to deal in the Software without restriction, including without limitation 84a49301eSmrg * on the rights to use, copy, modify, merge, publish, distribute, sub 94a49301eSmrg * license, and/or sell copies of the Software, and to permit persons to whom 104a49301eSmrg * the Software is furnished to do so, subject to the following conditions: 114a49301eSmrg * 124a49301eSmrg * The above copyright notice and this permission notice (including the next 134a49301eSmrg * paragraph) shall be included in all copies or substantial portions of the 144a49301eSmrg * Software. 154a49301eSmrg * 164a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 174a49301eSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 184a49301eSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 194a49301eSmrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 204a49301eSmrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 214a49301eSmrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 224a49301eSmrg * USE OR OTHER DEALINGS IN THE SOFTWARE. */ 234a49301eSmrg 244a49301eSmrg/* r300_render: Vertex and index buffer primitive emission. Contains both 254a49301eSmrg * HW TCL fastpath rendering, and SW TCL Draw-assisted rendering. */ 264a49301eSmrg 274a49301eSmrg#include "draw/draw_context.h" 284a49301eSmrg#include "draw/draw_vbuf.h" 294a49301eSmrg 30cdc920a0Smrg#include "util/u_inlines.h" 314a49301eSmrg 327ec681f3Smrg#include "util/format/u_format.h" 337ec681f3Smrg#include "util/u_draw.h" 344a49301eSmrg#include "util/u_memory.h" 353464ebd5Sriastradh#include "util/u_upload_mgr.h" 364a49301eSmrg#include "util/u_prim.h" 374a49301eSmrg 384a49301eSmrg#include "r300_cs.h" 394a49301eSmrg#include "r300_context.h" 403464ebd5Sriastradh#include "r300_screen_buffer.h" 414a49301eSmrg#include "r300_emit.h" 424a49301eSmrg#include "r300_reg.h" 433464ebd5Sriastradh 443464ebd5Sriastradh#include <limits.h> 453464ebd5Sriastradh 463464ebd5Sriastradh#define IMMD_DWORDS 32 473464ebd5Sriastradh 483464ebd5Sriastradhstatic uint32_t r300_translate_primitive(unsigned prim) 493464ebd5Sriastradh{ 503464ebd5Sriastradh static const int prim_conv[] = { 513464ebd5Sriastradh R300_VAP_VF_CNTL__PRIM_POINTS, 523464ebd5Sriastradh R300_VAP_VF_CNTL__PRIM_LINES, 533464ebd5Sriastradh R300_VAP_VF_CNTL__PRIM_LINE_LOOP, 543464ebd5Sriastradh R300_VAP_VF_CNTL__PRIM_LINE_STRIP, 553464ebd5Sriastradh R300_VAP_VF_CNTL__PRIM_TRIANGLES, 563464ebd5Sriastradh R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP, 573464ebd5Sriastradh R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN, 583464ebd5Sriastradh R300_VAP_VF_CNTL__PRIM_QUADS, 593464ebd5Sriastradh R300_VAP_VF_CNTL__PRIM_QUAD_STRIP, 603464ebd5Sriastradh R300_VAP_VF_CNTL__PRIM_POLYGON, 613464ebd5Sriastradh -1, 623464ebd5Sriastradh -1, 633464ebd5Sriastradh -1, 643464ebd5Sriastradh -1 653464ebd5Sriastradh }; 663464ebd5Sriastradh unsigned hwprim = prim_conv[prim]; 673464ebd5Sriastradh 683464ebd5Sriastradh assert(hwprim != -1); 693464ebd5Sriastradh return hwprim; 704a49301eSmrg} 714a49301eSmrg 72cdc920a0Smrgstatic uint32_t r300_provoking_vertex_fixes(struct r300_context *r300, 73cdc920a0Smrg unsigned mode) 74cdc920a0Smrg{ 75cdc920a0Smrg struct r300_rs_state* rs = (struct r300_rs_state*)r300->rs_state.state; 76cdc920a0Smrg uint32_t color_control = rs->color_control; 77cdc920a0Smrg 78cdc920a0Smrg /* By default (see r300_state.c:r300_create_rs_state) color_control is 79cdc920a0Smrg * initialized to provoking the first vertex. 80cdc920a0Smrg * 81cdc920a0Smrg * Triangle fans must be reduced to the second vertex, not the first, in 82cdc920a0Smrg * Gallium flatshade-first mode, as per the GL spec. 83cdc920a0Smrg * (http://www.opengl.org/registry/specs/ARB/provoking_vertex.txt) 84cdc920a0Smrg * 85cdc920a0Smrg * Quads never provoke correctly in flatshade-first mode. The first 86cdc920a0Smrg * vertex is never considered as provoking, so only the second, third, 87cdc920a0Smrg * and fourth vertices can be selected, and both "third" and "last" modes 88cdc920a0Smrg * select the fourth vertex. This is probably due to D3D lacking quads. 89cdc920a0Smrg * 90cdc920a0Smrg * Similarly, polygons reduce to the first, not the last, vertex, when in 91cdc920a0Smrg * "last" mode, and all other modes start from the second vertex. 92cdc920a0Smrg * 93cdc920a0Smrg * ~ C. 94cdc920a0Smrg */ 95cdc920a0Smrg 96cdc920a0Smrg if (rs->rs.flatshade_first) { 97cdc920a0Smrg switch (mode) { 98cdc920a0Smrg case PIPE_PRIM_TRIANGLE_FAN: 99cdc920a0Smrg color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_SECOND; 100cdc920a0Smrg break; 101cdc920a0Smrg case PIPE_PRIM_QUADS: 102cdc920a0Smrg case PIPE_PRIM_QUAD_STRIP: 103cdc920a0Smrg case PIPE_PRIM_POLYGON: 104cdc920a0Smrg color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_LAST; 105cdc920a0Smrg break; 106cdc920a0Smrg default: 107cdc920a0Smrg color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_FIRST; 108cdc920a0Smrg break; 109cdc920a0Smrg } 110cdc920a0Smrg } else { 111cdc920a0Smrg color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_LAST; 112cdc920a0Smrg } 113cdc920a0Smrg 114cdc920a0Smrg return color_control; 115cdc920a0Smrg} 116cdc920a0Smrg 1173464ebd5Sriastradhvoid r500_emit_index_bias(struct r300_context *r300, int index_bias) 1183464ebd5Sriastradh{ 1193464ebd5Sriastradh CS_LOCALS(r300); 1203464ebd5Sriastradh 1213464ebd5Sriastradh BEGIN_CS(2); 1223464ebd5Sriastradh OUT_CS_REG(R500_VAP_INDEX_OFFSET, 1233464ebd5Sriastradh (index_bias & 0xFFFFFF) | (index_bias < 0 ? 1<<24 : 0)); 1243464ebd5Sriastradh END_CS; 1253464ebd5Sriastradh} 1263464ebd5Sriastradh 1273464ebd5Sriastradhstatic void r300_emit_draw_init(struct r300_context *r300, unsigned mode, 128af69d88dSmrg unsigned max_index) 1293464ebd5Sriastradh{ 1303464ebd5Sriastradh CS_LOCALS(r300); 1313464ebd5Sriastradh 132af69d88dSmrg assert(max_index < (1 << 24)); 133af69d88dSmrg 1343464ebd5Sriastradh BEGIN_CS(5); 1353464ebd5Sriastradh OUT_CS_REG(R300_GA_COLOR_CONTROL, 1363464ebd5Sriastradh r300_provoking_vertex_fixes(r300, mode)); 1373464ebd5Sriastradh OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); 1383464ebd5Sriastradh OUT_CS(max_index); 139af69d88dSmrg OUT_CS(0); 1403464ebd5Sriastradh END_CS; 1413464ebd5Sriastradh} 1423464ebd5Sriastradh 1433464ebd5Sriastradh/* This function splits the index bias value into two parts: 1443464ebd5Sriastradh * - buffer_offset: the value that can be safely added to buffer offsets 1453464ebd5Sriastradh * in r300_emit_vertex_arrays (it must yield a positive offset when added to 1463464ebd5Sriastradh * a vertex buffer offset) 1473464ebd5Sriastradh * - index_offset: the value that must be manually subtracted from indices 1483464ebd5Sriastradh * in an index buffer to achieve negative offsets. */ 1493464ebd5Sriastradhstatic void r300_split_index_bias(struct r300_context *r300, int index_bias, 1503464ebd5Sriastradh int *buffer_offset, int *index_offset) 1513464ebd5Sriastradh{ 152af69d88dSmrg struct pipe_vertex_buffer *vb, *vbufs = r300->vertex_buffer; 1533464ebd5Sriastradh struct pipe_vertex_element *velem = r300->velems->velem; 1543464ebd5Sriastradh unsigned i, size; 1553464ebd5Sriastradh int max_neg_bias; 1563464ebd5Sriastradh 1573464ebd5Sriastradh if (index_bias < 0) { 1583464ebd5Sriastradh /* See how large index bias we may subtract. We must be careful 1593464ebd5Sriastradh * here because negative buffer offsets are not allowed 1603464ebd5Sriastradh * by the DRM API. */ 1613464ebd5Sriastradh max_neg_bias = INT_MAX; 1623464ebd5Sriastradh for (i = 0; i < r300->velems->count; i++) { 1633464ebd5Sriastradh vb = &vbufs[velem[i].vertex_buffer_index]; 1643464ebd5Sriastradh size = (vb->buffer_offset + velem[i].src_offset) / vb->stride; 1653464ebd5Sriastradh max_neg_bias = MIN2(max_neg_bias, size); 1663464ebd5Sriastradh } 1673464ebd5Sriastradh 1683464ebd5Sriastradh /* Now set the minimum allowed value. */ 1693464ebd5Sriastradh *buffer_offset = MAX2(-max_neg_bias, index_bias); 1703464ebd5Sriastradh } else { 1713464ebd5Sriastradh /* A positive index bias is OK. */ 1723464ebd5Sriastradh *buffer_offset = index_bias; 1733464ebd5Sriastradh } 1743464ebd5Sriastradh 1753464ebd5Sriastradh *index_offset = index_bias - *buffer_offset; 1763464ebd5Sriastradh} 1773464ebd5Sriastradh 1783464ebd5Sriastradhenum r300_prepare_flags { 1793464ebd5Sriastradh PREP_EMIT_STATES = (1 << 0), /* call emit_dirty_state and friends? */ 1803464ebd5Sriastradh PREP_VALIDATE_VBOS = (1 << 1), /* validate VBOs? */ 1813464ebd5Sriastradh PREP_EMIT_VARRAYS = (1 << 2), /* call emit_vertex_arrays? */ 1823464ebd5Sriastradh PREP_EMIT_VARRAYS_SWTCL = (1 << 3), /* call emit_vertex_arrays_swtcl? */ 1833464ebd5Sriastradh PREP_INDEXED = (1 << 4) /* is this draw_elements? */ 1843464ebd5Sriastradh}; 1853464ebd5Sriastradh 1863464ebd5Sriastradh/** 1873464ebd5Sriastradh * Check if the requested number of dwords is available in the CS and 1883464ebd5Sriastradh * if not, flush. 1893464ebd5Sriastradh * \param r300 The context. 1903464ebd5Sriastradh * \param flags See r300_prepare_flags. 1913464ebd5Sriastradh * \param cs_dwords The number of dwords to reserve in CS. 1923464ebd5Sriastradh * \return TRUE if the CS was flushed 1933464ebd5Sriastradh */ 1943464ebd5Sriastradhstatic boolean r300_reserve_cs_dwords(struct r300_context *r300, 1953464ebd5Sriastradh enum r300_prepare_flags flags, 1963464ebd5Sriastradh unsigned cs_dwords) 1973464ebd5Sriastradh{ 1983464ebd5Sriastradh boolean flushed = FALSE; 1993464ebd5Sriastradh boolean emit_states = flags & PREP_EMIT_STATES; 2003464ebd5Sriastradh boolean emit_vertex_arrays = flags & PREP_EMIT_VARRAYS; 2013464ebd5Sriastradh boolean emit_vertex_arrays_swtcl = flags & PREP_EMIT_VARRAYS_SWTCL; 2023464ebd5Sriastradh 2033464ebd5Sriastradh /* Add dirty state, index offset, and AOS. */ 2043464ebd5Sriastradh if (emit_states) 2053464ebd5Sriastradh cs_dwords += r300_get_num_dirty_dwords(r300); 2063464ebd5Sriastradh 2073464ebd5Sriastradh if (r300->screen->caps.is_r500) 2083464ebd5Sriastradh cs_dwords += 2; /* emit_index_offset */ 2093464ebd5Sriastradh 2103464ebd5Sriastradh if (emit_vertex_arrays) 2113464ebd5Sriastradh cs_dwords += 55; /* emit_vertex_arrays */ 2123464ebd5Sriastradh 2133464ebd5Sriastradh if (emit_vertex_arrays_swtcl) 2143464ebd5Sriastradh cs_dwords += 7; /* emit_vertex_arrays_swtcl */ 2153464ebd5Sriastradh 2163464ebd5Sriastradh cs_dwords += r300_get_num_cs_end_dwords(r300); 2173464ebd5Sriastradh 2183464ebd5Sriastradh /* Reserve requested CS space. */ 2197ec681f3Smrg if (!r300->rws->cs_check_space(&r300->cs, cs_dwords, false)) { 22001e04c3fSmrg r300_flush(&r300->context, PIPE_FLUSH_ASYNC, NULL); 2213464ebd5Sriastradh flushed = TRUE; 2223464ebd5Sriastradh } 2233464ebd5Sriastradh 2243464ebd5Sriastradh return flushed; 2253464ebd5Sriastradh} 2263464ebd5Sriastradh 2273464ebd5Sriastradh/** 2283464ebd5Sriastradh * Validate buffers and emit dirty state. 2293464ebd5Sriastradh * \param r300 The context. 2303464ebd5Sriastradh * \param flags See r300_prepare_flags. 2313464ebd5Sriastradh * \param index_buffer The index buffer to validate. The parameter may be NULL. 2323464ebd5Sriastradh * \param buffer_offset The offset passed to emit_vertex_arrays. 2333464ebd5Sriastradh * \param index_bias The index bias to emit. 2343464ebd5Sriastradh * \param instance_id Index of instance to render 2353464ebd5Sriastradh * \return TRUE if rendering should be skipped 2363464ebd5Sriastradh */ 2373464ebd5Sriastradhstatic boolean r300_emit_states(struct r300_context *r300, 2383464ebd5Sriastradh enum r300_prepare_flags flags, 2393464ebd5Sriastradh struct pipe_resource *index_buffer, 2403464ebd5Sriastradh int buffer_offset, 2413464ebd5Sriastradh int index_bias, int instance_id) 242cdc920a0Smrg{ 2433464ebd5Sriastradh boolean emit_states = flags & PREP_EMIT_STATES; 2443464ebd5Sriastradh boolean emit_vertex_arrays = flags & PREP_EMIT_VARRAYS; 2453464ebd5Sriastradh boolean emit_vertex_arrays_swtcl = flags & PREP_EMIT_VARRAYS_SWTCL; 2463464ebd5Sriastradh boolean indexed = flags & PREP_INDEXED; 2473464ebd5Sriastradh boolean validate_vbos = flags & PREP_VALIDATE_VBOS; 2483464ebd5Sriastradh 2493464ebd5Sriastradh /* Validate buffers and emit dirty state if needed. */ 2503464ebd5Sriastradh if (emit_states || (emit_vertex_arrays && validate_vbos)) { 2513464ebd5Sriastradh if (!r300_emit_buffer_validate(r300, validate_vbos, 2523464ebd5Sriastradh index_buffer)) { 2533464ebd5Sriastradh fprintf(stderr, "r300: CS space validation failed. " 2543464ebd5Sriastradh "(not enough memory?) Skipping rendering.\n"); 2553464ebd5Sriastradh return FALSE; 2563464ebd5Sriastradh } 257cdc920a0Smrg } 2583464ebd5Sriastradh 2593464ebd5Sriastradh if (emit_states) 2603464ebd5Sriastradh r300_emit_dirty_state(r300); 2613464ebd5Sriastradh 2623464ebd5Sriastradh if (r300->screen->caps.is_r500) { 2633464ebd5Sriastradh if (r300->screen->caps.has_tcl) 2643464ebd5Sriastradh r500_emit_index_bias(r300, index_bias); 2653464ebd5Sriastradh else 2663464ebd5Sriastradh r500_emit_index_bias(r300, 0); 2673464ebd5Sriastradh } 2683464ebd5Sriastradh 2693464ebd5Sriastradh if (emit_vertex_arrays && 2703464ebd5Sriastradh (r300->vertex_arrays_dirty || 2713464ebd5Sriastradh r300->vertex_arrays_indexed != indexed || 2723464ebd5Sriastradh r300->vertex_arrays_offset != buffer_offset || 2733464ebd5Sriastradh r300->vertex_arrays_instance_id != instance_id)) { 2743464ebd5Sriastradh r300_emit_vertex_arrays(r300, buffer_offset, indexed, instance_id); 2753464ebd5Sriastradh 2763464ebd5Sriastradh r300->vertex_arrays_dirty = FALSE; 2773464ebd5Sriastradh r300->vertex_arrays_indexed = indexed; 2783464ebd5Sriastradh r300->vertex_arrays_offset = buffer_offset; 2793464ebd5Sriastradh r300->vertex_arrays_instance_id = instance_id; 2803464ebd5Sriastradh } 2813464ebd5Sriastradh 2823464ebd5Sriastradh if (emit_vertex_arrays_swtcl) 2833464ebd5Sriastradh r300_emit_vertex_arrays_swtcl(r300, indexed); 2843464ebd5Sriastradh 2853464ebd5Sriastradh return TRUE; 2863464ebd5Sriastradh} 2873464ebd5Sriastradh 2883464ebd5Sriastradh/** 2893464ebd5Sriastradh * Check if the requested number of dwords is available in the CS and 2903464ebd5Sriastradh * if not, flush. Then validate buffers and emit dirty state. 2913464ebd5Sriastradh * \param r300 The context. 2923464ebd5Sriastradh * \param flags See r300_prepare_flags. 2933464ebd5Sriastradh * \param index_buffer The index buffer to validate. The parameter may be NULL. 2943464ebd5Sriastradh * \param cs_dwords The number of dwords to reserve in CS. 2953464ebd5Sriastradh * \param buffer_offset The offset passed to emit_vertex_arrays. 2963464ebd5Sriastradh * \param index_bias The index bias to emit. 2973464ebd5Sriastradh * \param instance_id The instance to render. 2983464ebd5Sriastradh * \return TRUE if rendering should be skipped 2993464ebd5Sriastradh */ 3003464ebd5Sriastradhstatic boolean r300_prepare_for_rendering(struct r300_context *r300, 3013464ebd5Sriastradh enum r300_prepare_flags flags, 3023464ebd5Sriastradh struct pipe_resource *index_buffer, 3033464ebd5Sriastradh unsigned cs_dwords, 3043464ebd5Sriastradh int buffer_offset, 3053464ebd5Sriastradh int index_bias, 3063464ebd5Sriastradh int instance_id) 3073464ebd5Sriastradh{ 3083464ebd5Sriastradh /* Make sure there is enough space in the command stream and emit states. */ 3093464ebd5Sriastradh if (r300_reserve_cs_dwords(r300, flags, cs_dwords)) 3103464ebd5Sriastradh flags |= PREP_EMIT_STATES; 3113464ebd5Sriastradh 3123464ebd5Sriastradh return r300_emit_states(r300, flags, index_buffer, buffer_offset, 3133464ebd5Sriastradh index_bias, instance_id); 314cdc920a0Smrg} 315cdc920a0Smrg 316cdc920a0Smrgstatic boolean immd_is_good_idea(struct r300_context *r300, 3173464ebd5Sriastradh unsigned count) 318cdc920a0Smrg{ 3193464ebd5Sriastradh if (DBG_ON(r300, DBG_NO_IMMD)) { 3203464ebd5Sriastradh return FALSE; 3213464ebd5Sriastradh } 3223464ebd5Sriastradh 3233464ebd5Sriastradh if (count * r300->velems->vertex_size_dwords > IMMD_DWORDS) { 3243464ebd5Sriastradh return FALSE; 3253464ebd5Sriastradh } 3263464ebd5Sriastradh 327af69d88dSmrg /* Buffers can only be used for read by r300 (except query buffers, but 3287ec681f3Smrg * those can't be bound by an gallium frontend as vertex buffers). */ 3293464ebd5Sriastradh return TRUE; 330cdc920a0Smrg} 331cdc920a0Smrg 3323464ebd5Sriastradh/***************************************************************************** 3333464ebd5Sriastradh * The HWTCL draw functions. * 3343464ebd5Sriastradh ****************************************************************************/ 3353464ebd5Sriastradh 3363464ebd5Sriastradhstatic void r300_draw_arrays_immediate(struct r300_context *r300, 3377ec681f3Smrg const struct pipe_draw_info *info, 3387ec681f3Smrg const struct pipe_draw_start_count_bias *draw) 339cdc920a0Smrg{ 340cdc920a0Smrg struct pipe_vertex_element* velem; 341cdc920a0Smrg struct pipe_vertex_buffer* vbuf; 3423464ebd5Sriastradh unsigned vertex_element_count = r300->velems->count; 3433464ebd5Sriastradh unsigned i, v, vbi; 344cdc920a0Smrg 345cdc920a0Smrg /* Size of the vertex, in dwords. */ 3463464ebd5Sriastradh unsigned vertex_size = r300->velems->vertex_size_dwords; 347cdc920a0Smrg 3483464ebd5Sriastradh /* The number of dwords for this draw operation. */ 3497ec681f3Smrg unsigned dwords = 4 + draw->count * vertex_size; 350cdc920a0Smrg 351cdc920a0Smrg /* Size of the vertex element, in dwords. */ 352cdc920a0Smrg unsigned size[PIPE_MAX_ATTRIBS]; 353cdc920a0Smrg 354cdc920a0Smrg /* Stride to the same attrib in the next vertex in the vertex buffer, 355cdc920a0Smrg * in dwords. */ 3563464ebd5Sriastradh unsigned stride[PIPE_MAX_ATTRIBS]; 357cdc920a0Smrg 358cdc920a0Smrg /* Mapped vertex buffers. */ 359cdc920a0Smrg uint32_t* map[PIPE_MAX_ATTRIBS] = {0}; 3603464ebd5Sriastradh uint32_t* mapelem[PIPE_MAX_ATTRIBS]; 361cdc920a0Smrg 362cdc920a0Smrg CS_LOCALS(r300); 363cdc920a0Smrg 3643464ebd5Sriastradh if (!r300_prepare_for_rendering(r300, PREP_EMIT_STATES, NULL, dwords, 0, 0, -1)) 3653464ebd5Sriastradh return; 3663464ebd5Sriastradh 367cdc920a0Smrg /* Calculate the vertex size, offsets, strides etc. and map the buffers. */ 368cdc920a0Smrg for (i = 0; i < vertex_element_count; i++) { 3693464ebd5Sriastradh velem = &r300->velems->velem[i]; 3703464ebd5Sriastradh size[i] = r300->velems->format_size[i] / 4; 371cdc920a0Smrg vbi = velem->vertex_buffer_index; 372af69d88dSmrg vbuf = &r300->vertex_buffer[vbi]; 3733464ebd5Sriastradh stride[i] = vbuf->stride / 4; 374cdc920a0Smrg 375cdc920a0Smrg /* Map the buffer. */ 376cdc920a0Smrg if (!map[vbi]) { 3777ec681f3Smrg map[vbi] = (uint32_t*)r300->rws->buffer_map(r300->rws, 37801e04c3fSmrg r300_resource(vbuf->buffer.resource)->buf, 3797ec681f3Smrg &r300->cs, PIPE_MAP_READ | PIPE_MAP_UNSYNCHRONIZED); 3807ec681f3Smrg map[vbi] += (vbuf->buffer_offset / 4) + stride[i] * draw->start; 381cdc920a0Smrg } 3823464ebd5Sriastradh mapelem[i] = map[vbi] + (velem->src_offset / 4); 383cdc920a0Smrg } 384cdc920a0Smrg 3857ec681f3Smrg r300_emit_draw_init(r300, info->mode, draw->count-1); 386cdc920a0Smrg 387cdc920a0Smrg BEGIN_CS(dwords); 388cdc920a0Smrg OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size); 3897ec681f3Smrg OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, draw->count * vertex_size); 3907ec681f3Smrg OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (draw->count << 16) | 3913464ebd5Sriastradh r300_translate_primitive(info->mode)); 392cdc920a0Smrg 393cdc920a0Smrg /* Emit vertices. */ 3947ec681f3Smrg for (v = 0; v < draw->count; v++) { 395cdc920a0Smrg for (i = 0; i < vertex_element_count; i++) { 3963464ebd5Sriastradh OUT_CS_TABLE(&mapelem[i][stride[i] * v], size[i]); 397cdc920a0Smrg } 398cdc920a0Smrg } 399cdc920a0Smrg END_CS; 400cdc920a0Smrg} 401cdc920a0Smrg 4024a49301eSmrgstatic void r300_emit_draw_arrays(struct r300_context *r300, 4034a49301eSmrg unsigned mode, 4044a49301eSmrg unsigned count) 4054a49301eSmrg{ 406cdc920a0Smrg boolean alt_num_verts = count > 65535; 4074a49301eSmrg CS_LOCALS(r300); 4084a49301eSmrg 4093464ebd5Sriastradh if (count >= (1 << 24)) { 4103464ebd5Sriastradh fprintf(stderr, "r300: Got a huge number of vertices: %i, " 4113464ebd5Sriastradh "refusing to render.\n", count); 4123464ebd5Sriastradh return; 4133464ebd5Sriastradh } 4143464ebd5Sriastradh 415af69d88dSmrg r300_emit_draw_init(r300, mode, count-1); 4163464ebd5Sriastradh 4173464ebd5Sriastradh BEGIN_CS(2 + (alt_num_verts ? 2 : 0)); 418cdc920a0Smrg if (alt_num_verts) { 419cdc920a0Smrg OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count); 420cdc920a0Smrg } 4214a49301eSmrg OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0); 4224a49301eSmrg OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) | 423cdc920a0Smrg r300_translate_primitive(mode) | 424cdc920a0Smrg (alt_num_verts ? R500_VAP_VF_CNTL__USE_ALT_NUM_VERTS : 0)); 4254a49301eSmrg END_CS; 4264a49301eSmrg} 4274a49301eSmrg 4284a49301eSmrgstatic void r300_emit_draw_elements(struct r300_context *r300, 4293464ebd5Sriastradh struct pipe_resource* indexBuffer, 4304a49301eSmrg unsigned indexSize, 4313464ebd5Sriastradh unsigned max_index, 4324a49301eSmrg unsigned mode, 4334a49301eSmrg unsigned start, 4343464ebd5Sriastradh unsigned count, 4353464ebd5Sriastradh uint16_t *imm_indices3) 4364a49301eSmrg{ 4373464ebd5Sriastradh uint32_t count_dwords, offset_dwords; 438cdc920a0Smrg boolean alt_num_verts = count > 65535; 4394a49301eSmrg CS_LOCALS(r300); 4404a49301eSmrg 441af69d88dSmrg if (count >= (1 << 24)) { 4423464ebd5Sriastradh fprintf(stderr, "r300: Got a huge number of vertices: %i, " 4433464ebd5Sriastradh "refusing to render (max_index: %i).\n", count, max_index); 4443464ebd5Sriastradh return; 4453464ebd5Sriastradh } 446cdc920a0Smrg 447af69d88dSmrg DBG(r300, DBG_DRAW, "r300: Indexbuf of %u indices, max %u\n", 448af69d88dSmrg count, max_index); 4493464ebd5Sriastradh 450af69d88dSmrg r300_emit_draw_init(r300, mode, max_index); 4513464ebd5Sriastradh 4523464ebd5Sriastradh /* If start is odd, render the first triangle with indices embedded 4533464ebd5Sriastradh * in the command stream. This will increase start by 3 and make it 4543464ebd5Sriastradh * even. We can then proceed without a fallback. */ 4553464ebd5Sriastradh if (indexSize == 2 && (start & 1) && 4563464ebd5Sriastradh mode == PIPE_PRIM_TRIANGLES) { 4573464ebd5Sriastradh BEGIN_CS(4); 4583464ebd5Sriastradh OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, 2); 4593464ebd5Sriastradh OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (3 << 16) | 4603464ebd5Sriastradh R300_VAP_VF_CNTL__PRIM_TRIANGLES); 4613464ebd5Sriastradh OUT_CS(imm_indices3[1] << 16 | imm_indices3[0]); 4623464ebd5Sriastradh OUT_CS(imm_indices3[2]); 4633464ebd5Sriastradh END_CS; 4643464ebd5Sriastradh 4653464ebd5Sriastradh start += 3; 4663464ebd5Sriastradh count -= 3; 4673464ebd5Sriastradh if (!count) 4683464ebd5Sriastradh return; 4693464ebd5Sriastradh } 470cdc920a0Smrg 4713464ebd5Sriastradh offset_dwords = indexSize * start / sizeof(uint32_t); 4724a49301eSmrg 4733464ebd5Sriastradh BEGIN_CS(8 + (alt_num_verts ? 2 : 0)); 474cdc920a0Smrg if (alt_num_verts) { 475cdc920a0Smrg OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count); 476cdc920a0Smrg } 4774a49301eSmrg OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, 0); 4784a49301eSmrg if (indexSize == 4) { 479cdc920a0Smrg count_dwords = count; 4804a49301eSmrg OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | 4814a49301eSmrg R300_VAP_VF_CNTL__INDEX_SIZE_32bit | 482cdc920a0Smrg r300_translate_primitive(mode) | 483cdc920a0Smrg (alt_num_verts ? R500_VAP_VF_CNTL__USE_ALT_NUM_VERTS : 0)); 4844a49301eSmrg } else { 485cdc920a0Smrg count_dwords = (count + 1) / 2; 4864a49301eSmrg OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | 487cdc920a0Smrg r300_translate_primitive(mode) | 488cdc920a0Smrg (alt_num_verts ? R500_VAP_VF_CNTL__USE_ALT_NUM_VERTS : 0)); 4894a49301eSmrg } 4904a49301eSmrg 4914a49301eSmrg OUT_CS_PKT3(R300_PACKET3_INDX_BUFFER, 2); 4924a49301eSmrg OUT_CS(R300_INDX_BUFFER_ONE_REG_WR | (R300_VAP_PORT_IDX0 >> 2) | 4934a49301eSmrg (0 << R300_INDX_BUFFER_SKIP_SHIFT)); 494cdc920a0Smrg OUT_CS(offset_dwords << 2); 4953464ebd5Sriastradh OUT_CS(count_dwords); 4963464ebd5Sriastradh OUT_CS_RELOC(r300_resource(indexBuffer)); 4974a49301eSmrg END_CS; 4984a49301eSmrg} 4994a49301eSmrg 5003464ebd5Sriastradhstatic void r300_draw_elements_immediate(struct r300_context *r300, 5017ec681f3Smrg const struct pipe_draw_info *info, 5027ec681f3Smrg const struct pipe_draw_start_count_bias *draw) 5034a49301eSmrg{ 504af69d88dSmrg const uint8_t *ptr1; 505af69d88dSmrg const uint16_t *ptr2; 506af69d88dSmrg const uint32_t *ptr4; 50701e04c3fSmrg unsigned index_size = info->index_size; 5087ec681f3Smrg unsigned i, count_dwords = index_size == 4 ? draw->count : 5097ec681f3Smrg (draw->count + 1) / 2; 5103464ebd5Sriastradh CS_LOCALS(r300); 511cdc920a0Smrg 5123464ebd5Sriastradh /* 19 dwords for r300_draw_elements_immediate. Give up if the function fails. */ 5133464ebd5Sriastradh if (!r300_prepare_for_rendering(r300, 5143464ebd5Sriastradh PREP_EMIT_STATES | PREP_VALIDATE_VBOS | PREP_EMIT_VARRAYS | 5157ec681f3Smrg PREP_INDEXED, NULL, 2+count_dwords, 0, draw->index_bias, -1)) 5163464ebd5Sriastradh return; 517cdc920a0Smrg 518af69d88dSmrg r300_emit_draw_init(r300, info->mode, info->max_index); 519cdc920a0Smrg 5203464ebd5Sriastradh BEGIN_CS(2 + count_dwords); 5213464ebd5Sriastradh OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, count_dwords); 5223464ebd5Sriastradh 5233464ebd5Sriastradh switch (index_size) { 5243464ebd5Sriastradh case 1: 52501e04c3fSmrg ptr1 = (uint8_t*)info->index.user; 5267ec681f3Smrg ptr1 += draw->start; 5273464ebd5Sriastradh 5287ec681f3Smrg OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (draw->count << 16) | 5293464ebd5Sriastradh r300_translate_primitive(info->mode)); 5303464ebd5Sriastradh 5317ec681f3Smrg if (draw->index_bias && !r300->screen->caps.is_r500) { 5327ec681f3Smrg for (i = 0; i < draw->count-1; i += 2) 5337ec681f3Smrg OUT_CS(((ptr1[i+1] + draw->index_bias) << 16) | 5347ec681f3Smrg (ptr1[i] + draw->index_bias)); 5353464ebd5Sriastradh 5367ec681f3Smrg if (draw->count & 1) 5377ec681f3Smrg OUT_CS(ptr1[i] + draw->index_bias); 5383464ebd5Sriastradh } else { 5397ec681f3Smrg for (i = 0; i < draw->count-1; i += 2) 5403464ebd5Sriastradh OUT_CS(((ptr1[i+1]) << 16) | 5413464ebd5Sriastradh (ptr1[i] )); 5423464ebd5Sriastradh 5437ec681f3Smrg if (draw->count & 1) 5443464ebd5Sriastradh OUT_CS(ptr1[i]); 5453464ebd5Sriastradh } 5463464ebd5Sriastradh break; 5474a49301eSmrg 5483464ebd5Sriastradh case 2: 54901e04c3fSmrg ptr2 = (uint16_t*)info->index.user; 5507ec681f3Smrg ptr2 += draw->start; 5513464ebd5Sriastradh 5527ec681f3Smrg OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (draw->count << 16) | 5533464ebd5Sriastradh r300_translate_primitive(info->mode)); 5543464ebd5Sriastradh 5557ec681f3Smrg if (draw->index_bias && !r300->screen->caps.is_r500) { 5567ec681f3Smrg for (i = 0; i < draw->count-1; i += 2) 5577ec681f3Smrg OUT_CS(((ptr2[i+1] + draw->index_bias) << 16) | 5587ec681f3Smrg (ptr2[i] + draw->index_bias)); 5593464ebd5Sriastradh 5607ec681f3Smrg if (draw->count & 1) 5617ec681f3Smrg OUT_CS(ptr2[i] + draw->index_bias); 5623464ebd5Sriastradh } else { 5633464ebd5Sriastradh OUT_CS_TABLE(ptr2, count_dwords); 5643464ebd5Sriastradh } 5653464ebd5Sriastradh break; 5663464ebd5Sriastradh 5673464ebd5Sriastradh case 4: 56801e04c3fSmrg ptr4 = (uint32_t*)info->index.user; 5697ec681f3Smrg ptr4 += draw->start; 5703464ebd5Sriastradh 5717ec681f3Smrg OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (draw->count << 16) | 5723464ebd5Sriastradh R300_VAP_VF_CNTL__INDEX_SIZE_32bit | 5733464ebd5Sriastradh r300_translate_primitive(info->mode)); 5744a49301eSmrg 5757ec681f3Smrg if (draw->index_bias && !r300->screen->caps.is_r500) { 5767ec681f3Smrg for (i = 0; i < draw->count; i++) 5777ec681f3Smrg OUT_CS(ptr4[i] + draw->index_bias); 5783464ebd5Sriastradh } else { 5793464ebd5Sriastradh OUT_CS_TABLE(ptr4, count_dwords); 5803464ebd5Sriastradh } 5813464ebd5Sriastradh break; 5823464ebd5Sriastradh } 5833464ebd5Sriastradh END_CS; 5844a49301eSmrg} 5854a49301eSmrg 5863464ebd5Sriastradhstatic void r300_draw_elements(struct r300_context *r300, 5873464ebd5Sriastradh const struct pipe_draw_info *info, 5887ec681f3Smrg const struct pipe_draw_start_count_bias *draw, 5893464ebd5Sriastradh int instance_id) 5904a49301eSmrg{ 59101e04c3fSmrg struct pipe_resource *indexBuffer = 59201e04c3fSmrg info->has_user_indices ? NULL : info->index.resource; 59301e04c3fSmrg unsigned indexSize = info->index_size; 5943464ebd5Sriastradh struct pipe_resource* orgIndexBuffer = indexBuffer; 5957ec681f3Smrg unsigned start = draw->start; 5967ec681f3Smrg unsigned count = draw->count; 5973464ebd5Sriastradh boolean alt_num_verts = r300->screen->caps.is_r500 && 598cdc920a0Smrg count > 65536; 599cdc920a0Smrg unsigned short_count; 6003464ebd5Sriastradh int buffer_offset = 0, index_offset = 0; /* for index bias emulation */ 6013464ebd5Sriastradh uint16_t indices3[3]; 6024a49301eSmrg 6037ec681f3Smrg if (draw->index_bias && !r300->screen->caps.is_r500) { 6047ec681f3Smrg r300_split_index_bias(r300, draw->index_bias, &buffer_offset, 605af69d88dSmrg &index_offset); 6064a49301eSmrg } 6074a49301eSmrg 60801e04c3fSmrg r300_translate_index_buffer(r300, info, &indexBuffer, 609af69d88dSmrg &indexSize, index_offset, &start, count); 6104a49301eSmrg 6113464ebd5Sriastradh /* Fallback for misaligned ushort indices. */ 612af69d88dSmrg if (indexSize == 2 && (start & 1) && indexBuffer) { 6133464ebd5Sriastradh /* If we got here, then orgIndexBuffer == indexBuffer. */ 6147ec681f3Smrg uint16_t *ptr = r300->rws->buffer_map(r300->rws, r300_resource(orgIndexBuffer)->buf, 6157ec681f3Smrg &r300->cs, 6167ec681f3Smrg PIPE_MAP_READ | 6177ec681f3Smrg PIPE_MAP_UNSYNCHRONIZED); 6184a49301eSmrg 6193464ebd5Sriastradh if (info->mode == PIPE_PRIM_TRIANGLES) { 6203464ebd5Sriastradh memcpy(indices3, ptr + start, 6); 6213464ebd5Sriastradh } else { 6223464ebd5Sriastradh /* Copy the mapped index buffer directly to the upload buffer. 6233464ebd5Sriastradh * The start index will be aligned simply from the fact that 6243464ebd5Sriastradh * every sub-buffer in the upload buffer is aligned. */ 6253464ebd5Sriastradh r300_upload_index_buffer(r300, &indexBuffer, indexSize, &start, 6263464ebd5Sriastradh count, (uint8_t*)ptr); 6273464ebd5Sriastradh } 6283464ebd5Sriastradh } else { 62901e04c3fSmrg if (info->has_user_indices) 6303464ebd5Sriastradh r300_upload_index_buffer(r300, &indexBuffer, indexSize, 6313464ebd5Sriastradh &start, count, 63201e04c3fSmrg info->index.user); 6333464ebd5Sriastradh } 6343464ebd5Sriastradh 6353464ebd5Sriastradh /* 19 dwords for emit_draw_elements. Give up if the function fails. */ 6363464ebd5Sriastradh if (!r300_prepare_for_rendering(r300, 6373464ebd5Sriastradh PREP_EMIT_STATES | PREP_VALIDATE_VBOS | PREP_EMIT_VARRAYS | 6387ec681f3Smrg PREP_INDEXED, indexBuffer, 19, buffer_offset, draw->index_bias, 6393464ebd5Sriastradh instance_id)) 6403464ebd5Sriastradh goto done; 6414a49301eSmrg 642cdc920a0Smrg if (alt_num_verts || count <= 65535) { 643af69d88dSmrg r300_emit_draw_elements(r300, indexBuffer, indexSize, 6443464ebd5Sriastradh info->max_index, info->mode, start, count, 6453464ebd5Sriastradh indices3); 646cdc920a0Smrg } else { 647cdc920a0Smrg do { 6483464ebd5Sriastradh /* The maximum must be divisible by 4 and 3, 6493464ebd5Sriastradh * so that quad and triangle lists are split correctly. 6503464ebd5Sriastradh * 6513464ebd5Sriastradh * Strips, loops, and fans won't work. */ 6523464ebd5Sriastradh short_count = MIN2(count, 65532); 6533464ebd5Sriastradh 6543464ebd5Sriastradh r300_emit_draw_elements(r300, indexBuffer, indexSize, 655af69d88dSmrg info->max_index, 6563464ebd5Sriastradh info->mode, start, short_count, indices3); 657cdc920a0Smrg 658cdc920a0Smrg start += short_count; 659cdc920a0Smrg count -= short_count; 660cdc920a0Smrg 6613464ebd5Sriastradh /* 15 dwords for emit_draw_elements */ 6623464ebd5Sriastradh if (count) { 6633464ebd5Sriastradh if (!r300_prepare_for_rendering(r300, 6643464ebd5Sriastradh PREP_VALIDATE_VBOS | PREP_EMIT_VARRAYS | PREP_INDEXED, 6657ec681f3Smrg indexBuffer, 19, buffer_offset, draw->index_bias, 6663464ebd5Sriastradh instance_id)) 6673464ebd5Sriastradh goto done; 668cdc920a0Smrg } 669cdc920a0Smrg } while (count); 670cdc920a0Smrg } 6714a49301eSmrg 6723464ebd5Sriastradhdone: 673cdc920a0Smrg if (indexBuffer != orgIndexBuffer) { 6743464ebd5Sriastradh pipe_resource_reference( &indexBuffer, NULL ); 6753464ebd5Sriastradh } 6763464ebd5Sriastradh} 6773464ebd5Sriastradh 6783464ebd5Sriastradhstatic void r300_draw_arrays(struct r300_context *r300, 6793464ebd5Sriastradh const struct pipe_draw_info *info, 6807ec681f3Smrg const struct pipe_draw_start_count_bias *draw, 6813464ebd5Sriastradh int instance_id) 6823464ebd5Sriastradh{ 6833464ebd5Sriastradh boolean alt_num_verts = r300->screen->caps.is_r500 && 6847ec681f3Smrg draw->count > 65536; 6857ec681f3Smrg unsigned start = draw->start; 6867ec681f3Smrg unsigned count = draw->count; 6873464ebd5Sriastradh unsigned short_count; 6883464ebd5Sriastradh 6893464ebd5Sriastradh /* 9 spare dwords for emit_draw_arrays. Give up if the function fails. */ 6903464ebd5Sriastradh if (!r300_prepare_for_rendering(r300, 6913464ebd5Sriastradh PREP_EMIT_STATES | PREP_VALIDATE_VBOS | PREP_EMIT_VARRAYS, 6923464ebd5Sriastradh NULL, 9, start, 0, instance_id)) 6933464ebd5Sriastradh return; 6943464ebd5Sriastradh 6953464ebd5Sriastradh if (alt_num_verts || count <= 65535) { 6963464ebd5Sriastradh r300_emit_draw_arrays(r300, info->mode, count); 6973464ebd5Sriastradh } else { 6983464ebd5Sriastradh do { 6993464ebd5Sriastradh /* The maximum must be divisible by 4 and 3, 7003464ebd5Sriastradh * so that quad and triangle lists are split correctly. 7013464ebd5Sriastradh * 7023464ebd5Sriastradh * Strips, loops, and fans won't work. */ 7033464ebd5Sriastradh short_count = MIN2(count, 65532); 7043464ebd5Sriastradh r300_emit_draw_arrays(r300, info->mode, short_count); 7053464ebd5Sriastradh 7063464ebd5Sriastradh start += short_count; 7073464ebd5Sriastradh count -= short_count; 7083464ebd5Sriastradh 7093464ebd5Sriastradh /* 9 spare dwords for emit_draw_arrays. Give up if the function fails. */ 7103464ebd5Sriastradh if (count) { 7113464ebd5Sriastradh if (!r300_prepare_for_rendering(r300, 7123464ebd5Sriastradh PREP_VALIDATE_VBOS | PREP_EMIT_VARRAYS, NULL, 9, 7133464ebd5Sriastradh start, 0, instance_id)) 7143464ebd5Sriastradh return; 7153464ebd5Sriastradh } 7163464ebd5Sriastradh } while (count); 717cdc920a0Smrg } 7184a49301eSmrg} 7194a49301eSmrg 7203464ebd5Sriastradhstatic void r300_draw_arrays_instanced(struct r300_context *r300, 7217ec681f3Smrg const struct pipe_draw_info *info, 7227ec681f3Smrg const struct pipe_draw_start_count_bias *draw) 7233464ebd5Sriastradh{ 7243464ebd5Sriastradh int i; 7253464ebd5Sriastradh 7263464ebd5Sriastradh for (i = 0; i < info->instance_count; i++) 7277ec681f3Smrg r300_draw_arrays(r300, info, draw, i); 7283464ebd5Sriastradh} 7293464ebd5Sriastradh 7303464ebd5Sriastradhstatic void r300_draw_elements_instanced(struct r300_context *r300, 7317ec681f3Smrg const struct pipe_draw_info *info, 7327ec681f3Smrg const struct pipe_draw_start_count_bias *draw) 7334a49301eSmrg{ 7343464ebd5Sriastradh int i; 735cdc920a0Smrg 7363464ebd5Sriastradh for (i = 0; i < info->instance_count; i++) 7377ec681f3Smrg r300_draw_elements(r300, info, draw, i); 7384a49301eSmrg} 7394a49301eSmrg 740af69d88dSmrgstatic unsigned r300_max_vertex_count(struct r300_context *r300) 741af69d88dSmrg{ 742af69d88dSmrg unsigned i, nr = r300->velems->count; 743af69d88dSmrg struct pipe_vertex_element *velems = r300->velems->velem; 744af69d88dSmrg unsigned result = ~0; 745af69d88dSmrg 746af69d88dSmrg for (i = 0; i < nr; i++) { 747af69d88dSmrg struct pipe_vertex_buffer *vb = 748af69d88dSmrg &r300->vertex_buffer[velems[i].vertex_buffer_index]; 749af69d88dSmrg unsigned size, max_count, value; 750af69d88dSmrg 751af69d88dSmrg /* We're not interested in constant and per-instance attribs. */ 75201e04c3fSmrg if (!vb->buffer.resource || 753af69d88dSmrg !vb->stride || 754af69d88dSmrg velems[i].instance_divisor) { 755af69d88dSmrg continue; 756af69d88dSmrg } 757af69d88dSmrg 75801e04c3fSmrg size = vb->buffer.resource->width0; 759af69d88dSmrg 760af69d88dSmrg /* Subtract buffer_offset. */ 761af69d88dSmrg value = vb->buffer_offset; 762af69d88dSmrg if (value >= size) { 763af69d88dSmrg return 0; 764af69d88dSmrg } 765af69d88dSmrg size -= value; 766af69d88dSmrg 767af69d88dSmrg /* Subtract src_offset. */ 768af69d88dSmrg value = velems[i].src_offset; 769af69d88dSmrg if (value >= size) { 770af69d88dSmrg return 0; 771af69d88dSmrg } 772af69d88dSmrg size -= value; 773af69d88dSmrg 774af69d88dSmrg /* Subtract format_size. */ 775af69d88dSmrg value = r300->velems->format_size[i]; 776af69d88dSmrg if (value >= size) { 777af69d88dSmrg return 0; 778af69d88dSmrg } 779af69d88dSmrg size -= value; 780af69d88dSmrg 781af69d88dSmrg /* Compute the max count. */ 782af69d88dSmrg max_count = 1 + size / vb->stride; 783af69d88dSmrg result = MIN2(result, max_count); 784af69d88dSmrg } 785af69d88dSmrg return result; 786af69d88dSmrg} 787af69d88dSmrg 788af69d88dSmrg 7893464ebd5Sriastradhstatic void r300_draw_vbo(struct pipe_context* pipe, 7907ec681f3Smrg const struct pipe_draw_info *dinfo, 7917ec681f3Smrg unsigned drawid_offset, 7927ec681f3Smrg const struct pipe_draw_indirect_info *indirect, 7937ec681f3Smrg const struct pipe_draw_start_count_bias *draws, 7947ec681f3Smrg unsigned num_draws) 7954a49301eSmrg{ 7967ec681f3Smrg if (num_draws > 1) { 7977ec681f3Smrg util_draw_multi(pipe, dinfo, drawid_offset, indirect, draws, num_draws); 7987ec681f3Smrg return; 7997ec681f3Smrg } 8007ec681f3Smrg 8014a49301eSmrg struct r300_context* r300 = r300_context(pipe); 8023464ebd5Sriastradh struct pipe_draw_info info = *dinfo; 8037ec681f3Smrg struct pipe_draw_start_count_bias draw = draws[0]; 8044a49301eSmrg 8053464ebd5Sriastradh if (r300->skip_rendering || 8067ec681f3Smrg !u_trim_pipe_prim(info.mode, &draw.count)) { 807cdc920a0Smrg return; 8084a49301eSmrg } 8094a49301eSmrg 8104a49301eSmrg r300_update_derived_state(r300); 8114a49301eSmrg 8123464ebd5Sriastradh /* Draw. */ 81301e04c3fSmrg if (info.index_size) { 814af69d88dSmrg unsigned max_count = r300_max_vertex_count(r300); 815af69d88dSmrg 816af69d88dSmrg if (!max_count) { 817af69d88dSmrg fprintf(stderr, "r300: Skipping a draw command. There is a buffer " 818af69d88dSmrg " which is too small to be used for rendering.\n"); 819af69d88dSmrg return; 820af69d88dSmrg } 821af69d88dSmrg 822af69d88dSmrg if (max_count == ~0) { 823af69d88dSmrg /* There are no per-vertex vertex elements. Use the hardware maximum. */ 824af69d88dSmrg max_count = 0xffffff; 825af69d88dSmrg } 826af69d88dSmrg 827af69d88dSmrg info.max_index = max_count - 1; 8283464ebd5Sriastradh 8293464ebd5Sriastradh if (info.instance_count <= 1) { 8307ec681f3Smrg if (draw.count <= 8 && info.has_user_indices) { 8317ec681f3Smrg r300_draw_elements_immediate(r300, &info, &draw); 8323464ebd5Sriastradh } else { 8337ec681f3Smrg r300_draw_elements(r300, &info, &draw, -1); 8343464ebd5Sriastradh } 8353464ebd5Sriastradh } else { 8367ec681f3Smrg r300_draw_elements_instanced(r300, &info, &draw); 8373464ebd5Sriastradh } 8383464ebd5Sriastradh } else { 8393464ebd5Sriastradh if (info.instance_count <= 1) { 8407ec681f3Smrg if (immd_is_good_idea(r300, draw.count)) { 8417ec681f3Smrg r300_draw_arrays_immediate(r300, &info, &draw); 8423464ebd5Sriastradh } else { 8437ec681f3Smrg r300_draw_arrays(r300, &info, &draw, -1); 8443464ebd5Sriastradh } 845cdc920a0Smrg } else { 8467ec681f3Smrg r300_draw_arrays_instanced(r300, &info, &draw); 847cdc920a0Smrg } 8484a49301eSmrg } 8494a49301eSmrg} 8504a49301eSmrg 8514a49301eSmrg/**************************************************************************** 8524a49301eSmrg * The rest of this file is for SW TCL rendering only. Please be polite and * 8534a49301eSmrg * keep these functions separated so that they are easier to locate. ~C. * 8544a49301eSmrg ***************************************************************************/ 8554a49301eSmrg 8563464ebd5Sriastradh/* SW TCL elements, using Draw. */ 8573464ebd5Sriastradhstatic void r300_swtcl_draw_vbo(struct pipe_context* pipe, 8587ec681f3Smrg const struct pipe_draw_info *info, 8597ec681f3Smrg unsigned drawid_offset, 8607ec681f3Smrg const struct pipe_draw_indirect_info *indirect, 8617ec681f3Smrg const struct pipe_draw_start_count_bias *draws, 8627ec681f3Smrg unsigned num_draws) 8634a49301eSmrg{ 8647ec681f3Smrg if (num_draws > 1) { 8657ec681f3Smrg util_draw_multi(pipe, info, drawid_offset, indirect, draws, num_draws); 8667ec681f3Smrg return; 8677ec681f3Smrg } 8687ec681f3Smrg 8694a49301eSmrg struct r300_context* r300 = r300_context(pipe); 8707ec681f3Smrg struct pipe_draw_start_count_bias draw = draws[0]; 8714a49301eSmrg 8723464ebd5Sriastradh if (r300->skip_rendering) { 873cdc920a0Smrg return; 8744a49301eSmrg } 8754a49301eSmrg 8767ec681f3Smrg if (!u_trim_pipe_prim(info->mode, &draw.count)) 87701e04c3fSmrg return; 87801e04c3fSmrg 87901e04c3fSmrg if (info->index_size) { 88001e04c3fSmrg draw_set_indexes(r300->draw, 88101e04c3fSmrg info->has_user_indices ? 88201e04c3fSmrg info->index.user : 88301e04c3fSmrg r300_resource(info->index.resource)->malloced_buffer, 88401e04c3fSmrg info->index_size, ~0); 88501e04c3fSmrg } 88601e04c3fSmrg 8873464ebd5Sriastradh r300_update_derived_state(r300); 8884a49301eSmrg 8897ec681f3Smrg draw_vbo(r300->draw, info, drawid_offset, NULL, &draw, 1, 0); 8903464ebd5Sriastradh draw_flush(r300->draw); 8914a49301eSmrg} 8924a49301eSmrg 8934a49301eSmrg/* Object for rendering using Draw. */ 8944a49301eSmrgstruct r300_render { 8954a49301eSmrg /* Parent class */ 8964a49301eSmrg struct vbuf_render base; 8974a49301eSmrg 8984a49301eSmrg /* Pipe context */ 8994a49301eSmrg struct r300_context* r300; 9004a49301eSmrg 9014a49301eSmrg /* Vertex information */ 9024a49301eSmrg size_t vertex_size; 9034a49301eSmrg unsigned prim; 9044a49301eSmrg unsigned hwprim; 9054a49301eSmrg 9064a49301eSmrg /* VBO */ 9074a49301eSmrg size_t vbo_max_used; 908af69d88dSmrg uint8_t *vbo_ptr; 9094a49301eSmrg}; 9104a49301eSmrg 91101e04c3fSmrgstatic inline struct r300_render* 9124a49301eSmrgr300_render(struct vbuf_render* render) 9134a49301eSmrg{ 9144a49301eSmrg return (struct r300_render*)render; 9154a49301eSmrg} 9164a49301eSmrg 9174a49301eSmrgstatic const struct vertex_info* 9184a49301eSmrgr300_render_get_vertex_info(struct vbuf_render* render) 9194a49301eSmrg{ 9204a49301eSmrg struct r300_render* r300render = r300_render(render); 9214a49301eSmrg struct r300_context* r300 = r300render->r300; 9224a49301eSmrg 923cdc920a0Smrg return &r300->vertex_info; 9244a49301eSmrg} 9254a49301eSmrg 9264a49301eSmrgstatic boolean r300_render_allocate_vertices(struct vbuf_render* render, 927af69d88dSmrg ushort vertex_size, 928af69d88dSmrg ushort count) 9294a49301eSmrg{ 9304a49301eSmrg struct r300_render* r300render = r300_render(render); 9314a49301eSmrg struct r300_context* r300 = r300render->r300; 932af69d88dSmrg struct radeon_winsys *rws = r300->rws; 9334a49301eSmrg size_t size = (size_t)vertex_size * (size_t)count; 9344a49301eSmrg 9353464ebd5Sriastradh DBG(r300, DBG_DRAW, "r300: render_allocate_vertices (size: %d)\n", size); 9363464ebd5Sriastradh 937af69d88dSmrg if (!r300->vbo || size + r300->draw_vbo_offset > r300->vbo->size) { 938af69d88dSmrg pb_reference(&r300->vbo, NULL); 93901e04c3fSmrg r300->vbo = NULL; 940af69d88dSmrg r300render->vbo_ptr = NULL; 941af69d88dSmrg 942af69d88dSmrg r300->vbo = rws->buffer_create(rws, 943af69d88dSmrg MAX2(R300_MAX_DRAW_VBO_SIZE, size), 94401e04c3fSmrg R300_BUFFER_ALIGNMENT, 9459f464c52Smaya RADEON_DOMAIN_GTT, 9469f464c52Smaya RADEON_FLAG_NO_INTERPROCESS_SHARING); 947af69d88dSmrg if (!r300->vbo) { 948af69d88dSmrg return FALSE; 949af69d88dSmrg } 9503464ebd5Sriastradh r300->draw_vbo_offset = 0; 9517ec681f3Smrg r300render->vbo_ptr = rws->buffer_map(rws, r300->vbo, &r300->cs, 9527ec681f3Smrg PIPE_MAP_WRITE); 9534a49301eSmrg } 9544a49301eSmrg 9554a49301eSmrg r300render->vertex_size = vertex_size; 956af69d88dSmrg return TRUE; 9574a49301eSmrg} 9584a49301eSmrg 9594a49301eSmrgstatic void* r300_render_map_vertices(struct vbuf_render* render) 9604a49301eSmrg{ 9614a49301eSmrg struct r300_render* r300render = r300_render(render); 9623464ebd5Sriastradh struct r300_context* r300 = r300render->r300; 9634a49301eSmrg 9643464ebd5Sriastradh DBG(r300, DBG_DRAW, "r300: render_map_vertices\n"); 9653464ebd5Sriastradh 9663464ebd5Sriastradh assert(r300render->vbo_ptr); 967af69d88dSmrg return r300render->vbo_ptr + r300->draw_vbo_offset; 9684a49301eSmrg} 9694a49301eSmrg 9704a49301eSmrgstatic void r300_render_unmap_vertices(struct vbuf_render* render, 9714a49301eSmrg ushort min, 9724a49301eSmrg ushort max) 9734a49301eSmrg{ 9744a49301eSmrg struct r300_render* r300render = r300_render(render); 9753464ebd5Sriastradh struct r300_context* r300 = r300render->r300; 9763464ebd5Sriastradh 9773464ebd5Sriastradh DBG(r300, DBG_DRAW, "r300: render_unmap_vertices\n"); 9784a49301eSmrg 9794a49301eSmrg r300render->vbo_max_used = MAX2(r300render->vbo_max_used, 9804a49301eSmrg r300render->vertex_size * (max + 1)); 9814a49301eSmrg} 9824a49301eSmrg 9834a49301eSmrgstatic void r300_render_release_vertices(struct vbuf_render* render) 9844a49301eSmrg{ 9854a49301eSmrg struct r300_render* r300render = r300_render(render); 9863464ebd5Sriastradh struct r300_context* r300 = r300render->r300; 9874a49301eSmrg 9883464ebd5Sriastradh DBG(r300, DBG_DRAW, "r300: render_release_vertices\n"); 9893464ebd5Sriastradh 9903464ebd5Sriastradh r300->draw_vbo_offset += r300render->vbo_max_used; 9914a49301eSmrg r300render->vbo_max_used = 0; 9924a49301eSmrg} 9934a49301eSmrg 994af69d88dSmrgstatic void r300_render_set_primitive(struct vbuf_render* render, 99501e04c3fSmrg enum pipe_prim_type prim) 9964a49301eSmrg{ 9974a49301eSmrg struct r300_render* r300render = r300_render(render); 9984a49301eSmrg 9994a49301eSmrg r300render->prim = prim; 10004a49301eSmrg r300render->hwprim = r300_translate_primitive(prim); 10014a49301eSmrg} 10024a49301eSmrg 10034a49301eSmrgstatic void r300_render_draw_arrays(struct vbuf_render* render, 10043464ebd5Sriastradh unsigned start, 10053464ebd5Sriastradh unsigned count) 10064a49301eSmrg{ 10074a49301eSmrg struct r300_render* r300render = r300_render(render); 10084a49301eSmrg struct r300_context* r300 = r300render->r300; 10093464ebd5Sriastradh uint8_t* ptr; 10103464ebd5Sriastradh unsigned i; 10113464ebd5Sriastradh unsigned dwords = 6; 10124a49301eSmrg 10134a49301eSmrg CS_LOCALS(r300); 10143464ebd5Sriastradh (void) i; (void) ptr; 10154a49301eSmrg 1016af69d88dSmrg assert(start == 0); 1017af69d88dSmrg assert(count < (1 << 16)); 1018af69d88dSmrg 10193464ebd5Sriastradh DBG(r300, DBG_DRAW, "r300: render_draw_arrays (count: %d)\n", count); 10204a49301eSmrg 1021af69d88dSmrg if (!r300_prepare_for_rendering(r300, 1022af69d88dSmrg PREP_EMIT_STATES | PREP_EMIT_VARRAYS_SWTCL, 1023af69d88dSmrg NULL, dwords, 0, 0, -1)) { 1024af69d88dSmrg return; 10253464ebd5Sriastradh } 10264a49301eSmrg 10273464ebd5Sriastradh BEGIN_CS(dwords); 10283464ebd5Sriastradh OUT_CS_REG(R300_GA_COLOR_CONTROL, 10293464ebd5Sriastradh r300_provoking_vertex_fixes(r300, r300render->prim)); 10303464ebd5Sriastradh OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, count - 1); 10314a49301eSmrg OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0); 10324a49301eSmrg OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) | 10334a49301eSmrg r300render->hwprim); 10344a49301eSmrg END_CS; 10354a49301eSmrg} 10364a49301eSmrg 10373464ebd5Sriastradhstatic void r300_render_draw_elements(struct vbuf_render* render, 10383464ebd5Sriastradh const ushort* indices, 10393464ebd5Sriastradh uint count) 10404a49301eSmrg{ 10414a49301eSmrg struct r300_render* r300render = r300_render(render); 10424a49301eSmrg struct r300_context* r300 = r300render->r300; 1043af69d88dSmrg unsigned max_index = (r300->vbo->size - r300->draw_vbo_offset) / 10443464ebd5Sriastradh (r300render->r300->vertex_info.size * 4) - 1; 1045af69d88dSmrg struct pipe_resource *index_buffer = NULL; 1046af69d88dSmrg unsigned index_buffer_offset; 10474a49301eSmrg 10484a49301eSmrg CS_LOCALS(r300); 10493464ebd5Sriastradh DBG(r300, DBG_DRAW, "r300: render_draw_elements (count: %d)\n", count); 10504a49301eSmrg 105101e04c3fSmrg u_upload_data(r300->uploader, 0, count * 2, 4, indices, 1052af69d88dSmrg &index_buffer_offset, &index_buffer); 1053af69d88dSmrg if (!index_buffer) { 1054af69d88dSmrg return; 10554a49301eSmrg } 10563464ebd5Sriastradh 1057af69d88dSmrg if (!r300_prepare_for_rendering(r300, 1058af69d88dSmrg PREP_EMIT_STATES | 1059af69d88dSmrg PREP_EMIT_VARRAYS_SWTCL | PREP_INDEXED, 1060af69d88dSmrg index_buffer, 12, 0, 0, -1)) { 1061af69d88dSmrg pipe_resource_reference(&index_buffer, NULL); 1062af69d88dSmrg return; 1063af69d88dSmrg } 10643464ebd5Sriastradh 1065af69d88dSmrg BEGIN_CS(12); 1066af69d88dSmrg OUT_CS_REG(R300_GA_COLOR_CONTROL, 1067af69d88dSmrg r300_provoking_vertex_fixes(r300, r300render->prim)); 1068af69d88dSmrg OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, max_index); 10693464ebd5Sriastradh 1070af69d88dSmrg OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, 0); 1071af69d88dSmrg OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | 1072af69d88dSmrg r300render->hwprim); 10733464ebd5Sriastradh 1074af69d88dSmrg OUT_CS_PKT3(R300_PACKET3_INDX_BUFFER, 2); 1075af69d88dSmrg OUT_CS(R300_INDX_BUFFER_ONE_REG_WR | (R300_VAP_PORT_IDX0 >> 2)); 1076af69d88dSmrg OUT_CS(index_buffer_offset); 1077af69d88dSmrg OUT_CS((count + 1) / 2); 1078af69d88dSmrg OUT_CS_RELOC(r300_resource(index_buffer)); 1079af69d88dSmrg END_CS; 10803464ebd5Sriastradh 1081af69d88dSmrg pipe_resource_reference(&index_buffer, NULL); 10824a49301eSmrg} 10834a49301eSmrg 10844a49301eSmrgstatic void r300_render_destroy(struct vbuf_render* render) 10854a49301eSmrg{ 10864a49301eSmrg FREE(render); 10874a49301eSmrg} 10884a49301eSmrg 10894a49301eSmrgstatic struct vbuf_render* r300_render_create(struct r300_context* r300) 10904a49301eSmrg{ 10914a49301eSmrg struct r300_render* r300render = CALLOC_STRUCT(r300_render); 10924a49301eSmrg 10934a49301eSmrg r300render->r300 = r300; 10944a49301eSmrg 1095af69d88dSmrg r300render->base.max_vertex_buffer_bytes = R300_MAX_DRAW_VBO_SIZE; 10964a49301eSmrg r300render->base.max_indices = 16 * 1024; 10974a49301eSmrg 10984a49301eSmrg r300render->base.get_vertex_info = r300_render_get_vertex_info; 10994a49301eSmrg r300render->base.allocate_vertices = r300_render_allocate_vertices; 11004a49301eSmrg r300render->base.map_vertices = r300_render_map_vertices; 11014a49301eSmrg r300render->base.unmap_vertices = r300_render_unmap_vertices; 11024a49301eSmrg r300render->base.set_primitive = r300_render_set_primitive; 11033464ebd5Sriastradh r300render->base.draw_elements = r300_render_draw_elements; 11044a49301eSmrg r300render->base.draw_arrays = r300_render_draw_arrays; 11054a49301eSmrg r300render->base.release_vertices = r300_render_release_vertices; 11064a49301eSmrg r300render->base.destroy = r300_render_destroy; 11074a49301eSmrg 11084a49301eSmrg return &r300render->base; 11094a49301eSmrg} 11104a49301eSmrg 11114a49301eSmrgstruct draw_stage* r300_draw_stage(struct r300_context* r300) 11124a49301eSmrg{ 11134a49301eSmrg struct vbuf_render* render; 11144a49301eSmrg struct draw_stage* stage; 11154a49301eSmrg 11164a49301eSmrg render = r300_render_create(r300); 11174a49301eSmrg 11184a49301eSmrg if (!render) { 11194a49301eSmrg return NULL; 11204a49301eSmrg } 11214a49301eSmrg 11224a49301eSmrg stage = draw_vbuf_stage(r300->draw, render); 11234a49301eSmrg 11244a49301eSmrg if (!stage) { 11254a49301eSmrg render->destroy(render); 11264a49301eSmrg return NULL; 11274a49301eSmrg } 11284a49301eSmrg 11294a49301eSmrg draw_set_render(r300->draw, render); 11304a49301eSmrg 11314a49301eSmrg return stage; 11324a49301eSmrg} 11333464ebd5Sriastradh 11343464ebd5Sriastradh/**************************************************************************** 11353464ebd5Sriastradh * End of SW TCL functions * 11363464ebd5Sriastradh ***************************************************************************/ 11373464ebd5Sriastradh 11383464ebd5Sriastradh/* This functions is used to draw a rectangle for the blitter module. 11393464ebd5Sriastradh * 11403464ebd5Sriastradh * If we rendered a quad, the pixels on the main diagonal 11413464ebd5Sriastradh * would be computed and stored twice, which makes the clear/copy codepaths 11423464ebd5Sriastradh * somewhat inefficient. Instead we use a rectangular point sprite. */ 1143af69d88dSmrgvoid r300_blitter_draw_rectangle(struct blitter_context *blitter, 114401e04c3fSmrg void *vertex_elements_cso, 114501e04c3fSmrg blitter_get_vs_func get_vs, 1146af69d88dSmrg int x1, int y1, int x2, int y2, 114701e04c3fSmrg float depth, unsigned num_instances, 1148af69d88dSmrg enum blitter_attrib_type type, 114901e04c3fSmrg const union blitter_attrib *attrib) 11503464ebd5Sriastradh{ 11513464ebd5Sriastradh struct r300_context *r300 = r300_context(util_blitter_get_pipe(blitter)); 11523464ebd5Sriastradh unsigned last_sprite_coord_enable = r300->sprite_coord_enable; 11533464ebd5Sriastradh unsigned width = x2 - x1; 11543464ebd5Sriastradh unsigned height = y2 - y1; 11553464ebd5Sriastradh unsigned vertex_size = 11563464ebd5Sriastradh type == UTIL_BLITTER_ATTRIB_COLOR || !r300->draw ? 8 : 4; 11573464ebd5Sriastradh unsigned dwords = 13 + vertex_size + 115801e04c3fSmrg (type == UTIL_BLITTER_ATTRIB_TEXCOORD_XY ? 7 : 0); 115901e04c3fSmrg static const union blitter_attrib zeros; 11603464ebd5Sriastradh CS_LOCALS(r300); 11613464ebd5Sriastradh 1162af69d88dSmrg /* XXX workaround for a lockup in MSAA resolve on SWTCL chipsets, this 1163af69d88dSmrg * function most probably doesn't handle type=NONE correctly */ 116401e04c3fSmrg if ((!r300->screen->caps.has_tcl && type == UTIL_BLITTER_ATTRIB_NONE) || 116501e04c3fSmrg type == UTIL_BLITTER_ATTRIB_TEXCOORD_XYZW || 116601e04c3fSmrg num_instances > 1) { 116701e04c3fSmrg util_blitter_draw_rectangle(blitter, vertex_elements_cso, get_vs, 116801e04c3fSmrg x1, y1, x2, y2, 116901e04c3fSmrg depth, num_instances, type, attrib); 11703464ebd5Sriastradh return; 1171af69d88dSmrg } 11723464ebd5Sriastradh 1173af69d88dSmrg if (r300->skip_rendering) 1174af69d88dSmrg return; 11753464ebd5Sriastradh 117601e04c3fSmrg r300->context.bind_vertex_elements_state(&r300->context, vertex_elements_cso); 117701e04c3fSmrg r300->context.bind_vs_state(&r300->context, get_vs(blitter)); 117801e04c3fSmrg 117901e04c3fSmrg if (type == UTIL_BLITTER_ATTRIB_TEXCOORD_XY) 11803464ebd5Sriastradh r300->sprite_coord_enable = 1; 11813464ebd5Sriastradh 11823464ebd5Sriastradh r300_update_derived_state(r300); 11833464ebd5Sriastradh 11843464ebd5Sriastradh /* Mark some states we don't care about as non-dirty. */ 11853464ebd5Sriastradh r300->viewport_state.dirty = FALSE; 11863464ebd5Sriastradh 11873464ebd5Sriastradh if (!r300_prepare_for_rendering(r300, PREP_EMIT_STATES, NULL, dwords, 0, 0, -1)) 11883464ebd5Sriastradh goto done; 11893464ebd5Sriastradh 11903464ebd5Sriastradh DBG(r300, DBG_DRAW, "r300: draw_rectangle\n"); 11913464ebd5Sriastradh 11923464ebd5Sriastradh BEGIN_CS(dwords); 11933464ebd5Sriastradh /* Set up GA. */ 11943464ebd5Sriastradh OUT_CS_REG(R300_GA_POINT_SIZE, (height * 6) | ((width * 6) << 16)); 11953464ebd5Sriastradh 119601e04c3fSmrg if (type == UTIL_BLITTER_ATTRIB_TEXCOORD_XY) { 11973464ebd5Sriastradh /* Set up the GA to generate texcoords. */ 11983464ebd5Sriastradh OUT_CS_REG(R300_GB_ENABLE, R300_GB_POINT_STUFF_ENABLE | 11993464ebd5Sriastradh (R300_GB_TEX_STR << R300_GB_TEX0_SOURCE_SHIFT)); 12003464ebd5Sriastradh OUT_CS_REG_SEQ(R300_GA_POINT_S0, 4); 120101e04c3fSmrg OUT_CS_32F(attrib->texcoord.x1); 120201e04c3fSmrg OUT_CS_32F(attrib->texcoord.y2); 120301e04c3fSmrg OUT_CS_32F(attrib->texcoord.x2); 120401e04c3fSmrg OUT_CS_32F(attrib->texcoord.y1); 12053464ebd5Sriastradh } 12063464ebd5Sriastradh 12073464ebd5Sriastradh /* Set up VAP controls. */ 12083464ebd5Sriastradh OUT_CS_REG(R300_VAP_CLIP_CNTL, R300_CLIP_DISABLE); 12093464ebd5Sriastradh OUT_CS_REG(R300_VAP_VTE_CNTL, R300_VTX_XY_FMT | R300_VTX_Z_FMT); 12103464ebd5Sriastradh OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size); 12113464ebd5Sriastradh OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); 12123464ebd5Sriastradh OUT_CS(1); 12133464ebd5Sriastradh OUT_CS(0); 12143464ebd5Sriastradh 12153464ebd5Sriastradh /* Draw. */ 12163464ebd5Sriastradh OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, vertex_size); 12173464ebd5Sriastradh OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (1 << 16) | 12183464ebd5Sriastradh R300_VAP_VF_CNTL__PRIM_POINTS); 12193464ebd5Sriastradh 12203464ebd5Sriastradh OUT_CS_32F(x1 + width * 0.5f); 12213464ebd5Sriastradh OUT_CS_32F(y1 + height * 0.5f); 12223464ebd5Sriastradh OUT_CS_32F(depth); 12233464ebd5Sriastradh OUT_CS_32F(1); 12243464ebd5Sriastradh 12253464ebd5Sriastradh if (vertex_size == 8) { 12263464ebd5Sriastradh if (!attrib) 1227af69d88dSmrg attrib = &zeros; 122801e04c3fSmrg OUT_CS_TABLE(attrib->color, 4); 12293464ebd5Sriastradh } 12303464ebd5Sriastradh END_CS; 12313464ebd5Sriastradh 12323464ebd5Sriastradhdone: 12333464ebd5Sriastradh /* Restore the state. */ 12343464ebd5Sriastradh r300_mark_atom_dirty(r300, &r300->rs_state); 12353464ebd5Sriastradh r300_mark_atom_dirty(r300, &r300->viewport_state); 12363464ebd5Sriastradh 12373464ebd5Sriastradh r300->sprite_coord_enable = last_sprite_coord_enable; 12383464ebd5Sriastradh} 12393464ebd5Sriastradh 12403464ebd5Sriastradhvoid r300_init_render_functions(struct r300_context *r300) 12413464ebd5Sriastradh{ 12423464ebd5Sriastradh /* Set draw functions based on presence of HW TCL. */ 12433464ebd5Sriastradh if (r300->screen->caps.has_tcl) { 12443464ebd5Sriastradh r300->context.draw_vbo = r300_draw_vbo; 12453464ebd5Sriastradh } else { 12463464ebd5Sriastradh r300->context.draw_vbo = r300_swtcl_draw_vbo; 12473464ebd5Sriastradh } 12483464ebd5Sriastradh 12493464ebd5Sriastradh /* Plug in the two-sided stencil reference value fallback if needed. */ 12503464ebd5Sriastradh if (!r300->screen->caps.is_r500) 12513464ebd5Sriastradh r300_plug_in_stencil_ref_fallback(r300); 12523464ebd5Sriastradh} 1253