1848b8605Smrg/* 2848b8605Smrg * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org> 3848b8605Smrg * 4848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5848b8605Smrg * copy of this software and associated documentation files (the "Software"), 6848b8605Smrg * to deal in the Software without restriction, including without limitation 7848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 9848b8605Smrg * Software is furnished to do so, subject to the following conditions: 10848b8605Smrg * 11848b8605Smrg * The above copyright notice and this permission notice (including the next 12848b8605Smrg * paragraph) shall be included in all copies or substantial portions of the 13848b8605Smrg * Software. 14848b8605Smrg * 15848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16848b8605Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19848b8605Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20848b8605Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21848b8605Smrg * SOFTWARE. 22848b8605Smrg * 23848b8605Smrg * Authors: 24848b8605Smrg * Rob Clark <robclark@freedesktop.org> 25848b8605Smrg */ 26848b8605Smrg 27848b8605Smrg#ifndef FREEDRENO_DRAW_H_ 28848b8605Smrg#define FREEDRENO_DRAW_H_ 29848b8605Smrg 30848b8605Smrg#include "pipe/p_state.h" 31848b8605Smrg#include "pipe/p_context.h" 32848b8605Smrg 33848b8605Smrg#include "freedreno_context.h" 34848b8605Smrg#include "freedreno_resource.h" 35848b8605Smrg#include "freedreno_screen.h" 36848b8605Smrg#include "freedreno_util.h" 37848b8605Smrg 38848b8605Smrgstruct fd_ringbuffer; 39848b8605Smrg 40848b8605Smrgvoid fd_draw_init(struct pipe_context *pctx); 41848b8605Smrg 42848b8605Smrgstatic inline void 43b8e80941Smrgfd_draw(struct fd_batch *batch, struct fd_ringbuffer *ring, 44848b8605Smrg enum pc_di_primtype primtype, 45848b8605Smrg enum pc_di_vis_cull_mode vismode, 46848b8605Smrg enum pc_di_src_sel src_sel, uint32_t count, 47b8e80941Smrg uint8_t instances, 48848b8605Smrg enum pc_di_index_size idx_type, 49848b8605Smrg uint32_t idx_size, uint32_t idx_offset, 50b8e80941Smrg struct pipe_resource *idx_buffer) 51848b8605Smrg{ 52848b8605Smrg /* for debug after a lock up, write a unique counter value 53848b8605Smrg * to scratch7 for each draw, to make it easier to match up 54848b8605Smrg * register dumps to cmdstream. The combination of IB 55848b8605Smrg * (scratch6) and DRAW is enough to "triangulate" the 56848b8605Smrg * particular draw that caused lockup. 57848b8605Smrg */ 58848b8605Smrg emit_marker(ring, 7); 59848b8605Smrg 60b8e80941Smrg if (is_a3xx_p0(batch->ctx->screen)) { 61848b8605Smrg /* dummy-draw workaround: */ 62848b8605Smrg OUT_PKT3(ring, CP_DRAW_INDX, 3); 63848b8605Smrg OUT_RING(ring, 0x00000000); 64848b8605Smrg OUT_RING(ring, DRAW(1, DI_SRC_SEL_AUTO_INDEX, 65b8e80941Smrg INDEX_SIZE_IGN, USE_VISIBILITY, 0)); 66848b8605Smrg OUT_RING(ring, 0); /* NumIndices */ 67848b8605Smrg 68848b8605Smrg /* ugg, hard-code register offset to avoid pulling in the 69848b8605Smrg * a3xx register headers into something #included from a2xx 70848b8605Smrg */ 71848b8605Smrg OUT_PKT0(ring, 0x2206, 1); /* A3XX_HLSQ_CONST_VSPRESV_RANGE_REG */ 72848b8605Smrg OUT_RING(ring, 0); 73848b8605Smrg } 74848b8605Smrg 75b8e80941Smrg if (is_a20x(batch->ctx->screen)) { 76b8e80941Smrg /* a20x has a different draw command for drawing with binning data 77b8e80941Smrg * note: if we do patching we will have to insert a NOP 78b8e80941Smrg * 79b8e80941Smrg * binning data is is 1 byte/vertex (8x8x4 bin position of vertex) 80b8e80941Smrg * base ptr set by the CP_SET_DRAW_INIT_FLAGS command 81b8e80941Smrg * 82b8e80941Smrg * TODO: investigate the faceness_cull_select parameter to see how 83b8e80941Smrg * it is used with hw binning to use "faceness" bits 84848b8605Smrg */ 85b8e80941Smrg uint32_t size = 2; 86b8e80941Smrg if (vismode) 87b8e80941Smrg size += 2; 88b8e80941Smrg if (idx_buffer) 89b8e80941Smrg size += 2; 90b8e80941Smrg 91b8e80941Smrg BEGIN_RING(ring, size+1); 92b8e80941Smrg if (vismode) 93b8e80941Smrg util_dynarray_append(&batch->draw_patches, uint32_t*, ring->cur); 94b8e80941Smrg 95b8e80941Smrg OUT_PKT3(ring, vismode ? CP_DRAW_INDX_BIN : CP_DRAW_INDX, size); 96b8e80941Smrg OUT_RING(ring, 0x00000000); 97b8e80941Smrg OUT_RING(ring, DRAW_A20X(primtype, DI_FACE_CULL_NONE, src_sel, 98b8e80941Smrg idx_type, vismode, vismode, count)); 99b8e80941Smrg if (vismode == USE_VISIBILITY) { 100b8e80941Smrg OUT_RING(ring, batch->num_vertices); 101b8e80941Smrg OUT_RING(ring, count); 102b8e80941Smrg } 103848b8605Smrg } else { 104b8e80941Smrg OUT_PKT3(ring, CP_DRAW_INDX, idx_buffer ? 5 : 3); 105b8e80941Smrg OUT_RING(ring, 0x00000000); /* viz query info. */ 106b8e80941Smrg if (vismode == USE_VISIBILITY) { 107b8e80941Smrg /* leave vis mode blank for now, it will be patched up when 108b8e80941Smrg * we know if we are binning or not 109b8e80941Smrg */ 110b8e80941Smrg OUT_RINGP(ring, DRAW(primtype, src_sel, idx_type, 0, instances), 111b8e80941Smrg &batch->draw_patches); 112b8e80941Smrg } else { 113b8e80941Smrg OUT_RING(ring, DRAW(primtype, src_sel, idx_type, vismode, instances)); 114b8e80941Smrg } 115b8e80941Smrg OUT_RING(ring, count); /* NumIndices */ 116848b8605Smrg } 117b8e80941Smrg 118b8e80941Smrg if (idx_buffer) { 119b8e80941Smrg OUT_RELOC(ring, fd_resource(idx_buffer)->bo, idx_offset, 0, 0); 120848b8605Smrg OUT_RING (ring, idx_size); 121848b8605Smrg } 122848b8605Smrg 123848b8605Smrg emit_marker(ring, 7); 124848b8605Smrg 125b8e80941Smrg fd_reset_wfi(batch); 126848b8605Smrg} 127848b8605Smrg 128848b8605Smrg 129848b8605Smrgstatic inline enum pc_di_index_size 130848b8605Smrgsize2indextype(unsigned index_size) 131848b8605Smrg{ 132848b8605Smrg switch (index_size) { 133848b8605Smrg case 1: return INDEX_SIZE_8_BIT; 134848b8605Smrg case 2: return INDEX_SIZE_16_BIT; 135848b8605Smrg case 4: return INDEX_SIZE_32_BIT; 136848b8605Smrg } 137848b8605Smrg DBG("unsupported index size: %d", index_size); 138848b8605Smrg assert(0); 139848b8605Smrg return INDEX_SIZE_IGN; 140848b8605Smrg} 141848b8605Smrg 142848b8605Smrg/* this is same for a2xx/a3xx, so split into helper: */ 143848b8605Smrgstatic inline void 144b8e80941Smrgfd_draw_emit(struct fd_batch *batch, struct fd_ringbuffer *ring, 145b8e80941Smrg enum pc_di_primtype primtype, 146848b8605Smrg enum pc_di_vis_cull_mode vismode, 147b8e80941Smrg const struct pipe_draw_info *info, 148b8e80941Smrg unsigned index_offset) 149848b8605Smrg{ 150b8e80941Smrg struct pipe_resource *idx_buffer = NULL; 151848b8605Smrg enum pc_di_index_size idx_type = INDEX_SIZE_IGN; 152848b8605Smrg enum pc_di_src_sel src_sel; 153848b8605Smrg uint32_t idx_size, idx_offset; 154848b8605Smrg 155b8e80941Smrg if (info->index_size) { 156b8e80941Smrg assert(!info->has_user_indices); 157848b8605Smrg 158b8e80941Smrg idx_buffer = info->index.resource; 159b8e80941Smrg idx_type = size2indextype(info->index_size); 160b8e80941Smrg idx_size = info->index_size * info->count; 161b8e80941Smrg idx_offset = index_offset + info->start * info->index_size; 162848b8605Smrg src_sel = DI_SRC_SEL_DMA; 163848b8605Smrg } else { 164b8e80941Smrg idx_buffer = NULL; 165848b8605Smrg idx_type = INDEX_SIZE_IGN; 166848b8605Smrg idx_size = 0; 167848b8605Smrg idx_offset = 0; 168848b8605Smrg src_sel = DI_SRC_SEL_AUTO_INDEX; 169848b8605Smrg } 170848b8605Smrg 171b8e80941Smrg fd_draw(batch, ring, primtype, vismode, src_sel, 172b8e80941Smrg info->count, info->instance_count - 1, 173b8e80941Smrg idx_type, idx_size, idx_offset, idx_buffer); 174848b8605Smrg} 175848b8605Smrg 176848b8605Smrg#endif /* FREEDRENO_DRAW_H_ */ 177