1 /* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */ 2 3 /* 4 * Copyright (C) 2014 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 "fd4_draw.h" 38 #include "fd4_context.h" 39 #include "fd4_emit.h" 40 #include "fd4_program.h" 41 #include "fd4_format.h" 42 #include "fd4_zsa.h" 43 44 45 static void 46 draw_impl(struct fd_context *ctx, struct fd_ringbuffer *ring, 47 struct fd4_emit *emit, unsigned index_offset) 48 { 49 const struct pipe_draw_info *info = emit->info; 50 enum pc_di_primtype primtype = ctx->primtypes[info->mode]; 51 52 fd4_emit_state(ctx, ring, emit); 53 54 if (emit->dirty & (FD_DIRTY_VTXBUF | FD_DIRTY_VTXSTATE)) 55 fd4_emit_vertex_bufs(ring, emit); 56 57 OUT_PKT0(ring, REG_A4XX_VFD_INDEX_OFFSET, 2); 58 OUT_RING(ring, info->index_size ? info->index_bias : info->start); /* VFD_INDEX_OFFSET */ 59 OUT_RING(ring, info->start_instance); /* ??? UNKNOWN_2209 */ 60 61 OUT_PKT0(ring, REG_A4XX_PC_RESTART_INDEX, 1); 62 OUT_RING(ring, info->primitive_restart ? /* PC_RESTART_INDEX */ 63 info->restart_index : 0xffffffff); 64 65 /* points + psize -> spritelist: */ 66 if (ctx->rasterizer->point_size_per_vertex && 67 fd4_emit_get_vp(emit)->writes_psize && 68 (info->mode == PIPE_PRIM_POINTS)) 69 primtype = DI_PT_POINTLIST_PSIZE; 70 71 fd4_draw_emit(ctx->batch, ring, primtype, 72 emit->key.binning_pass ? IGNORE_VISIBILITY : USE_VISIBILITY, 73 info, index_offset); 74 } 75 76 /* fixup dirty shader state in case some "unrelated" (from the state- 77 * tracker's perspective) state change causes us to switch to a 78 * different variant. 79 */ 80 static void 81 fixup_shader_state(struct fd_context *ctx, struct ir3_shader_key *key) 82 { 83 struct fd4_context *fd4_ctx = fd4_context(ctx); 84 struct ir3_shader_key *last_key = &fd4_ctx->last_key; 85 86 if (!ir3_shader_key_equal(last_key, key)) { 87 if (ir3_shader_key_changes_fs(last_key, key)) { 88 ctx->dirty_shader[PIPE_SHADER_FRAGMENT] |= FD_DIRTY_SHADER_PROG; 89 ctx->dirty |= FD_DIRTY_PROG; 90 } 91 92 if (ir3_shader_key_changes_vs(last_key, key)) { 93 ctx->dirty_shader[PIPE_SHADER_VERTEX] |= FD_DIRTY_SHADER_PROG; 94 ctx->dirty |= FD_DIRTY_PROG; 95 } 96 97 fd4_ctx->last_key = *key; 98 } 99 } 100 101 static bool 102 fd4_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info, 103 unsigned index_offset) 104 { 105 struct fd4_context *fd4_ctx = fd4_context(ctx); 106 struct fd4_emit emit = { 107 .debug = &ctx->debug, 108 .vtx = &ctx->vtx, 109 .prog = &ctx->prog, 110 .info = info, 111 .key = { 112 .color_two_side = ctx->rasterizer->light_twoside, 113 .vclamp_color = ctx->rasterizer->clamp_vertex_color, 114 .fclamp_color = ctx->rasterizer->clamp_fragment_color, 115 .rasterflat = ctx->rasterizer->flatshade, 116 .half_precision = ctx->in_blit && 117 fd_half_precision(&ctx->batch->framebuffer), 118 .ucp_enables = ctx->rasterizer->clip_plane_enable, 119 .has_per_samp = (fd4_ctx->fsaturate || fd4_ctx->vsaturate || 120 fd4_ctx->fastc_srgb || fd4_ctx->vastc_srgb), 121 .vsaturate_s = fd4_ctx->vsaturate_s, 122 .vsaturate_t = fd4_ctx->vsaturate_t, 123 .vsaturate_r = fd4_ctx->vsaturate_r, 124 .fsaturate_s = fd4_ctx->fsaturate_s, 125 .fsaturate_t = fd4_ctx->fsaturate_t, 126 .fsaturate_r = fd4_ctx->fsaturate_r, 127 .vastc_srgb = fd4_ctx->vastc_srgb, 128 .fastc_srgb = fd4_ctx->fastc_srgb, 129 }, 130 .rasterflat = ctx->rasterizer->flatshade, 131 .sprite_coord_enable = ctx->rasterizer->sprite_coord_enable, 132 .sprite_coord_mode = ctx->rasterizer->sprite_coord_mode, 133 }; 134 135 fixup_shader_state(ctx, &emit.key); 136 137 enum fd_dirty_3d_state dirty = ctx->dirty; 138 139 /* do regular pass first, since that is more likely to fail compiling: */ 140 141 if (!(fd4_emit_get_vp(&emit) && fd4_emit_get_fp(&emit))) 142 return false; 143 144 emit.key.binning_pass = false; 145 emit.dirty = dirty; 146 147 struct fd_ringbuffer *ring = ctx->batch->draw; 148 149 if (ctx->rasterizer->rasterizer_discard) { 150 fd_wfi(ctx->batch, ring); 151 OUT_PKT3(ring, CP_REG_RMW, 3); 152 OUT_RING(ring, REG_A4XX_RB_RENDER_CONTROL); 153 OUT_RING(ring, ~A4XX_RB_RENDER_CONTROL_DISABLE_COLOR_PIPE); 154 OUT_RING(ring, A4XX_RB_RENDER_CONTROL_DISABLE_COLOR_PIPE); 155 } 156 157 draw_impl(ctx, ctx->batch->draw, &emit, index_offset); 158 159 if (ctx->rasterizer->rasterizer_discard) { 160 fd_wfi(ctx->batch, ring); 161 OUT_PKT3(ring, CP_REG_RMW, 3); 162 OUT_RING(ring, REG_A4XX_RB_RENDER_CONTROL); 163 OUT_RING(ring, ~A4XX_RB_RENDER_CONTROL_DISABLE_COLOR_PIPE); 164 OUT_RING(ring, 0); 165 } 166 167 /* and now binning pass: */ 168 emit.key.binning_pass = true; 169 emit.dirty = dirty & ~(FD_DIRTY_BLEND); 170 emit.vp = NULL; /* we changed key so need to refetch vp */ 171 emit.fp = NULL; 172 draw_impl(ctx, ctx->batch->binning, &emit, index_offset); 173 174 fd_context_all_clean(ctx); 175 176 return true; 177 } 178 179 void 180 fd4_draw_init(struct pipe_context *pctx) 181 { 182 struct fd_context *ctx = fd_context(pctx); 183 ctx->draw_vbo = fd4_draw_vbo; 184 } 185