1 /* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */ 2 3 /* 4 * Copyright (C) 2012-2013 Rob Clark <robclark (at) freedesktop.org> 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the next 14 * paragraph) shall be included in all copies or substantial portions of the 15 * Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 * SOFTWARE. 24 * 25 * Authors: 26 * Rob Clark <robclark (at) freedesktop.org> 27 */ 28 29 #include "pipe/p_state.h" 30 #include "util/u_string.h" 31 #include "util/u_memory.h" 32 #include "util/u_prim.h" 33 34 #include "freedreno_state.h" 35 #include "freedreno_resource.h" 36 37 #include "fd2_draw.h" 38 #include "fd2_context.h" 39 #include "fd2_emit.h" 40 #include "fd2_program.h" 41 #include "fd2_util.h" 42 #include "fd2_zsa.h" 43 44 45 static void 46 emit_cacheflush(struct fd_ringbuffer *ring) 47 { 48 unsigned i; 49 50 for (i = 0; i < 12; i++) { 51 OUT_PKT3(ring, CP_EVENT_WRITE, 1); 52 OUT_RING(ring, CACHE_FLUSH); 53 } 54 } 55 56 static void 57 emit_vertexbufs(struct fd_context *ctx) 58 { 59 struct fd_vertex_stateobj *vtx = ctx->vtx.vtx; 60 struct fd_vertexbuf_stateobj *vertexbuf = &ctx->vtx.vertexbuf; 61 struct fd2_vertex_buf bufs[PIPE_MAX_ATTRIBS]; 62 unsigned i; 63 64 if (!vtx->num_elements) 65 return; 66 67 for (i = 0; i < vtx->num_elements; i++) { 68 struct pipe_vertex_element *elem = &vtx->pipe[i]; 69 struct pipe_vertex_buffer *vb = 70 &vertexbuf->vb[elem->vertex_buffer_index]; 71 bufs[i].offset = vb->buffer_offset; 72 bufs[i].size = fd_bo_size(fd_resource(vb->buffer)->bo); 73 bufs[i].prsc = vb->buffer; 74 } 75 76 // NOTE I believe the 0x78 (or 0x9c in solid_vp) relates to the 77 // CONST(20,0) (or CONST(26,0) in soliv_vp) 78 79 fd2_emit_vertex_bufs(ctx->batch->draw, 0x78, bufs, vtx->num_elements); 80 } 81 82 static bool 83 fd2_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info) 84 { 85 struct fd_ringbuffer *ring = ctx->batch->draw; 86 87 if (ctx->dirty & FD_DIRTY_VTXBUF) 88 emit_vertexbufs(ctx); 89 90 fd2_emit_state(ctx, ctx->dirty); 91 92 OUT_PKT3(ring, CP_SET_CONSTANT, 2); 93 OUT_RING(ring, CP_REG(REG_A2XX_VGT_INDX_OFFSET)); 94 OUT_RING(ring, info->start); 95 96 OUT_PKT3(ring, CP_SET_CONSTANT, 2); 97 OUT_RING(ring, CP_REG(REG_A2XX_VGT_VERTEX_REUSE_BLOCK_CNTL)); 98 OUT_RING(ring, 0x0000003b); 99 100 OUT_PKT0(ring, REG_A2XX_TC_CNTL_STATUS, 1); 101 OUT_RING(ring, A2XX_TC_CNTL_STATUS_L2_INVALIDATE); 102 103 OUT_WFI (ring); 104 105 OUT_PKT3(ring, CP_SET_CONSTANT, 3); 106 OUT_RING(ring, CP_REG(REG_A2XX_VGT_MAX_VTX_INDX)); 107 OUT_RING(ring, info->max_index); /* VGT_MAX_VTX_INDX */ 108 OUT_RING(ring, info->min_index); /* VGT_MIN_VTX_INDX */ 109 110 fd_draw_emit(ctx->batch, ring, ctx->primtypes[info->mode], 111 IGNORE_VISIBILITY, info); 112 113 OUT_PKT3(ring, CP_SET_CONSTANT, 2); 114 OUT_RING(ring, CP_REG(REG_A2XX_UNKNOWN_2010)); 115 OUT_RING(ring, 0x00000000); 116 117 emit_cacheflush(ring); 118 119 return true; 120 } 121 122 123 static void 124 fd2_clear(struct fd_context *ctx, unsigned buffers, 125 const union pipe_color_union *color, double depth, unsigned stencil) 126 { 127 struct fd2_context *fd2_ctx = fd2_context(ctx); 128 struct fd_ringbuffer *ring = ctx->batch->draw; 129 struct pipe_framebuffer_state *fb = &ctx->batch->framebuffer; 130 uint32_t reg, colr = 0; 131 132 if ((buffers & PIPE_CLEAR_COLOR) && fb->nr_cbufs) 133 colr = pack_rgba(fb->cbufs[0]->format, color->f); 134 135 /* emit generic state now: */ 136 fd2_emit_state(ctx, ctx->dirty & 137 (FD_DIRTY_BLEND | FD_DIRTY_VIEWPORT | 138 FD_DIRTY_FRAMEBUFFER | FD_DIRTY_SCISSOR)); 139 140 fd2_emit_vertex_bufs(ring, 0x9c, (struct fd2_vertex_buf[]) { 141 { .prsc = fd2_ctx->solid_vertexbuf, .size = 48 }, 142 }, 1); 143 144 OUT_PKT3(ring, CP_SET_CONSTANT, 2); 145 OUT_RING(ring, CP_REG(REG_A2XX_VGT_INDX_OFFSET)); 146 OUT_RING(ring, 0); 147 148 OUT_PKT3(ring, CP_SET_CONSTANT, 2); 149 OUT_RING(ring, CP_REG(REG_A2XX_VGT_VERTEX_REUSE_BLOCK_CNTL)); 150 OUT_RING(ring, 0x0000028f); 151 152 fd2_program_emit(ring, &ctx->solid_prog); 153 154 OUT_PKT0(ring, REG_A2XX_TC_CNTL_STATUS, 1); 155 OUT_RING(ring, A2XX_TC_CNTL_STATUS_L2_INVALIDATE); 156 157 OUT_PKT3(ring, CP_SET_CONSTANT, 2); 158 OUT_RING(ring, CP_REG(REG_A2XX_CLEAR_COLOR)); 159 OUT_RING(ring, colr); 160 161 OUT_PKT3(ring, CP_SET_CONSTANT, 2); 162 OUT_RING(ring, CP_REG(REG_A2XX_A220_RB_LRZ_VSC_CONTROL)); 163 OUT_RING(ring, 0x00000084); 164 165 OUT_PKT3(ring, CP_SET_CONSTANT, 2); 166 OUT_RING(ring, CP_REG(REG_A2XX_RB_COPY_CONTROL)); 167 reg = 0; 168 if (buffers & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) { 169 reg |= A2XX_RB_COPY_CONTROL_DEPTH_CLEAR_ENABLE; 170 switch (fd_pipe2depth(fb->zsbuf->format)) { 171 case DEPTHX_24_8: 172 if (buffers & PIPE_CLEAR_DEPTH) 173 reg |= A2XX_RB_COPY_CONTROL_CLEAR_MASK(0xe); 174 if (buffers & PIPE_CLEAR_STENCIL) 175 reg |= A2XX_RB_COPY_CONTROL_CLEAR_MASK(0x1); 176 break; 177 case DEPTHX_16: 178 if (buffers & PIPE_CLEAR_DEPTH) 179 reg |= A2XX_RB_COPY_CONTROL_CLEAR_MASK(0xf); 180 break; 181 default: 182 debug_assert(0); 183 break; 184 } 185 } 186 OUT_RING(ring, reg); 187 188 OUT_PKT3(ring, CP_SET_CONSTANT, 2); 189 OUT_RING(ring, CP_REG(REG_A2XX_RB_DEPTH_CLEAR)); 190 reg = 0; 191 if (buffers & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) { 192 switch (fd_pipe2depth(fb->zsbuf->format)) { 193 case DEPTHX_24_8: 194 reg = (((uint32_t)(0xffffff * depth)) << 8) | 195 (stencil & 0xff); 196 break; 197 case DEPTHX_16: 198 reg = (uint32_t)(0xffffffff * depth); 199 break; 200 default: 201 debug_assert(0); 202 break; 203 } 204 } 205 OUT_RING(ring, reg); 206 207 OUT_PKT3(ring, CP_SET_CONSTANT, 2); 208 OUT_RING(ring, CP_REG(REG_A2XX_RB_DEPTHCONTROL)); 209 reg = 0; 210 if (buffers & PIPE_CLEAR_DEPTH) { 211 reg |= A2XX_RB_DEPTHCONTROL_ZFUNC(FUNC_ALWAYS) | 212 A2XX_RB_DEPTHCONTROL_Z_ENABLE | 213 A2XX_RB_DEPTHCONTROL_Z_WRITE_ENABLE | 214 A2XX_RB_DEPTHCONTROL_EARLY_Z_ENABLE; 215 } 216 if (buffers & PIPE_CLEAR_STENCIL) { 217 reg |= A2XX_RB_DEPTHCONTROL_STENCILFUNC(FUNC_ALWAYS) | 218 A2XX_RB_DEPTHCONTROL_STENCIL_ENABLE | 219 A2XX_RB_DEPTHCONTROL_STENCILZPASS(STENCIL_REPLACE); 220 } 221 OUT_RING(ring, reg); 222 223 OUT_PKT3(ring, CP_SET_CONSTANT, 3); 224 OUT_RING(ring, CP_REG(REG_A2XX_RB_STENCILREFMASK_BF)); 225 OUT_RING(ring, 0xff000000 | A2XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK(0xff)); 226 OUT_RING(ring, 0xff000000 | A2XX_RB_STENCILREFMASK_STENCILWRITEMASK(0xff)); 227 228 OUT_PKT3(ring, CP_SET_CONSTANT, 2); 229 OUT_RING(ring, CP_REG(REG_A2XX_RB_COLORCONTROL)); 230 OUT_RING(ring, A2XX_RB_COLORCONTROL_ALPHA_FUNC(FUNC_ALWAYS) | 231 A2XX_RB_COLORCONTROL_BLEND_DISABLE | 232 A2XX_RB_COLORCONTROL_ROP_CODE(12) | 233 A2XX_RB_COLORCONTROL_DITHER_MODE(DITHER_DISABLE) | 234 A2XX_RB_COLORCONTROL_DITHER_TYPE(DITHER_PIXEL)); 235 236 OUT_PKT3(ring, CP_SET_CONSTANT, 3); 237 OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_CLIP_CNTL)); 238 OUT_RING(ring, 0x00000000); /* PA_CL_CLIP_CNTL */ 239 OUT_RING(ring, A2XX_PA_SU_SC_MODE_CNTL_PROVOKING_VTX_LAST | /* PA_SU_SC_MODE_CNTL */ 240 A2XX_PA_SU_SC_MODE_CNTL_FRONT_PTYPE(PC_DRAW_TRIANGLES) | 241 A2XX_PA_SU_SC_MODE_CNTL_BACK_PTYPE(PC_DRAW_TRIANGLES)); 242 243 OUT_PKT3(ring, CP_SET_CONSTANT, 2); 244 OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_AA_MASK)); 245 OUT_RING(ring, 0x0000ffff); 246 247 OUT_PKT3(ring, CP_SET_CONSTANT, 3); 248 OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_WINDOW_SCISSOR_TL)); 249 OUT_RING(ring, xy2d(0,0)); /* PA_SC_WINDOW_SCISSOR_TL */ 250 OUT_RING(ring, xy2d(fb->width, /* PA_SC_WINDOW_SCISSOR_BR */ 251 fb->height)); 252 253 OUT_PKT3(ring, CP_SET_CONSTANT, 2); 254 OUT_RING(ring, CP_REG(REG_A2XX_RB_COLOR_MASK)); 255 if (buffers & PIPE_CLEAR_COLOR) { 256 OUT_RING(ring, A2XX_RB_COLOR_MASK_WRITE_RED | 257 A2XX_RB_COLOR_MASK_WRITE_GREEN | 258 A2XX_RB_COLOR_MASK_WRITE_BLUE | 259 A2XX_RB_COLOR_MASK_WRITE_ALPHA); 260 } else { 261 OUT_RING(ring, 0x0); 262 } 263 264 OUT_PKT3(ring, CP_SET_CONSTANT, 3); 265 OUT_RING(ring, CP_REG(REG_A2XX_VGT_MAX_VTX_INDX)); 266 OUT_RING(ring, 3); /* VGT_MAX_VTX_INDX */ 267 OUT_RING(ring, 0); /* VGT_MIN_VTX_INDX */ 268 269 fd_draw(ctx->batch, ring, DI_PT_RECTLIST, IGNORE_VISIBILITY, 270 DI_SRC_SEL_AUTO_INDEX, 3, 0, INDEX_SIZE_IGN, 0, 0, NULL); 271 272 OUT_PKT3(ring, CP_SET_CONSTANT, 2); 273 OUT_RING(ring, CP_REG(REG_A2XX_A220_RB_LRZ_VSC_CONTROL)); 274 OUT_RING(ring, 0x00000000); 275 276 OUT_PKT3(ring, CP_SET_CONSTANT, 2); 277 OUT_RING(ring, CP_REG(REG_A2XX_RB_COPY_CONTROL)); 278 OUT_RING(ring, 0x00000000); 279 } 280 281 void 282 fd2_draw_init(struct pipe_context *pctx) 283 { 284 struct fd_context *ctx = fd_context(pctx); 285 ctx->draw_vbo = fd2_draw_vbo; 286 ctx->clear = fd2_clear; 287 } 288