Home | History | Annotate | Download | only in a4xx
      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