1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2009 Corbin Simpson <MostAwesomeDude@gmail.com> 3bf215546Sopenharmony_ci * Copyright 2010 Marek Olšák <maraeo@gmail.com> 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 8bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub 9bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom 10bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 14bf215546Sopenharmony_ci * Software. 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 20bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 22bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci/* r300_render: Vertex and index buffer primitive emission. Contains both 25bf215546Sopenharmony_ci * HW TCL fastpath rendering, and SW TCL Draw-assisted rendering. */ 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "draw/draw_context.h" 28bf215546Sopenharmony_ci#include "draw/draw_vbuf.h" 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include "util/u_inlines.h" 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci#include "util/format/u_format.h" 33bf215546Sopenharmony_ci#include "util/u_draw.h" 34bf215546Sopenharmony_ci#include "util/u_memory.h" 35bf215546Sopenharmony_ci#include "util/u_upload_mgr.h" 36bf215546Sopenharmony_ci#include "util/u_prim.h" 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci#include "r300_cs.h" 39bf215546Sopenharmony_ci#include "r300_context.h" 40bf215546Sopenharmony_ci#include "r300_screen_buffer.h" 41bf215546Sopenharmony_ci#include "r300_emit.h" 42bf215546Sopenharmony_ci#include "r300_reg.h" 43bf215546Sopenharmony_ci#include "r300_vs.h" 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci#include <limits.h> 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_ci#define IMMD_DWORDS 32 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_cistatic uint32_t r300_translate_primitive(unsigned prim) 50bf215546Sopenharmony_ci{ 51bf215546Sopenharmony_ci static const int prim_conv[] = { 52bf215546Sopenharmony_ci R300_VAP_VF_CNTL__PRIM_POINTS, 53bf215546Sopenharmony_ci R300_VAP_VF_CNTL__PRIM_LINES, 54bf215546Sopenharmony_ci R300_VAP_VF_CNTL__PRIM_LINE_LOOP, 55bf215546Sopenharmony_ci R300_VAP_VF_CNTL__PRIM_LINE_STRIP, 56bf215546Sopenharmony_ci R300_VAP_VF_CNTL__PRIM_TRIANGLES, 57bf215546Sopenharmony_ci R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP, 58bf215546Sopenharmony_ci R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN, 59bf215546Sopenharmony_ci R300_VAP_VF_CNTL__PRIM_QUADS, 60bf215546Sopenharmony_ci R300_VAP_VF_CNTL__PRIM_QUAD_STRIP, 61bf215546Sopenharmony_ci R300_VAP_VF_CNTL__PRIM_POLYGON, 62bf215546Sopenharmony_ci -1, 63bf215546Sopenharmony_ci -1, 64bf215546Sopenharmony_ci -1, 65bf215546Sopenharmony_ci -1 66bf215546Sopenharmony_ci }; 67bf215546Sopenharmony_ci unsigned hwprim = prim_conv[prim]; 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci assert(hwprim != -1); 70bf215546Sopenharmony_ci return hwprim; 71bf215546Sopenharmony_ci} 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_cistatic uint32_t r300_provoking_vertex_fixes(struct r300_context *r300, 74bf215546Sopenharmony_ci unsigned mode) 75bf215546Sopenharmony_ci{ 76bf215546Sopenharmony_ci struct r300_rs_state* rs = (struct r300_rs_state*)r300->rs_state.state; 77bf215546Sopenharmony_ci uint32_t color_control = rs->color_control; 78bf215546Sopenharmony_ci 79bf215546Sopenharmony_ci /* By default (see r300_state.c:r300_create_rs_state) color_control is 80bf215546Sopenharmony_ci * initialized to provoking the first vertex. 81bf215546Sopenharmony_ci * 82bf215546Sopenharmony_ci * Triangle fans must be reduced to the second vertex, not the first, in 83bf215546Sopenharmony_ci * Gallium flatshade-first mode, as per the GL spec. 84bf215546Sopenharmony_ci * (http://www.opengl.org/registry/specs/ARB/provoking_vertex.txt) 85bf215546Sopenharmony_ci * 86bf215546Sopenharmony_ci * Quads never provoke correctly in flatshade-first mode. The first 87bf215546Sopenharmony_ci * vertex is never considered as provoking, so only the second, third, 88bf215546Sopenharmony_ci * and fourth vertices can be selected, and both "third" and "last" modes 89bf215546Sopenharmony_ci * select the fourth vertex. This is probably due to D3D lacking quads. 90bf215546Sopenharmony_ci * 91bf215546Sopenharmony_ci * Similarly, polygons reduce to the first, not the last, vertex, when in 92bf215546Sopenharmony_ci * "last" mode, and all other modes start from the second vertex. 93bf215546Sopenharmony_ci * 94bf215546Sopenharmony_ci * ~ C. 95bf215546Sopenharmony_ci */ 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci if (rs->rs.flatshade_first) { 98bf215546Sopenharmony_ci switch (mode) { 99bf215546Sopenharmony_ci case PIPE_PRIM_TRIANGLE_FAN: 100bf215546Sopenharmony_ci color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_SECOND; 101bf215546Sopenharmony_ci break; 102bf215546Sopenharmony_ci case PIPE_PRIM_QUADS: 103bf215546Sopenharmony_ci case PIPE_PRIM_QUAD_STRIP: 104bf215546Sopenharmony_ci case PIPE_PRIM_POLYGON: 105bf215546Sopenharmony_ci color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_LAST; 106bf215546Sopenharmony_ci break; 107bf215546Sopenharmony_ci default: 108bf215546Sopenharmony_ci color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_FIRST; 109bf215546Sopenharmony_ci break; 110bf215546Sopenharmony_ci } 111bf215546Sopenharmony_ci } else { 112bf215546Sopenharmony_ci color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_LAST; 113bf215546Sopenharmony_ci } 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci return color_control; 116bf215546Sopenharmony_ci} 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_civoid r500_emit_index_bias(struct r300_context *r300, int index_bias) 119bf215546Sopenharmony_ci{ 120bf215546Sopenharmony_ci CS_LOCALS(r300); 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci BEGIN_CS(2); 123bf215546Sopenharmony_ci OUT_CS_REG(R500_VAP_INDEX_OFFSET, 124bf215546Sopenharmony_ci (index_bias & 0xFFFFFF) | (index_bias < 0 ? 1<<24 : 0)); 125bf215546Sopenharmony_ci END_CS; 126bf215546Sopenharmony_ci} 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_cistatic void r300_emit_draw_init(struct r300_context *r300, unsigned mode, 129bf215546Sopenharmony_ci unsigned max_index) 130bf215546Sopenharmony_ci{ 131bf215546Sopenharmony_ci CS_LOCALS(r300); 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci assert(max_index < (1 << 24)); 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_ci BEGIN_CS(5); 136bf215546Sopenharmony_ci OUT_CS_REG(R300_GA_COLOR_CONTROL, 137bf215546Sopenharmony_ci r300_provoking_vertex_fixes(r300, mode)); 138bf215546Sopenharmony_ci OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); 139bf215546Sopenharmony_ci OUT_CS(max_index); 140bf215546Sopenharmony_ci OUT_CS(0); 141bf215546Sopenharmony_ci END_CS; 142bf215546Sopenharmony_ci} 143bf215546Sopenharmony_ci 144bf215546Sopenharmony_ci/* This function splits the index bias value into two parts: 145bf215546Sopenharmony_ci * - buffer_offset: the value that can be safely added to buffer offsets 146bf215546Sopenharmony_ci * in r300_emit_vertex_arrays (it must yield a positive offset when added to 147bf215546Sopenharmony_ci * a vertex buffer offset) 148bf215546Sopenharmony_ci * - index_offset: the value that must be manually subtracted from indices 149bf215546Sopenharmony_ci * in an index buffer to achieve negative offsets. */ 150bf215546Sopenharmony_cistatic void r300_split_index_bias(struct r300_context *r300, int index_bias, 151bf215546Sopenharmony_ci int *buffer_offset, int *index_offset) 152bf215546Sopenharmony_ci{ 153bf215546Sopenharmony_ci struct pipe_vertex_buffer *vb, *vbufs = r300->vertex_buffer; 154bf215546Sopenharmony_ci struct pipe_vertex_element *velem = r300->velems->velem; 155bf215546Sopenharmony_ci unsigned i, size; 156bf215546Sopenharmony_ci int max_neg_bias; 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_ci if (index_bias < 0) { 159bf215546Sopenharmony_ci /* See how large index bias we may subtract. We must be careful 160bf215546Sopenharmony_ci * here because negative buffer offsets are not allowed 161bf215546Sopenharmony_ci * by the DRM API. */ 162bf215546Sopenharmony_ci max_neg_bias = INT_MAX; 163bf215546Sopenharmony_ci for (i = 0; i < r300->velems->count; i++) { 164bf215546Sopenharmony_ci vb = &vbufs[velem[i].vertex_buffer_index]; 165bf215546Sopenharmony_ci size = (vb->buffer_offset + velem[i].src_offset) / vb->stride; 166bf215546Sopenharmony_ci max_neg_bias = MIN2(max_neg_bias, size); 167bf215546Sopenharmony_ci } 168bf215546Sopenharmony_ci 169bf215546Sopenharmony_ci /* Now set the minimum allowed value. */ 170bf215546Sopenharmony_ci *buffer_offset = MAX2(-max_neg_bias, index_bias); 171bf215546Sopenharmony_ci } else { 172bf215546Sopenharmony_ci /* A positive index bias is OK. */ 173bf215546Sopenharmony_ci *buffer_offset = index_bias; 174bf215546Sopenharmony_ci } 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_ci *index_offset = index_bias - *buffer_offset; 177bf215546Sopenharmony_ci} 178bf215546Sopenharmony_ci 179bf215546Sopenharmony_cienum r300_prepare_flags { 180bf215546Sopenharmony_ci PREP_EMIT_STATES = (1 << 0), /* call emit_dirty_state and friends? */ 181bf215546Sopenharmony_ci PREP_VALIDATE_VBOS = (1 << 1), /* validate VBOs? */ 182bf215546Sopenharmony_ci PREP_EMIT_VARRAYS = (1 << 2), /* call emit_vertex_arrays? */ 183bf215546Sopenharmony_ci PREP_EMIT_VARRAYS_SWTCL = (1 << 3), /* call emit_vertex_arrays_swtcl? */ 184bf215546Sopenharmony_ci PREP_INDEXED = (1 << 4) /* is this draw_elements? */ 185bf215546Sopenharmony_ci}; 186bf215546Sopenharmony_ci 187bf215546Sopenharmony_ci/** 188bf215546Sopenharmony_ci * Check if the requested number of dwords is available in the CS and 189bf215546Sopenharmony_ci * if not, flush. 190bf215546Sopenharmony_ci * \param r300 The context. 191bf215546Sopenharmony_ci * \param flags See r300_prepare_flags. 192bf215546Sopenharmony_ci * \param cs_dwords The number of dwords to reserve in CS. 193bf215546Sopenharmony_ci * \return TRUE if the CS was flushed 194bf215546Sopenharmony_ci */ 195bf215546Sopenharmony_cistatic boolean r300_reserve_cs_dwords(struct r300_context *r300, 196bf215546Sopenharmony_ci enum r300_prepare_flags flags, 197bf215546Sopenharmony_ci unsigned cs_dwords) 198bf215546Sopenharmony_ci{ 199bf215546Sopenharmony_ci boolean flushed = FALSE; 200bf215546Sopenharmony_ci boolean emit_states = flags & PREP_EMIT_STATES; 201bf215546Sopenharmony_ci boolean emit_vertex_arrays = flags & PREP_EMIT_VARRAYS; 202bf215546Sopenharmony_ci boolean emit_vertex_arrays_swtcl = flags & PREP_EMIT_VARRAYS_SWTCL; 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci /* Add dirty state, index offset, and AOS. */ 205bf215546Sopenharmony_ci if (emit_states) 206bf215546Sopenharmony_ci cs_dwords += r300_get_num_dirty_dwords(r300); 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_ci if (r300->screen->caps.is_r500) 209bf215546Sopenharmony_ci cs_dwords += 2; /* emit_index_offset */ 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci if (emit_vertex_arrays) 212bf215546Sopenharmony_ci cs_dwords += 55; /* emit_vertex_arrays */ 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci if (emit_vertex_arrays_swtcl) 215bf215546Sopenharmony_ci cs_dwords += 7; /* emit_vertex_arrays_swtcl */ 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_ci cs_dwords += r300_get_num_cs_end_dwords(r300); 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_ci /* Reserve requested CS space. */ 220bf215546Sopenharmony_ci if (!r300->rws->cs_check_space(&r300->cs, cs_dwords)) { 221bf215546Sopenharmony_ci r300_flush(&r300->context, PIPE_FLUSH_ASYNC, NULL); 222bf215546Sopenharmony_ci flushed = TRUE; 223bf215546Sopenharmony_ci } 224bf215546Sopenharmony_ci 225bf215546Sopenharmony_ci return flushed; 226bf215546Sopenharmony_ci} 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci/** 229bf215546Sopenharmony_ci * Validate buffers and emit dirty state. 230bf215546Sopenharmony_ci * \param r300 The context. 231bf215546Sopenharmony_ci * \param flags See r300_prepare_flags. 232bf215546Sopenharmony_ci * \param index_buffer The index buffer to validate. The parameter may be NULL. 233bf215546Sopenharmony_ci * \param buffer_offset The offset passed to emit_vertex_arrays. 234bf215546Sopenharmony_ci * \param index_bias The index bias to emit. 235bf215546Sopenharmony_ci * \param instance_id Index of instance to render 236bf215546Sopenharmony_ci * \return TRUE if rendering should be skipped 237bf215546Sopenharmony_ci */ 238bf215546Sopenharmony_cistatic boolean r300_emit_states(struct r300_context *r300, 239bf215546Sopenharmony_ci enum r300_prepare_flags flags, 240bf215546Sopenharmony_ci struct pipe_resource *index_buffer, 241bf215546Sopenharmony_ci int buffer_offset, 242bf215546Sopenharmony_ci int index_bias, int instance_id) 243bf215546Sopenharmony_ci{ 244bf215546Sopenharmony_ci boolean emit_states = flags & PREP_EMIT_STATES; 245bf215546Sopenharmony_ci boolean emit_vertex_arrays = flags & PREP_EMIT_VARRAYS; 246bf215546Sopenharmony_ci boolean emit_vertex_arrays_swtcl = flags & PREP_EMIT_VARRAYS_SWTCL; 247bf215546Sopenharmony_ci boolean indexed = flags & PREP_INDEXED; 248bf215546Sopenharmony_ci boolean validate_vbos = flags & PREP_VALIDATE_VBOS; 249bf215546Sopenharmony_ci 250bf215546Sopenharmony_ci /* Validate buffers and emit dirty state if needed. */ 251bf215546Sopenharmony_ci if (emit_states || (emit_vertex_arrays && validate_vbos)) { 252bf215546Sopenharmony_ci if (!r300_emit_buffer_validate(r300, validate_vbos, 253bf215546Sopenharmony_ci index_buffer)) { 254bf215546Sopenharmony_ci fprintf(stderr, "r300: CS space validation failed. " 255bf215546Sopenharmony_ci "(not enough memory?) Skipping rendering.\n"); 256bf215546Sopenharmony_ci return FALSE; 257bf215546Sopenharmony_ci } 258bf215546Sopenharmony_ci } 259bf215546Sopenharmony_ci 260bf215546Sopenharmony_ci if (emit_states) 261bf215546Sopenharmony_ci r300_emit_dirty_state(r300); 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_ci if (r300->screen->caps.is_r500) { 264bf215546Sopenharmony_ci if (r300->screen->caps.has_tcl) 265bf215546Sopenharmony_ci r500_emit_index_bias(r300, index_bias); 266bf215546Sopenharmony_ci else 267bf215546Sopenharmony_ci r500_emit_index_bias(r300, 0); 268bf215546Sopenharmony_ci } 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_ci if (emit_vertex_arrays && 271bf215546Sopenharmony_ci (r300->vertex_arrays_dirty || 272bf215546Sopenharmony_ci r300->vertex_arrays_indexed != indexed || 273bf215546Sopenharmony_ci r300->vertex_arrays_offset != buffer_offset || 274bf215546Sopenharmony_ci r300->vertex_arrays_instance_id != instance_id)) { 275bf215546Sopenharmony_ci r300_emit_vertex_arrays(r300, buffer_offset, indexed, instance_id); 276bf215546Sopenharmony_ci 277bf215546Sopenharmony_ci r300->vertex_arrays_dirty = FALSE; 278bf215546Sopenharmony_ci r300->vertex_arrays_indexed = indexed; 279bf215546Sopenharmony_ci r300->vertex_arrays_offset = buffer_offset; 280bf215546Sopenharmony_ci r300->vertex_arrays_instance_id = instance_id; 281bf215546Sopenharmony_ci } 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_ci if (emit_vertex_arrays_swtcl) 284bf215546Sopenharmony_ci r300_emit_vertex_arrays_swtcl(r300, indexed); 285bf215546Sopenharmony_ci 286bf215546Sopenharmony_ci return TRUE; 287bf215546Sopenharmony_ci} 288bf215546Sopenharmony_ci 289bf215546Sopenharmony_ci/** 290bf215546Sopenharmony_ci * Check if the requested number of dwords is available in the CS and 291bf215546Sopenharmony_ci * if not, flush. Then validate buffers and emit dirty state. 292bf215546Sopenharmony_ci * \param r300 The context. 293bf215546Sopenharmony_ci * \param flags See r300_prepare_flags. 294bf215546Sopenharmony_ci * \param index_buffer The index buffer to validate. The parameter may be NULL. 295bf215546Sopenharmony_ci * \param cs_dwords The number of dwords to reserve in CS. 296bf215546Sopenharmony_ci * \param buffer_offset The offset passed to emit_vertex_arrays. 297bf215546Sopenharmony_ci * \param index_bias The index bias to emit. 298bf215546Sopenharmony_ci * \param instance_id The instance to render. 299bf215546Sopenharmony_ci * \return TRUE if rendering should be skipped 300bf215546Sopenharmony_ci */ 301bf215546Sopenharmony_cistatic boolean r300_prepare_for_rendering(struct r300_context *r300, 302bf215546Sopenharmony_ci enum r300_prepare_flags flags, 303bf215546Sopenharmony_ci struct pipe_resource *index_buffer, 304bf215546Sopenharmony_ci unsigned cs_dwords, 305bf215546Sopenharmony_ci int buffer_offset, 306bf215546Sopenharmony_ci int index_bias, 307bf215546Sopenharmony_ci int instance_id) 308bf215546Sopenharmony_ci{ 309bf215546Sopenharmony_ci /* Make sure there is enough space in the command stream and emit states. */ 310bf215546Sopenharmony_ci if (r300_reserve_cs_dwords(r300, flags, cs_dwords)) 311bf215546Sopenharmony_ci flags |= PREP_EMIT_STATES; 312bf215546Sopenharmony_ci 313bf215546Sopenharmony_ci return r300_emit_states(r300, flags, index_buffer, buffer_offset, 314bf215546Sopenharmony_ci index_bias, instance_id); 315bf215546Sopenharmony_ci} 316bf215546Sopenharmony_ci 317bf215546Sopenharmony_cistatic boolean immd_is_good_idea(struct r300_context *r300, 318bf215546Sopenharmony_ci unsigned count) 319bf215546Sopenharmony_ci{ 320bf215546Sopenharmony_ci if (DBG_ON(r300, DBG_NO_IMMD)) { 321bf215546Sopenharmony_ci return FALSE; 322bf215546Sopenharmony_ci } 323bf215546Sopenharmony_ci 324bf215546Sopenharmony_ci if (count * r300->velems->vertex_size_dwords > IMMD_DWORDS) { 325bf215546Sopenharmony_ci return FALSE; 326bf215546Sopenharmony_ci } 327bf215546Sopenharmony_ci 328bf215546Sopenharmony_ci /* Buffers can only be used for read by r300 (except query buffers, but 329bf215546Sopenharmony_ci * those can't be bound by an gallium frontend as vertex buffers). */ 330bf215546Sopenharmony_ci return TRUE; 331bf215546Sopenharmony_ci} 332bf215546Sopenharmony_ci 333bf215546Sopenharmony_ci/***************************************************************************** 334bf215546Sopenharmony_ci * The HWTCL draw functions. * 335bf215546Sopenharmony_ci ****************************************************************************/ 336bf215546Sopenharmony_ci 337bf215546Sopenharmony_cistatic void r300_draw_arrays_immediate(struct r300_context *r300, 338bf215546Sopenharmony_ci const struct pipe_draw_info *info, 339bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draw) 340bf215546Sopenharmony_ci{ 341bf215546Sopenharmony_ci struct pipe_vertex_element* velem; 342bf215546Sopenharmony_ci struct pipe_vertex_buffer* vbuf; 343bf215546Sopenharmony_ci unsigned vertex_element_count = r300->velems->count; 344bf215546Sopenharmony_ci unsigned i, v, vbi; 345bf215546Sopenharmony_ci 346bf215546Sopenharmony_ci /* Size of the vertex, in dwords. */ 347bf215546Sopenharmony_ci unsigned vertex_size = r300->velems->vertex_size_dwords; 348bf215546Sopenharmony_ci 349bf215546Sopenharmony_ci /* The number of dwords for this draw operation. */ 350bf215546Sopenharmony_ci unsigned dwords = 4 + draw->count * vertex_size; 351bf215546Sopenharmony_ci 352bf215546Sopenharmony_ci /* Size of the vertex element, in dwords. */ 353bf215546Sopenharmony_ci unsigned size[PIPE_MAX_ATTRIBS]; 354bf215546Sopenharmony_ci 355bf215546Sopenharmony_ci /* Stride to the same attrib in the next vertex in the vertex buffer, 356bf215546Sopenharmony_ci * in dwords. */ 357bf215546Sopenharmony_ci unsigned stride[PIPE_MAX_ATTRIBS]; 358bf215546Sopenharmony_ci 359bf215546Sopenharmony_ci /* Mapped vertex buffers. */ 360bf215546Sopenharmony_ci uint32_t* map[PIPE_MAX_ATTRIBS] = {0}; 361bf215546Sopenharmony_ci uint32_t* mapelem[PIPE_MAX_ATTRIBS]; 362bf215546Sopenharmony_ci 363bf215546Sopenharmony_ci CS_LOCALS(r300); 364bf215546Sopenharmony_ci 365bf215546Sopenharmony_ci if (!r300_prepare_for_rendering(r300, PREP_EMIT_STATES, NULL, dwords, 0, 0, -1)) 366bf215546Sopenharmony_ci return; 367bf215546Sopenharmony_ci 368bf215546Sopenharmony_ci /* Calculate the vertex size, offsets, strides etc. and map the buffers. */ 369bf215546Sopenharmony_ci for (i = 0; i < vertex_element_count; i++) { 370bf215546Sopenharmony_ci velem = &r300->velems->velem[i]; 371bf215546Sopenharmony_ci size[i] = r300->velems->format_size[i] / 4; 372bf215546Sopenharmony_ci vbi = velem->vertex_buffer_index; 373bf215546Sopenharmony_ci vbuf = &r300->vertex_buffer[vbi]; 374bf215546Sopenharmony_ci stride[i] = vbuf->stride / 4; 375bf215546Sopenharmony_ci 376bf215546Sopenharmony_ci /* Map the buffer. */ 377bf215546Sopenharmony_ci if (!map[vbi]) { 378bf215546Sopenharmony_ci map[vbi] = (uint32_t*)r300->rws->buffer_map(r300->rws, 379bf215546Sopenharmony_ci r300_resource(vbuf->buffer.resource)->buf, 380bf215546Sopenharmony_ci &r300->cs, PIPE_MAP_READ | PIPE_MAP_UNSYNCHRONIZED); 381bf215546Sopenharmony_ci map[vbi] += (vbuf->buffer_offset / 4) + stride[i] * draw->start; 382bf215546Sopenharmony_ci } 383bf215546Sopenharmony_ci mapelem[i] = map[vbi] + (velem->src_offset / 4); 384bf215546Sopenharmony_ci } 385bf215546Sopenharmony_ci 386bf215546Sopenharmony_ci r300_emit_draw_init(r300, info->mode, draw->count-1); 387bf215546Sopenharmony_ci 388bf215546Sopenharmony_ci BEGIN_CS(dwords); 389bf215546Sopenharmony_ci OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size); 390bf215546Sopenharmony_ci OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, draw->count * vertex_size); 391bf215546Sopenharmony_ci OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (draw->count << 16) | 392bf215546Sopenharmony_ci r300_translate_primitive(info->mode)); 393bf215546Sopenharmony_ci 394bf215546Sopenharmony_ci /* Emit vertices. */ 395bf215546Sopenharmony_ci for (v = 0; v < draw->count; v++) { 396bf215546Sopenharmony_ci for (i = 0; i < vertex_element_count; i++) { 397bf215546Sopenharmony_ci OUT_CS_TABLE(&mapelem[i][stride[i] * v], size[i]); 398bf215546Sopenharmony_ci } 399bf215546Sopenharmony_ci } 400bf215546Sopenharmony_ci END_CS; 401bf215546Sopenharmony_ci} 402bf215546Sopenharmony_ci 403bf215546Sopenharmony_cistatic void r300_emit_draw_arrays(struct r300_context *r300, 404bf215546Sopenharmony_ci unsigned mode, 405bf215546Sopenharmony_ci unsigned count) 406bf215546Sopenharmony_ci{ 407bf215546Sopenharmony_ci boolean alt_num_verts = count > 65535; 408bf215546Sopenharmony_ci CS_LOCALS(r300); 409bf215546Sopenharmony_ci 410bf215546Sopenharmony_ci if (count >= (1 << 24)) { 411bf215546Sopenharmony_ci fprintf(stderr, "r300: Got a huge number of vertices: %i, " 412bf215546Sopenharmony_ci "refusing to render.\n", count); 413bf215546Sopenharmony_ci return; 414bf215546Sopenharmony_ci } 415bf215546Sopenharmony_ci 416bf215546Sopenharmony_ci r300_emit_draw_init(r300, mode, count-1); 417bf215546Sopenharmony_ci 418bf215546Sopenharmony_ci BEGIN_CS(2 + (alt_num_verts ? 2 : 0)); 419bf215546Sopenharmony_ci if (alt_num_verts) { 420bf215546Sopenharmony_ci OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count); 421bf215546Sopenharmony_ci } 422bf215546Sopenharmony_ci OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0); 423bf215546Sopenharmony_ci OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) | 424bf215546Sopenharmony_ci r300_translate_primitive(mode) | 425bf215546Sopenharmony_ci (alt_num_verts ? R500_VAP_VF_CNTL__USE_ALT_NUM_VERTS : 0)); 426bf215546Sopenharmony_ci END_CS; 427bf215546Sopenharmony_ci} 428bf215546Sopenharmony_ci 429bf215546Sopenharmony_cistatic void r300_emit_draw_elements(struct r300_context *r300, 430bf215546Sopenharmony_ci struct pipe_resource* indexBuffer, 431bf215546Sopenharmony_ci unsigned indexSize, 432bf215546Sopenharmony_ci unsigned max_index, 433bf215546Sopenharmony_ci unsigned mode, 434bf215546Sopenharmony_ci unsigned start, 435bf215546Sopenharmony_ci unsigned count, 436bf215546Sopenharmony_ci uint16_t *imm_indices3) 437bf215546Sopenharmony_ci{ 438bf215546Sopenharmony_ci uint32_t count_dwords, offset_dwords; 439bf215546Sopenharmony_ci boolean alt_num_verts = count > 65535; 440bf215546Sopenharmony_ci CS_LOCALS(r300); 441bf215546Sopenharmony_ci 442bf215546Sopenharmony_ci if (count >= (1 << 24)) { 443bf215546Sopenharmony_ci fprintf(stderr, "r300: Got a huge number of vertices: %i, " 444bf215546Sopenharmony_ci "refusing to render (max_index: %i).\n", count, max_index); 445bf215546Sopenharmony_ci return; 446bf215546Sopenharmony_ci } 447bf215546Sopenharmony_ci 448bf215546Sopenharmony_ci DBG(r300, DBG_DRAW, "r300: Indexbuf of %u indices, max %u\n", 449bf215546Sopenharmony_ci count, max_index); 450bf215546Sopenharmony_ci 451bf215546Sopenharmony_ci r300_emit_draw_init(r300, mode, max_index); 452bf215546Sopenharmony_ci 453bf215546Sopenharmony_ci /* If start is odd, render the first triangle with indices embedded 454bf215546Sopenharmony_ci * in the command stream. This will increase start by 3 and make it 455bf215546Sopenharmony_ci * even. We can then proceed without a fallback. */ 456bf215546Sopenharmony_ci if (indexSize == 2 && (start & 1) && 457bf215546Sopenharmony_ci mode == PIPE_PRIM_TRIANGLES) { 458bf215546Sopenharmony_ci BEGIN_CS(4); 459bf215546Sopenharmony_ci OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, 2); 460bf215546Sopenharmony_ci OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (3 << 16) | 461bf215546Sopenharmony_ci R300_VAP_VF_CNTL__PRIM_TRIANGLES); 462bf215546Sopenharmony_ci OUT_CS(imm_indices3[1] << 16 | imm_indices3[0]); 463bf215546Sopenharmony_ci OUT_CS(imm_indices3[2]); 464bf215546Sopenharmony_ci END_CS; 465bf215546Sopenharmony_ci 466bf215546Sopenharmony_ci start += 3; 467bf215546Sopenharmony_ci count -= 3; 468bf215546Sopenharmony_ci if (!count) 469bf215546Sopenharmony_ci return; 470bf215546Sopenharmony_ci } 471bf215546Sopenharmony_ci 472bf215546Sopenharmony_ci offset_dwords = indexSize * start / sizeof(uint32_t); 473bf215546Sopenharmony_ci 474bf215546Sopenharmony_ci BEGIN_CS(8 + (alt_num_verts ? 2 : 0)); 475bf215546Sopenharmony_ci if (alt_num_verts) { 476bf215546Sopenharmony_ci OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count); 477bf215546Sopenharmony_ci } 478bf215546Sopenharmony_ci OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, 0); 479bf215546Sopenharmony_ci if (indexSize == 4) { 480bf215546Sopenharmony_ci count_dwords = count; 481bf215546Sopenharmony_ci OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | 482bf215546Sopenharmony_ci R300_VAP_VF_CNTL__INDEX_SIZE_32bit | 483bf215546Sopenharmony_ci r300_translate_primitive(mode) | 484bf215546Sopenharmony_ci (alt_num_verts ? R500_VAP_VF_CNTL__USE_ALT_NUM_VERTS : 0)); 485bf215546Sopenharmony_ci } else { 486bf215546Sopenharmony_ci count_dwords = (count + 1) / 2; 487bf215546Sopenharmony_ci OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | 488bf215546Sopenharmony_ci r300_translate_primitive(mode) | 489bf215546Sopenharmony_ci (alt_num_verts ? R500_VAP_VF_CNTL__USE_ALT_NUM_VERTS : 0)); 490bf215546Sopenharmony_ci } 491bf215546Sopenharmony_ci 492bf215546Sopenharmony_ci OUT_CS_PKT3(R300_PACKET3_INDX_BUFFER, 2); 493bf215546Sopenharmony_ci OUT_CS(R300_INDX_BUFFER_ONE_REG_WR | (R300_VAP_PORT_IDX0 >> 2) | 494bf215546Sopenharmony_ci (0 << R300_INDX_BUFFER_SKIP_SHIFT)); 495bf215546Sopenharmony_ci OUT_CS(offset_dwords << 2); 496bf215546Sopenharmony_ci OUT_CS(count_dwords); 497bf215546Sopenharmony_ci OUT_CS_RELOC(r300_resource(indexBuffer)); 498bf215546Sopenharmony_ci END_CS; 499bf215546Sopenharmony_ci} 500bf215546Sopenharmony_ci 501bf215546Sopenharmony_cistatic void r300_draw_elements_immediate(struct r300_context *r300, 502bf215546Sopenharmony_ci const struct pipe_draw_info *info, 503bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draw) 504bf215546Sopenharmony_ci{ 505bf215546Sopenharmony_ci const uint8_t *ptr1; 506bf215546Sopenharmony_ci const uint16_t *ptr2; 507bf215546Sopenharmony_ci const uint32_t *ptr4; 508bf215546Sopenharmony_ci unsigned index_size = info->index_size; 509bf215546Sopenharmony_ci unsigned i, count_dwords = index_size == 4 ? draw->count : 510bf215546Sopenharmony_ci (draw->count + 1) / 2; 511bf215546Sopenharmony_ci CS_LOCALS(r300); 512bf215546Sopenharmony_ci 513bf215546Sopenharmony_ci /* 19 dwords for r300_draw_elements_immediate. Give up if the function fails. */ 514bf215546Sopenharmony_ci if (!r300_prepare_for_rendering(r300, 515bf215546Sopenharmony_ci PREP_EMIT_STATES | PREP_VALIDATE_VBOS | PREP_EMIT_VARRAYS | 516bf215546Sopenharmony_ci PREP_INDEXED, NULL, 2+count_dwords, 0, draw->index_bias, -1)) 517bf215546Sopenharmony_ci return; 518bf215546Sopenharmony_ci 519bf215546Sopenharmony_ci r300_emit_draw_init(r300, info->mode, info->max_index); 520bf215546Sopenharmony_ci 521bf215546Sopenharmony_ci BEGIN_CS(2 + count_dwords); 522bf215546Sopenharmony_ci OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, count_dwords); 523bf215546Sopenharmony_ci 524bf215546Sopenharmony_ci switch (index_size) { 525bf215546Sopenharmony_ci case 1: 526bf215546Sopenharmony_ci ptr1 = (uint8_t*)info->index.user; 527bf215546Sopenharmony_ci ptr1 += draw->start; 528bf215546Sopenharmony_ci 529bf215546Sopenharmony_ci OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (draw->count << 16) | 530bf215546Sopenharmony_ci r300_translate_primitive(info->mode)); 531bf215546Sopenharmony_ci 532bf215546Sopenharmony_ci if (draw->index_bias && !r300->screen->caps.is_r500) { 533bf215546Sopenharmony_ci for (i = 0; i < draw->count-1; i += 2) 534bf215546Sopenharmony_ci OUT_CS(((ptr1[i+1] + draw->index_bias) << 16) | 535bf215546Sopenharmony_ci (ptr1[i] + draw->index_bias)); 536bf215546Sopenharmony_ci 537bf215546Sopenharmony_ci if (draw->count & 1) 538bf215546Sopenharmony_ci OUT_CS(ptr1[i] + draw->index_bias); 539bf215546Sopenharmony_ci } else { 540bf215546Sopenharmony_ci for (i = 0; i < draw->count-1; i += 2) 541bf215546Sopenharmony_ci OUT_CS(((ptr1[i+1]) << 16) | 542bf215546Sopenharmony_ci (ptr1[i] )); 543bf215546Sopenharmony_ci 544bf215546Sopenharmony_ci if (draw->count & 1) 545bf215546Sopenharmony_ci OUT_CS(ptr1[i]); 546bf215546Sopenharmony_ci } 547bf215546Sopenharmony_ci break; 548bf215546Sopenharmony_ci 549bf215546Sopenharmony_ci case 2: 550bf215546Sopenharmony_ci ptr2 = (uint16_t*)info->index.user; 551bf215546Sopenharmony_ci ptr2 += draw->start; 552bf215546Sopenharmony_ci 553bf215546Sopenharmony_ci OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (draw->count << 16) | 554bf215546Sopenharmony_ci r300_translate_primitive(info->mode)); 555bf215546Sopenharmony_ci 556bf215546Sopenharmony_ci if (draw->index_bias && !r300->screen->caps.is_r500) { 557bf215546Sopenharmony_ci for (i = 0; i < draw->count-1; i += 2) 558bf215546Sopenharmony_ci OUT_CS(((ptr2[i+1] + draw->index_bias) << 16) | 559bf215546Sopenharmony_ci (ptr2[i] + draw->index_bias)); 560bf215546Sopenharmony_ci 561bf215546Sopenharmony_ci if (draw->count & 1) 562bf215546Sopenharmony_ci OUT_CS(ptr2[i] + draw->index_bias); 563bf215546Sopenharmony_ci } else { 564bf215546Sopenharmony_ci OUT_CS_TABLE(ptr2, count_dwords); 565bf215546Sopenharmony_ci } 566bf215546Sopenharmony_ci break; 567bf215546Sopenharmony_ci 568bf215546Sopenharmony_ci case 4: 569bf215546Sopenharmony_ci ptr4 = (uint32_t*)info->index.user; 570bf215546Sopenharmony_ci ptr4 += draw->start; 571bf215546Sopenharmony_ci 572bf215546Sopenharmony_ci OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (draw->count << 16) | 573bf215546Sopenharmony_ci R300_VAP_VF_CNTL__INDEX_SIZE_32bit | 574bf215546Sopenharmony_ci r300_translate_primitive(info->mode)); 575bf215546Sopenharmony_ci 576bf215546Sopenharmony_ci if (draw->index_bias && !r300->screen->caps.is_r500) { 577bf215546Sopenharmony_ci for (i = 0; i < draw->count; i++) 578bf215546Sopenharmony_ci OUT_CS(ptr4[i] + draw->index_bias); 579bf215546Sopenharmony_ci } else { 580bf215546Sopenharmony_ci OUT_CS_TABLE(ptr4, count_dwords); 581bf215546Sopenharmony_ci } 582bf215546Sopenharmony_ci break; 583bf215546Sopenharmony_ci } 584bf215546Sopenharmony_ci END_CS; 585bf215546Sopenharmony_ci} 586bf215546Sopenharmony_ci 587bf215546Sopenharmony_cistatic void r300_draw_elements(struct r300_context *r300, 588bf215546Sopenharmony_ci const struct pipe_draw_info *info, 589bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draw, 590bf215546Sopenharmony_ci int instance_id) 591bf215546Sopenharmony_ci{ 592bf215546Sopenharmony_ci struct pipe_resource *indexBuffer = 593bf215546Sopenharmony_ci info->has_user_indices ? NULL : info->index.resource; 594bf215546Sopenharmony_ci unsigned indexSize = info->index_size; 595bf215546Sopenharmony_ci struct pipe_resource* orgIndexBuffer = indexBuffer; 596bf215546Sopenharmony_ci unsigned start = draw->start; 597bf215546Sopenharmony_ci unsigned count = draw->count; 598bf215546Sopenharmony_ci boolean alt_num_verts = r300->screen->caps.is_r500 && 599bf215546Sopenharmony_ci count > 65536; 600bf215546Sopenharmony_ci unsigned short_count; 601bf215546Sopenharmony_ci int buffer_offset = 0, index_offset = 0; /* for index bias emulation */ 602bf215546Sopenharmony_ci uint16_t indices3[3]; 603bf215546Sopenharmony_ci 604bf215546Sopenharmony_ci if (draw->index_bias && !r300->screen->caps.is_r500) { 605bf215546Sopenharmony_ci r300_split_index_bias(r300, draw->index_bias, &buffer_offset, 606bf215546Sopenharmony_ci &index_offset); 607bf215546Sopenharmony_ci } 608bf215546Sopenharmony_ci 609bf215546Sopenharmony_ci r300_translate_index_buffer(r300, info, &indexBuffer, 610bf215546Sopenharmony_ci &indexSize, index_offset, &start, count); 611bf215546Sopenharmony_ci 612bf215546Sopenharmony_ci /* Fallback for misaligned ushort indices. */ 613bf215546Sopenharmony_ci if (indexSize == 2 && (start & 1) && indexBuffer) { 614bf215546Sopenharmony_ci /* If we got here, then orgIndexBuffer == indexBuffer. */ 615bf215546Sopenharmony_ci uint16_t *ptr = r300->rws->buffer_map(r300->rws, r300_resource(orgIndexBuffer)->buf, 616bf215546Sopenharmony_ci &r300->cs, 617bf215546Sopenharmony_ci PIPE_MAP_READ | 618bf215546Sopenharmony_ci PIPE_MAP_UNSYNCHRONIZED); 619bf215546Sopenharmony_ci 620bf215546Sopenharmony_ci if (info->mode == PIPE_PRIM_TRIANGLES) { 621bf215546Sopenharmony_ci memcpy(indices3, ptr + start, 6); 622bf215546Sopenharmony_ci } else { 623bf215546Sopenharmony_ci /* Copy the mapped index buffer directly to the upload buffer. 624bf215546Sopenharmony_ci * The start index will be aligned simply from the fact that 625bf215546Sopenharmony_ci * every sub-buffer in the upload buffer is aligned. */ 626bf215546Sopenharmony_ci r300_upload_index_buffer(r300, &indexBuffer, indexSize, &start, 627bf215546Sopenharmony_ci count, (uint8_t*)ptr); 628bf215546Sopenharmony_ci } 629bf215546Sopenharmony_ci } else { 630bf215546Sopenharmony_ci if (info->has_user_indices) 631bf215546Sopenharmony_ci r300_upload_index_buffer(r300, &indexBuffer, indexSize, 632bf215546Sopenharmony_ci &start, count, 633bf215546Sopenharmony_ci info->index.user); 634bf215546Sopenharmony_ci } 635bf215546Sopenharmony_ci 636bf215546Sopenharmony_ci /* 19 dwords for emit_draw_elements. Give up if the function fails. */ 637bf215546Sopenharmony_ci if (!r300_prepare_for_rendering(r300, 638bf215546Sopenharmony_ci PREP_EMIT_STATES | PREP_VALIDATE_VBOS | PREP_EMIT_VARRAYS | 639bf215546Sopenharmony_ci PREP_INDEXED, indexBuffer, 19, buffer_offset, draw->index_bias, 640bf215546Sopenharmony_ci instance_id)) 641bf215546Sopenharmony_ci goto done; 642bf215546Sopenharmony_ci 643bf215546Sopenharmony_ci if (alt_num_verts || count <= 65535) { 644bf215546Sopenharmony_ci r300_emit_draw_elements(r300, indexBuffer, indexSize, 645bf215546Sopenharmony_ci info->max_index, info->mode, start, count, 646bf215546Sopenharmony_ci indices3); 647bf215546Sopenharmony_ci } else { 648bf215546Sopenharmony_ci do { 649bf215546Sopenharmony_ci /* The maximum must be divisible by 4 and 3, 650bf215546Sopenharmony_ci * so that quad and triangle lists are split correctly. 651bf215546Sopenharmony_ci * 652bf215546Sopenharmony_ci * Strips, loops, and fans won't work. */ 653bf215546Sopenharmony_ci short_count = MIN2(count, 65532); 654bf215546Sopenharmony_ci 655bf215546Sopenharmony_ci r300_emit_draw_elements(r300, indexBuffer, indexSize, 656bf215546Sopenharmony_ci info->max_index, 657bf215546Sopenharmony_ci info->mode, start, short_count, indices3); 658bf215546Sopenharmony_ci 659bf215546Sopenharmony_ci start += short_count; 660bf215546Sopenharmony_ci count -= short_count; 661bf215546Sopenharmony_ci 662bf215546Sopenharmony_ci /* 15 dwords for emit_draw_elements */ 663bf215546Sopenharmony_ci if (count) { 664bf215546Sopenharmony_ci if (!r300_prepare_for_rendering(r300, 665bf215546Sopenharmony_ci PREP_VALIDATE_VBOS | PREP_EMIT_VARRAYS | PREP_INDEXED, 666bf215546Sopenharmony_ci indexBuffer, 19, buffer_offset, draw->index_bias, 667bf215546Sopenharmony_ci instance_id)) 668bf215546Sopenharmony_ci goto done; 669bf215546Sopenharmony_ci } 670bf215546Sopenharmony_ci } while (count); 671bf215546Sopenharmony_ci } 672bf215546Sopenharmony_ci 673bf215546Sopenharmony_cidone: 674bf215546Sopenharmony_ci if (indexBuffer != orgIndexBuffer) { 675bf215546Sopenharmony_ci pipe_resource_reference( &indexBuffer, NULL ); 676bf215546Sopenharmony_ci } 677bf215546Sopenharmony_ci} 678bf215546Sopenharmony_ci 679bf215546Sopenharmony_cistatic void r300_draw_arrays(struct r300_context *r300, 680bf215546Sopenharmony_ci const struct pipe_draw_info *info, 681bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draw, 682bf215546Sopenharmony_ci int instance_id) 683bf215546Sopenharmony_ci{ 684bf215546Sopenharmony_ci boolean alt_num_verts = r300->screen->caps.is_r500 && 685bf215546Sopenharmony_ci draw->count > 65536; 686bf215546Sopenharmony_ci unsigned start = draw->start; 687bf215546Sopenharmony_ci unsigned count = draw->count; 688bf215546Sopenharmony_ci unsigned short_count; 689bf215546Sopenharmony_ci 690bf215546Sopenharmony_ci /* 9 spare dwords for emit_draw_arrays. Give up if the function fails. */ 691bf215546Sopenharmony_ci if (!r300_prepare_for_rendering(r300, 692bf215546Sopenharmony_ci PREP_EMIT_STATES | PREP_VALIDATE_VBOS | PREP_EMIT_VARRAYS, 693bf215546Sopenharmony_ci NULL, 9, start, 0, instance_id)) 694bf215546Sopenharmony_ci return; 695bf215546Sopenharmony_ci 696bf215546Sopenharmony_ci if (alt_num_verts || count <= 65535) { 697bf215546Sopenharmony_ci r300_emit_draw_arrays(r300, info->mode, count); 698bf215546Sopenharmony_ci } else { 699bf215546Sopenharmony_ci do { 700bf215546Sopenharmony_ci /* The maximum must be divisible by 4 and 3, 701bf215546Sopenharmony_ci * so that quad and triangle lists are split correctly. 702bf215546Sopenharmony_ci * 703bf215546Sopenharmony_ci * Strips, loops, and fans won't work. */ 704bf215546Sopenharmony_ci short_count = MIN2(count, 65532); 705bf215546Sopenharmony_ci r300_emit_draw_arrays(r300, info->mode, short_count); 706bf215546Sopenharmony_ci 707bf215546Sopenharmony_ci start += short_count; 708bf215546Sopenharmony_ci count -= short_count; 709bf215546Sopenharmony_ci 710bf215546Sopenharmony_ci /* 9 spare dwords for emit_draw_arrays. Give up if the function fails. */ 711bf215546Sopenharmony_ci if (count) { 712bf215546Sopenharmony_ci if (!r300_prepare_for_rendering(r300, 713bf215546Sopenharmony_ci PREP_VALIDATE_VBOS | PREP_EMIT_VARRAYS, NULL, 9, 714bf215546Sopenharmony_ci start, 0, instance_id)) 715bf215546Sopenharmony_ci return; 716bf215546Sopenharmony_ci } 717bf215546Sopenharmony_ci } while (count); 718bf215546Sopenharmony_ci } 719bf215546Sopenharmony_ci} 720bf215546Sopenharmony_ci 721bf215546Sopenharmony_cistatic void r300_draw_arrays_instanced(struct r300_context *r300, 722bf215546Sopenharmony_ci const struct pipe_draw_info *info, 723bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draw) 724bf215546Sopenharmony_ci{ 725bf215546Sopenharmony_ci int i; 726bf215546Sopenharmony_ci 727bf215546Sopenharmony_ci for (i = 0; i < info->instance_count; i++) 728bf215546Sopenharmony_ci r300_draw_arrays(r300, info, draw, i); 729bf215546Sopenharmony_ci} 730bf215546Sopenharmony_ci 731bf215546Sopenharmony_cistatic void r300_draw_elements_instanced(struct r300_context *r300, 732bf215546Sopenharmony_ci const struct pipe_draw_info *info, 733bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draw) 734bf215546Sopenharmony_ci{ 735bf215546Sopenharmony_ci int i; 736bf215546Sopenharmony_ci 737bf215546Sopenharmony_ci for (i = 0; i < info->instance_count; i++) 738bf215546Sopenharmony_ci r300_draw_elements(r300, info, draw, i); 739bf215546Sopenharmony_ci} 740bf215546Sopenharmony_ci 741bf215546Sopenharmony_cistatic unsigned r300_max_vertex_count(struct r300_context *r300) 742bf215546Sopenharmony_ci{ 743bf215546Sopenharmony_ci unsigned i, nr = r300->velems->count; 744bf215546Sopenharmony_ci struct pipe_vertex_element *velems = r300->velems->velem; 745bf215546Sopenharmony_ci unsigned result = ~0; 746bf215546Sopenharmony_ci 747bf215546Sopenharmony_ci for (i = 0; i < nr; i++) { 748bf215546Sopenharmony_ci struct pipe_vertex_buffer *vb = 749bf215546Sopenharmony_ci &r300->vertex_buffer[velems[i].vertex_buffer_index]; 750bf215546Sopenharmony_ci unsigned size, max_count, value; 751bf215546Sopenharmony_ci 752bf215546Sopenharmony_ci /* We're not interested in constant and per-instance attribs. */ 753bf215546Sopenharmony_ci if (!vb->buffer.resource || 754bf215546Sopenharmony_ci !vb->stride || 755bf215546Sopenharmony_ci velems[i].instance_divisor) { 756bf215546Sopenharmony_ci continue; 757bf215546Sopenharmony_ci } 758bf215546Sopenharmony_ci 759bf215546Sopenharmony_ci size = vb->buffer.resource->width0; 760bf215546Sopenharmony_ci 761bf215546Sopenharmony_ci /* Subtract buffer_offset. */ 762bf215546Sopenharmony_ci value = vb->buffer_offset; 763bf215546Sopenharmony_ci if (value >= size) { 764bf215546Sopenharmony_ci return 0; 765bf215546Sopenharmony_ci } 766bf215546Sopenharmony_ci size -= value; 767bf215546Sopenharmony_ci 768bf215546Sopenharmony_ci /* Subtract src_offset. */ 769bf215546Sopenharmony_ci value = velems[i].src_offset; 770bf215546Sopenharmony_ci if (value >= size) { 771bf215546Sopenharmony_ci return 0; 772bf215546Sopenharmony_ci } 773bf215546Sopenharmony_ci size -= value; 774bf215546Sopenharmony_ci 775bf215546Sopenharmony_ci /* Subtract format_size. */ 776bf215546Sopenharmony_ci value = r300->velems->format_size[i]; 777bf215546Sopenharmony_ci if (value >= size) { 778bf215546Sopenharmony_ci return 0; 779bf215546Sopenharmony_ci } 780bf215546Sopenharmony_ci size -= value; 781bf215546Sopenharmony_ci 782bf215546Sopenharmony_ci /* Compute the max count. */ 783bf215546Sopenharmony_ci max_count = 1 + size / vb->stride; 784bf215546Sopenharmony_ci result = MIN2(result, max_count); 785bf215546Sopenharmony_ci } 786bf215546Sopenharmony_ci return result; 787bf215546Sopenharmony_ci} 788bf215546Sopenharmony_ci 789bf215546Sopenharmony_ci 790bf215546Sopenharmony_cistatic void r300_draw_vbo(struct pipe_context* pipe, 791bf215546Sopenharmony_ci const struct pipe_draw_info *dinfo, 792bf215546Sopenharmony_ci unsigned drawid_offset, 793bf215546Sopenharmony_ci const struct pipe_draw_indirect_info *indirect, 794bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draws, 795bf215546Sopenharmony_ci unsigned num_draws) 796bf215546Sopenharmony_ci{ 797bf215546Sopenharmony_ci if (num_draws > 1) { 798bf215546Sopenharmony_ci util_draw_multi(pipe, dinfo, drawid_offset, indirect, draws, num_draws); 799bf215546Sopenharmony_ci return; 800bf215546Sopenharmony_ci } 801bf215546Sopenharmony_ci 802bf215546Sopenharmony_ci struct r300_context* r300 = r300_context(pipe); 803bf215546Sopenharmony_ci struct pipe_draw_info info = *dinfo; 804bf215546Sopenharmony_ci struct pipe_draw_start_count_bias draw = draws[0]; 805bf215546Sopenharmony_ci 806bf215546Sopenharmony_ci if (r300->skip_rendering || 807bf215546Sopenharmony_ci !u_trim_pipe_prim(info.mode, &draw.count)) { 808bf215546Sopenharmony_ci return; 809bf215546Sopenharmony_ci } 810bf215546Sopenharmony_ci 811bf215546Sopenharmony_ci if (r300->sprite_coord_enable != 0) 812bf215546Sopenharmony_ci if ((info.mode == PIPE_PRIM_POINTS) != r300->is_point) { 813bf215546Sopenharmony_ci r300->is_point = !r300->is_point; 814bf215546Sopenharmony_ci r300_mark_atom_dirty(r300, &r300->rs_block_state); 815bf215546Sopenharmony_ci } 816bf215546Sopenharmony_ci 817bf215546Sopenharmony_ci r300_update_derived_state(r300); 818bf215546Sopenharmony_ci 819bf215546Sopenharmony_ci /* Skip draw if we failed to compile the vertex shader. */ 820bf215546Sopenharmony_ci if (r300_vs(r300)->shader->dummy) 821bf215546Sopenharmony_ci return; 822bf215546Sopenharmony_ci 823bf215546Sopenharmony_ci /* Draw. */ 824bf215546Sopenharmony_ci if (info.index_size) { 825bf215546Sopenharmony_ci unsigned max_count = r300_max_vertex_count(r300); 826bf215546Sopenharmony_ci 827bf215546Sopenharmony_ci if (!max_count) { 828bf215546Sopenharmony_ci fprintf(stderr, "r300: Skipping a draw command. There is a buffer " 829bf215546Sopenharmony_ci " which is too small to be used for rendering.\n"); 830bf215546Sopenharmony_ci return; 831bf215546Sopenharmony_ci } 832bf215546Sopenharmony_ci 833bf215546Sopenharmony_ci if (max_count == ~0) { 834bf215546Sopenharmony_ci /* There are no per-vertex vertex elements. Use the hardware maximum. */ 835bf215546Sopenharmony_ci max_count = 0xffffff; 836bf215546Sopenharmony_ci } 837bf215546Sopenharmony_ci 838bf215546Sopenharmony_ci info.max_index = max_count - 1; 839bf215546Sopenharmony_ci 840bf215546Sopenharmony_ci if (info.instance_count <= 1) { 841bf215546Sopenharmony_ci if (draw.count <= 8 && info.has_user_indices) { 842bf215546Sopenharmony_ci r300_draw_elements_immediate(r300, &info, &draw); 843bf215546Sopenharmony_ci } else { 844bf215546Sopenharmony_ci r300_draw_elements(r300, &info, &draw, -1); 845bf215546Sopenharmony_ci } 846bf215546Sopenharmony_ci } else { 847bf215546Sopenharmony_ci r300_draw_elements_instanced(r300, &info, &draw); 848bf215546Sopenharmony_ci } 849bf215546Sopenharmony_ci } else { 850bf215546Sopenharmony_ci if (info.instance_count <= 1) { 851bf215546Sopenharmony_ci if (immd_is_good_idea(r300, draw.count)) { 852bf215546Sopenharmony_ci r300_draw_arrays_immediate(r300, &info, &draw); 853bf215546Sopenharmony_ci } else { 854bf215546Sopenharmony_ci r300_draw_arrays(r300, &info, &draw, -1); 855bf215546Sopenharmony_ci } 856bf215546Sopenharmony_ci } else { 857bf215546Sopenharmony_ci r300_draw_arrays_instanced(r300, &info, &draw); 858bf215546Sopenharmony_ci } 859bf215546Sopenharmony_ci } 860bf215546Sopenharmony_ci} 861bf215546Sopenharmony_ci 862bf215546Sopenharmony_ci/**************************************************************************** 863bf215546Sopenharmony_ci * The rest of this file is for SW TCL rendering only. Please be polite and * 864bf215546Sopenharmony_ci * keep these functions separated so that they are easier to locate. ~C. * 865bf215546Sopenharmony_ci ***************************************************************************/ 866bf215546Sopenharmony_ci 867bf215546Sopenharmony_ci/* SW TCL elements, using Draw. */ 868bf215546Sopenharmony_cistatic void r300_swtcl_draw_vbo(struct pipe_context* pipe, 869bf215546Sopenharmony_ci const struct pipe_draw_info *info, 870bf215546Sopenharmony_ci unsigned drawid_offset, 871bf215546Sopenharmony_ci const struct pipe_draw_indirect_info *indirect, 872bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draws, 873bf215546Sopenharmony_ci unsigned num_draws) 874bf215546Sopenharmony_ci{ 875bf215546Sopenharmony_ci if (num_draws > 1) { 876bf215546Sopenharmony_ci util_draw_multi(pipe, info, drawid_offset, indirect, draws, num_draws); 877bf215546Sopenharmony_ci return; 878bf215546Sopenharmony_ci } 879bf215546Sopenharmony_ci 880bf215546Sopenharmony_ci struct r300_context* r300 = r300_context(pipe); 881bf215546Sopenharmony_ci struct pipe_draw_start_count_bias draw = draws[0]; 882bf215546Sopenharmony_ci 883bf215546Sopenharmony_ci if (r300->skip_rendering) { 884bf215546Sopenharmony_ci return; 885bf215546Sopenharmony_ci } 886bf215546Sopenharmony_ci 887bf215546Sopenharmony_ci if (!u_trim_pipe_prim(info->mode, &draw.count)) 888bf215546Sopenharmony_ci return; 889bf215546Sopenharmony_ci 890bf215546Sopenharmony_ci if (info->index_size) { 891bf215546Sopenharmony_ci draw_set_indexes(r300->draw, 892bf215546Sopenharmony_ci info->has_user_indices ? 893bf215546Sopenharmony_ci info->index.user : 894bf215546Sopenharmony_ci r300_resource(info->index.resource)->malloced_buffer, 895bf215546Sopenharmony_ci info->index_size, ~0); 896bf215546Sopenharmony_ci } 897bf215546Sopenharmony_ci 898bf215546Sopenharmony_ci if (r300->sprite_coord_enable != 0) 899bf215546Sopenharmony_ci if ((info->mode == PIPE_PRIM_POINTS) != r300->is_point) { 900bf215546Sopenharmony_ci r300->is_point = !r300->is_point; 901bf215546Sopenharmony_ci r300_mark_atom_dirty(r300, &r300->rs_block_state); 902bf215546Sopenharmony_ci } 903bf215546Sopenharmony_ci 904bf215546Sopenharmony_ci r300_update_derived_state(r300); 905bf215546Sopenharmony_ci 906bf215546Sopenharmony_ci draw_vbo(r300->draw, info, drawid_offset, NULL, &draw, 1, 0); 907bf215546Sopenharmony_ci draw_flush(r300->draw); 908bf215546Sopenharmony_ci} 909bf215546Sopenharmony_ci 910bf215546Sopenharmony_ci/* Object for rendering using Draw. */ 911bf215546Sopenharmony_cistruct r300_render { 912bf215546Sopenharmony_ci /* Parent class */ 913bf215546Sopenharmony_ci struct vbuf_render base; 914bf215546Sopenharmony_ci 915bf215546Sopenharmony_ci /* Pipe context */ 916bf215546Sopenharmony_ci struct r300_context* r300; 917bf215546Sopenharmony_ci 918bf215546Sopenharmony_ci /* Vertex information */ 919bf215546Sopenharmony_ci size_t vertex_size; 920bf215546Sopenharmony_ci unsigned prim; 921bf215546Sopenharmony_ci unsigned hwprim; 922bf215546Sopenharmony_ci 923bf215546Sopenharmony_ci /* VBO */ 924bf215546Sopenharmony_ci size_t vbo_max_used; 925bf215546Sopenharmony_ci uint8_t *vbo_ptr; 926bf215546Sopenharmony_ci}; 927bf215546Sopenharmony_ci 928bf215546Sopenharmony_cistatic inline struct r300_render* 929bf215546Sopenharmony_cir300_render(struct vbuf_render* render) 930bf215546Sopenharmony_ci{ 931bf215546Sopenharmony_ci return (struct r300_render*)render; 932bf215546Sopenharmony_ci} 933bf215546Sopenharmony_ci 934bf215546Sopenharmony_cistatic const struct vertex_info* 935bf215546Sopenharmony_cir300_render_get_vertex_info(struct vbuf_render* render) 936bf215546Sopenharmony_ci{ 937bf215546Sopenharmony_ci struct r300_render* r300render = r300_render(render); 938bf215546Sopenharmony_ci struct r300_context* r300 = r300render->r300; 939bf215546Sopenharmony_ci 940bf215546Sopenharmony_ci return &r300->vertex_info; 941bf215546Sopenharmony_ci} 942bf215546Sopenharmony_ci 943bf215546Sopenharmony_cistatic boolean r300_render_allocate_vertices(struct vbuf_render* render, 944bf215546Sopenharmony_ci ushort vertex_size, 945bf215546Sopenharmony_ci ushort count) 946bf215546Sopenharmony_ci{ 947bf215546Sopenharmony_ci struct r300_render* r300render = r300_render(render); 948bf215546Sopenharmony_ci struct r300_context* r300 = r300render->r300; 949bf215546Sopenharmony_ci struct radeon_winsys *rws = r300->rws; 950bf215546Sopenharmony_ci size_t size = (size_t)vertex_size * (size_t)count; 951bf215546Sopenharmony_ci 952bf215546Sopenharmony_ci DBG(r300, DBG_DRAW, "r300: render_allocate_vertices (size: %d)\n", size); 953bf215546Sopenharmony_ci 954bf215546Sopenharmony_ci if (!r300->vbo || size + r300->draw_vbo_offset > r300->vbo->size) { 955bf215546Sopenharmony_ci pb_reference(&r300->vbo, NULL); 956bf215546Sopenharmony_ci r300->vbo = NULL; 957bf215546Sopenharmony_ci r300render->vbo_ptr = NULL; 958bf215546Sopenharmony_ci 959bf215546Sopenharmony_ci r300->vbo = rws->buffer_create(rws, 960bf215546Sopenharmony_ci MAX2(R300_MAX_DRAW_VBO_SIZE, size), 961bf215546Sopenharmony_ci R300_BUFFER_ALIGNMENT, 962bf215546Sopenharmony_ci RADEON_DOMAIN_GTT, 963bf215546Sopenharmony_ci RADEON_FLAG_NO_INTERPROCESS_SHARING); 964bf215546Sopenharmony_ci if (!r300->vbo) { 965bf215546Sopenharmony_ci return FALSE; 966bf215546Sopenharmony_ci } 967bf215546Sopenharmony_ci r300->draw_vbo_offset = 0; 968bf215546Sopenharmony_ci r300render->vbo_ptr = rws->buffer_map(rws, r300->vbo, &r300->cs, 969bf215546Sopenharmony_ci PIPE_MAP_WRITE); 970bf215546Sopenharmony_ci } 971bf215546Sopenharmony_ci 972bf215546Sopenharmony_ci r300render->vertex_size = vertex_size; 973bf215546Sopenharmony_ci return TRUE; 974bf215546Sopenharmony_ci} 975bf215546Sopenharmony_ci 976bf215546Sopenharmony_cistatic void* r300_render_map_vertices(struct vbuf_render* render) 977bf215546Sopenharmony_ci{ 978bf215546Sopenharmony_ci struct r300_render* r300render = r300_render(render); 979bf215546Sopenharmony_ci struct r300_context* r300 = r300render->r300; 980bf215546Sopenharmony_ci 981bf215546Sopenharmony_ci DBG(r300, DBG_DRAW, "r300: render_map_vertices\n"); 982bf215546Sopenharmony_ci 983bf215546Sopenharmony_ci assert(r300render->vbo_ptr); 984bf215546Sopenharmony_ci return r300render->vbo_ptr + r300->draw_vbo_offset; 985bf215546Sopenharmony_ci} 986bf215546Sopenharmony_ci 987bf215546Sopenharmony_cistatic void r300_render_unmap_vertices(struct vbuf_render* render, 988bf215546Sopenharmony_ci ushort min, 989bf215546Sopenharmony_ci ushort max) 990bf215546Sopenharmony_ci{ 991bf215546Sopenharmony_ci struct r300_render* r300render = r300_render(render); 992bf215546Sopenharmony_ci struct r300_context* r300 = r300render->r300; 993bf215546Sopenharmony_ci 994bf215546Sopenharmony_ci DBG(r300, DBG_DRAW, "r300: render_unmap_vertices\n"); 995bf215546Sopenharmony_ci 996bf215546Sopenharmony_ci r300render->vbo_max_used = MAX2(r300render->vbo_max_used, 997bf215546Sopenharmony_ci r300render->vertex_size * (max + 1)); 998bf215546Sopenharmony_ci} 999bf215546Sopenharmony_ci 1000bf215546Sopenharmony_cistatic void r300_render_release_vertices(struct vbuf_render* render) 1001bf215546Sopenharmony_ci{ 1002bf215546Sopenharmony_ci struct r300_render* r300render = r300_render(render); 1003bf215546Sopenharmony_ci struct r300_context* r300 = r300render->r300; 1004bf215546Sopenharmony_ci 1005bf215546Sopenharmony_ci DBG(r300, DBG_DRAW, "r300: render_release_vertices\n"); 1006bf215546Sopenharmony_ci 1007bf215546Sopenharmony_ci r300->draw_vbo_offset += r300render->vbo_max_used; 1008bf215546Sopenharmony_ci r300render->vbo_max_used = 0; 1009bf215546Sopenharmony_ci} 1010bf215546Sopenharmony_ci 1011bf215546Sopenharmony_cistatic void r300_render_set_primitive(struct vbuf_render* render, 1012bf215546Sopenharmony_ci enum pipe_prim_type prim) 1013bf215546Sopenharmony_ci{ 1014bf215546Sopenharmony_ci struct r300_render* r300render = r300_render(render); 1015bf215546Sopenharmony_ci 1016bf215546Sopenharmony_ci r300render->prim = prim; 1017bf215546Sopenharmony_ci r300render->hwprim = r300_translate_primitive(prim); 1018bf215546Sopenharmony_ci} 1019bf215546Sopenharmony_ci 1020bf215546Sopenharmony_cistatic void r300_render_draw_arrays(struct vbuf_render* render, 1021bf215546Sopenharmony_ci unsigned start, 1022bf215546Sopenharmony_ci unsigned count) 1023bf215546Sopenharmony_ci{ 1024bf215546Sopenharmony_ci struct r300_render* r300render = r300_render(render); 1025bf215546Sopenharmony_ci struct r300_context* r300 = r300render->r300; 1026bf215546Sopenharmony_ci uint8_t* ptr; 1027bf215546Sopenharmony_ci unsigned i; 1028bf215546Sopenharmony_ci unsigned dwords = 6; 1029bf215546Sopenharmony_ci 1030bf215546Sopenharmony_ci CS_LOCALS(r300); 1031bf215546Sopenharmony_ci (void) i; (void) ptr; 1032bf215546Sopenharmony_ci 1033bf215546Sopenharmony_ci assert(start == 0); 1034bf215546Sopenharmony_ci assert(count < (1 << 16)); 1035bf215546Sopenharmony_ci 1036bf215546Sopenharmony_ci DBG(r300, DBG_DRAW, "r300: render_draw_arrays (count: %d)\n", count); 1037bf215546Sopenharmony_ci 1038bf215546Sopenharmony_ci if (!r300_prepare_for_rendering(r300, 1039bf215546Sopenharmony_ci PREP_EMIT_STATES | PREP_EMIT_VARRAYS_SWTCL, 1040bf215546Sopenharmony_ci NULL, dwords, 0, 0, -1)) { 1041bf215546Sopenharmony_ci return; 1042bf215546Sopenharmony_ci } 1043bf215546Sopenharmony_ci 1044bf215546Sopenharmony_ci BEGIN_CS(dwords); 1045bf215546Sopenharmony_ci OUT_CS_REG(R300_GA_COLOR_CONTROL, 1046bf215546Sopenharmony_ci r300_provoking_vertex_fixes(r300, r300render->prim)); 1047bf215546Sopenharmony_ci OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, count - 1); 1048bf215546Sopenharmony_ci OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0); 1049bf215546Sopenharmony_ci OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) | 1050bf215546Sopenharmony_ci r300render->hwprim); 1051bf215546Sopenharmony_ci END_CS; 1052bf215546Sopenharmony_ci} 1053bf215546Sopenharmony_ci 1054bf215546Sopenharmony_cistatic void r300_render_draw_elements(struct vbuf_render* render, 1055bf215546Sopenharmony_ci const ushort* indices, 1056bf215546Sopenharmony_ci uint count) 1057bf215546Sopenharmony_ci{ 1058bf215546Sopenharmony_ci struct r300_render* r300render = r300_render(render); 1059bf215546Sopenharmony_ci struct r300_context* r300 = r300render->r300; 1060bf215546Sopenharmony_ci unsigned max_index = (r300->vbo->size - r300->draw_vbo_offset) / 1061bf215546Sopenharmony_ci (r300render->r300->vertex_info.size * 4) - 1; 1062bf215546Sopenharmony_ci struct pipe_resource *index_buffer = NULL; 1063bf215546Sopenharmony_ci unsigned index_buffer_offset; 1064bf215546Sopenharmony_ci 1065bf215546Sopenharmony_ci CS_LOCALS(r300); 1066bf215546Sopenharmony_ci DBG(r300, DBG_DRAW, "r300: render_draw_elements (count: %d)\n", count); 1067bf215546Sopenharmony_ci 1068bf215546Sopenharmony_ci u_upload_data(r300->uploader, 0, count * 2, 4, indices, 1069bf215546Sopenharmony_ci &index_buffer_offset, &index_buffer); 1070bf215546Sopenharmony_ci if (!index_buffer) { 1071bf215546Sopenharmony_ci return; 1072bf215546Sopenharmony_ci } 1073bf215546Sopenharmony_ci 1074bf215546Sopenharmony_ci if (!r300_prepare_for_rendering(r300, 1075bf215546Sopenharmony_ci PREP_EMIT_STATES | 1076bf215546Sopenharmony_ci PREP_EMIT_VARRAYS_SWTCL | PREP_INDEXED, 1077bf215546Sopenharmony_ci index_buffer, 12, 0, 0, -1)) { 1078bf215546Sopenharmony_ci pipe_resource_reference(&index_buffer, NULL); 1079bf215546Sopenharmony_ci return; 1080bf215546Sopenharmony_ci } 1081bf215546Sopenharmony_ci 1082bf215546Sopenharmony_ci BEGIN_CS(12); 1083bf215546Sopenharmony_ci OUT_CS_REG(R300_GA_COLOR_CONTROL, 1084bf215546Sopenharmony_ci r300_provoking_vertex_fixes(r300, r300render->prim)); 1085bf215546Sopenharmony_ci OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, max_index); 1086bf215546Sopenharmony_ci 1087bf215546Sopenharmony_ci OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, 0); 1088bf215546Sopenharmony_ci OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | 1089bf215546Sopenharmony_ci r300render->hwprim); 1090bf215546Sopenharmony_ci 1091bf215546Sopenharmony_ci OUT_CS_PKT3(R300_PACKET3_INDX_BUFFER, 2); 1092bf215546Sopenharmony_ci OUT_CS(R300_INDX_BUFFER_ONE_REG_WR | (R300_VAP_PORT_IDX0 >> 2)); 1093bf215546Sopenharmony_ci OUT_CS(index_buffer_offset); 1094bf215546Sopenharmony_ci OUT_CS((count + 1) / 2); 1095bf215546Sopenharmony_ci OUT_CS_RELOC(r300_resource(index_buffer)); 1096bf215546Sopenharmony_ci END_CS; 1097bf215546Sopenharmony_ci 1098bf215546Sopenharmony_ci pipe_resource_reference(&index_buffer, NULL); 1099bf215546Sopenharmony_ci} 1100bf215546Sopenharmony_ci 1101bf215546Sopenharmony_cistatic void r300_render_destroy(struct vbuf_render* render) 1102bf215546Sopenharmony_ci{ 1103bf215546Sopenharmony_ci FREE(render); 1104bf215546Sopenharmony_ci} 1105bf215546Sopenharmony_ci 1106bf215546Sopenharmony_cistatic struct vbuf_render* r300_render_create(struct r300_context* r300) 1107bf215546Sopenharmony_ci{ 1108bf215546Sopenharmony_ci struct r300_render* r300render = CALLOC_STRUCT(r300_render); 1109bf215546Sopenharmony_ci 1110bf215546Sopenharmony_ci r300render->r300 = r300; 1111bf215546Sopenharmony_ci 1112bf215546Sopenharmony_ci r300render->base.max_vertex_buffer_bytes = R300_MAX_DRAW_VBO_SIZE; 1113bf215546Sopenharmony_ci r300render->base.max_indices = 16 * 1024; 1114bf215546Sopenharmony_ci 1115bf215546Sopenharmony_ci r300render->base.get_vertex_info = r300_render_get_vertex_info; 1116bf215546Sopenharmony_ci r300render->base.allocate_vertices = r300_render_allocate_vertices; 1117bf215546Sopenharmony_ci r300render->base.map_vertices = r300_render_map_vertices; 1118bf215546Sopenharmony_ci r300render->base.unmap_vertices = r300_render_unmap_vertices; 1119bf215546Sopenharmony_ci r300render->base.set_primitive = r300_render_set_primitive; 1120bf215546Sopenharmony_ci r300render->base.draw_elements = r300_render_draw_elements; 1121bf215546Sopenharmony_ci r300render->base.draw_arrays = r300_render_draw_arrays; 1122bf215546Sopenharmony_ci r300render->base.release_vertices = r300_render_release_vertices; 1123bf215546Sopenharmony_ci r300render->base.destroy = r300_render_destroy; 1124bf215546Sopenharmony_ci 1125bf215546Sopenharmony_ci return &r300render->base; 1126bf215546Sopenharmony_ci} 1127bf215546Sopenharmony_ci 1128bf215546Sopenharmony_cistruct draw_stage* r300_draw_stage(struct r300_context* r300) 1129bf215546Sopenharmony_ci{ 1130bf215546Sopenharmony_ci struct vbuf_render* render; 1131bf215546Sopenharmony_ci struct draw_stage* stage; 1132bf215546Sopenharmony_ci 1133bf215546Sopenharmony_ci render = r300_render_create(r300); 1134bf215546Sopenharmony_ci 1135bf215546Sopenharmony_ci if (!render) { 1136bf215546Sopenharmony_ci return NULL; 1137bf215546Sopenharmony_ci } 1138bf215546Sopenharmony_ci 1139bf215546Sopenharmony_ci stage = draw_vbuf_stage(r300->draw, render); 1140bf215546Sopenharmony_ci 1141bf215546Sopenharmony_ci if (!stage) { 1142bf215546Sopenharmony_ci render->destroy(render); 1143bf215546Sopenharmony_ci return NULL; 1144bf215546Sopenharmony_ci } 1145bf215546Sopenharmony_ci 1146bf215546Sopenharmony_ci draw_set_render(r300->draw, render); 1147bf215546Sopenharmony_ci 1148bf215546Sopenharmony_ci return stage; 1149bf215546Sopenharmony_ci} 1150bf215546Sopenharmony_ci 1151bf215546Sopenharmony_ci/**************************************************************************** 1152bf215546Sopenharmony_ci * End of SW TCL functions * 1153bf215546Sopenharmony_ci ***************************************************************************/ 1154bf215546Sopenharmony_ci 1155bf215546Sopenharmony_ci/* This functions is used to draw a rectangle for the blitter module. 1156bf215546Sopenharmony_ci * 1157bf215546Sopenharmony_ci * If we rendered a quad, the pixels on the main diagonal 1158bf215546Sopenharmony_ci * would be computed and stored twice, which makes the clear/copy codepaths 1159bf215546Sopenharmony_ci * somewhat inefficient. Instead we use a rectangular point sprite. */ 1160bf215546Sopenharmony_civoid r300_blitter_draw_rectangle(struct blitter_context *blitter, 1161bf215546Sopenharmony_ci void *vertex_elements_cso, 1162bf215546Sopenharmony_ci blitter_get_vs_func get_vs, 1163bf215546Sopenharmony_ci int x1, int y1, int x2, int y2, 1164bf215546Sopenharmony_ci float depth, unsigned num_instances, 1165bf215546Sopenharmony_ci enum blitter_attrib_type type, 1166bf215546Sopenharmony_ci const union blitter_attrib *attrib) 1167bf215546Sopenharmony_ci{ 1168bf215546Sopenharmony_ci struct r300_context *r300 = r300_context(util_blitter_get_pipe(blitter)); 1169bf215546Sopenharmony_ci unsigned last_sprite_coord_enable = r300->sprite_coord_enable; 1170bf215546Sopenharmony_ci unsigned last_is_point = r300->is_point; 1171bf215546Sopenharmony_ci unsigned width = x2 - x1; 1172bf215546Sopenharmony_ci unsigned height = y2 - y1; 1173bf215546Sopenharmony_ci unsigned vertex_size = 1174bf215546Sopenharmony_ci type == UTIL_BLITTER_ATTRIB_COLOR || !r300->draw ? 8 : 4; 1175bf215546Sopenharmony_ci unsigned dwords = 13 + vertex_size + 1176bf215546Sopenharmony_ci (type == UTIL_BLITTER_ATTRIB_TEXCOORD_XY ? 7 : 0); 1177bf215546Sopenharmony_ci static const union blitter_attrib zeros; 1178bf215546Sopenharmony_ci CS_LOCALS(r300); 1179bf215546Sopenharmony_ci 1180bf215546Sopenharmony_ci /* XXX workaround for a lockup in MSAA resolve on SWTCL chipsets, this 1181bf215546Sopenharmony_ci * function most probably doesn't handle type=NONE correctly */ 1182bf215546Sopenharmony_ci if ((!r300->screen->caps.has_tcl && type == UTIL_BLITTER_ATTRIB_NONE) || 1183bf215546Sopenharmony_ci type == UTIL_BLITTER_ATTRIB_TEXCOORD_XYZW || 1184bf215546Sopenharmony_ci num_instances > 1) { 1185bf215546Sopenharmony_ci util_blitter_draw_rectangle(blitter, vertex_elements_cso, get_vs, 1186bf215546Sopenharmony_ci x1, y1, x2, y2, 1187bf215546Sopenharmony_ci depth, num_instances, type, attrib); 1188bf215546Sopenharmony_ci return; 1189bf215546Sopenharmony_ci } 1190bf215546Sopenharmony_ci 1191bf215546Sopenharmony_ci if (r300->skip_rendering) 1192bf215546Sopenharmony_ci return; 1193bf215546Sopenharmony_ci 1194bf215546Sopenharmony_ci r300->context.bind_vertex_elements_state(&r300->context, vertex_elements_cso); 1195bf215546Sopenharmony_ci r300->context.bind_vs_state(&r300->context, get_vs(blitter)); 1196bf215546Sopenharmony_ci 1197bf215546Sopenharmony_ci if (type == UTIL_BLITTER_ATTRIB_TEXCOORD_XY) { 1198bf215546Sopenharmony_ci r300->sprite_coord_enable = 1; 1199bf215546Sopenharmony_ci r300->is_point = true; 1200bf215546Sopenharmony_ci } 1201bf215546Sopenharmony_ci 1202bf215546Sopenharmony_ci r300_update_derived_state(r300); 1203bf215546Sopenharmony_ci 1204bf215546Sopenharmony_ci /* Mark some states we don't care about as non-dirty. */ 1205bf215546Sopenharmony_ci r300->viewport_state.dirty = FALSE; 1206bf215546Sopenharmony_ci 1207bf215546Sopenharmony_ci if (!r300_prepare_for_rendering(r300, PREP_EMIT_STATES, NULL, dwords, 0, 0, -1)) 1208bf215546Sopenharmony_ci goto done; 1209bf215546Sopenharmony_ci 1210bf215546Sopenharmony_ci DBG(r300, DBG_DRAW, "r300: draw_rectangle\n"); 1211bf215546Sopenharmony_ci 1212bf215546Sopenharmony_ci BEGIN_CS(dwords); 1213bf215546Sopenharmony_ci /* Set up GA. */ 1214bf215546Sopenharmony_ci OUT_CS_REG(R300_GA_POINT_SIZE, (height * 6) | ((width * 6) << 16)); 1215bf215546Sopenharmony_ci 1216bf215546Sopenharmony_ci if (type == UTIL_BLITTER_ATTRIB_TEXCOORD_XY) { 1217bf215546Sopenharmony_ci /* Set up the GA to generate texcoords. */ 1218bf215546Sopenharmony_ci OUT_CS_REG(R300_GB_ENABLE, R300_GB_POINT_STUFF_ENABLE | 1219bf215546Sopenharmony_ci (R300_GB_TEX_STR << R300_GB_TEX0_SOURCE_SHIFT)); 1220bf215546Sopenharmony_ci OUT_CS_REG_SEQ(R300_GA_POINT_S0, 4); 1221bf215546Sopenharmony_ci OUT_CS_32F(attrib->texcoord.x1); 1222bf215546Sopenharmony_ci OUT_CS_32F(attrib->texcoord.y2); 1223bf215546Sopenharmony_ci OUT_CS_32F(attrib->texcoord.x2); 1224bf215546Sopenharmony_ci OUT_CS_32F(attrib->texcoord.y1); 1225bf215546Sopenharmony_ci } 1226bf215546Sopenharmony_ci 1227bf215546Sopenharmony_ci /* Set up VAP controls. */ 1228bf215546Sopenharmony_ci OUT_CS_REG(R300_VAP_CLIP_CNTL, R300_CLIP_DISABLE); 1229bf215546Sopenharmony_ci OUT_CS_REG(R300_VAP_VTE_CNTL, R300_VTX_XY_FMT | R300_VTX_Z_FMT); 1230bf215546Sopenharmony_ci OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size); 1231bf215546Sopenharmony_ci OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); 1232bf215546Sopenharmony_ci OUT_CS(1); 1233bf215546Sopenharmony_ci OUT_CS(0); 1234bf215546Sopenharmony_ci 1235bf215546Sopenharmony_ci /* Draw. */ 1236bf215546Sopenharmony_ci OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, vertex_size); 1237bf215546Sopenharmony_ci OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (1 << 16) | 1238bf215546Sopenharmony_ci R300_VAP_VF_CNTL__PRIM_POINTS); 1239bf215546Sopenharmony_ci 1240bf215546Sopenharmony_ci OUT_CS_32F(x1 + width * 0.5f); 1241bf215546Sopenharmony_ci OUT_CS_32F(y1 + height * 0.5f); 1242bf215546Sopenharmony_ci OUT_CS_32F(depth); 1243bf215546Sopenharmony_ci OUT_CS_32F(1); 1244bf215546Sopenharmony_ci 1245bf215546Sopenharmony_ci if (vertex_size == 8) { 1246bf215546Sopenharmony_ci if (!attrib) 1247bf215546Sopenharmony_ci attrib = &zeros; 1248bf215546Sopenharmony_ci OUT_CS_TABLE(attrib->color, 4); 1249bf215546Sopenharmony_ci } 1250bf215546Sopenharmony_ci END_CS; 1251bf215546Sopenharmony_ci 1252bf215546Sopenharmony_cidone: 1253bf215546Sopenharmony_ci /* Restore the state. */ 1254bf215546Sopenharmony_ci r300_mark_atom_dirty(r300, &r300->rs_state); 1255bf215546Sopenharmony_ci r300_mark_atom_dirty(r300, &r300->viewport_state); 1256bf215546Sopenharmony_ci 1257bf215546Sopenharmony_ci r300->sprite_coord_enable = last_sprite_coord_enable; 1258bf215546Sopenharmony_ci r300->is_point = last_is_point; 1259bf215546Sopenharmony_ci} 1260bf215546Sopenharmony_ci 1261bf215546Sopenharmony_civoid r300_init_render_functions(struct r300_context *r300) 1262bf215546Sopenharmony_ci{ 1263bf215546Sopenharmony_ci /* Set draw functions based on presence of HW TCL. */ 1264bf215546Sopenharmony_ci if (r300->screen->caps.has_tcl) { 1265bf215546Sopenharmony_ci r300->context.draw_vbo = r300_draw_vbo; 1266bf215546Sopenharmony_ci } else { 1267bf215546Sopenharmony_ci r300->context.draw_vbo = r300_swtcl_draw_vbo; 1268bf215546Sopenharmony_ci } 1269bf215546Sopenharmony_ci 1270bf215546Sopenharmony_ci /* Plug in the two-sided stencil reference value fallback if needed. */ 1271bf215546Sopenharmony_ci if (!r300->screen->caps.is_r500) 1272bf215546Sopenharmony_ci r300_plug_in_stencil_ref_fallback(r300); 1273bf215546Sopenharmony_ci} 1274